Package-level declarations
Types
Content commitment of an application message body, version 1 (docs/application-delivery.md). A client keeps it with a committed inbound message so that a later message with the same logical ID but another body is detected instead of acknowledged. Local storage only: it is never sent and is not part of any wire format.
KSecureMessage ciphertext wire format, version 1. The output goes into EncryptedEnvelope.payload. Framing only: no cryptography happens here and the ratchet bytes are carried unchanged. Full specification: docs/wire-format.md.
The local device's authentication key pair: a 32-byte Ed25519 seed and the 32-byte Ed25519 public key. Created by ProtocolEngine.createDeviceAuthenticationKey. The private key never leaves the device; the server only gets publicKey. A plain class, so toString() never prints key bytes.
Routine device authentication key rotation, format version 1 (docs/device-authentication-rotation.md). All three constructions share the rotation statement:
A statement with both proofs: authorizationSignature by the current key, proofOfPossession by the replacement key.
Identifies one rotation statement: 32 bytes, SHA-256 over the domain KSecureMessage-DeviceAuthRotationId-v1 and the statement. The server records the ID of the rotation that installed a device's current key, so a retry of the same rotation is recognized. It is never an authorization.
The transition a routine rotation asks for: address's registered key currentPublicKey at authentication epoch expectedAuthEpoch is to be replaced by replacementPublicKey. timestamp (whole milliseconds) and nonce make each statement single-use.
Device recovery format version 1 (docs/device-recovery.md). All three constructions share the recovery statement:
A request authorized by its DeviceRecoveryRequest.authorizer: authorizerSignature is the authorizer's device authentication key's signature over the recovery statement. Carries both proofs; the target device submits it to the server.
Transfer encoding of recovery requests and authorizations, version 1, for applications that move them between devices (QR code, file, their own channel). Not signed as such: the signatures inside cover the statement.
Identifies one recovery statement: 32 bytes, SHA-256 over the domain KSecureMessage-DeviceRecoveryId-v1 and the statement. The server records the ID of the recovery that installed a device's current key, so a retry of the same recovery is recognized. It is never an authorization.
A device's request to replace its registered device authentication key with replacementPublicKey, to be authorized by authorizer, another device of the same user. proofOfPossession is the replacement key's signature over the recovery statement (DeviceRecovery), so the request cannot name a key its sender does not hold.
ProtocolEngine backed by Kodium's X3DH and Double Ratchet.
Last-device recovery, format version 1 (docs/last-device-recovery.md). Recovery statement:
A statement with both proofs: recoverySignature by the offline recovery key, proofOfPossession by the replacement key.
Server-chosen identifier of one last-device recovery challenge: 16 random bytes. Not secret.
Identifies one last-device recovery statement: 32 bytes, SHA-256 over the domain KSecureMessage-LastDeviceRecoveryId-v1 and the statement. The server records the ID of the recovery that installed a device's current key, so a retry of the same recovery is recognized. Never an authorization.
The offline last-device recovery key of a user: a 32-byte Ed25519 seed and its 32-byte public key. Created by ProtocolEngine.createLastDeviceRecoveryKey; the application keeps it offline (for example printed or in a password manager) in the canonical text form encode. Only publicKey is ever sent to the server. The library never persists it.
A user's registration of publicKey as its last-device recovery key. proofOfPossession is the recovery key's signature over u32 length | domain | u32 length | userId | publicKey, so nobody can register a key they do not hold (a registration cannot be replaced in milestone 18).
The transition a last-device recovery asks for: challenge's target, at the challenge's epoch, gets replacementPublicKey, authorized by the recovery key recoveryPublicKey. The replacement key must differ from the recovery key.
Long-term identity key pair of the local device.
One-time prekey pair. Delete the private key after a session was accepted with it (see SessionAcceptanceResult.consumedOneTimePreKeyId).
Shape of the public prekey material KSecureMessage publishes. Lets code outside the protocol engine (the server, transports) check untrusted publications without Kodium. This is a format check only: it does not verify the signed prekey signature, which initiators do before X3DH.
High-level protocol boundary implemented with Kodium.
Failures raised by a ProtocolEngine. Messages never contain key material. The underlying cause is kept for debugging.
The public messaging identity key of a device: SIZE bytes (X25519 key followed by Ed25519 key), as in a prekey bundle. Immutable: the bytes are copied in and out.
Delayed recovery key reset, format version 1 (docs/recovery-key-reset.md). Integers are big-endian, strings u32 length | UTF-8.
The cancellation of the pending reset resetId of userId's recovery key currentPublicKey at expectedEpoch (requested at requestedAt, eligible from eligibleAt) by that recovery key itself.
A completion statement with the new recovery key's newKeyProofOfPossession.
Identifies one reset completion statement: 32 bytes, SHA-256 over the domain KSecureMessage-RecoveryKeyResetId-v1 and the statement. The server records the ID of the completion that installed the current recovery key, so a retry of the same completion is recognized. Never an authorization. Not the server-chosen RecoveryKeyResetId of the pending reset.
The completion of the pending reset resetId of userId's recovery key currentPublicKey at recovery key epoch expectedEpoch, requested at requestedAt and eligible from eligibleAt (both server times, whole milliseconds), with newPublicKey, by the registered device completer of the same user.
A query for userId's pending reset by the holder of its current recovery key currentPublicKey at timestamp (whole milliseconds, checked against the server clock with RecoveryKeyReset.VALIDITY_WINDOW).
Recovery key revocation, format version 1 (docs/recovery-key-lifecycle.md). Revocation statement:
Identifies one recovery key revocation statement: 32 bytes, SHA-256 over the domain KSecureMessage-RecoveryKeyRevocationId-v1 and the statement. Never an authorization.
The revocation a user asks for: userId's recovery key currentPublicKey, registered at recovery key epoch expectedEpoch, is to be removed without a replacement, authorized by the device authorizer of the same user.
Recovery key rotation, format version 1 (docs/recovery-key-lifecycle.md). Rotation statement:
A statement with both proofs: currentKeySignature by the current recovery key, newKeyProofOfPossession by the new recovery key.
Identifies one recovery key rotation statement: 32 bytes, SHA-256 over the domain KSecureMessage-RecoveryKeyRotationId-v1 and the statement. The server records the ID of the rotation that installed the current recovery key, so a retry of the same rotation is recognized. Never an authorization.
The rotation a user asks for: userId's recovery key currentPublicKey, registered at recovery key epoch expectedEpoch, is to be replaced by newPublicKey, authorized by the device authorizer of the same user. timestamp (whole milliseconds) and nonce make each statement single-use.
The authentication a device attaches to a ServerRequest: when it was made (epoch milliseconds, no finer), a fresh nonce and the Ed25519 signature over ServerRequestAuthentication.canonicalInput.
Single-use value of one authenticated request: SIZE random bytes. The server accepts each nonce once per device within the validity window.
The raw safety number: SHA-256 over both devices' addresses and identity keys, SIZE bytes.
Safety number version 1 of two devices (docs/identity-verification.md).
Machine-readable safety number payload, version 1, for a QR code or any other channel the application picks. Both devices produce identical bytes.
Result of comparing a local SafetyNumber with one scanned from the other device.
A decoded verification payload: the two devices in canonical order and their fingerprint. Decoding proves nothing; compare it with SafetyNumber.compare.
Content of one decrypted KSecureMessage message: the reliability frame that is the ratchet plaintext (docs/message-reliability.md). It is encrypted, so the server never sees it.
Reliability frame format, version 1. Its output is the plaintext handed to ProtocolEngine.encrypt; the ciphertext wire format (CiphertextMessageCodec) is not affected. Full specification: docs/message-reliability.md.
Persisted state of one end-to-end session with remote.
Canonical paths of the device-scoped HTTP API v1. The client builds its request URLs from them; the server rebuilds them from the decoded route parameters. Signatures cover these paths, never a raw request URI.
What an authenticated request is about: the device it acts for, the HTTP method, the canonical path (ServerApiPaths) and the exact bytes of the HTTP request body (empty for a request without body).
Signs and verifies server requests with a device authentication key, format version 1 (docs/server-authentication.md). The signed input is:
Lifecycle facts about a stored session, see docs/session-lifecycle.md.
Identifies one X3DH session initiation: 32 bytes (see docs/session-lifecycle.md).
Whether the user confirmed a pinned remote identity out of band (docs/identity-verification.md).