Documentation
¶
Index ¶
- func CreateSessionID(userA, deviceA, userB, deviceB string) string
- func GenerateX3DHKeyMaterial(deviceID string, numOneTimePreKeys int) (*X3DHKeyMaterial, *PublicPreKeyBundle, error)
- func PerformX3DHInitiator(myIdentityKey ed25519.PrivateKey, peerBundle *PublicPreKeyBundle) (sessionKey, associatedData []byte, ephemeralPub *ecdh.PublicKey, ...)
- func PerformX3DHResponder(myIdentityKey ed25519.PrivateKey, mySignedPreKey *ecdh.PrivateKey, ...) (sessionKey, associatedData []byte, err error)
- type DefaultSessionManager
- type DoubleRatchetSession
- func (s *DoubleRatchetSession) Decrypt(ciphertext []byte) ([]byte, error)
- func (s *DoubleRatchetSession) Encrypt(plaintext []byte) ([]byte, error)
- func (s *DoubleRatchetSession) Ratchet(peerPub *ecdh.PublicKey) error
- func (s *DoubleRatchetSession) RecvKey() []byte
- func (s *DoubleRatchetSession) SendKey() []byte
- type EncryptedMessage
- type KeyStore
- type PublicPreKeyBundle
- type SQLKeyStore
- func (s *SQLKeyStore) ConsumeOneTimePreKey(ctx context.Context, userID string) error
- func (s *SQLKeyStore) LoadIdentityPublicKey(ctx context.Context, userID string) ([]byte, error)
- func (s *SQLKeyStore) LoadPreKeyBundle(ctx context.Context, userID string) (*PublicPreKeyBundle, error)
- func (s *SQLKeyStore) LoadSession(ctx context.Context, sessionID string) ([]byte, error)
- func (s *SQLKeyStore) SaveIdentityPublicKey(ctx context.Context, userID string, pubKey []byte) error
- func (s *SQLKeyStore) SavePreKeyBundle(ctx context.Context, userID string, bundle *PublicPreKeyBundle) error
- func (s *SQLKeyStore) SaveSession(ctx context.Context, sessionID string, state []byte) error
- type Session
- type X3DHKeyMaterial
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func CreateSessionID ¶ added in v0.3.0
CreateSessionID returns a deterministic session ID for a pair of user:device identifiers.
func GenerateX3DHKeyMaterial ¶ added in v0.3.0
func GenerateX3DHKeyMaterial(deviceID string, numOneTimePreKeys int) (*X3DHKeyMaterial, *PublicPreKeyBundle, error)
GenerateX3DHKeyMaterial generates a full set of X3DH keys for a new user/device.
func PerformX3DHInitiator ¶ added in v0.3.0
func PerformX3DHInitiator( myIdentityKey ed25519.PrivateKey, peerBundle *PublicPreKeyBundle, ) (sessionKey, associatedData []byte, ephemeralPub *ecdh.PublicKey, usedOPKID uint32, hasOPK bool, err error)
PerformX3DHInitiator executes the initiator side of X3DH.
func PerformX3DHResponder ¶ added in v0.3.0
func PerformX3DHResponder( myIdentityKey ed25519.PrivateKey, mySignedPreKey *ecdh.PrivateKey, myOneTimePreKey *ecdh.PrivateKey, senderIdentityPub ed25519.PublicKey, senderEphemeralPub *ecdh.PublicKey, ) (sessionKey, associatedData []byte, err error)
PerformX3DHResponder executes the responder side of X3DH.
Types ¶
type DefaultSessionManager ¶ added in v0.3.0
type DefaultSessionManager struct {
// contains filtered or unexported fields
}
DefaultSessionManager manages E2EE session persistence.
func NewSessionManager ¶ added in v0.3.0
func NewSessionManager(store KeyStore) *DefaultSessionManager
NewSessionManager creates a new session manager backed by a KeyStore.
type DoubleRatchetSession ¶ added in v0.3.0
type DoubleRatchetSession struct {
// contains filtered or unexported fields
}
DoubleRatchetSession wraps mellium's DHRatchet with message encryption. Each peer maintains one of these for every active conversation.
func NewDoubleRatchetInitiator ¶ added in v0.3.0
func NewDoubleRatchetInitiator(sessionKey []byte, ephemeralPriv *ecdh.PrivateKey, peerSPKPub *ecdh.PublicKey) (*DoubleRatchetSession, error)
NewDoubleRatchetInitiator creates a session for the initiator (Alice). After X3DH, Alice uses the shared session key as the root key and her ephemeral key as the initial ratchet private key.
Flow: Alice calls Step(Bob's SPK public) to derive the first send key.
func NewDoubleRatchetResponder ¶ added in v0.3.0
func NewDoubleRatchetResponder(sessionKey []byte, spkPriv *ecdh.PrivateKey) (*DoubleRatchetSession, error)
NewDoubleRatchetResponder creates a session for the responder (Bob). After X3DH, Bob uses the shared session key as the root key and generates a new ratchet key pair. Bob waits for Alice's first message before stepping.
func (*DoubleRatchetSession) Decrypt ¶ added in v0.3.0
func (s *DoubleRatchetSession) Decrypt(ciphertext []byte) ([]byte, error)
Decrypt decrypts a ciphertext message using the current receiving key.
func (*DoubleRatchetSession) Encrypt ¶ added in v0.3.0
func (s *DoubleRatchetSession) Encrypt(plaintext []byte) ([]byte, error)
Encrypt encrypts a plaintext message using the current sending key. Uses XChaCha20-Poly1305 for AEAD encryption.
func (*DoubleRatchetSession) Ratchet ¶ added in v0.3.0
func (s *DoubleRatchetSession) Ratchet(peerPub *ecdh.PublicKey) error
Ratchet advances the ratchet state with the peer's current DH public key. Returns new send and recv message keys.
func (*DoubleRatchetSession) RecvKey ¶ added in v0.3.0
func (s *DoubleRatchetSession) RecvKey() []byte
RecvKey returns the current receiving key (useful for session serialization).
func (*DoubleRatchetSession) SendKey ¶ added in v0.3.0
func (s *DoubleRatchetSession) SendKey() []byte
SendKey returns the current sending key (useful for session serialization).
type EncryptedMessage ¶ added in v0.3.0
type EncryptedMessage struct {
SenderID string `json:"sender_id"`
ReceiverID string `json:"receiver_id"`
Ciphertext []byte `json:"ciphertext"`
Header []byte `json:"header"` // Double Ratchet header (DH public key, message counter, etc.)
Timestamp int64 `json:"timestamp"`
}
EncryptedMessage represents the wire format for an E2EE message. It contains the encrypted ciphertext and the ratchet header needed by the receiver to derive the correct decryption key.
func Deserialize ¶ added in v0.3.0
func Deserialize(data []byte) (*EncryptedMessage, error)
Deserialize decodes a JSON payload into an EncryptedMessage.
func (*EncryptedMessage) Serialize ¶ added in v0.3.0
func (m *EncryptedMessage) Serialize() ([]byte, error)
Serialize encodes the encrypted message to JSON for transport.
type KeyStore ¶ added in v0.3.0
type KeyStore interface {
// Identity Keys (public only, for server-side storage)
SaveIdentityPublicKey(ctx context.Context, userID string, pubKey []byte) error
LoadIdentityPublicKey(ctx context.Context, userID string) ([]byte, error)
// PreKey Bundles (public bundle for X3DH)
SavePreKeyBundle(ctx context.Context, userID string, bundle *PublicPreKeyBundle) error
LoadPreKeyBundle(ctx context.Context, userID string) (*PublicPreKeyBundle, error)
ConsumeOneTimePreKey(ctx context.Context, userID string) error
// Session State (ratchet state, stored client-side)
SaveSession(ctx context.Context, sessionID string, state []byte) error
LoadSession(ctx context.Context, sessionID string) ([]byte, error)
}
KeyStore defines the interface for persistence of E2EE key material. The server stores ONLY public keys and prekey bundles. Private keys are stored ONLY on the client side.
type PublicPreKeyBundle ¶ added in v0.3.0
type PublicPreKeyBundle struct {
DeviceID string `json:"device_id"` // Unique ID for the device publishing this bundle
IdentityKey ed25519.PublicKey `json:"identity_key"` // Ed25519 identity public key
SignedPreKey *ecdh.PublicKey `json:"-"` // X25519 signed prekey (public)
SPKSignature []byte `json:"spk_signature"` // Ed25519 signature of the SPK
SPKCreatedAt int64 `json:"spk_created_at"` // Timestamp when the SPK was generated
OneTimePreKeys map[uint32]*ecdh.PublicKey `json:"-"` // X25519 one-time prekeys (indexed)
// Serialized forms for JSON transport
SignedPreKeyBytes []byte `json:"signed_prekey"`
OneTimePreKeysBytes map[uint32][]byte `json:"one_time_prekeys,omitempty"`
}
PublicPreKeyBundle contains the public keys a user (per device) publishes to the server for asynchronous X3DH key agreement. This is the Signal Protocol PreKeyBundle.
func (*PublicPreKeyBundle) MarshalKeys ¶ added in v0.3.0
func (b *PublicPreKeyBundle) MarshalKeys()
MarshalKeys populates the byte fields from the key objects for transport.
func (*PublicPreKeyBundle) UnmarshalKeys ¶ added in v0.3.0
func (b *PublicPreKeyBundle) UnmarshalKeys() error
UnmarshalKeys populates the key objects from the byte fields after transport.
type SQLKeyStore ¶ added in v0.3.0
type SQLKeyStore struct {
// contains filtered or unexported fields
}
SQLKeyStore implements the KeyStore interface using a SQL database. The server uses this to store public identity keys and prekey bundles. Clients use this to store session state.
func NewSQLKeyStore ¶ added in v0.3.0
func NewSQLKeyStore(backend *db.Backend, prefix string) (*SQLKeyStore, error)
NewSQLKeyStore creates a new SQL-based key store.
func (*SQLKeyStore) ConsumeOneTimePreKey ¶ added in v0.3.0
func (s *SQLKeyStore) ConsumeOneTimePreKey(ctx context.Context, userID string) error
func (*SQLKeyStore) LoadIdentityPublicKey ¶ added in v0.3.0
func (*SQLKeyStore) LoadPreKeyBundle ¶ added in v0.3.0
func (s *SQLKeyStore) LoadPreKeyBundle(ctx context.Context, userID string) (*PublicPreKeyBundle, error)
func (*SQLKeyStore) LoadSession ¶ added in v0.3.0
func (*SQLKeyStore) SaveIdentityPublicKey ¶ added in v0.3.0
func (*SQLKeyStore) SavePreKeyBundle ¶ added in v0.3.0
func (s *SQLKeyStore) SavePreKeyBundle(ctx context.Context, userID string, bundle *PublicPreKeyBundle) error
func (*SQLKeyStore) SaveSession ¶ added in v0.3.0
type Session ¶ added in v0.3.0
type Session struct {
ID string `json:"id"`
UserA string `json:"user_a"`
UserB string `json:"user_b"`
State []byte `json:"state"` // Serialized Double Ratchet state
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
}
Session tracks the E2EE state between two users/devices.
type X3DHKeyMaterial ¶ added in v0.3.0
type X3DHKeyMaterial struct {
IdentityKey ed25519.PrivateKey // Ed25519 identity key (long-lived)
SignedPreKey *ecdh.PrivateKey // X25519 signed prekey (medium-lived)
SPKSignature []byte // Ed25519 signature of the SPK public key
OneTimePreKeys []*ecdh.PrivateKey // X25519 one-time prekeys (single-use)
}
X3DHKeyMaterial holds all the private key material for a user's X3DH identity. This is stored ONLY on the client side. Never on the server.