Security model¶
What the handshake proves¶
A completed handshake proves to the server that the client knows the password the stored verifier was made from. It proves to the client that the server holds that verifier. Neither side sends the password or the verifier. No certificate is involved. Both proofs are the Finished messages: with a wrong password or without the verifier, the two sides derive different keys and the handshake fails (RFC 5054, Section 2.6).
The username is not protected. The client sends it in the clear in the ClientHello (RFC 5054, Section 3.3), so anyone on the path can read it.
What the library checks¶
- Groups. Both sides use only the seven groups of RFC 5054, Appendix A. The client refuses any
other prime or generator and, by default, the 1024 and 1536 bit groups, with an
insufficient_securityalert. - Public values. RFC 5054 requires both sides to refuse a public value that is zero modulo
Nand calls these checks crucial in Section 3.1. The server refuses such anAand the client such aBwith anillegal_parameteralert. Both also refuse values that are not belowNor that giveu = 0. - Exponents. The secret exponents
aandbare 384 bits drawn fromConfig.Rand, above the 256 bits RFC 5054 asks for. - Constant-time arithmetic. The modular arithmetic uses
filippo.io/bigmod. The client computes
(B - k*g^x)^(a + u*x)asbase^a * (base^u)^x, so the secretsaandxstay in constant-time exponentiations and their sum is never formed. - Finished messages. Both sides compare the Finished message in constant time.
- Protocol. Only TLS 1.2, no renegotiation, no session resumption and no compression.
What RFC 5054 prescribes¶
SRP in TLS uses SHA-1 for the SRP values x, u and k. The cipher suites protect records with CBC
and HMAC-SHA1. RFC 5054, Section 3.4 explains why attacks on the collision resistance of SHA-1 do
not affect these uses. The CBC record layer keeps the Lucky13 countermeasures of crypto/tls, which
are partial: they apply only to the SHA-1 based MACs, which are the only MACs here.
What the caller must do¶
- Protect the verifiers. Whoever reads a verifier can test password guesses offline and can pose as the server to that user (RFC 5054, Section 3.3).
- Limit password guessing. Every handshake tests one guess. Count failures and refuse clients over the limit, as Limiting password guessing describes.
- Keep the simulated verifier seed secret and stable. See Simulated verifiers.
- Bound the handshake. See Denial of service.
- Keep
KeyLogWriteroff in production. The key log decrypts every connection it covers. - Choose passwords that resist offline guessing. There is no tunable work factor: testing a guess against a stolen verifier costs two SHA-1 hashes and one modular exponentiation.
Denial of service¶
The library sets no handshake deadline and no connection limit. A client that connects and sends nothing keeps the connection open until the caller closes it.
The handshake is costly for the server. The client can make it do most of the work before proving anything:
- A single ClientHello makes the server call
GetVerifierand, when it returns a verifier, computeBwith one modular exponentiation. - A ClientKeyExchange with any value of
Amakes the server compute two more exponentiations for the premaster secret. - Only then does the client's Finished message show whether it knows the password.
The exponents have fixed lengths, so the cost grows roughly with the square of the group size. A
simulated verifier costs the same as a real one. Set a deadline on every accepted connection before its handshake with SetDeadline or
HandshakeContext. Limit the connections a client can open.
A reverse proxy in front of the server can enforce both. Returning ErrAccessDenied from
GetVerifier refuses a client before step 1's exponentiation.
Fixes from Go¶
Most of the code is a copy of crypto/tls. A CI job that runs on every push and pull request to dev and main and
weekly compares the copied files with the newest Go release and fails when Go changed one of them, so fixes to Go's TLS
code are ported.
Development describes the process and the
security policy how such fixes are
rated and released.
Reporting a vulnerability¶
Report vulnerabilities privately through GitHub security advisories. The security policy describes the process and the fix targets.