e2ee

package
v0.2.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Apr 4, 2026 License: AGPL-3.0 Imports: 10 Imported by: 0

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func GenerateKey

func GenerateKey() ([]byte, error)

GenerateKey generates a random 32-byte key suitable for XChaCha20-Poly1305.

func SerializeRatchetMessage

func SerializeRatchetMessage(msg *RatchetMessage) []byte

SerializeRatchetMessage encodes a RatchetMessage to bytes. Format: [DH_len:2][DH][N:4][PN:4][CT_len:4][CT]

func VerifySignature

func VerifySignature(publicKey, signature, publicKeyToVerify []byte) bool

VerifySignature verifies an HMAC-SHA256 signature of a public key.

func X3DHInitiator

func X3DHInitiator(myIdentityPriv, theirBundle *PreKeyBundle) (sharedSecret []byte, ephemeralPub []byte, err error)

X3DH performs the initiator side of the X3DH key agreement. Returns the shared secret and the ephemeral key pair (for inclusion in the X3DH message).

The shared secret is computed as:

DH1 = DH(IKa, SPKb)
DH2 = DH(EKa, IKb)
DH3 = DH(EKa, SPKb)
DH4 = DH(EKa, OPKb)

SK = KDF(DH1 || DH2 || DH3 || DH4)

func X3DHResponderKeys

func X3DHResponderKeys(
	mySignedPreKeyPriv []byte,
	myOneTimePreKeyPriv []byte,
	senderIdentityPub []byte,
	senderEphemeralPub []byte,
	myIdentityPriv []byte,
) ([]byte, error)

X3DHResponderKeys performs the responder-side X3DH. The responder uses their private keys to compute the same shared secret.

Types

type ClientEncryptor

type ClientEncryptor struct {
	// contains filtered or unexported fields
}

ClientEncryptor is a utility for client-side encryption/decryption using XChaCha20-Poly1305.

func NewEncryptor

func NewEncryptor(sharedSecret []byte) (*ClientEncryptor, error)

NewEncryptor creates a new encryptor using a 32-byte shared secret.

func (*ClientEncryptor) Decrypt

func (e *ClientEncryptor) Decrypt(ciphertext []byte) ([]byte, error)

Decrypt decrypts ciphertext with leading nonce.

func (*ClientEncryptor) Encrypt

func (e *ClientEncryptor) Encrypt(plaintext []byte) ([]byte, error)

Encrypt encrypts plaintext and prepends a random 24-byte nonce.

func (*ClientEncryptor) RotateKey

func (e *ClientEncryptor) RotateKey(newKey []byte) error

RotateKey rotates the encryption key. Old ciphertexts cannot be decrypted with the new key.

type Encryptor

type Encryptor = ClientEncryptor

Encryptor is a utility for encryption/decryption using XChaCha20-Poly1305.

type HandshakeManager

type HandshakeManager struct {
	// contains filtered or unexported fields
}

HandshakeManager facilitates public key exchange between peers. It stores ONLY public keys temporarily during the handshake process.

func NewHandshakeManager

func NewHandshakeManager() *HandshakeManager

NewHandshakeManager creates a new server-side handshake facilitator.

func (*HandshakeManager) GetPublicKey

func (hm *HandshakeManager) GetPublicKey(peerID string) ([]byte, bool)

GetPublicKey retrieves a peer's public key.

func (*HandshakeManager) RemovePeer

func (hm *HandshakeManager) RemovePeer(peerID string)

RemovePeer cleans up public key material for a peer.

func (*HandshakeManager) StorePublicKey

func (hm *HandshakeManager) StorePublicKey(peerID string, pubKey []byte)

StorePublicKey stores a peer's public key (received from the client).

type IdentityKey

type IdentityKey = KeyPair

IdentityKey is a long-lived key pair identifying a user.

type KeyPair

type KeyPair struct {
	PublicKey  []byte
	PrivateKey []byte
}

KeyPair holds an X25519 public/private key pair.

func X3DHInitiatorKeys

func X3DHInitiatorKeys(
	identityPriv []byte,
	identityPub []byte,
	recipientIdentityPub []byte,
	recipientSignedPreKeyPub []byte,
	recipientOneTimePreKeyPub []byte,
) (sharedSecret []byte, ephemeral *KeyPair, err error)

X3DHInitiatorKeys performs the initiator-side X3DH with raw key material. Returns the shared secret and the ephemeral key pair (for reuse as the ratchet DH key).

type OneTimePreKey

type OneTimePreKey struct {
	KeyPair
	KeyID uint32
}

OneTimePreKey is a single-use key pair used in X3DH for forward secrecy.

type PreKeyBundle

type PreKeyBundle struct {
	IdentityKey     []byte // public key
	SignedPreKey    []byte // public key
	SignedPreKeyID  uint32
	Signature       []byte // signature of SignedPreKey by IdentityKey
	OneTimePreKey   []byte // public key (optional, nil if consumed)
	OneTimePreKeyID uint32 // 0 if no one-time pre-key
}

PreKeyBundle contains the public keys a user publishes to the server for asynchronous X3DH key agreement.

type RatchetMessage

type RatchetMessage struct {
	DH         []byte `json:"dh"` // sender's current DH public key
	N          uint32 `json:"n"`  // message number in the sending chain
	PN         uint32 `json:"pn"` // previous chain length
	Ciphertext []byte `json:"ct"` // encrypted message (with AEAD nonce prepended)
}

RatchetMessage is the wire format for a Double Ratchet encrypted message.

func DeserializeRatchetMessage

func DeserializeRatchetMessage(data []byte) (*RatchetMessage, error)

DeserializeRatchetMessage decodes bytes to a RatchetMessage.

type RatchetState

type RatchetState struct {

	// DH keys
	DHs *KeyPair // sending ratchet key pair

	// Remote peer's current DH public key
	DHr []byte

	// Root key (32 bytes) — updated on every DH ratchet step
	RootKey []byte

	// Sending chain key — KDF'd on each message sent
	CKs []byte

	// Receiving chain key — KDF'd on each message received
	CKr []byte

	// Message counters
	Ns uint32 // sending
	Nr uint32 // receiving
	PN uint32 // number of messages in previous sending chain

	// Skipped message keys: map of (DH public key, counter) -> message key
	// For handling out-of-order messages
	SkippedKeys map[string]map[uint32][]byte

	// Max skipped keys to prevent DoS
	MaxSkipped uint32
	// contains filtered or unexported fields
}

RatchetState holds the complete state of a Double Ratchet session. This implements the Signal Double Ratchet Algorithm.

func NewRatchetSession

func NewRatchetSession(sharedSecret, identityPriv, remoteSignedPreKeyPub []byte, dhKeyPair *KeyPair) *RatchetState

NewRatchetSession creates a new Double Ratchet session for the INITIATOR (Alice).

After X3DH, Alice has the shared secret (SK). She uses her X3DH ephemeral key pair as her initial ratchet DH key pair (DHs).

Chain key derivation follows Signal spec:

CKs = KDF(SK, DH(Alice.IK_priv, Bob.SPK_pub))   — matches Bob's CKr
CKr = nil (will be set on first DH ratchet step when receiving a reply)

func NewRatchetSessionFromReceived

func NewRatchetSessionFromReceived(sharedSecret, signedPreKeyPriv, remoteIdentityPub, senderEphemeralPub []byte, myDHKeyPair *KeyPair) *RatchetState

NewRatchetSessionFromReceived creates the RESPONDER's (Bob's) session.

Bob receives Alice's initial message containing Alice's ephemeral DH public key. Bob generates his own ratchet DH key pair but does NOT send yet.

Chain key derivation:

CKr = KDF(SK, DH(SPK_b_priv, IK_a_pub))   — matches Alice's CKs
CKs = nil (will be set on first DH ratchet step when Bob first sends)

func (*RatchetState) Decrypt

func (rs *RatchetState) Decrypt(msg *RatchetMessage) ([]byte, error)

Decrypt decrypts an incoming RatchetMessage.

func (*RatchetState) Encrypt

func (rs *RatchetState) Encrypt(plaintext []byte) (*RatchetMessage, error)

Encrypt encrypts a plaintext message using the Double Ratchet.

type SignedPreKey

type SignedPreKey struct {
	KeyPair
	KeyID     uint32
	Signature []byte // Ed25519 signature of PublicKey by IdentityKey
}

SignedPreKey is a medium-lived key pair signed by the identity key.

type SimpleKeyExchange

type SimpleKeyExchange struct {
	// contains filtered or unexported fields
}

SimpleKeyExchange is a legacy key exchange that just returns the remote key directly. Kept for backwards compatibility with tests.

func NewSimpleKeyExchange

func NewSimpleKeyExchange() *SimpleKeyExchange

NewSimpleKeyExchange creates a new simple key exchange manager.

func (*SimpleKeyExchange) ExchangeKey

func (kx *SimpleKeyExchange) ExchangeKey(peerID string, remoteKey []byte) ([]byte, error)

ExchangeKey performs a simple key exchange by returning the remote key.

func (*SimpleKeyExchange) GenerateKeyPair

func (kx *SimpleKeyExchange) GenerateKeyPair(peerID string) (*KeyPair, error)

GenerateKeyPair generates a random key pair for a peer.

type X3DHIdentity

type X3DHIdentity struct {
	IdentityKey    *IdentityKey
	SignedPreKey   *SignedPreKey
	OneTimePreKeys map[uint32]*OneTimePreKey // keyID -> key
	// contains filtered or unexported fields
}

X3DHIdentity holds a user's X3DH key material.

func NewX3DHIdentity

func NewX3DHIdentity() (*X3DHIdentity, error)

NewX3DHIdentity generates a complete X3DH identity set.

func (*X3DHIdentity) ConsumeOneTimePreKey

func (id *X3DHIdentity) ConsumeOneTimePreKey(keyID uint32)

ConsumeOneTimePreKey removes a one-time pre-key after use.

func (*X3DHIdentity) GenerateOneTimePreKeys

func (id *X3DHIdentity) GenerateOneTimePreKeys(n int) error

GenerateOneTimePreKeys generates N one-time pre-keys.

func (*X3DHIdentity) GetBundle

func (id *X3DHIdentity) GetBundle() *PreKeyBundle

GetBundle returns the public PreKeyBundle for publishing to the server.

type X25519KeyExchange

type X25519KeyExchange struct {
	// contains filtered or unexported fields
}

X25519KeyExchange implements Diffie-Hellman key exchange using Curve25519.

func NewX25519KeyExchange

func NewX25519KeyExchange() *X25519KeyExchange

NewX25519KeyExchange creates a new X25519 key exchange manager.

func (*X25519KeyExchange) DeriveSharedSecret

func (kx *X25519KeyExchange) DeriveSharedSecret(peerID string, remotePublicKey []byte) ([]byte, error)

DeriveSharedSecret computes the shared secret using ECDH (Curve25519). The caller must supply the remote peer's public key.

func (*X25519KeyExchange) GenerateKeyPair

func (kx *X25519KeyExchange) GenerateKeyPair(peerID string) (*KeyPair, error)

GenerateKeyPair generates a new X25519 key pair for a peer.

func (*X25519KeyExchange) GetPublicKey

func (kx *X25519KeyExchange) GetPublicKey(peerID string) ([]byte, error)

GetPublicKey returns the public key for a peer.

func (*X25519KeyExchange) RemovePeer

func (kx *X25519KeyExchange) RemovePeer(peerID string)

RemovePeer zeroes out the private key and removes the key pair.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL