SRP-6a (Secure Remote Password Protocol, Version 6a) is a cryptographic protocol that allows secure authentication without the server ever knowing the user's password. In this deep dive, we'll explore how ZeroNote uses SRP-6a to ensure your authentication data remains completely private.
๐ What is SRP-6a?
The Secure Remote Password (SRP) protocol is a zero-knowledge proof authentication system. Unlike traditional password authentication where the server stores password hashes, SRP-6a allows the server to verify that a client knows the password without the server ever learning what that password is.
๐ฏ Key Benefits of SRP-6a
- Zero-Knowledge: Server never sees the password
- Mutual Authentication: Both client and server prove their identity
- Forward Secrecy: Past sessions remain secure even if long-term secrets are compromised
- Resistance to Attacks: Protected against dictionary, replay, and man-in-the-middle attacks
๐งฎ The Mathematics Behind SRP-6a
SRP-6a is based on the discrete logarithm problem in finite fields. Here's the mathematical foundation:
Setup Parameters
N = Large safe prime (typically 2048+ bits)
g = Generator modulo N
k = Multiplier parameter (k = H(N, g))
H() = Cryptographic hash function (SHA-256)
Registration Phase
When a user registers, the following happens:
// Client side (registration)
const password = "user_password";
const salt = crypto.getRandomValues(new Uint8Array(32));
// Derive password verifier
const x = H(salt + H(username + ":" + password));
const v = g^x mod N;
// Send to server: username, salt, v (verifier)
// Server stores: username, salt, v
// Password is never transmitted or stored!
๐ The Authentication Dance
The SRP-6a authentication process involves a carefully choreographed exchange of cryptographic values:
Step 1: Client Initiates
// Client generates ephemeral keypair
const a = randomBigInt(); // Private ephemeral key
const A = g^a mod N; // Public ephemeral key
// Send username and A to server
Step 2: Server Responds
// Server generates its ephemeral keypair
const b = randomBigInt(); // Private ephemeral key
const B = (k*v + g^b) mod N; // Public ephemeral key
// Server sends salt and B to client
Step 3: Both Sides Compute Session Key
// Client side computation
const u = H(A + B);
const x = H(salt + H(username + ":" + password));
const S_client = (B - k*g^x)^(a + u*x) mod N;
const K_client = H(S_client);
// Server side computation
const u = H(A + B);
const S_server = (A * v^u)^b mod N;
const K_server = H(S_server);
// If authentication is successful: K_client === K_server
๐ก๏ธ Security Proofs and Verification
The final step involves mutual proof of knowledge:
// Client proves knowledge of password
const M1 = H(A + B + K_client);
// Server verifies and responds with proof
const M2 = H(A + M1 + K_client);
// Both sides now have authenticated session key K
โก ZeroNote's SRP-6a Implementation
At ZeroNote, we've implemented SRP-6a with additional security enhancements:
Enhanced Security Features
- 4096-bit safe primes for maximum security
- PBKDF2 key stretching before SRP-6a computation
- Constant-time operations to prevent timing attacks
- Session binding to prevent session hijacking
- Rate limiting on authentication attempts
Code Example: ZeroNote SRP-6a Client
class ZeroNoteSRPClient {
constructor() {
this.N = BigInt('0x' + ZERONOTE_SRP_PRIME_4096);
this.g = BigInt(2);
this.k = this.computeK();
}
async authenticate(username, password) {
// Step 1: Generate client ephemeral
this.a = this.generatePrivateEphemeral();
this.A = this.modPow(this.g, this.a, this.N);
// Step 2: Send username and A, receive salt and B
const response = await fetch('/api/auth/challenge', {
method: 'POST',
body: JSON.stringify({ username, A: this.A.toString(16) })
});
const { salt, B } = await response.json();
this.B = BigInt('0x' + B);
// Step 3: Compute session key
const u = this.computeU(this.A, this.B);
const x = await this.computeX(salt, username, password);
const S = this.computeClientS(this.B, this.k, this.g, x, this.a, u);
this.K = await this.hashBigInt(S);
// Step 4: Generate proof
const M1 = await this.computeM1(this.A, this.B, this.K);
// Step 5: Send proof and verify server response
const authResponse = await fetch('/api/auth/verify', {
method: 'POST',
body: JSON.stringify({ M1: M1.toString(16) })
});
const { M2, sessionToken } = await authResponse.json();
// Verify server proof
const expectedM2 = await this.computeM2(this.A, M1, this.K);
if (M2 !== expectedM2.toString(16)) {
throw new Error('Server authentication failed');
}
return { sessionToken, sessionKey: this.K };
}
// ... implementation details ...
}
๐ Common SRP-6a Vulnerabilities and Mitigations
Small Subgroup Attacks
Vulnerability: Malicious clients can choose special values for A that belong to small subgroups.
Mitigation: Always validate that A and B are in the correct range and not zero.
2-for-1 Dictionary Attacks
Vulnerability: Attacker can test two passwords per authentication attempt.
Mitigation: Use proper parameter validation and rate limiting.
Implementation Pitfalls
โ ๏ธ Critical Implementation Notes
- Never reuse ephemeral values (a, b)
- Always use cryptographically secure random number generation
- Implement constant-time comparisons for M1/M2 verification
- Validate all received parameters before computation
- Use safe primes and verify generator properties
๐ Performance Considerations
SRP-6a involves multiple large number exponentiations, which can be computationally expensive. ZeroNote optimizes performance through:
- Precomputed tables for common exponentiations
- Montgomery ladder for efficient modular exponentiation
- WebAssembly implementation for client-side performance
- Caching of session keys for subsequent requests
๐ Integration with ZeroNote's Architecture
SRP-6a is just one component of ZeroNote's comprehensive security architecture:
- SRP-6a Authentication: Proves user identity without revealing password
- Derived Session Keys: Used for encrypting subsequent API communications
- Note Encryption: Separate encryption keys derived from user input
- Forward Secrecy: Each session uses unique ephemeral keys
๐ Further Reading
Want to dive deeper into SRP-6a? Here are some excellent resources:
- RFC 5054: Using SRP for TLS Authentication
- Stanford SRP Homepage
- Wikipedia: Secure Remote Password Protocol
๐ฏ Key Takeaways
SRP-6a represents the gold standard for password-based authentication in zero-knowledge systems. By implementing SRP-6a, ZeroNote ensures that even we, as the service provider, never have access to your passwords. This is cryptographic proof that your authentication data remains private, even from us.