PreKey bundles are unclear to me
xnyhps opened this issue · comments
I'm quite confused about the data that is pushed to the 'urn:xmpp:omemo:0:bundles:1234'
node.
- Why is there one
<signedPreKeyPublic>
element? What is this key for? Are the other 100<preKeyPublic>
PreKeys not signed? - What key is used to sign that PreKey? So far, only a Curve25519 key has been created, which is a ECDH curve.
As each PreKey can only be used once, the party that sends their initial PreKeyWhisperMessage later loses this race condition.
- Why can a PreKey only be used once? As far as I understand, it only weakens the forward-secrecy to reuse a PreKey (compromising the private key of that PreKey could allow decrypting two sessions instead of one). But if the damage has already been done and it has been used by two contacts, why not use the key? Of course it should be erased as soon as possible, but I think it would be fine to delay that until MAM has caught up.
-
With regards to my first point, I had some time, so I did a bit of digging in the TextSecure source. It looks like the handling of incoming PreKeyBundles happens mostly in https://github.com/WhisperSystems/libaxolotl-java/blob/4b48599f8925a242584901b4f204017a63d7c768/java/src/main/java/org/whispersystems/libaxolotl/SessionBuilder.java#L211.
It seems that in V2, PreKeys were used almost as described as in https://whispersystems.org/blog/asynchronous-security. The only difference being that PreKeys are not signed. (I think this does not break the encryption or forward-secrecy, at best an attacker can cause a user to create an invalid session.)
In V3, there are still 100 unsigned PreKeys generated, but also one signed PreKey. When building a session with another V3 client, the signed PreKey is used instead of the normal PreKey. There is an extra, fourth DH step that involves an unsigned PreKey and the session key:
The signed PreKey is not expired after a single use (the unsigned PreKey still is). It appears a new signed PreKey is generated every time a new bundle is uploaded.
(There's also a "last resort" PreKey, but it appears only the server handles that differently.)
-
As for my second point, the private Curve25519 key is converted to a Ed25519 key using this function:
Using the same key in two different cryptographic algorithms is generally a bad idea, but apparently it is safe for ECDH and ECDSA.
@xnyhps did you answer your own question? Or is there anything left unclear?
My third question is still unanswered. The text in §4.7 and §5 of the current draft seems to only deal with a situation where the receiving device is currently online, not on what to do when synchronizing the messages from MAM. In that situation the receiver can't immediately update the PreKeyBundle, so there's a large risk of many senders using the same PreKey. I think it should recommend to only delete the PreKey private key once the MAM history has fully synchronized.