async_postgres/pg_auth

Types

ScramState = object
  clientNonce*: string
  clientFirstBare*: string
  serverSignature*: array[32, byte]
  gs2Header*: string         ## GS2 header: "n,," (no binding) or "p=tls-server-end-point,,"
  channelBindingData*: seq[byte] ## Channel binding data (empty for non-PLUS)
Intermediate state for SCRAM-SHA-256 authentication handshake.

Procs

proc computeTlsServerEndpoint(certDer: openArray[byte]): seq[byte] {....raises: [],
    tags: [RootEffect], forbids: [].}
Compute tls-server-end-point channel binding data per RFC 5929. Always uses SHA-256, matching PostgreSQL (libpq) behavior.
proc md5AuthHash(user, password: string; salt: array[4, byte]): string {.
    ...raises: [], tags: [], forbids: [].}
Compute MD5 authentication hash for PostgreSQL. Returns "md5" followed by hex of MD5(MD5(password+user) + salt).
proc scramClientFinalMessage(password: string; serverFirstData: openArray[byte];
                             state: var ScramState): seq[byte] {.
    ...raises: [CatchableError, CatchableError], tags: [RootEffect], forbids: [].}
Generate the SCRAM-SHA-256 client-final message from the server's first response. Computes the client proof and stores the expected server signature in state.
proc scramClientFirstMessage(user: string; nonce: string; state: var ScramState;
                             cbType: string = ""; cbData: seq[byte] = @[]): seq[
    byte] {....raises: [], tags: [], forbids: [].}
Overload with explicit nonce for testing.
proc scramClientFirstMessage(user: string; state: var ScramState;
                             cbType: string = ""; cbData: seq[byte] = @[]): seq[
    byte] {....raises: [CatchableError], tags: [], forbids: [].}
Generate the SCRAM-SHA-256 client-first message with a random nonce. When cbType is non-empty, use channel binding (SCRAM-SHA-256-PLUS).
proc scramEscapeUsername(user: string): string {....raises: [], tags: [],
    forbids: [].}
Escape username for SCRAM per RFC 5802 Section 5.1. '=' is encoded as '=3D' and ',' is encoded as '=2C'.
proc scramVerifyServerFinal(serverFinalData: openArray[byte]; state: ScramState): bool {.
    ...raises: [], tags: [], forbids: [].}
Verify the server's final SCRAM-SHA-256 signature matches the expected value. The caller is expected to wipe state.serverSignature after verification since it is no longer needed and would aid an attacker impersonating the server.

Templates

template burnStr(s: var string)
Wipe a string's heap buffer. Compiler is prevented from eliding the write because nimcrypto's burnMem uses a volatile memset.