When using Keybase, occasionally, people will track your identity. This has cryptographic value. Your identity on Keybase is based on what you do online and how long you have done it. As people track you, they cryptographically sign your Keybase identity. This creates a snapshot in time that states you've taken the precautions to verify the identity, by checking the digital signature of each of their online proofs. This snapshot is frozen in time, and as more and more people track your identity, the stronger the statement of the validity of that identity. In other words, Keybase compliments the PGP Web of Trust, without actually replacing key signing parties, or actually signing PGP keys.
In this post, I want to discuss what it takes to verify signatures of Keybase identity proofs, so you can verify that Keybase isn't doing anything sneaky the data. In this post, I am going to verify the identity proofs of a friend of mine, Joshua Galvez as an example of how to verify each identity proof out-of-band (not using the Keybase client software).
First, all identity proofs are stored in JSON, which is a standardized format. The JSON object is cleanly formatted for easy readability, so you can examine what has been signed, and exactly what you are verifying. Nothing should be hidden up Keybase's sleeves. To start, I am going to navigate to Josh's Keybase identity page. I see that he has proved he owns a Twitter account, a Github account, a reddit account, and a personal website, all with his personal OpenPGP key.
To verify the proofs, I need to get a physical copy of the statement. Again, I am going to do this all out-of-band, away from the Keybase client software. As such, I'll copy and paste each statement proof into a text editor, and save it to disk, as well as each PGP signature. I'll do this with his Twitter account as an example.
Because of the brevity of Twitter, a full JSON object with a PGP signature can't be sent. So, Keybase keeps this proof on their server, with a link in the tweet pointing to the proof. So, we'll need to get it there. The link in his tweet points to https://keybase.io/zevlag/sigs/0Pl859RFLHZuEi7ozQyrbT1cphZCxYQMuoyM. There is a "Show the proof" link on the page, which gives me all the necessary data for verifying his identity. All I need is his JSON object and his PGP signature. I need to combine them in a single file, and save it to disk. As such, my file will look like this:
{ "body": { "client": { "name": "keybase.io node.js client", "version": "0.7.3" }, "key": { "fingerprint": "12c5e8619f36b0bb86b5be9aea1f03e20cf2fdbd", "host": "keybase.io", "key_id": "EA1F03E20CF2FDBD", "uid": "2b26e905f5b23528d91662374e840d00", "username": "zevlag" }, "service": { "name": "twitter", "username": "zevlag" }, "type": "web_service_binding", "version": 1 }, "ctime": 1416507777, "expire_in": 157680000, "prev": null, "seqno": 1, "tag": "signature" } -----BEGIN PGP MESSAGE----- Version: GnuPG/MacGPG2 v2.0.22 (Darwin) Comment: GPGTools - https://gpgtools.org owGbwMvMwMVYnXN9yvZMuQbG0wdeJjGE5BnOrlZKyk+pVLKqVkrOyUzNKwGx8hJz U5WslLJTK5MSi1P1MvMV8vJTUvWyihWganSUylKLijPz84CqDPTM9YyVanVAykGa 0zLz0lOLCooyQWYpGRolm6ZamBlaphmbJRkkJVmYJZkmpVompiYaphkYpxoZJKcZ paUkpQCNzMgvLkGxVQlsZnxmClDU1dHQzcDY1cjA2c3IzcXJBShXCpYwSjIyS7U0 ME0zTTIyNjWySLE0NDMzMjY3SbUwMUgxMAApLE4tgnqpKrUsJzEd5FqgWFlmciqS d0vKM0tKUotwaSipLAAJlKcmxUP1xidl5qUAfYscHIZAlcklmSC9hiaGZqYG5kCg o5RaUZBZlBqfCVJham5mYQAEOkoFRallSlZ5pTk5IPcU5uUDZYEWAe2zUirOTM9L LCktSlWq7WSSYWFg5GJgY2UCxRgDF6cALB6Z5wowNEXaavBftOToU3lx8YCcUIzU Y5FN3LxXjrbNOum2oiQyrMMszfWM5Kz+D3O5ZZJabOUO2v99UPBMRmqZy6ZLdh0n 1t92OPT+7ILwL2+Y+rfoLDJxufXh7ykfZos1L66fVhc+e1HOw9rEuChW+eBJkbCE 3y42k3yXNJ5sSpDc9Ujhcewsw3nuM86G/8tbzGUo9OSERcif0wou4Qtnnj2cs6Nz nk3qLUvHWRfX753v+mPlNMm2hXZbbjzIF3XaK93JZj/5im6QyA3fjy6CbKGtqi1X Am+d+ljtGD0h5MPRDLPG3Xtmiqps3Hfo7fGvUUwF6gnzHm7xdD42banr8wMHfZ6q a26o3nPras+GHwERx898vvTq14lfxgKc7wXOXEl30bN7KTa/TERMXK2nafZT9qOb 7sSvSnjLsj9jw1nVGaKcvtd8855Xr6/eySwtsjPOapVT85JPisu3l/ten/XqxPa8 mRxWAvrLdl9NXNS46zYPW61MwJQPYQfYN3DxTX3ucMO5Qd/EftWeF0depDlsme7S pTmr0Eey8sqkPo9f63/yfFgg9GPP3PY/22KP7+2Ifm7/N6FZ95xh2bXXM9dPvJ79 gCVVbH5m4OKOTI3aD9bWnVekglJLpwboJb6dfPC4V0vmpgWxb0w49JfE3j8fHHNa jTnvgo3T+vzZ4mcOG06+/2CpebSKtmlTyIyYPzYbDXWczSPVPN28Yhr7rwIA =V5X5 -----END PGP MESSAGE-----
I'll save this to disk as /tmp/zevlag-twitter.txt
Now, I just need Josh's public PGP key imported from a key server. I can, and should use Keybase here. Instead of using the MIT PGP key server, and running the risk of getting the wrong key, I can be reasonably confident I will get the correct key from Keybase. The raw public key can be accessed by appending "key.asc" at the end of their identity URL. So, in this case https://keybase.io/zevlag/key.asc. So, I'll grab it via the shell:
$ wget -O - https://keybase.io/zevlag/key.asc 2> /dev/random | gpg --import -
Now that I have Josh's public key imported into my GPG public key ring, I am read to verify Josh's Twitter proof of identity:
$ gpg --verify /tmp/zevlag-twitter.txt gpg: Signature made Thu 20 Nov 2014 11:23:23 AM MST using RSA key ID B7691E80 gpg: Good signature from "Joshua Galvez <josh@zevlag.com>" gpg: aka "Joshua Galvez (Work - Emery Telcom) <jgalvez@emerytelcom.com>" gpg: aka "keybase.io/zevlag <zevlag@keybase.io>" gpg: WARNING: This key is not certified with a trusted signature! gpg: There is no indication that the signature belongs to the owner. Primary key fingerprint: 12C5 E861 9F36 B0BB 86B5 BE9A EA1F 03E2 0CF2 FDBD Subkey fingerprint: DC35 E3CF 1179 41A9 7D72 BC9A 7B6C D794 B769 1E80
At this point, I can confirm that the owner of the private key for 0xEA1F03E20CF2FDBD cryptographically signed a JSON object for Twitter. Further, that individual has access to the Twitter account, so the signature can be posted. After verifying the other accounts, I can be reasonably confident that the individual is who they claim- Josh Galvez. Otherwise, an attacker has successfully compromised all of Josh Galvez's online accounts, as well as his OpenPGP key (or forged a new one), and either compromised his Keybase account, or created one masquerading as him. The former seems more likely than the latter. Further, because I have previously met with and engaged online with Josh, I have no doubt that this is indeed Josh Galvez, and 0xEA1F03E20CF2FDBD is indeed his public key.
So, I can now track Josh through Keybase, which means me cryptographically signing his Keybase identity, and creating a snapshot in time that says "I am reasonably sure this is Josh Galvez, these accounts are part of his online presence, and 0xEA1F03E20CF2FDBD is his OpenPGP key. Staying out of band from the Keybase client software, I can do this entirely with curl(1) and gpg(1).
Navigating to his Keybase identity, I'll click the "Track zevlag" button. A pop-up displays with the following options:
- in the browser
- command line with keybase
- command line with [bash + GPG + cURL]
I have not integrated an encrypted copy of my private key with Keybase, so tracking Josh in the browser is unavailable to me. Further, I wish to do this out-of-band from Keybase anyway, so I'll select "command line with [bash + GPG + cURL]" and click "Continue". This displays that I need to copy and paste the following content into my shell:
echo '{"body": (... large JSON object snipped ....) }' | \ gpg -u 'e0413539273a6534a3e1925922eee0488086060f' -a --sign | \ perl -e '$_ = join("", <>); s/([^\w\.@ -])/sprintf("%%%2.2x",ord($1))/eg; s/ /+/g; print("sig=", $_)' | \ curl -d @- \ -d type=track \ -d session=lgHZIDg3ZWNjY2NiNTRiMTBiNThjOTQ2NDJhODA3MzM2NjAwzlSh4WnOAeEzgNkgZjZmNWVmZDg4YzcwZDI2NDNlZGY2ZWYyYTc3M2IyMDLEIM0QqHGrtfga4a%2Bnz7soXFHqFbbiio7PaVGjh7DfyyPG \ -d csrf_token=lgHZIDg3ZWNjY2NiNTRiMTBiNThjOTQ2NDJhODA3MzM2NjAwzlSkLg7OAAFRgMDEIA8egS4XVUzH%2BkPY8pMJbmMFiN3%2BAdZEdTm7Buvm551L \ -d plain_out=1 \ -d uid=2b26e905f5b23528d91662374e840d00 https://keybase.io/_/api/1.0/follow.json
After entering that into my shell, and hitting enter, I am presented with typing in my passphrase for my private key, which in turn signs the object, and uses the Keybase API to post the result. I can then reload my profile, and see that I am now tracking Josh with Keybase. This means that at this point in time, I have made a cryptographic statement regarding the key ownership and identity of Joshua Galvez. Of course, I can revoke that statement at any time, if for any reason I believe his account has become compromised, he himself has become untrustworthy, or for other reasons.
Post a Comment