KodiumProtocolEngine

ProtocolEngine backed by Kodium's X3DH and Double Ratchet.

Key encoding: private keys are Kodium's raw 32-byte secret, public keys are Kodium's 64-byte unified key (X25519 encryption key followed by Ed25519 signing key).

Every operation imports the ratchet from SecureSession.state, works on a throwaway Kodium session and exports it again. Kodium mutates its session even when decryption fails, so a failed call must never produce a new state; the caller's stored session stays valid.

Kodium's X3DH neither verifies the signed prekey signature nor defines associated data. This engine verifies the signature before key agreement. Sessions it creates use session initiation version 2 (S1): the associated data of every ratchet message is the canonical initiation transcript (SessionInitiationId.v2Transcript) with both device addresses, both identity keys, the whole ephemeral key and both prekey IDs. Sessions created before S1 keep their version 1 associated data initiatorIdentityKey || responderIdentityKey.

Constructors

Link copied to clipboard
constructor()

Functions

Link copied to clipboard
open suspend override fun acceptSession(localIdentity: LocalIdentity, localAddress: DeviceAddress, remote: DeviceAddress, signedPreKey: SignedPreKeyPair, oneTimePreKey: OneTimePreKeyPair?, message: PreKeyMessage): SessionAcceptanceResult

Creates the responder side of a session from the first message, sent by remote to localAddress, and decrypts it. Only a SessionInitiationVersion.V2 message is accepted: its transcript, built from both addresses and every header field, is the associated data, so a changed address or header field fails decryption and nothing is created. A SessionInitiationVersion.V1 message throws ProtocolException.InvalidMessage. The caller looks up signedPreKey and oneTimePreKey by the IDs in message. It must delete SessionAcceptanceResult.consumedOneTimePreKeyId once the result is persisted.

Link copied to clipboard

Creates the device authentication key pair (docs/server-authentication.md). Separate from the messaging identity: it only authenticates the device to the server, see ServerRequestAuthentication.

Link copied to clipboard
open suspend override fun createIdentity(): LocalIdentity
Link copied to clipboard

Creates an offline last-device recovery key (docs/last-device-recovery.md). Separate from the messaging identity and from every device authentication key; the application keeps it offline.

Link copied to clipboard
open suspend override fun createOneTimePreKeys(firstId: OneTimePreKeyId, count: Int): List<OneTimePreKeyPair>

Creates count one-time prekeys with consecutive IDs starting at firstId.

Link copied to clipboard
open suspend override fun createSignedPreKey(identity: LocalIdentity, id: SignedPreKeyId): SignedPreKeyPair
Link copied to clipboard
open suspend override fun decrypt(session: SecureSession, message: CiphertextMessage, localIdentityKey: ByteArray): DecryptionResult

Decrypts message on an existing session of the device whose public identity key is localIdentityKey. A PreKeyMessage is accepted too; the initiator may send several before it sees a reply. It must have the session's initiation version, belong to the initiation that created session (see sessionInfo), and the local device must be the session's responder with the message's identity key as initiator; otherwise ProtocolException.InvalidMessage is thrown.

Link copied to clipboard
open suspend override fun encrypt(session: SecureSession, plaintext: ByteArray): EncryptionResult
Link copied to clipboard
open suspend override fun initiateSession(localIdentity: LocalIdentity, localAddress: DeviceAddress, remoteBundle: PreKeyBundle): SecureSession

Verifies remoteBundle and starts a session as initiator from localAddress to the bundle's address, always with session initiation version 2 (S1): the associated data binds both addresses and every initiation header field (docs/session-lifecycle.md). The session stays pending: encrypt returns PreKeyMessages until the first message from the remote side is decrypted.

Link copied to clipboard
open override fun sessionInfo(session: SecureSession): SessionInfo

Describes session without changing it. Throws ProtocolException.InvalidSessionState for an unreadable state.

Link copied to clipboard
open override fun sessionRemoteIdentityKey(session: SecureSession, localIdentityKey: ByteArray): ByteArray?

The remote identity key session was established with, or null if that cannot be told apart from the local one: exactly one of the session's two identity keys must equal localIdentityKey, and the other one is returned. Never returns the local key. Used to pin a session created before identity pinning (S1, finding F9).