0
# Key Exchange
1
2
SJCL provides Secure Remote Password (SRP) protocol implementation for password-authenticated key agreement, allowing secure authentication and key derivation without transmitting passwords over the network.
3
4
## Capabilities
5
6
### SRP (Secure Remote Password)
7
8
The Secure Remote Password protocol allows two parties to authenticate each other and derive a shared secret using only a password, without ever transmitting the password itself.
9
10
```javascript { .api }
11
/**
12
* Calculate SRP verifier for user registration
13
* @param {string} I - Username/identity
14
* @param {string} P - Password
15
* @param {BitArray} s - Salt (random value)
16
* @param {Object} [group] - SRP group parameters (default: SRP-6a with 1024-bit prime)
17
* @returns {BitArray} SRP verifier value
18
*/
19
sjcl.keyexchange.srp.makeVerifier(I, P, s, group);
20
21
/**
22
* Calculate SRP x value (private key derived from password)
23
* @param {string} I - Username/identity
24
* @param {string} P - Password
25
* @param {BitArray} s - Salt value
26
* @returns {BitArray} SRP x value (private key)
27
*/
28
sjcl.keyexchange.srp.makeX(I, P, s);
29
```
30
31
**Usage Examples:**
32
33
```javascript
34
const sjcl = require('sjcl');
35
36
// User registration phase
37
function registerUser(username, password) {
38
// Generate random salt
39
const salt = sjcl.random.randomWords(4); // 128-bit salt
40
41
// Calculate verifier for storage on server
42
const verifier = sjcl.keyexchange.srp.makeVerifier(username, password, salt);
43
44
// Store username, salt, and verifier on server
45
// NEVER store the actual password
46
return {
47
username: username,
48
salt: salt,
49
verifier: verifier
50
};
51
}
52
53
// Example registration
54
const userRecord = registerUser("alice@example.com", "strongPassword123");
55
console.log("User registered with salt:", sjcl.codec.hex.fromBits(userRecord.salt));
56
console.log("Verifier:", sjcl.codec.hex.fromBits(userRecord.verifier));
57
58
// Calculate x value (used internally during authentication)
59
const xValue = sjcl.keyexchange.srp.makeX("alice@example.com", "strongPassword123", userRecord.salt);
60
console.log("X value:", sjcl.codec.hex.fromBits(xValue));
61
```
62
63
## SRP Protocol Overview
64
65
The SRP protocol consists of several phases:
66
67
### 1. Registration Phase
68
69
During user registration, the client calculates a verifier that the server stores instead of the password.
70
71
```javascript
72
const sjcl = require('sjcl');
73
74
function srpRegistration(username, password) {
75
// Client generates salt (or server can generate and send to client)
76
const salt = sjcl.random.randomWords(4);
77
78
// Client calculates verifier
79
const verifier = sjcl.keyexchange.srp.makeVerifier(username, password, salt);
80
81
// Send username, salt, and verifier to server for storage
82
return {
83
username: username,
84
salt: sjcl.codec.hex.fromBits(salt),
85
verifier: sjcl.codec.hex.fromBits(verifier)
86
};
87
}
88
89
// Usage
90
const registration = srpRegistration("user@domain.com", "mySecurePassword");
91
console.log("Registration data:", registration);
92
```
93
94
### 2. Authentication Phase
95
96
During authentication, both client and server perform calculations to verify the password without transmitting it.
97
98
```javascript
99
const sjcl = require('sjcl');
100
101
// Client-side authentication start
102
function clientAuthStart(username, password, saltFromServer) {
103
// Convert salt from hex if received from server
104
const salt = sjcl.codec.hex.toBits(saltFromServer);
105
106
// Calculate x (private key)
107
const x = sjcl.keyexchange.srp.makeX(username, password, salt);
108
109
// In full SRP implementation, client would also:
110
// 1. Generate random 'a' value
111
// 2. Calculate A = g^a mod N (public key)
112
// 3. Send A to server
113
114
return {
115
x: x,
116
// Additional SRP values would be calculated here
117
};
118
}
119
120
// Server-side verification preparation
121
function serverPrepareAuth(storedUserRecord) {
122
// Server has stored: username, salt, verifier
123
// In full SRP implementation, server would:
124
// 1. Generate random 'b' value
125
// 2. Calculate B = (kv + g^b) mod N
126
// 3. Send B and salt to client
127
128
return {
129
salt: storedUserRecord.salt,
130
// B value would be calculated and included
131
};
132
}
133
```
134
135
## SRP Security Properties
136
137
### Key Features
138
139
1. **Password Never Transmitted**: The actual password never goes over the network
140
2. **Zero-Knowledge**: Server learns nothing about the password
141
3. **Mutual Authentication**: Both parties verify each other's identity
142
4. **Forward Secrecy**: Session keys are ephemeral
143
5. **Offline Attack Resistance**: Server compromise doesn't immediately reveal passwords
144
145
### Security Considerations
146
147
```javascript
148
const sjcl = require('sjcl');
149
150
// Best practices for SRP implementation
151
class SRPBestPractices {
152
static generateSecureSalt() {
153
// Use at least 128 bits of random salt
154
return sjcl.random.randomWords(4);
155
}
156
157
static validateUsername(username) {
158
// Normalize username to prevent attacks
159
return username.toLowerCase().trim();
160
}
161
162
static strengthenPassword(password) {
163
// Consider additional password strengthening
164
// This is a simplified example
165
if (password.length < 8) {
166
throw new Error("Password too short");
167
}
168
return password;
169
}
170
171
static secureRegistration(username, password) {
172
const normalizedUsername = SRPBestPractices.validateUsername(username);
173
const strengthenedPassword = SRPBestPractices.strengthenPassword(password);
174
const salt = SRPBestPractices.generateSecureSalt();
175
176
const verifier = sjcl.keyexchange.srp.makeVerifier(
177
normalizedUsername,
178
strengthenedPassword,
179
salt
180
);
181
182
return {
183
username: normalizedUsername,
184
salt: salt,
185
verifier: verifier,
186
timestamp: Date.now()
187
};
188
}
189
}
190
191
// Usage with best practices
192
try {
193
const secureReg = SRPBestPractices.secureRegistration("User@Example.com", "MyStrongPassword123!");
194
console.log("Secure registration successful");
195
} catch (error) {
196
console.error("Registration failed:", error.message);
197
}
198
```
199
200
## Advanced SRP Usage
201
202
### Custom Group Parameters
203
204
SRP can use different mathematical groups for different security levels:
205
206
```javascript
207
const sjcl = require('sjcl');
208
209
// Example of using SRP with custom parameters
210
function srpWithCustomGroup(username, password, salt, customGroup) {
211
// Custom group would define different prime modulus and generator
212
// This is an advanced feature for specific security requirements
213
214
const verifier = sjcl.keyexchange.srp.makeVerifier(
215
username,
216
password,
217
salt,
218
customGroup
219
);
220
221
return verifier;
222
}
223
224
// Note: Custom groups require careful cryptographic analysis
225
// Default parameters are recommended for most applications
226
```
227
228
### SRP with Additional Key Derivation
229
230
Combine SRP with other key derivation methods:
231
232
```javascript
233
const sjcl = require('sjcl');
234
235
function enhancedSRPRegistration(username, password, additionalEntropy) {
236
// Generate salt
237
const salt = sjcl.random.randomWords(4);
238
239
// Optional: Strengthen password with additional entropy
240
const strengthenedPassword = password + additionalEntropy;
241
242
// Calculate SRP verifier
243
const verifier = sjcl.keyexchange.srp.makeVerifier(username, strengthenedPassword, salt);
244
245
// Derive additional keys using HKDF
246
const masterKey = sjcl.misc.hkdf(
247
verifier,
248
256,
249
salt,
250
sjcl.codec.utf8String.toBits("SRP-master-key")
251
);
252
253
const authKey = sjcl.misc.hkdf(
254
masterKey,
255
256,
256
salt,
257
sjcl.codec.utf8String.toBits("authentication")
258
);
259
260
return {
261
username: username,
262
salt: salt,
263
verifier: verifier,
264
authKey: authKey
265
};
266
}
267
268
// Usage
269
const enhancedReg = enhancedSRPRegistration(
270
"user@example.com",
271
"password123",
272
"device-specific-entropy"
273
);
274
```
275
276
## Integration Examples
277
278
### Web Application Integration
279
280
Example of integrating SRP into a web application:
281
282
```javascript
283
const sjcl = require('sjcl');
284
285
class WebSRPClient {
286
constructor(apiEndpoint) {
287
this.apiEndpoint = apiEndpoint;
288
}
289
290
async register(username, password) {
291
// Client-side registration
292
const salt = sjcl.random.randomWords(4);
293
const verifier = sjcl.keyexchange.srp.makeVerifier(username, password, salt);
294
295
// Send to server
296
const registrationData = {
297
username: username,
298
salt: sjcl.codec.hex.fromBits(salt),
299
verifier: sjcl.codec.hex.fromBits(verifier)
300
};
301
302
// In real implementation, this would be an HTTP request
303
console.log("Would send to server:", registrationData);
304
return true;
305
}
306
307
async authenticate(username, password) {
308
// Step 1: Get salt from server
309
// const { salt } = await fetch(`${this.apiEndpoint}/auth/salt/${username}`);
310
311
// Step 2: Calculate client credentials
312
const salt = sjcl.random.randomWords(4); // In real app, from server
313
const x = sjcl.keyexchange.srp.makeX(username, password, salt);
314
315
// Step 3: Continue with full SRP protocol
316
// (Additional steps would involve A/B value exchange)
317
318
console.log("Authentication x value calculated");
319
return { success: true, sessionKey: "derived-session-key" };
320
}
321
}
322
323
// Usage
324
const srpClient = new WebSRPClient("https://api.example.com");
325
// srpClient.register("user@example.com", "securePassword");
326
```
327
328
## Security Recommendations
329
330
1. **Salt Generation**: Always use cryptographically secure random salts (≥128 bits)
331
2. **Password Policy**: Enforce strong password requirements
332
3. **Username Handling**: Normalize usernames consistently
333
4. **Timing Attacks**: Be aware that SRP operations are not constant-time
334
5. **Group Parameters**: Use well-vetted SRP group parameters
335
6. **Protocol Completion**: Implement the full SRP protocol, not just verifier generation
336
7. **Session Management**: Properly manage derived session keys
337
8. **Transport Security**: Always use SRP over secure channels (HTTPS/TLS)
338
339
## Common Use Cases
340
341
1. **Password-Based Authentication**: Secure login without password transmission
342
2. **Zero-Knowledge Proofs**: Prove password knowledge without revealing it
343
3. **Mutual Authentication**: Both client and server authenticate each other
344
4. **Key Agreement**: Derive shared session keys from passwords
345
5. **Enterprise SSO**: Single sign-on systems requiring password verification
346
6. **Secure Messaging**: Authenticate messaging clients without storing passwords
347
348
## Limitations
349
350
1. **Protocol Complexity**: SRP requires careful implementation of the full protocol
351
2. **Performance**: More computationally expensive than simple password hashing
352
3. **Implementation Risk**: Incorrect implementation can compromise security
353
4. **Limited Library Support**: Not all platforms have mature SRP implementations
354
5. **User Experience**: May require additional steps compared to traditional authentication