KBChat - Private, Encrypted Chat via KBFS

by Samuel Hofius

I recently found out about a service called Keybase through an online acquaintance who offered to provide me with an invite to be a beta tester for the service (which, at the time I'm writing this, is the only way to sign up for the service).

Keybase, according to their website, maps your identity to your public keys, and vice versa.  I've been interested in cryptography (and more specifically, encrypting communications between people) for a long time now, but I've never made time to properly research it and play with it.  So when I was offered an invite to a service that seemed to make it simple to diveinto encrypted communication, I jumped at it.

At some point along the way, I found out about a feature of Keybase called KBFS 2 (Keybase Filesystem).  KBFS is described as a cryptographically secure file mount.  It is similar to services like Dropbox, Google Drive, and others.  There are, however, several key differences between KBFS and other cloud-based storage services, and I will go over a couple of them in this article.  One big difference between KBFS and other cloud-based storage services is the fact that two Keybase users can share files with each other in a manner that is both private and encrypted.  Another is that KBFS mounts very cleanly into your operating system.

These are the two main points that make "kbchat.sh" possible.

Once the Keybase app is installed and logged in on your Linux machine, you will find your KBFS mounted at: /keybase

Within this directory you will find two folders: /keybase/public and /keybase/private

You can access any Keybase user's public files (including your own) at: /keybase/public/{username}

(Of course, you need to replace any text in this article that's in curly braces with the correct username).

You can access your own private files at: /keybase/private/{yourname}

The real magic of KBFS (as it pertains to kbchat.sh) comes in when you access a shared folder between yourself and someone else by going to: /keybase/private/{yourname},{theirname}

Any files in this shared folder will be signed and encrypted with both users' private keys, making the files available securely to both parties.

The idea behind kbchat.sh is very simple.

The script creates a file called "chat.log" within a shared folder between yourself and the person with whom you are chatting.

A tmux session is spawned with two panes.  The top pane runs a "tail -f" (follow) command on the chat.log, which continously displays the last 10 lines of the log, plus any new lines that are added to the file while the script is running.

The bottom pane loops infinitely with the Bash "read" command, and reads your input into a variable.

Once input is received, the value of that variable is appended to the chat log file along with the current UTC date and time, as well as your Keybase username.  There's more to the script, as I've added some color to the usernames and the option to wrap text in *asterisks* to make it appear bold.

I've also added an option to close down the chat by typing "!exit" (although the chat.log file stays in the shared folder of both users).

For now, kbchat.sh only supports Linux, so that is what I've focused on in this article.

KBFS, however, supports Windows, Mac, and Linux.  The code will be available on GitHub, and you're free to make any changes.

Also please feel free to write your own script which brings this idea to other operating systems.

References
#!/bin/bash

####### -- kbchat.sh -- #######
#
# Written by Samuel Hofius
#
# Private, encrypted chat via KBFS
#
# Usage: ./kbchat.sh <user>
#
# where <user> is the user you're chatting with
#
###############################

# display help if no remote user was entered
if [ -z ${1+x} ]; then
	echo ""
	echo "KBChat - Private, encrypted chat via KBFS"
	echo ""
	echo "Usage: $0 <user>"
	echo ""
	echo "	user [required]:	keybase.io username to chat with"
	echo ""
	exit
fi

# make sure we're not running as root as keybase doesn't allow this
userid=$(id -u)
[ $userid == '0' ] && \
       	echo -e "This script cannot run as root.\nExiting..." && \
       	exit

# get keybase user
kbuser=$(keybase status |grep "Username" |cut -d":" -f2 |tr -d [:space:])

# write script that will be used for the top pane
cat > /tmp/top_pane_$1.sh << EOF
#!$(which bash)
touch /keybase/private/$kbuser,$1/chat.log
tail -f /keybase/private/$kbuser,$1/chat.log | sed \\
     -e "s/\($kbuser:\)/\o033[31m\o033[1m\1\o033[0m/" \\
     -e "s/\($1:\)/\o033[34m\o033[1m\\1\o033[0m/" \\
     -e "s/\*\(.*\)\*/\o033[1m\\1\o033[0m/"
EOF

# write script that will be used for the bottom pane
cat > /tmp/bottom_pane_$1.sh << EOF
#!$(which bash)
function cleanup {
    rm /tmp/top_pane_$1.sh
    rm /tmp/bottom_pane_$1.sh
    tmux kill-session -t kbchat_$1
}

while true; do
    echo -en "\rMessage: "
    read messg
    [ "\$messg" == '!exit' ] && break

    echo "[\$(TZ=UTC date '+%F %H:%M')] $kbuser: \$messg" >> \\
         /keybase/private/$kbuser,$1/chat.log && \\
         clear
done
cleanup
EOF

chmod +x /tmp/top_pane_$1.sh
chmod +x /tmp/bottom_pane_$1.sh

# set up tmux session
tmux new-session -d -s "kbchat_$1" "/tmp/top_pane_$1.sh"
tmux split-window -v "/tmp/bottom_pane_$1.sh"
tmux resize-pane -D 20
tmux attach-session

Code: kbchat.sh

Return to $2600 Index