ServerRequestAuthentication

Signs and verifies server requests with a device authentication key, format version 1 (docs/server-authentication.md). The signed input is:

u32 length | "KSecureMessage-ServerAuth-v1" (UTF-8)
u32 length | userId (UTF-8) | u32 length | deviceId (UTF-8)
u32 length | method (ASCII, upper case)
u32 length | canonical path (UTF-8)
SHA-256(body) (32)
timestamp: i64, epoch milliseconds
nonce (16)

Integers are big-endian. The signature is Ed25519 over the whole input. The domain string keeps signatures made for anything else (signed prekeys, other protocols) from verifying as a request signature.

Properties

Link copied to clipboard
const val PUBLIC_KEY_SIZE: Int

Size of a device authentication public key (Ed25519).

Link copied to clipboard
const val SIGNATURE_SIZE: Int

Size of a request signature (Ed25519).

Functions

Link copied to clipboard
fun canonicalInput(request: ServerRequest, timestamp: Instant, nonce: RequestNonce): ByteArray

The bytes the signature covers. Throws IllegalArgumentException for a method that is not upper-case ASCII letters.

Link copied to clipboard
fun sign(keyPair: DeviceAuthenticationKeyPair, request: ServerRequest, timestamp: Instant, nonce: RequestNonce = RequestNonce.random()): RequestAuthentication

Authenticates request at timestamp (truncated to milliseconds) with a fresh nonce.

Link copied to clipboard
fun verify(publicKey: ByteArray, request: ServerRequest, authentication: RequestAuthentication): Boolean

true if authentication is a valid signature over request by the holder of publicKey. Checks the signature only: time window and nonce reuse are the server's job. Malformed keys, signatures and requests give false.