Documentation
¶
Overview ¶
Package omemo implements the Signal protocol cryptographic primitives for OMEMO v2 (XEP-0384) encryption in XMPP.
This package provides X3DH key agreement, Double Ratchet message encryption, and a high-level Manager API for encrypting and decrypting OMEMO messages. It is a standalone cryptographic module with no dependency on the main xmpp-go module -- users wire the two together on the client side.
Index ¶
- Variables
- func Ed25519PrivateKeyToX25519(edPriv ed25519.PrivateKey) (*ecdh.PrivateKey, error)
- func Ed25519PublicKeyToX25519(edPub ed25519.PublicKey) ([]byte, error)
- func GenerateX25519KeyPair() (*ecdh.PrivateKey, error)
- func X3DHRespond(localIdentity *IdentityKeyPair, localSPK *ecdh.PrivateKey, ...) ([]byte, error)
- type Address
- type Bundle
- type BundlePreKey
- type EncryptedMessage
- type IdentityKeyPair
- type Manager
- func (m *Manager) Decrypt(sender Address, msg *EncryptedMessage) ([]byte, error)
- func (m *Manager) DecryptPreKeyMessage(sender Address, senderIdentityKey ed25519.PublicKey, ephemeralPubKey []byte, ...) ([]byte, error)
- func (m *Manager) Encrypt(plaintext []byte, recipients ...Address) (*EncryptedMessage, error)
- func (m *Manager) GenerateBundle(preKeyCount int) (*Bundle, error)
- func (m *Manager) ProcessBundle(addr Address, bundle *Bundle)
- type MemoryStore
- func (s *MemoryStore) ContainsSession(addr Address) (bool, error)
- func (s *MemoryStore) GetIdentityKeyPair() (*IdentityKeyPair, error)
- func (s *MemoryStore) GetLocalDeviceID() (uint32, error)
- func (s *MemoryStore) GetPreKey(id uint32) (*PreKeyRecord, error)
- func (s *MemoryStore) GetRemoteIdentity(addr Address) (ed25519.PublicKey, error)
- func (s *MemoryStore) GetSession(addr Address) ([]byte, error)
- func (s *MemoryStore) GetSignedPreKey(id uint32) (*SignedPreKeyRecord, error)
- func (s *MemoryStore) IsTrusted(addr Address, key ed25519.PublicKey) (bool, error)
- func (s *MemoryStore) RemovePreKey(id uint32) error
- func (s *MemoryStore) SaveIdentityKeyPair(ikp *IdentityKeyPair) error
- func (s *MemoryStore) SavePreKey(record *PreKeyRecord) error
- func (s *MemoryStore) SaveRemoteIdentity(addr Address, key ed25519.PublicKey) error
- func (s *MemoryStore) SaveSession(addr Address, data []byte) error
- func (s *MemoryStore) SaveSignedPreKey(record *SignedPreKeyRecord) error
- type MessageKey
- type PendingPreKey
- type PreKeyRecord
- type RatchetHeader
- type RatchetState
- type Session
- type SignedPreKeyRecord
- type Store
- type X3DHResult
Constants ¶
This section is empty.
Variables ¶
var ( ErrNoSession = errors.New("omemo: no session exists for address") ErrInvalidSignature = errors.New("omemo: invalid signature") ErrInvalidMessage = errors.New("omemo: invalid message") ErrDuplicateMessage = errors.New("omemo: duplicate message") ErrUntrustedIdentity = errors.New("omemo: untrusted identity key") ErrNoPreKey = errors.New("omemo: no pre-key available") ErrInvalidKeyLength = errors.New("omemo: invalid key length") ErrSkippedKeyLimit = errors.New("omemo: too many skipped message keys") )
Functions ¶
func Ed25519PrivateKeyToX25519 ¶
func Ed25519PrivateKeyToX25519(edPriv ed25519.PrivateKey) (*ecdh.PrivateKey, error)
Ed25519PrivateKeyToX25519 converts an Ed25519 private key to an X25519 private key. It hashes the 32-byte seed with SHA-512, clamps the first 32 bytes, and uses the result as the X25519 scalar.
func Ed25519PublicKeyToX25519 ¶
Ed25519PublicKeyToX25519 converts an Ed25519 public key to an X25519 public key using the birational map u = (1+y)/(1-y) mod p.
func GenerateX25519KeyPair ¶
func GenerateX25519KeyPair() (*ecdh.PrivateKey, error)
GenerateX25519KeyPair generates a new X25519 key pair.
func X3DHRespond ¶
func X3DHRespond( localIdentity *IdentityKeyPair, localSPK *ecdh.PrivateKey, localOPK *ecdh.PrivateKey, remoteIdentityKey ed25519.PublicKey, ephemeralPubKey []byte, ) ([]byte, error)
X3DHRespond performs the X3DH key agreement as the responder (Bob).
Types ¶
type Bundle ¶
type Bundle struct {
IdentityKey ed25519.PublicKey
SignedPreKey []byte // 32 bytes, X25519 public key
SignedPreKeyID uint32
SignedPreKeySignature []byte // Ed25519 signature over SignedPreKey
PreKeys []BundlePreKey
}
Bundle holds the public key material needed for X3DH key agreement.
type BundlePreKey ¶
BundlePreKey is a one-time pre-key in a bundle.
type EncryptedMessage ¶
type EncryptedMessage struct {
SenderDeviceID uint32
Keys []MessageKey
IV []byte // 12 bytes
Payload []byte // AES-GCM ciphertext without auth tag
}
EncryptedMessage represents an OMEMO encrypted message ready for XML serialization.
type IdentityKeyPair ¶
type IdentityKeyPair struct {
PrivateKey ed25519.PrivateKey
PublicKey ed25519.PublicKey
}
IdentityKeyPair holds an Ed25519 identity key pair.
func GenerateIdentityKeyPair ¶
func GenerateIdentityKeyPair() (*IdentityKeyPair, error)
GenerateIdentityKeyPair generates a new Ed25519 identity key pair.
type Manager ¶
type Manager struct {
// contains filtered or unexported fields
}
Manager provides the high-level API for OMEMO encryption and decryption.
func (*Manager) Decrypt ¶
func (m *Manager) Decrypt(sender Address, msg *EncryptedMessage) ([]byte, error)
Decrypt decrypts an OMEMO encrypted message.
func (*Manager) DecryptPreKeyMessage ¶
func (m *Manager) DecryptPreKeyMessage( sender Address, senderIdentityKey ed25519.PublicKey, ephemeralPubKey []byte, usedPreKeyID *uint32, signedPreKeyID uint32, msg *EncryptedMessage, ) ([]byte, error)
DecryptPreKeyMessage handles the full pre-key message decryption flow. It takes the sender's identity key, ephemeral key, and optionally the used pre-key ID to establish a new session as Bob and decrypt the message.
func (*Manager) Encrypt ¶
func (m *Manager) Encrypt(plaintext []byte, recipients ...Address) (*EncryptedMessage, error)
Encrypt encrypts plaintext for multiple recipients.
func (*Manager) GenerateBundle ¶
GenerateBundle generates a new OMEMO bundle for the local device.
func (*Manager) ProcessBundle ¶
ProcessBundle stores a remote bundle for later X3DH initiation.
type MemoryStore ¶
type MemoryStore struct {
// contains filtered or unexported fields
}
MemoryStore is an in-memory Store implementation for testing. It uses a Trust On First Use (TOFU) model for identity trust.
func NewMemoryStore ¶
func NewMemoryStore(deviceID uint32) *MemoryStore
NewMemoryStore creates a new in-memory store with the given device ID.
func (*MemoryStore) ContainsSession ¶
func (s *MemoryStore) ContainsSession(addr Address) (bool, error)
func (*MemoryStore) GetIdentityKeyPair ¶
func (s *MemoryStore) GetIdentityKeyPair() (*IdentityKeyPair, error)
func (*MemoryStore) GetLocalDeviceID ¶
func (s *MemoryStore) GetLocalDeviceID() (uint32, error)
func (*MemoryStore) GetPreKey ¶
func (s *MemoryStore) GetPreKey(id uint32) (*PreKeyRecord, error)
func (*MemoryStore) GetRemoteIdentity ¶
func (s *MemoryStore) GetRemoteIdentity(addr Address) (ed25519.PublicKey, error)
func (*MemoryStore) GetSession ¶
func (s *MemoryStore) GetSession(addr Address) ([]byte, error)
func (*MemoryStore) GetSignedPreKey ¶
func (s *MemoryStore) GetSignedPreKey(id uint32) (*SignedPreKeyRecord, error)
func (*MemoryStore) RemovePreKey ¶
func (s *MemoryStore) RemovePreKey(id uint32) error
func (*MemoryStore) SaveIdentityKeyPair ¶
func (s *MemoryStore) SaveIdentityKeyPair(ikp *IdentityKeyPair) error
func (*MemoryStore) SavePreKey ¶
func (s *MemoryStore) SavePreKey(record *PreKeyRecord) error
func (*MemoryStore) SaveRemoteIdentity ¶
func (s *MemoryStore) SaveRemoteIdentity(addr Address, key ed25519.PublicKey) error
func (*MemoryStore) SaveSession ¶
func (s *MemoryStore) SaveSession(addr Address, data []byte) error
func (*MemoryStore) SaveSignedPreKey ¶
func (s *MemoryStore) SaveSignedPreKey(record *SignedPreKeyRecord) error
type MessageKey ¶
type MessageKey struct {
DeviceID uint32
Data []byte // ratchet-encrypted key material (header + ciphertext)
IsPreKey bool // true if this is a pre-key message (first message in a session)
}
MessageKey holds the encrypted key material for a single recipient device.
type PendingPreKey ¶
type PendingPreKey struct {
PreKeyID *uint32
SignedPreKeyID uint32
EphemeralPubKey []byte // 32 bytes, X25519
}
PendingPreKey tracks pre-key info for the initial message.
type PreKeyRecord ¶
type PreKeyRecord struct {
ID uint32
PrivateKey []byte // 32 bytes, X25519
PublicKey []byte // 32 bytes, X25519
}
PreKeyRecord holds a one-time pre-key pair.
type RatchetHeader ¶
type RatchetHeader struct {
DHPub []byte // 32 bytes, X25519 public ratchet key
N uint32 // message number in sending chain
PN uint32 // previous chain length
}
RatchetHeader contains the public information sent with each ratchet message.
func (*RatchetHeader) MarshalBinary ¶
func (h *RatchetHeader) MarshalBinary() ([]byte, error)
MarshalBinary encodes a RatchetHeader to bytes.
func (*RatchetHeader) UnmarshalBinary ¶
func (h *RatchetHeader) UnmarshalBinary(data []byte) error
UnmarshalBinary decodes a RatchetHeader from bytes.
type RatchetState ¶
type RatchetState struct {
DHs *ecdh.PrivateKey // our current ratchet key pair
DHr []byte // their current ratchet public key (32 bytes)
RK []byte // root key (32 bytes)
CKs []byte // sending chain key (32 bytes)
CKr []byte // receiving chain key (32 bytes)
Ns uint32 // sending message number
Nr uint32 // receiving message number
PN uint32 // previous sending chain length
MKSkipped map[skippedKey][]byte // skipped message keys
}
RatchetState holds the state of a Double Ratchet session.
func InitRatchetAsAlice ¶
func InitRatchetAsAlice(sharedSecret, remoteSPK []byte) (*RatchetState, error)
InitRatchetAsAlice initializes a Double Ratchet as Alice (initiator). Alice generates a new DH pair and derives the first sending chain from DH with Bob's SPK.
func InitRatchetAsBob ¶
func InitRatchetAsBob(sharedSecret []byte, localSPK *ecdh.PrivateKey) *RatchetState
InitRatchetAsBob initializes a Double Ratchet as Bob (responder). Bob uses SPK as initial ratchet key, waits for Alice's first message to complete DH ratchet.
func (*RatchetState) MarshalBinary ¶
func (s *RatchetState) MarshalBinary() ([]byte, error)
MarshalBinary serializes the RatchetState to bytes.
func (*RatchetState) RatchetDecrypt ¶
func (s *RatchetState) RatchetDecrypt(header *RatchetHeader, ciphertext []byte) ([]byte, error)
RatchetDecrypt decrypts a message using the Double Ratchet.
func (*RatchetState) RatchetEncrypt ¶
func (s *RatchetState) RatchetEncrypt(plaintext []byte) (*RatchetHeader, []byte, error)
RatchetEncrypt encrypts plaintext using the Double Ratchet.
func (*RatchetState) UnmarshalBinary ¶
func (s *RatchetState) UnmarshalBinary(data []byte) error
UnmarshalBinary deserializes a RatchetState from bytes.
type Session ¶
type Session struct {
Ratchet *RatchetState
RemoteIdentity ed25519.PublicKey
PendingPreKey *PendingPreKey // set until the first reply is received
}
Session wraps a Double Ratchet state with session metadata.
func InitSessionAsAlice ¶
func InitSessionAsAlice( localIdentity *IdentityKeyPair, remoteBundle *Bundle, ) (*Session, error)
InitSessionAsAlice creates a new session as the initiator using X3DH.
func InitSessionAsBob ¶
func InitSessionAsBob( localIdentity *IdentityKeyPair, localSPK *ecdh.PrivateKey, localOPK *ecdh.PrivateKey, remoteIdentityKey ed25519.PublicKey, ephemeralPubKey []byte, ) (*Session, error)
InitSessionAsBob creates a new session as the responder using X3DH.
func (*Session) Decrypt ¶
func (s *Session) Decrypt(header *RatchetHeader, ciphertext []byte) ([]byte, error)
Decrypt decrypts a message using this session's ratchet.
func (*Session) MarshalBinary ¶
MarshalBinary serializes the session state.
func (*Session) UnmarshalBinary ¶
UnmarshalBinary deserializes a session from bytes.
type SignedPreKeyRecord ¶
type SignedPreKeyRecord struct {
ID uint32
PrivateKey []byte // 32 bytes, X25519
PublicKey []byte // 32 bytes, X25519
Signature []byte // Ed25519 signature over PublicKey
}
SignedPreKeyRecord holds a signed pre-key pair with its signature.
type Store ¶
type Store interface {
// GetIdentityKeyPair returns the local identity key pair.
GetIdentityKeyPair() (*IdentityKeyPair, error)
// SaveIdentityKeyPair stores the local identity key pair.
SaveIdentityKeyPair(ikp *IdentityKeyPair) error
// GetLocalDeviceID returns the local device ID.
GetLocalDeviceID() (uint32, error)
// GetRemoteIdentity returns the stored identity public key for an address.
GetRemoteIdentity(addr Address) (ed25519.PublicKey, error)
// SaveRemoteIdentity stores a remote identity public key.
SaveRemoteIdentity(addr Address, key ed25519.PublicKey) error
// IsTrusted returns whether the identity key for an address is trusted.
IsTrusted(addr Address, key ed25519.PublicKey) (bool, error)
// GetPreKey returns a pre-key by ID.
GetPreKey(id uint32) (*PreKeyRecord, error)
// SavePreKey stores a pre-key.
SavePreKey(record *PreKeyRecord) error
// RemovePreKey removes a pre-key by ID.
RemovePreKey(id uint32) error
// GetSignedPreKey returns a signed pre-key by ID.
GetSignedPreKey(id uint32) (*SignedPreKeyRecord, error)
// SaveSignedPreKey stores a signed pre-key.
SaveSignedPreKey(record *SignedPreKeyRecord) error
// GetSession returns the serialized session state for an address.
GetSession(addr Address) ([]byte, error)
// SaveSession stores the serialized session state for an address.
SaveSession(addr Address, data []byte) error
// ContainsSession returns whether a session exists for an address.
ContainsSession(addr Address) (bool, error)
}
Store defines the persistence interface for OMEMO state.
type X3DHResult ¶
type X3DHResult struct {
EphemeralPubKey []byte // X25519 public key used by initiator
UsedPreKeyID *uint32
}
X3DHResult holds the result of an X3DH key agreement.
func X3DHInitiate ¶
func X3DHInitiate(localIdentity *IdentityKeyPair, remoteBundle *Bundle) (*X3DHResult, error)
X3DHInitiate performs the X3DH key agreement as the initiator (Alice).