consistent pcp/pbp formats (was: Curve p25519 Replacements for GnuPG?(x2 now) ..)
consistent key formats are critical
more than fine with me.
need to converge on: - endianness
I'm currently using big endian for multibyte values whereever they appear. It's already verified to work on little and big endian platforms (e.g. tested on aix/ppc)
- coordinate representation x, x&y, x and sign ... or bits to show which of these ... perhaps borrow ANSI method
Could you please explain this further?
- hint / indication of cipher suite / curve
In pcp there's already such a hint included in exported keys, however I'm not using it, since there's no choice of different curves in libsodium so far. But it's on the list.
- text encoding of binary format (ascii)
As already stated in the other subthread, I use Z85, while stef is using base85. Since Z85 is a subset of base85, I'm pretty sure we can agree on something.
- human readable format
There's a human readable version of keys in pcp, but the tool itself doesn't use it (example attached). It uses the z85 encoded binary part of such a file. pcp has some more fields stored in a key than pbp: - a key id (e.g. 0x54E9C62E1852EBC5) which is required to identify a key - some text fields (owner, mail) - a serial number - key format version number I'm not sure, how stef solved the ed25519 issue (you can't use a curve25519 secret key to create an ed25519 signature directly). After some discussion on the libsodium mailinglist we came up with this: When the user generates a new key, the ed25519 secret key will be generated first. The curve25519 secret will be derived from that, since the ed25519 already contains a usable curve25519 key. In pcp I store both of them for easier access, so the ed25519 and curve25519 secret and public keys are stored, the secret keys are encrypted and I store the nonce as well (see include/pcp/key.h). Speaking of key encryption: @stef: according to your docs you're already using scrypt() for key derivation. I'd like to use that as well, but it's not part of libsodium (afaik), so I use my own method for this til scrypt() is implemented in libsodium. That's because I want to avoid writing crypto code myself. Maybe we should iron out the details off-list? bes, Tom -- PGP Key: https://www.daemon.de/txt/tom-pgp-pubkey.txt S/Mime Cert: https://www.daemon.de/txt/tom-smime-cert.pem Bitmessage: BM-2DAcYUx3xByfwbx2bYYxeXgq3zDscez8wC -- This message has been scanned for viruses and dangerous content by MailScanner, and is believed to be clean.
On Jan 14, 2014, at 3:16 AM, Thomas von Dein <tom@vondein.org> wrote:
- coordinate representation x, x&y, x and sign ... or bits to show which of these ... perhaps borrow ANSI method
Could you please explain this further?
ANSI defined (and used by NIST and others) the use of the first byte of a elliptic curve point representation to indicate if it is: - both x&y coordinates - compressed with sign in the byte - ..just x (guessing on this need to go check) bit coin may use the same … easiest doc to find would be in RFCs However … if the key is solely for an initial DH exchange you may not need anything.
- hint / indication of cipher suite / curve
In pcp there's already such a hint included in exported keys, however I'm not using it, since there's no choice of different curves in libsodium so far. But it's on the list.
OIDs suck. A simple registry would be nice. You need to know the key type when publicly introduced … but there are applications where you would want to be stealthier on indicating suite usage
- text encoding of binary format (ascii)
As already stated in the other subthread, I use Z85, while stef is using base85. Since Z85 is a subset of base85, I'm pretty sure we can agree on something.
Not familiar with Z85 … pointer please ... base85 or Z85 are a decent balance of compression and robustness for applications like email signatures
- human readable format
There's a human readable version of keys in pcp, but the tool itself doesn't use it (example attached). It uses the z85 encoded binary part of such a file.
pcp has some more fields stored in a key than pbp:
- a key id (e.g. 0x54E9C62E1852EBC5) which is required to identify a key
base27 would be much better for a ‘id’ that humans read base16 is really old school
- some text fields (owner, mail) - a serial number - key format version number
I'm not sure, how stef solved the ed25519 issue (you can't use a curve25519 secret key to create an ed25519 signature directly). After some discussion on the libsodium mailinglist we came up with this: curve naming, test vectors, algorithm usage need work ...
When the user generates a new key, the ed25519 secret key will be generated first. The curve25519 secret will be derived from that, since the ed25519 already contains a usable curve25519 key. In pcp I store both of them for easier access, so the ed25519 and curve25519 secret and public keys are stored, the secret keys are encrypted and I store the nonce as well (see include/pcp/key.h).
Speaking of key encryption: @stef: according to your docs you're already using scrypt() for key derivation. I'd like to use that as well, but it's not part of libsodium (afaik), so I use my own method for this til scrypt() is implemented in libsodium. That's because I want to avoid writing crypto code myself.
Maybe we should iron out the details off-list?
I’m interested … Paul
bes, Tom
-- PGP Key: https://www.daemon.de/txt/tom-pgp-pubkey.txt S/Mime Cert: https://www.daemon.de/txt/tom-smime-cert.pem Bitmessage: BM-2DAcYUx3xByfwbx2bYYxeXgq3zDscez8wC
-- This message has been scanned for viruses and dangerous content by MailScanner, and is believed to be clean.
<key-alicia-pub.txt>
Thomas von Dein wrote:
consistent key formats are critical
more than fine with me.
need to converge on: - endianness
I'm currently using big endian for multibyte values whereever they appear. It's already verified to work on little and big endian platforms (e.g. tested on aix/ppc)
- coordinate representation x, x&y, x and sign ... or bits to show which of these ... perhaps borrow ANSI method
Could you please explain this further?
- hint / indication of cipher suite / curve
In pcp there's already such a hint included in exported keys, however I'm not using it, since there's no choice of different curves in libsodium so far. But it's on the list.
- text encoding of binary format (ascii)
As already stated in the other subthread, I use Z85, while stef is using base85. Since Z85 is a subset of base85, I'm pretty sure we can agree on something.
- human readable format
There's a human readable version of keys in pcp, but the tool itself doesn't use it (example attached). It uses the z85 encoded binary part of such a file.
pcp has some more fields stored in a key than pbp:
- a key id (e.g. 0x54E9C62E1852EBC5) which is required to identify a key - some text fields (owner, mail) - a serial number - key format version number
I'm not sure, how stef solved the ed25519 issue (you can't use a curve25519 secret key to create an ed25519 signature directly). After some discussion on the libsodium mailinglist we came up with this:
When the user generates a new key, the ed25519 secret key will be generated first. The curve25519 secret will be derived from that, since
In general, reusing keys for different purposes (signing and encryption) considered bad idea, even through it is possible (RSA signing and RSA encryption, DSA signing and ElGamal/DH encryption [fwiw, this one considered *very* bad idea]).
the ed25519 already contains a usable curve25519 key. In pcp I store both of them for easier access, so the ed25519 and curve25519 secret and public keys are stored, the secret keys are encrypted and I store the nonce as well (see include/pcp/key.h).
Speaking of key encryption: @stef: according to your docs you're already using scrypt() for key derivation. I'd like to use that as well, but it's not part of libsodium (afaik), so I use my own method for this til scrypt() is implemented in libsodium. That's because I want to avoid writing crypto code myself.
Maybe we should iron out the details off-list?
PS If I'm not mistaken, pcp is using longtime curve25519 secret key for message encryption. 1) Recipient needs to know sender public key. Bad. 2) Message remains decipherable by sender. Very bad. 3) Sender public key/identity leaks with each message. Very bad. 4) Sender needs access to her secret key. Bad. 5)6)7)... Wut? WTF? WHY????? Just generate single-use keypair, send public part with message, throw away secret part right after encryption. PPS gnupg devs are currently working on adding support for curve25519/ed25519; though, it's on very early development stage. Oh, well, NIH-NIH-NIH, let's invent our own square-wheel bycicle.
On Wed, Jan 15, 2014 at 02:46:08AM +0400, Yuriy Kaminskiy wrote:
When the user generates a new key, the ed25519 secret key will be generated first. The curve25519 secret will be derived from that, since
In general, reusing keys for different purposes (signing and encryption) considered bad idea, even through it is possible (RSA signing and RSA encryption, DSA signing and ElGamal/DH encryption [fwiw, this one considered *very* bad idea]).
Well, the libsodium developers not only told me how to do it, it was their idea. However, it's of course very simple to generate them separate.
1) Recipient needs to know sender public key. Bad.
That's the way curve25519 works. It would be possible to use one time keys but for this there has to be some kind of key exchange process before. But since pcp runs in offline mode, I'm not sure how to do this in a user friendly way.
2) Message remains decipherable by sender. Very bad.
No, it doesn't. In order to decrypt a message one needs the recipient secret key and the sender public key.
3) Sender public key/identity leaks with each message. Very bad.
Because? While I don't know how stef does it in pbp, I only add the key id to the cipher so that the recipient knows which key has to be used to decrypt. I'm not sure how it is bad to publish a key id. That's daily business with pgp as well.
4) Sender needs access to her secret key. Bad.
Again, this is how curve25519 is designed.
Just generate single-use keypair, send public part with message, throw away secret part right after encryption.
The sender needs a public key from the recipient anyways. And to be able to decrypt the message, the recipient has to retain her secret key.
Oh, well, NIH-NIH-NIH, let's invent our own square-wheel bycicle.
Funny, but neither I nor stef invented anything. DJB did. - Tom -- This message has been scanned for viruses and dangerous content by MailScanner, and is believed to be clean.
Thomas von Dein wrote:
On Wed, Jan 15, 2014 at 02:46:08AM +0400, Yuriy Kaminskiy wrote:
When the user generates a new key, the ed25519 secret key will be generated first. The curve25519 secret will be derived from that, since In general, reusing keys for different purposes (signing and encryption) considered bad idea, even through it is possible (RSA signing and RSA encryption, DSA signing and ElGamal/DH encryption [fwiw, this one considered *very* bad idea]).
Well, the libsodium developers not only told me how to do it, it was their idea. However, it's of course very simple to generate them separate.
It is *possible* to use same RSA keypair for encryption and signing (and earlier pgp versions used to that). Does not mean it is *good idea* (and newer openpgp/gnupg switched to use separate keys for signing/encryption/certificate signing purposes, by subkeys mechanism). (For DH/DSA it is even worse, you *can* reuse same keypair, but this leads to leak of secret key material. I'm not sure if same leak scenario apply to ECDH[curve25519]/EdDSA[ed25519], but better safe than sorry. And keypair reuse is bad from operational security pov anyway).
1) Recipient needs to know sender public key. Bad.
[clarification: sender *long-term* public key; of course, receiver needs to know public key that was used for message encryption; but this key need not be same with sender *long-term* key]
That's the way curve25519 works. It would be possible to use one time keys but for this there has to be some kind of key exchange process before. But since pcp runs in offline mode, I'm not sure how to do this in a user friendly way.
I explained: include (single-use) public key in message, in place of "hash of sender key id").
2) Message remains decipherable by sender. Very bad.
No, it doesn't. In order to decrypt a message one needs the recipient secret key and the sender public key.
Yes, it does. With your protocol, message can be alternatively deciphered with crypto_open_box(c, n, sender_public_key, receiver_secret_key); (by receiver, good) or, alternatively, with crypto_open_box(c, n, receiver_public_key, sender_secret_key); (by sender, *BAD*). With openpgp (and with my suggested change), sender does not retain secret key used for message encryption, and thus cannot decipher his own message.
3) Sender public key/identity leaks with each message. Very bad.
Because?
While I don't know how stef does it in pbp, I only add the key id to the cipher so that the recipient knows which key has to be used to decrypt. I'm not sure how it is bad to publish a key id. That's daily business with pgp as well.
Incorrect. This is NOT daily business with pgp. Openpgp does not use long-term sender keypair when it encrypt message (otherwise, how could you encrypt message without using passphrase?) and does not leak sender keyid (/by default/ gnupg leaks /recipient/ keyid, but it can be disabled with --hidden-recipient).
4) Sender needs access to her secret key. Bad.
Again, this is how curve25519 is designed.
This has NOTHING to do with either curve25519 (or nacl) design. It is only how *YOU* are using it.
Just generate single-use keypair, send public part with message, throw away secret part right after encryption.
The sender needs a public key from the recipient anyways. And to be able to decrypt the message, the recipient has to retain her secret key.
I said nothing about *recipient* secret key. Recipient, of course, need to access to her secret key to decipher message. And sender, of course, needs to know recipient long-term public key.
Oh, well, NIH-NIH-NIH, let's invent our own square-wheel bycicle.
Funny, but neither I nor stef invented anything. DJB did.
DJB has nothing to do with your self-invented protocol. DJB invented bending tool. *You* decided to use it to make square wheels. P.S. there were thing that openpgp did horrible wrong: keyids (they are harmful and useless crap). Funnily, you repeated their misdesign.
On Wed, Jan 15, 2014 at 04:29:44PM +0400, Yuriy Kaminskiy wrote:
Well, the libsodium developers not only told me how to do it, it was their idea. However, it's of course very simple to generate them separate.
It is *possible* to use same RSA keypair for encryption and signing (and earlier pgp versions used to that). Does not mean it is *good idea* (and newer openpgp/gnupg switched to use separate keys for signing/encryption/certificate signing purposes, by subkeys mechanism).
We're not talking about RSA, do we?
(For DH/DSA it is even worse, you *can* reuse same keypair, but this leads to leak of secret key material. I'm not sure if same leak scenario apply to ECDH[curve25519]/EdDSA[ed25519], but better safe than sorry. And keypair reuse is bad from operational security pov anyway).
As I alredy said, it's no problem to have separate keyspairs for signing and encrypting, just a couple of lines to change.
1) Recipient needs to know sender public key. Bad.
[clarification: sender *long-term* public key; of course, receiver needs to know public key that was used for message encryption; but this key need not be same with sender *long-term* key]
That's the way curve25519 works. It would be possible to use one time keys but for this there has to be some kind of key exchange process before. But since pcp runs in offline mode, I'm not sure how to do this in a user friendly way.
I explained: include (single-use) public key in message, in place of "hash of sender key id").
Ok, let me formulate it better: I can use a single-use keypair on the sender's side and include the public part in the message. Cool. But the sender would nevertheless need a public key from the recipient. This one has to be from a long-term key, since we're operating in a store-and-forward environment. But it doesn't make sense to use a single-use key only on one side of the communication, does it? As a sidenote, in pcp it's possible to generate a keypair for one recipient (it's derived from the long-term keypair), so you'd at least have one keypair per peer. But it's unclear to me, how to use single-use keys on both sides of a communication in a store-and-forward environment. Any hints?
2) Message remains decipherable by sender. Very bad.
No, it doesn't. In order to decrypt a message one needs the recipient secret key and the sender public key.
Yes, it does. With your protocol, message can be alternatively deciphered with crypto_open_box(c, n, sender_public_key, receiver_secret_key); (by receiver, good) or, alternatively, with crypto_open_box(c, n, receiver_public_key, sender_secret_key); (by sender, *BAD*).
Really? I'll try it, but if this is the case, then it's bad indeed.
With openpgp (and with my suggested change), sender does not retain secret key used for message encryption, and thus cannot decipher his own message.
Yea, I see.
Incorrect. This is NOT daily business with pgp. Openpgp does not use long-term sender keypair when it encrypt message (otherwise, how could you encrypt message without using passphrase?) and does not leak sender keyid (/by default/ gnupg leaks /recipient/ keyid, but it can be disabled with --hidden-recipient).
ok, got it.
DJB has nothing to do with your self-invented protocol. DJB invented bending tool. *You* decided to use it to make square wheels.
Come on, have a heart. The only thing I "invented", was how to store keys and encrypted files. It's just a fun project in it's early stages and everything can be changed. And I'm really glad when someone points out some errors I made.
P.S. there were thing that openpgp did horrible wrong: keyids (they are harmful and useless crap). Funnily, you repeated their misdesign.
ok, really got it. - Tom -- This message has been scanned for viruses and dangerous content by MailScanner, and is believed to be clean.
FWIW, I quickly looked at pbp [python? hate-hate-hate], it apparently has nearly same design defect: it uses long-term curve25519 keypair for message encryption. Unlike pcp, it does not include sender identification in message, receiver must try all public keys in her keyring. Which have advantage of not leaking sender identity to eavesdropper, but waste a lot of CPU on receiver side (as your keyring grows), and receiver also cannot search sender identity by keyid on [hypothetical] keyserver. NIH, NIH, NIH. Thomas von Dein wrote:
On Wed, Jan 15, 2014 at 04:29:44PM +0400, Yuriy Kaminskiy wrote:
Well, the libsodium developers not only told me how to do it, it was their idea. However, it's of course very simple to generate them separate. It is *possible* to use same RSA keypair for encryption and signing (and earlier pgp versions used to that). Does not mean it is *good idea* (and newer openpgp/gnupg switched to use separate keys for signing/encryption/certificate signing purposes, by subkeys mechanism).
We're not talking about RSA, do we?
Nearly same consideration apply to both?
(For DH/DSA it is even worse, you *can* reuse same keypair, but this leads to leak of secret key material. I'm not sure if same leak scenario apply to ECDH[curve25519]/EdDSA[ed25519], but better safe than sorry. And keypair reuse is bad from operational security pov anyway).
As I alredy said, it's no problem to have separate keyspairs for signing and encrypting, just a couple of lines to change.
1) Recipient needs to know sender public key. Bad. [clarification: sender *long-term* public key; of course, receiver needs to know public key that was used for message encryption; but this key need not be same with sender *long-term* key]
That's the way curve25519 works. It would be possible to use one time keys but for this there has to be some kind of key exchange process before. But since pcp runs in offline mode, I'm not sure how to do this in a user friendly way. I explained: include (single-use) public key in message, in place of "hash of sender key id").
Ok, let me formulate it better: I can use a single-use keypair on the sender's side and include the public part in the message. Cool. But the sender would nevertheless need a public key from the recipient. This one has to be from a long-term key, since we're operating in a
Well, yes. If you want to send message to someone, you need to obtain her (current/longterm) public key first, and you need verify it somehow (in-person exchange, web-of-trust, CA signature, etc; in case ephemeral encryption key, it should be signed by verified long-term identity key), otherwise you are vulnerable to MITM. I don't see any way around it.
store-and-forward environment. But it doesn't make sense to use a single-use key only on one side of the communication, does it?
Hmm? You cannot fix (1), (2), (3), (4) without using single-use keypair by sender side. So, of course, it makes sense. Single-use keypair on receiver side would be nice (PFS!), but it is not possible in store-and-forward.
As a sidenote, in pcp it's possible to generate a keypair for one recipient (it's derived from the long-term keypair), so you'd at least have one keypair per peer. But it's unclear to me, how to use single-use keys on both sides of a communication in a store-and-forward environment. Any hints?
I'm not sure how are they useful? (Once you use per-message keypairs, that is.)
2) Message remains decipherable by sender. Very bad. No, it doesn't. In order to decrypt a message one needs the recipient secret key and the sender public key. Yes, it does. With your protocol, message can be alternatively deciphered with crypto_open_box(c, n, sender_public_key, receiver_secret_key); (by receiver, good) or, alternatively, with crypto_open_box(c, n, receiver_public_key, sender_secret_key); (by sender, *BAD*).
Really? I'll try it, but if this is the case, then it's bad indeed.
That's how (any) DH works? You generate common secret from one side public key and other side private key?
With openpgp (and with my suggested change), sender does not retain secret key used for message encryption, and thus cannot decipher his own message.
Yea, I see.
Incorrect. This is NOT daily business with pgp. Openpgp does not use long-term sender keypair when it encrypt message (otherwise, how could you encrypt message without using passphrase?) and does not leak sender keyid (/by default/ gnupg leaks /recipient/ keyid, but it can be disabled with --hidden-recipient).
ok, got it.
DJB has nothing to do with your self-invented protocol. DJB invented bending tool. *You* decided to use it to make square wheels.
Come on, have a heart. The only thing I "invented", was how to store keys and encrypted files. It's just a fun project in it's early stages and everything can be changed. And I'm really glad when someone points out some errors I made.
P.S. there were thing that openpgp did horrible wrong: keyids (they are harmful and useless crap). Funnily, you repeated their misdesign.
Well, to be fair, openpgp standard had several edition, was reviewed by many people, etc, and still managed to get it wrong. Earlier versions of pgp also did a lot things wrong. Etc. SSL/TLS history is also full of mistakes, some fixed by newer version, some still remains (EtM), some even added by newer versions (cleartext SNI). It is not easy to mess up with crypto - it is /extremely/ easy :-( And that's why it is important to point out at mistakes early on, without any mercy :-)
ok, really got it.
PPS === cut platform.h === #ifndef HAVE_ARC4RANDOM_BUF // shitty OS. we're using libsodium's implementation === cut === LOL, I'm glad I'm on "shitty OS"; well, not quite (e.g. openbsd recently switched arc4random from rc4 to chacha); but I'd bet there are quite some "by- this-definition-non-shitty-OS" that 1) has arc4random_buf; 2) still uses RC4 under the hood. Then again, while rc4 is considered somewhat flaky, but it is not completely broken (yet), and still in wide use, so it is not *terrible* big deal. But DJB will frown on you, LOL.
Hi, On Mon, Jan 20, 2014 at 03:13:42PM +0400, Yuriy Kaminskiy wrote:
FWIW, I quickly looked at pbp [python? hate-hate-hate], it apparently has nearly same design defect: it uses long-term curve25519 keypair for message encryption. Unlike pcp, it does not include sender identification in message, receiver must try all public keys in her keyring.
Nope, the sender's public key is included by pbp with the encrypted message. Since yesterday pcp does the same. However, I use a dynamic keypair on the sender site now. I'm currently in the process to change the encrypted output format of pcp to match the one of pbp.
It is not easy to mess up with crypto - it is /extremely/ easy :-(
And that's why it is important to point out at mistakes early on, without any mercy :-)
Absolutely. Speaking of mistakes: I had even a note in the manpage where I mentioned that it might be a bad idea to include the key-id with encrypted messages, though I totally forgot it :) Oh - and I didn't really include the key-ids, but a hash from it instead. However, this has already been changed.
PPS === cut platform.h === #ifndef HAVE_ARC4RANDOM_BUF // shitty OS. we're using libsodium's implementation === cut === LOL, I'm glad I'm on "shitty OS"
Well, now you know, I don't like linux :) best regards, Tom -- This message has been scanned for viruses and dangerous content by MailScanner, and is believed to be clean.
Thomas von Dein wrote:
On Mon, Jan 20, 2014 at 03:13:42PM +0400, Yuriy Kaminskiy wrote:
FWIW, I quickly looked at pbp [python? hate-hate-hate], it apparently has nearly same design defect: it uses long-term curve25519 keypair for message encryption. Unlike pcp, it does not include sender identification in message, receiver must try all public keys in her keyring.
Nope, the sender's public key is included by pbp with the encrypted
Hmm? === cut pbp-git/doc/fileformats.txt === public key encrypted files have the following structure: 5[1]|nonce|len(recipients)[4]|[(recipients...)|c(packet key, nonce, msg) where recipients is a concatenated list of random_nonce|c(recipient crypto pk, random_nonce, packet key) ==== cut === Public key where? Well, if you look at code, actual format is a bit different: === according to pbp-git/pbp/pbp.py === 5[1]|len(recipients)[4]|(recipients...)|(secretboxes...) where recipients is a concatenated list of random_nonce|box(our identity privkey, recipient crypto pk, random_nonce, packet key) and secretboxes is a list of nonce|secretbox(packet key, nonce, msg[i:i+BLOCK_SIZE]); i+=BLOCK_SIZE; === cut === (Too lazy to dig in "chaining-dh" carefully; but it uses "normal pubkey encryption" for bootstrap anyway). Correct format should be: 6[1]|temp_keypair.pubkey|len(recipients)[4]|(recipients...)|(secretboxes...) where recipients is a concatenated list of random_nonce|box(temp_keypair.privkey, recipient crypto pk, random_nonce, packet key)
message. Since yesterday pcp does the same. However, I use a dynamic keypair on the sender site now. I'm currently in the process to change the encrypted output format of pcp to match the one of pbp.
It is not easy to mess up with crypto - it is /extremely/ easy :-(
And that's why it is important to point out at mistakes early on, without any mercy :-)
Absolutely. Speaking of mistakes: I had even a note in the manpage where I mentioned that it might be a bad idea to include the key-id with encrypted messages, though I totally forgot it :) Oh - and I didn't really include the key-ids, but a hash from it instead. However, this
(Well, this is already fixed and does not matter anymore, but...) For eavesdropper, it does not matter if you use keyid or hash(keyid), or hash(hash(hash(hash(keyid))))). If keyids are same, their hashes are same (this can be fixed by salting). If eavesdropper knows keyid, he can calculate hash(keyid) as well, and thus map messages to keyids (this *cannot* be fixed by salting).
has already been changed.
Yuriy, On Tue, Jan 21, 2014 at 01:32:23PM +0400, Yuriy Kaminskiy wrote:
Correct format should be: 6[1]|temp_keypair.pubkey|len(recipients)[4]|(recipients...)|(secretboxes...)
Let me recap to see if I really got it right: the sender does: - generate a random single-use keypair - generate a random secretbox key - secretbox the message 32k-wise with the former - box that key for each recipient - put into the output the cipher, the recipient stuff and the public key part of the random single-use keypair Is that right? So, in order to communicate with someone, only user A has to publish her public key. User B takes it, box()es a message for her, puts his (random) pk into it and sends it. A then uses the public key included in the message plus her own secret key, decrypts the message and drops B's public key afterwards. Because, usually with curve25519 both A and B had to exchange their public keys in advance to be able to communicate. The scheme above makes it a lot easier for users but is it sufficient securitywise? best, Tom -- This message has been scanned for viruses and dangerous content by MailScanner, and is believed to be clean.
On Tue, Jan 21, 2014 at 11:10:57AM +0100, Thomas von Dein wrote:
Because, usually with curve25519 both A and B had to exchange their public keys in advance to be able to communicate. The scheme above makes it a lot easier for users but is it sufficient securitywise?
the problem is you cannot be sure who the sender of the msg is, it might be a mitm. -- pgp: https://www.ctrlc.hu/~stef/stef.gpg pgp fp: FD52 DABD 5224 7F9C 63C6 3C12 FC97 D29F CA05 57EF otr fp: https://www.ctrlc.hu/~stef/otr.txt
On Tue, Jan 21, 2014 at 01:32:23PM +0400, Yuriy Kaminskiy wrote:
Well, if you look at code, actual format is a bit different:
thanks for catching that!
Correct format should be: 6[1]|temp_keypair.pubkey|len(recipients)[4]|(recipients...)|(secretboxes...) where recipients is a concatenated list of random_nonce|box(temp_keypair.privkey, recipient crypto pk, random_nonce, packet key)
i think in this case the temp_keypair.pubkey should actually be signed by the long-term signing key. otherwise it opens up again the trust problem. anyway i don't see immediately why the asym approach is better instead of the sym, as the asym does quite the same as the sym, only the key derivation is different. -- pgp: https://www.ctrlc.hu/~stef/stef.gpg pgp fp: FD52 DABD 5224 7F9C 63C6 3C12 FC97 D29F CA05 57EF otr fp: https://www.ctrlc.hu/~stef/otr.txt
Hi, a short update about the progress. I've made the following changes to pcp[1] so far: - asymmetrically and symmetrically encrypted files are now created in the same format as pbp does (binary output only). Verified to work with symmetric mode only because of some open issues. - the same applies for signatures, binary only as well. pcp has another format for armored sigs (which I like better). - crypt+sign is supported now as well (pcp only). - pcp can import and export pbp public keys. - encryption keys are derived using scrypt(). - crypto and signing keypairs are generated separately. The todo list contains a bunch of open issues anyway: - we still need a consistent pubkey file format. - we also need an agreement on armoring (base85 va z85). - cipher mode: currently pbp (and pcp now) encrypts data in ECB mode with a blocksize of 32k. I think CBC would be better, and I already implemented it (enabled with ./configure --enable-cbc). We'd need an agreement here as well. best regards, Tom [1] https://github.com/TLINDEN/pcp -- This message has been scanned for viruses and dangerous content by MailScanner, and is believed to be clean.
Thomas von Dein wrote:
a short update about the progress. I've made the following changes to pcp[1] so far:
- asymmetrically and symmetrically encrypted files are now created in the same format as pbp does (binary output only). Verified to work with symmetric mode only because of some open issues.
- the same applies for signatures, binary only as well. pcp has another format for armored sigs (which I like better).
- crypt+sign is supported now as well (pcp only).
Hmm... so, it sign plaintext, but transmit signature unencrypted. If attacker knows/expect content of message, he can discover (and prove) message authorship. This is not most likely scenario, but still totally not good. Signature should be encrypted too. And, same with pgp & co, it is vulnerable to "Surreptitious Forwarding" [1]: Alice sends to Bob "I love you", Bob decrypt message, re-encrypt it to Charlie, keeping Alice signature intact. To avoid this problem, you can include "len(recipients list)|recipients list" in signed material (thus, any attempt to alter recipient list will automagically invalidate signature) [XXX: not exactly usual, requires review]. [1] http://world.std.com/~dtd/sign_encrypt/sign_encrypt7.html#tth_sEc1.1 When you invent new protocol, it is very good idea too look at *existing standards first*. And then learn from known mistakes in them :-)
- pcp can import and export pbp public keys.
- encryption keys are derived using scrypt().
- crypto and signing keypairs are generated separately.
The todo list contains a bunch of open issues anyway:
- we still need a consistent pubkey file format.
- we also need an agreement on armoring (base85 va z85).
- cipher mode: currently pbp (and pcp now) encrypts data in ECB mode with a blocksize of 32k. I think CBC would be better, and I already
????????????????????????????? What ???????????????????????????????? With ECB, if you encrypt same block with same key, you have same ciphertext. Attacker can identify repetitive content, identify blocks that are same with blocks of known plaintext, etc. All that, obviously, bad. With pbp encryption scheme, each 32kb block is encrypted with stream cipher with *explicit random nonce*. Unlike ECB, if you encrypt same blocks on same key, you'll have *different* ciphertext (as they used different nonces). None of above ECB problems apply.
implemented it (enabled with ./configure --enable-cbc). We'd need an agreement here as well.
On Wed, Feb 05, 2014 at 01:03:00AM +0400, Yuriy Kaminskiy wrote:
If attacker knows/expect content of message, he can discover (and prove) message authorship. This is not most likely scenario, but still totally not good. Signature should be encrypted too.
Well, I can change that, no problem.
With pbp encryption scheme, each 32kb block is encrypted with stream cipher with *explicit random nonce*. Unlike ECB, if you encrypt same blocks on same key, you'll have *different* ciphertext (as they used different nonces). None of above ECB problems apply.
Which is the very same I do in pcp. It was just a question, i.e. "may cbc provide even more security than ecb+nonces?" - Tom -- This message has been scanned for viruses and dangerous content by MailScanner, and is believed to be clean.
On Wed, Feb 05, 2014 at 01:03:00AM +0400, Yuriy Kaminskiy wrote:
And, same with pgp & co, it is vulnerable to "Surreptitious Forwarding" [1]: Alice sends to Bob "I love you", Bob decrypt message, re-encrypt it to Charlie, keeping Alice signature intact. To avoid this problem, you can include "len(recipients list)|recipients list" in signed material (thus, any attempt to alter recipient list will automagically invalidate signature) [XXX: not exactly usual, requires review].
Good, I changed the scheme then. However, instead of adding the recipient list to the signature, I add it to the hash, since I sign the hash only anyway; and because it is a) easier to code and b) results in a signature with a static size. So, now the signature looks like this: nonce|crypto_secret_box( crypto_sign( crypto_generichash(cleartext + encrypted-recipientlist) ), nonce, symkey) Everything else is unchanged. So, an encrypted+signed file contains the number of recipients, the recipient-list (which consists of the pk-encrypted ephemeral key per user), the 32k-blockwise sym-encrypted message, followed by the encrypted signature. As usual the nonce used to encrypt the sig is prepended. - Tom -- This message has been scanned for viruses and dangerous content by MailScanner, and is believed to be clean.
So, here we go: # bob exports his pk bobby@io: % pbp -x -S Bob > bob.pbp Passphrase for decrypting master key for Bob: # alice exports her pk alicia@io: % pcp -p -b -O alice.pbp Enter passphrase to decrypt your secret key for signing the export: public key exported in PBP format. # bob imports alice' pk bobby@io: % pbp -X -i alice.pbp Success: imported public keys for Alicia bobby@io: % pbp -l valid b888 026a 38e2 cdf7 f0a6 6486 63a5 0fea Bob invalid ed32 1935 0310 fe6f 35c6 b44d be6b 3ca8 Alicia [1] # alice imports bobs pk alicia@io: % pcp -P -I bob.pbp -b key 0x87358A0988953A67 added to ~/.pcpvault. alicia@io: % pcp -l Key ID Type Creation Time Owner 0xB497AFF45654CD98 primary 2014-02-06T19:58:09 Alicia <> 0x87358A0988953A67 public 2014-02-06T18:58:02 bob <> # bob encrypts to alice bobby@io: % echo "HALLO ALICE, KNUTSCHI" > msg bobby@io: % pbp -c -i msg -o encrypted -r Alicia -S Bob Passphrase for decrypting encryption subkey for Bob: # alice decrypts it alicia@io: % pcp -d -I encrypted Enter passphrase to decrypt your secret key: HALLO ALICE, KNUTSCHI Decrypted 22 bytes successfully # other way around, alice encrypts to bob alicia@io: % echo "ACH, SCHNUCKI" | pcp -e -O encrypted -r Bob Enter passphrase to decrypt your secret key: Encrypted 164 bytes for: bob <> # and bob decrypts it bobby@io: % pbp -d -i encrypted -S Bob Passphrase for decrypting encryption subkey for Bob: ACH, SCHNUCKI good message from Alicia [1]: currently pbp shows pcp keys as "invalid", I'm not sure why, but it's on the todo list. Also, I didn't test if signatures are compatible yet, and there are many more things left to solve/agree, like keyformats, sign+crypt support in pbp, among others. best regards, Tom -- This message has been scanned for viruses and dangerous content by MailScanner, and is believed to be clean.
On Thu, Feb 6, 2014 at 2:24 PM, Thomas von Dein <tom@vondein.org> wrote:
bobby@io: % pbp -l valid b888 026a 38e2 cdf7 f0a6 6486 63a5 0fea Bob invalid ed32 1935 0310 fe6f 35c6 b44d be6b 3ca8 Alicia [1] alicia@io: % pcp -l Key ID Type Creation Time Owner 0xB497AFF45654CD98 primary 2014-02-06T19:58:09 Alicia <> 0x87358A0988953A67 public 2014-02-06T18:58:02 bob <>
Similar to gpg -k/-K, there should be some indication of the key width (parameters), algorithms, expiration, etc in the list of keys. An extended list option could work for that if not desired in a simple -l format.
Hi, On Thu, Feb 06, 2014 at 03:33:26PM -0500, grarpamp wrote:
Similar to gpg -k/-K, there should be some indication of the key width (parameters), algorithms, expiration, etc in the list of keys.
Would be easily possible but doesn't make much sense currently, since there's only 1 algorithm supported and the key size for it is static. Btw, at least in pcp there's a -t option which can be used to display all details about a key. regards, Tom -- This message has been scanned for viruses and dangerous content by MailScanner, and is believed to be clean.
On Thu, Feb 06, 2014 at 08:24:12PM +0100, Thomas von Dein wrote:
So, here we go:
# bob exports his pk bobby@io: % pbp -x -S Bob > bob.pbp Passphrase for decrypting master key for Bob:
# alice exports her pk alicia@io: % pcp -p -b -O alice.pbp Enter passphrase to decrypt your secret key for signing the export: public key exported in PBP format.
# bob imports alice' pk bobby@io: % pbp -X -i alice.pbp Success: imported public keys for Alicia
bobby@io: % pbp -l valid b888 026a 38e2 cdf7 f0a6 6486 63a5 0fea Bob invalid ed32 1935 0310 fe6f 35c6 b44d be6b 3ca8 Alicia [1]
# alice imports bobs pk alicia@io: % pcp -P -I bob.pbp -b key 0x87358A0988953A67 added to ~/.pcpvault.
alicia@io: % pcp -l Key ID Type Creation Time Owner 0xB497AFF45654CD98 primary 2014-02-06T19:58:09 Alicia <> 0x87358A0988953A67 public 2014-02-06T18:58:02 bob <>
# bob encrypts to alice bobby@io: % echo "HALLO ALICE, KNUTSCHI" > msg bobby@io: % pbp -c -i msg -o encrypted -r Alicia -S Bob Passphrase for decrypting encryption subkey for Bob:
# alice decrypts it alicia@io: % pcp -d -I encrypted Enter passphrase to decrypt your secret key: HALLO ALICE, KNUTSCHI Decrypted 22 bytes successfully
# other way around, alice encrypts to bob alicia@io: % echo "ACH, SCHNUCKI" | pcp -e -O encrypted -r Bob Enter passphrase to decrypt your secret key: Encrypted 164 bytes for: bob <>
# and bob decrypts it bobby@io: % pbp -d -i encrypted -S Bob Passphrase for decrypting encryption subkey for Bob: ACH, SCHNUCKI good message from Alicia
fuck yeah! ;)
[1]: currently pbp shows pcp keys as "invalid", I'm not sure why, but it's on the todo list.
ooh, thx, will check that!
Also, I didn't test if signatures are compatible yet, and there are many more things left to solve/agree, like keyformats, sign+crypt support in pbp, among others.
sign+crypt? why? crypt also does mac automatically. no need for sign+crypt at all. -- pgp: https://www.ctrlc.hu/~stef/stef.gpg pgp fp: FD52 DABD 5224 7F9C 63C6 3C12 FC97 D29F CA05 57EF otr fp: https://www.ctrlc.hu/~stef/otr.txt
howdy, On Mon, Jan 20, 2014 at 03:13:42PM +0400, Yuriy Kaminskiy wrote:
FWIW, I quickly looked at pbp [python? hate-hate-hate], it apparently has nearly same design defect: it uses long-term curve25519 keypair for message encryption.
does it? actually pbp generates a symmetric key, which is encrypted to the recipients encryption public key. btw, pbp creates 3 keys for each id, one long-term master for key-signing only, and two sub-keys one for encryption and one for generic signing. the encryption subkey is only used for the encryption of the message key. is that a problem? isn't that how pgp does it?
Unlike pcp, it does not include sender identification in message, receiver must try all public keys in her keyring.
this is mostly a problem only for verifying signatures, in a keyring with lots of public keys. but the operation is only on the hash of the message. for encryption this is neither so much a problem as traditionally the number of private keys one person holds is manageable. however even in these cases the wrong key is detected after decoding the message key, which again is a 32 byte ciphertext. so i don't expect this to be very slow. if this really becomes a problem you can start pbp with different home directories using the --basedir param.
Which have advantage of not leaking sender identity to eavesdropper, but waste a lot of CPU on receiver side (as your keyring grows),
indeed. but that was one of the design goals, to fix the problem openpgp being a strong selector and low hanging fruit in all forensic tools. i'm very happy to spend some cpu cycles on locating the right key if it means the adversary has a higher computational effort than me.
and receiver also cannot search sender identity by keyid on [hypothetical] keyserver.
indeed, this need has not been addressed yet.
Hmm? You cannot fix (1), (2), (3), (4) without using single-use keypair by sender side. So, of course, it makes sense. Single-use keypair on receiver side would be nice (PFS!), but it is not possible in store-and-forward.
i would be delighted to hear your commentary on https://raw.github.com/stef/pbp/master/doc/chaining-dh.txt
Really? I'll try it, but if this is the case, then it's bad indeed.
That's how (any) DH works? You generate common secret from one side public key and other side private key?
in the nacl implementation i believe something like this happens: P_a and S_b, as well as on the other side S_a and P_b are used in a ECDH secret derivation, which then is passed through hsalsa20 to derive the key, then this shared secret is used as a key for a salsa20xpoly1305 authenticating stream algo, that also needs a 32 byte nonce for encryption. so indeed both sides can decrypt the message encrypted to the other in this scheme. all this of course is overly simplified you can find the details on pp15 http://cr.yp.to/highspeed/naclcrypto-20090310.pdf cheers,s -- pgp: https://www.ctrlc.hu/~stef/stef.gpg pgp fp: FD52 DABD 5224 7F9C 63C6 3C12 FC97 D29F CA05 57EF otr fp: https://www.ctrlc.hu/~stef/otr.txt
On Tue, Jan 21, 2014 at 01:39:24AM +0100, stef wrote:
does it? actually pbp generates a symmetric key, which is encrypted to the recipients encryption public key.
this is two step encryption is only necessary to allow sending the same message to multiple recipients. otherwise i believe the crypto_secretbox way is the way to go if you are strictly 1-to-1 communicating. -- pgp: https://www.ctrlc.hu/~stef/stef.gpg pgp fp: FD52 DABD 5224 7F9C 63C6 3C12 FC97 D29F CA05 57EF otr fp: https://www.ctrlc.hu/~stef/otr.txt
howdy, On Tue, Jan 14, 2014 at 12:16:53PM +0100, Thomas von Dein wrote:
- coordinate representation x, x&y, x and sign ... or bits to show which of these ... perhaps borrow ANSI method
Could you please explain this further?
i believe this is not really necessary for this type of curve. especially if we manage to switch to elligator curves soonish.
- hint / indication of cipher suite / curve
In pcp there's already such a hint included in exported keys, however I'm not using it, since there's no choice of different curves in libsodium so far. But it's on the list.
unfortunately pbp has such a distinguisher, it decides between asym/sym encryption. i should somehow get rid of that.
- text encoding of binary format (ascii)
As already stated in the other subthread, I use Z85, while stef is using base85. Since Z85 is a subset of base85, I'm pretty sure we can agree on something.
absolutely. i like small keys, that's why we do ecc, not RSA. as it allows to use crypto e.g. also in tweets, signed tweets leave you with ~55 chars for messages, or as we recently found out also in the comment field of bank wiretransfers. i wasn't really joking doing a numberstation style output format. the https://en.wikipedia.org/wiki/PGP_word_list might be quite good for easy human voice transmission, like in key parties. takes a bit of time reciting 32 words, but might be easier than reciting a pgp keyid.
I'm not sure, how stef solved the ed25519 issue (you can't use a curve25519 secret key to create an ed25519 signature directly). After some discussion on the libsodium mailinglist we came up with this:
When the user generates a new key, the ed25519 secret key will be generated first. The curve25519 secret will be derived from that, since the ed25519 already contains a usable curve25519 key. In pcp I store both of them for easier access, so the ed25519 and curve25519 secret and public keys are stored, the secret keys are encrypted and I store the nonce as well (see include/pcp/key.h).
pbp uses separate and unrelated keys for confidentiality and others for signing.
Speaking of key encryption: @stef: according to your docs you're already using scrypt() for key derivation. I'd like to use that as well, but it's not part of libsodium (afaik), so I use my own method for this til scrypt() is implemented in libsodium. That's because I want to avoid writing crypto code myself.
http://ftp.de.debian.org/debian/pool/main/s/scrypt/scrypt_1.1.6.orig.tar.gz seems like a good start for reusing code. -- pgp: https://www.ctrlc.hu/~stef/stef.gpg pgp fp: FD52 DABD 5224 7F9C 63C6 3C12 FC97 D29F CA05 57EF otr fp: https://www.ctrlc.hu/~stef/otr.txt
participants (6)
-
grarpamp
-
nymble
-
rysiek
-
stef
-
Thomas von Dein
-
Yuriy Kaminskiy