Documentation ¶
Overview ¶
Package x3dh implements a variant of the Extended Triple Diffie-Hellman (X3DH) key agreement protocol.
The original X3DH algorithm by Marlinspike and Perrin[0] provides a certain amount of leeway. Thus, the following decisions were made. The used curve is the Curve25519 resp. X25519 as the ECDH function. SHA-256 is the used hash function.
This implementation does not contain support for one-time prekeys. Thus, the published signed prekey (SPK) needs to be rotated.
However, a serious difference from the standard is the choice of Ed25519 for the identity keys (IK). Originally, X25519 is used for all keys. As a drawback, Signal requires its XEdDSA[1] specification to allow signatures based on X25519. This implementation has chosen the "other way" and map Ed25519 keys to their X25519 equivalent, as described in RFC 7748[2] or this nice blog post by Filippo Valsorda[3]. This breaks compatibility!
[0] https://signal.org/docs/specifications/x3dh/ [1] https://signal.org/docs/specifications/xeddsa/ [2] https://tools.ietf.org/html/rfc7748#section-4.1 [3] https://blog.filippo.io/using-ed25519-keys-for-encryption/
The normal procedure is:
- Bob creates a signed prekey (SPK) and publishes it; CreateNewSpk.
- Alice fetches Bob's SPK including the signature and crafts an initial message; CreateInitialMessage.
- Bob receives this message and calculates the same session parameters.
Index ¶
- func CreateInitialMessage(idKey ed25519.PrivateKey, peerIdKey ed25519.PublicKey, spkPub, spkSig []byte) (sessKey, associatedData, ekPub []byte, err error)
- func CreateNewSpk(idKey ed25519.PrivateKey) (spkPub, spkPriv, spkSig []byte, err error)
- func ReceiveInitialMessage(idKey ed25519.PrivateKey, peerIdKey ed25519.PublicKey, spkPriv, ekPub []byte) (sessKey, associatedData []byte, err error)
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func CreateInitialMessage ¶
func CreateInitialMessage( idKey ed25519.PrivateKey, peerIdKey ed25519.PublicKey, spkPub, spkSig []byte, ) (sessKey, associatedData, ekPub []byte, err error)
CreateInitialMessage based on the peer's published signed prekey.
This function must be called by the active opening party. Internally an ephemeral key (X25519) will be generated and used with the X25519 equivalent of the two identity keys to establish an ECDH secret. The associated data are the concatenation of the two public keys.
func CreateNewSpk ¶
func CreateNewSpk(idKey ed25519.PrivateKey) (spkPub, spkPriv, spkSig []byte, err error)
CreateNewSpk creates a new X25519 signed prekey (SPK), both the public and private part. The public part is signed by the identity key.
The resulting triple (public IK, public SPK, signed public SPK) should be either sent to a peer or published on some keyserver. Based on this data, another peer can initiate a session by the CreateInitialMessage function.
func ReceiveInitialMessage ¶
func ReceiveInitialMessage( idKey ed25519.PrivateKey, peerIdKey ed25519.PublicKey, spkPriv, ekPub []byte, ) (sessKey, associatedData []byte, err error)
ReceiveInitialMessage handles the initial message from the passive party.
Therefore the same calculation is performed as for CreateInitialMessage, just in reverse.
Types ¶
This section is empty.