class PG::Scram
The client side of SCRAM-SHA-256 (RFC 5802, RFC 7677), as PostgreSQL
runs it: without channel binding (n,,), and with the user name left
empty, since the server takes the startup message's.
s = PG::Scram.new("pencil", nonce: "rOprNGfwEbeRWgbNEkqO", user: "user")
s.client_first # => "n,,n=user,r=rOprNGfwEbeRWgbNEkqO"
The password is used as it is: SASLprep, which PostgreSQL applies when the password is valid for it, changes only passwords with characters beyond ASCII that it maps or forbids, so such a password may be refused.
Constants
MECHANISM: String
The mechanism's name, as the server lists it.
MAX_ITERATIONS: Int
The most PBKDF2 rounds a server may ask for, unless the connection
says otherwise (max_scram_iterations): the server is not trusted
before its signature is checked, and a huge count would keep the
client hashing (PostgreSQL's default is 4096; from PostgreSQL 16 an
administrator may raise scram_iterations).
BLOCKING_ITERATIONS: Int
Above this many rounds, the hashing runs on a helper thread
(Task.blocking), so that the worker's other tasks go on meanwhile.
Class methods
def self.new(password: String, nonce: String? = …, user: String = …, max_iterations: Int = …) -> PG::Scram
A new exchange for password, with a random 18-byte nonce unless one
is given (tests).
def self.salted_password(password: String, salt: Bytes, rounds: Int) -> Bytes
PBKDF2-HMAC-SHA-256 of the password: on a helper thread when the
count is large (password and salt are immutable, so the block may
take them there).
Methods
def client_first -> String
The first message: the GS2 header and the bare part.
def client_final(server_first: String) -> String
The final message, answering the server's first message. Raises
PG::AuthenticationError when that message is malformed or its nonce
does not extend this client's.
def verify(server_final: String) -> Void
Checks the server's final message, which proves that the server knows
the password too. Raises PG::AuthenticationError when it does not,
or reports an error (e=).
def verified? -> Bool
Whether #verify checked the server's signature: until then the
server has not proved that it knows the password.