Hello everyone :)
Neal and I went to Paris for the Rustfest, and we had quite a productive week. Among other things, we thought a lot of how to implement an approximation of forward secrecy that only requires minimal changes to other implementations. This work resulted in several mails to the OpenPGP working group, the most complete description of our proposal being in [0].
0: https://mailarchive.ietf.org/arch/msg/openpgp/mk8_FSS-n4DVGfh_VwuGtEOS2xk
Furthermore, after an inspiring discussion with a Jabber/OMEMO developer, we believe we found a way to implement Signal's double ratchet protocol in a transport-protocol agnostic way in OpenPGP without requiring a rendezvous server. This, however, requires per-device keys, and keeping a lot of state, and therefore requires invasive changes to other implementations. Nevertheless, we are quite excited about the prospect :)
Besides conceptual work, we also got to do some hacking during the impl days. While some rough edges remain, we are happy to report that our low-level OpenPGP library can do almost anything that does not require secret keys.
Let's have a look at what we can do with our command line tools!
Symmetric Encryption/Decryption -------------------------------
% sq encrypt -s -i plaintext -o ciphertext.pgp Enter passphrase: huhu % sq decrypt -i ciphertext.pgp Enter passphrase to decrypt message: huhu Hello world!
Neat! What else?
% sq encrypt -s -s -i plaintext -o ciphertext.pgp Enter passphrase 1: huhu Enter passphrase 2: haha % sq decrypt -i ciphertext.pgp Enter passphrase to decrypt message: huhu Hello world! % sq decrypt -i ciphertext.pgp Enter passphrase to decrypt message: haha Hello world!
Sweet! Support for multiple passphrases.
Key Store ---------
Sequoia has a Key Store that manages and updates public keys. Let's see what my store has to offer:
% sq store list +-------+----------------------------------------------------+ | label | fingerprint | +-------+----------------------------------------------------+ | me | CBCD 8F03 0588 653E EDD7 E265 9B7D D433 F254 904A | | neal | 8F17 7771 18A3 3DDA 9BA4 8E62 AACB 3243 6300 52D9 | | kai | FEC1 5429 6C79 773B 1562 511A 65AC 504E B50A 8C43 | +-------+----------------------------------------------------+
The store maps user-defined labels to keys. Let's add another one!
% sq store add dkg 0EE5BE979282D80B9F7540F1CCD2ED94D21739E9 % sq store log dkg +------------------+----------------------------------------+ | timestamp | message | +------------------+----------------------------------------+ | 2018-05-31 19:13 | New binding dkg -> CCD2 ED94 D217 39E9 | +------------------+----------------------------------------+
Note that I only specified the fingerprint, I did not supply any key material. Now if I wait a little while, the keystore will reach out to the keyservers and fetch the key material. In the future, it should force an update if the user wants to use the key before an update occurred. It will continue to update the key at random intervals, like parciemonie (although currently we do not support TOR, that requires authentication support in the SOCKS middleware for our http library).
% sq store log dkg +------------------+----------------------------------------+ | timestamp | message | +------------------+----------------------------------------+ | 2018-05-31 19:16 | Update successful | | 2018-05-31 19:13 | New binding dkg -> CCD2 ED94 D217 39E9 | +------------------+----------------------------------------+
The log is a machine-readable history of this binding. Neat! What can we do with that now?
Asymmetric Encryption ---------------------
% sq encrypt -r me -r dkg -i plaintext -o ciphertext.pgp % gpg --decrypt ciphertext.pgp gpg: encrypted with 4096-bit RSA key, ID E3A32229449B0350, created 2017-12-04 "Daniel Kahn Gillmor dkg@fifthhorseman.net" gpg: encrypted with 2048-bit RSA key, ID 08CC70F8D8CC765A, created 2017-07-19 "Justus Winter justus@sequoia-pgp.org" Hello world!
Kai is working on secret key support, this should land soonish. As of now, we only support RSA, cv25519 is planned next.
To get an idea how to do that from Rust with our low-level API, please look at our example [1].
1: https://gitlab.com/sequoia-pgp/sequoia/blob/master/openpgp/examples/encrypt-...
Signature Verification ----------------------
We have been working on a replacement for gpgv, a stripped down version of GnuPG suitable for e.g. package verification. Our tool is called sqv:
% sqv --keyring me.pgp huhu.sig huhu ; echo $? CBCD 8F03 0588 653E EDD7 E265 9B7D D433 F254 904A 0
Packet Stream Dumping ---------------------
sq can be used to inspect OpenPGP data:
% sq dump -i huhu.signed.detached Signature(Signature { version: 4, sigtype: Binary, issuer: "256A 4E55 E4A7 2D97 AD24 68E7 88DC 7E33 385F 791D", pk_algo: RsaEncryptSign, hash_algo: SHA256, hashed_area: {IssuerFingerprint: SubpacketArea { critical: false, tag: IssuerFingerprint, value (21 bytes): [4, 37, 106, 78, 85, 228, 167, 45, 151, 173, 36, 104, 231, 136, 220, 126] }, SignatureCreationTime: SubpacketArea { critical: false, tag: SignatureCreationTime, value (4 bytes): [90, 233, 129, 79] }}, unhashed_area: {Issuer: SubpacketArea { critical: false, tag: Issuer, value (8 bytes): [136, 220, 126, 51, 56, 95, 121, 29] }}, hash_prefix: "4390", computed_hash: None, mpis: ["2047 bits: 7EB8 37F5 D246 0299 B633 15A5 599A A3CB 87D7 6E52 0CB9 820A E238 AF28 6FCE 77D3 FD24 871B 681E 59C3 6EE9 D848 00C6 7FF7 B3E5 CFD5 F1E1 0901 107B BE97 DA75 7BA0 E8F9 A8C7 BE98 5E8C 06CB BC36 014A DCF0 6A13 BC8E AD9D 52B5 BE46 4C19 55E6 10FD 44D4 649A D7F1 475A FC2B BD7A CA3A 88B7 E91F 3271 4F85 7BDA 4DDD C588 51C0 2B04 CC79 B10D 6DB2 D280 F06A 6556 26E0 BD74 67C7 7DF3 7011 83CA 3D0A 7AAB D378 89F0 E6B6 0F90 A2D4 B387 CE66 FF85 34DE 8204 16E7 4074 FDCA 81E7 A8F6 77FF FACB 8419 06F9 2469 294E F800 41AE 30FA 073F 632E D211 783A 3929 083A 3D67 0CA3 EBF6 FCBF D34F 43E0 2F85 DB4B 2559 F666 E1DA A476 8828 425D A7FA F906 1A19 CCD7 0614 1F95"] })
And for the real curious, we can print an annotated hex dump:
% sq dump --hex -i huhu.signed.detached Signature(Signature { version: 4, sigtype: Binary, issuer: "256A 4E55 E4A7 2D97 AD24 68E7 88DC 7E33 385F 791D", pk_algo: RsaEncryptSign, hash_algo: SHA256, hashed_area: {IssuerFingerprint: SubpacketArea { critical: false, tag: IssuerFingerprint, value (21 bytes): [4, 37, 106, 78, 85, 228, 167, 45, 151, 173, 36, 104, 231, 136, 220, 126] }, SignatureCreationTime: SubpacketArea { critical: false, tag: SignatureCreationTime, value (4 bytes): [90, 233, 129, 79] }}, unhashed_area: {Issuer: SubpacketArea { critical: false, tag: Issuer, value (8 bytes): [136, 220, 126, 51, 56, 95, 121, 29] }}, hash_prefix: "4390", computed_hash: None, mpis: ["2047 bits: 7EB8 37F5 D246 0299 B633 15A5 599A A3CB 87D7 6E52 0CB9 820A E238 AF28 6FCE 77D3 FD24 871B 681E 59C3 6EE9 D848 00C6 7FF7 B3E5 CFD5 F1E1 0901 107B BE97 DA75 7BA0 E8F9 A8C7 BE98 5E8C 06CB BC36 014A DCF0 6A13 BC8E AD9D 52B5 BE46 4C19 55E6 10FD 44D4 649A D7F1 475A FC2B BD7A CA3A 88B7 E91F 3271 4F85 7BDA 4DDD C588 51C0 2B04 CC79 B10D 6DB2 D280 F06A 6556 26E0 BD74 67C7 7DF3 7011 83CA 3D0A 7AAB D378 89F0 E6B6 0F90 A2D4 B387 CE66 FF85 34DE 8204 16E7 4074 FDCA 81E7 A8F6 77FF FACB 8419 06F9 2469 294E F800 41AE 30FA 073F 632E D211 783A 3929 083A 3D67 0CA3 EBF6 FCBF D34F 43E0 2F85 DB4B 2559 F666 E1DA A476 8828 425D A7FA F906 1A19 CCD7 0614 1F95"] })
00000000 89 01 33 header 00000003 04 version 00000004 00 sigtype 00000005 01 pk_algo 00000006 08 hash_algo 00000007 00 1d hashed_area_len 00000009 16 21 04 25 6a 4e 55 hashed_area 00000010 e4 a7 2d 97 ad 24 68 e7 88 dc 7e 33 38 5f 79 1d 00000020 05 02 5a e9 81 4f 00000026 00 0a unhashed_area_len 00000028 09 10 88 dc 7e 33 38 5f unhashed_area 00000030 79 1d 00000032 43 hash_prefix1 00000033 90 hash_prefix2 00000034 07 ff 7e b8 37 f5 d2 46 02 99 b6 33 mpis 00000040 15 a5 59 9a a3 cb 87 d7 6e 52 0c b9 82 0a e2 38 00000050 af 28 6f ce 77 d3 fd 24 87 1b 68 1e 59 c3 6e e9 00000060 d8 48 00 c6 7f f7 b3 e5 cf d5 f1 e1 09 01 10 7b 00000070 be 97 da 75 7b a0 e8 f9 a8 c7 be 98 5e 8c 06 cb 00000080 bc 36 01 4a dc f0 6a 13 bc 8e ad 9d 52 b5 be 46 00000090 4c 19 55 e6 10 fd 44 d4 64 9a d7 f1 47 5a fc 2b 000000a0 bd 7a ca 3a 88 b7 e9 1f 32 71 4f 85 7b da 4d dd 000000b0 c5 88 51 c0 2b 04 cc 79 b1 0d 6d b2 d2 80 f0 6a 000000c0 65 56 26 e0 bd 74 67 c7 7d f3 70 11 83 ca 3d 0a 000000d0 7a ab d3 78 89 f0 e6 b6 0f 90 a2 d4 b3 87 ce 66 000000e0 ff 85 34 de 82 04 16 e7 40 74 fd ca 81 e7 a8 f6 000000f0 77 ff fa cb 84 19 06 f9 24 69 29 4e f8 00 41 ae 00000100 30 fa 07 3f 63 2e d2 11 78 3a 39 29 08 3a 3d 67 00000110 0c a3 eb f6 fc bf d3 4f 43 e0 2f 85 db 4b 25 59 00000120 f6 66 e1 da a4 76 88 28 42 5d a7 fa f9 06 1a 19 00000130 cc d7 06 14 1f 95
Usability improvements ----------------------
Our tools now detect and automatically handle armored data. The store subcommand no longer takes the store name as positional argument. For an overview what our tools can do, see [2] and [3].
2: https://docs.sequoia-pgp.org/sq/index.html 3: https://docs.sequoia-pgp.org/sqv/index.html
Cheers, Justus