package primitives import ( "golang.org/x/crypto/ed25519" "golang.org/x/crypto/sha3" ) // Perform3DH encapsulates a triple-diffie-hellman key exchange. // In this exchange Alice and Bob both hold longterm identity keypairs // Both Alice and Bob generate an additional ephemeral key pair: // Three Diffie Hellman exchanges are then performed: // Alice Long Term <-> Bob Ephemeral // Alice Ephemeral <-> Bob Long Term // Alice Ephemeral <-> Bob Ephemeral // // Through this, a unique session key is derived. The exchange is offline-deniable (in the context of Tapir and Onion Service) func Perform3DH(longtermIdentity *Identity, ephemeralIdentity *Identity, remoteLongTermPublicKey ed25519.PublicKey, remoteEphemeralPublicKey ed25519.PublicKey, outbound bool) [32]byte { // 3DH Handshake l2e := longtermIdentity.EDH(remoteEphemeralPublicKey) e2l := ephemeralIdentity.EDH(remoteLongTermPublicKey) e2e := ephemeralIdentity.EDH(remoteEphemeralPublicKey) // We need to define an order for the result concatenation so that both sides derive the same key. var result [96]byte if outbound { copy(result[0:32], l2e) copy(result[32:64], e2l) copy(result[64:96], e2e) } else { copy(result[0:32], e2l) copy(result[32:64], l2e) copy(result[64:96], e2e) } return sha3.Sum256(result[:]) }