node-firebird 2.8.0 → 2.8.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/srp.js +17 -4
- package/package.json +1 -1
- package/src/srp.ts +18 -5
package/lib/srp.js
CHANGED
|
@@ -117,12 +117,16 @@ function clientProof(user, password, salt, A, B, a, hashAlgo = 'sha1') {
|
|
|
117
117
|
dump('n2', n2);
|
|
118
118
|
n1 = modPow(n1, n2, PRIME.N);
|
|
119
119
|
n2 = toBigInt(getHash('sha1', user));
|
|
120
|
-
|
|
120
|
+
// K is hashed as the raw fixed-length digest, exactly like the server's
|
|
121
|
+
// digest.process(sessionKey) over a 20-byte UCharBuffer. Converting it
|
|
122
|
+
// through bigint dropped a leading zero byte (~0.4% of connections) and
|
|
123
|
+
// broke the proof (issue #421).
|
|
124
|
+
var M = toBigInt(getHash(hashAlgo, toBuffer(n1), toBuffer(n2), salt, toBuffer(A), toBuffer(B), K));
|
|
121
125
|
dump('n1-2', n1);
|
|
122
126
|
dump('n2-2', n2);
|
|
123
127
|
dump('proof:M', M);
|
|
124
128
|
return {
|
|
125
|
-
clientSessionKey: K,
|
|
129
|
+
clientSessionKey: toBigInt(K),
|
|
126
130
|
authData: M,
|
|
127
131
|
};
|
|
128
132
|
}
|
|
@@ -162,12 +166,19 @@ function pad(n) {
|
|
|
162
166
|
/**
|
|
163
167
|
* Scramble keys.
|
|
164
168
|
*
|
|
169
|
+
* The server hashes the minimal (stripped) magnitude bytes of A and B
|
|
170
|
+
* (RemotePassword::computeScramble → processStrippedInt in Firebird's
|
|
171
|
+
* srp.cpp, identical in 3.0 through master) — NOT the 128-byte padded
|
|
172
|
+
* form, which the engine only uses for k = H(N, pad(g)). Padding here
|
|
173
|
+
* made u diverge whenever A or B had a leading zero byte (~0.8% of
|
|
174
|
+
* connections), failing the proof (issue #421).
|
|
175
|
+
*
|
|
165
176
|
* @param A BigInt Client public key.
|
|
166
177
|
* @param B BigInt Server public key.
|
|
167
178
|
* @returns {BigInt}
|
|
168
179
|
*/
|
|
169
180
|
function getScramble(A, B, hashAlgo = 'sha1') {
|
|
170
|
-
return BigInt('0x' + getHash(hashAlgo,
|
|
181
|
+
return BigInt('0x' + getHash(hashAlgo, toBuffer(A), toBuffer(B)));
|
|
171
182
|
}
|
|
172
183
|
/**
|
|
173
184
|
* Client session secret.
|
|
@@ -183,6 +194,8 @@ function getScramble(A, B, hashAlgo = 'sha1') {
|
|
|
183
194
|
* @param A BigInt Client public key.
|
|
184
195
|
* @param B BigInt Server public key.
|
|
185
196
|
* @param a BigInt Client private key.
|
|
197
|
+
* @returns Buffer The raw session-key digest (fixed length, may start
|
|
198
|
+
* with a zero byte — significant for the proof).
|
|
186
199
|
*/
|
|
187
200
|
function clientSession(user, password, salt, A, B, a, hashAlgo = 'sha1') {
|
|
188
201
|
var u = getScramble(A, B, 'sha1');
|
|
@@ -200,7 +213,7 @@ function clientSession(user, password, salt, A, B, a, hashAlgo = 'sha1') {
|
|
|
200
213
|
var ux = (u * x) % PRIME.N;
|
|
201
214
|
var aux = (a + ux) % PRIME.N;
|
|
202
215
|
var sessionSecret = modPow(diff, aux, PRIME.N);
|
|
203
|
-
var K =
|
|
216
|
+
var K = Buffer.from(getHash('sha1', toBuffer(sessionSecret)), 'hex');
|
|
204
217
|
dump('B', B);
|
|
205
218
|
dump('u', u);
|
|
206
219
|
dump('x', x);
|
package/package.json
CHANGED
package/src/srp.ts
CHANGED
|
@@ -133,14 +133,18 @@ export function clientProof(user: string, password: string, salt: Buffer, A: big
|
|
|
133
133
|
|
|
134
134
|
n1 = modPow(n1, n2, PRIME.N);
|
|
135
135
|
n2 = toBigInt(getHash('sha1', user));
|
|
136
|
-
|
|
136
|
+
// K is hashed as the raw fixed-length digest, exactly like the server's
|
|
137
|
+
// digest.process(sessionKey) over a 20-byte UCharBuffer. Converting it
|
|
138
|
+
// through bigint dropped a leading zero byte (~0.4% of connections) and
|
|
139
|
+
// broke the proof (issue #421).
|
|
140
|
+
var M = toBigInt(getHash(hashAlgo, toBuffer(n1), toBuffer(n2), salt, toBuffer(A), toBuffer(B), K));
|
|
137
141
|
|
|
138
142
|
dump('n1-2', n1);
|
|
139
143
|
dump('n2-2', n2);
|
|
140
144
|
dump('proof:M', M);
|
|
141
145
|
|
|
142
146
|
return {
|
|
143
|
-
clientSessionKey: K,
|
|
147
|
+
clientSessionKey: toBigInt(K),
|
|
144
148
|
authData: M,
|
|
145
149
|
};
|
|
146
150
|
}
|
|
@@ -186,12 +190,19 @@ function pad(n: bigint): Buffer {
|
|
|
186
190
|
/**
|
|
187
191
|
* Scramble keys.
|
|
188
192
|
*
|
|
193
|
+
* The server hashes the minimal (stripped) magnitude bytes of A and B
|
|
194
|
+
* (RemotePassword::computeScramble → processStrippedInt in Firebird's
|
|
195
|
+
* srp.cpp, identical in 3.0 through master) — NOT the 128-byte padded
|
|
196
|
+
* form, which the engine only uses for k = H(N, pad(g)). Padding here
|
|
197
|
+
* made u diverge whenever A or B had a leading zero byte (~0.8% of
|
|
198
|
+
* connections), failing the proof (issue #421).
|
|
199
|
+
*
|
|
189
200
|
* @param A BigInt Client public key.
|
|
190
201
|
* @param B BigInt Server public key.
|
|
191
202
|
* @returns {BigInt}
|
|
192
203
|
*/
|
|
193
204
|
function getScramble(A: bigint, B: bigint, hashAlgo: string = 'sha1'): bigint {
|
|
194
|
-
return BigInt('0x' + getHash(hashAlgo,
|
|
205
|
+
return BigInt('0x' + getHash(hashAlgo, toBuffer(A), toBuffer(B)));
|
|
195
206
|
}
|
|
196
207
|
|
|
197
208
|
/**
|
|
@@ -208,8 +219,10 @@ function getScramble(A: bigint, B: bigint, hashAlgo: string = 'sha1'): bigint {
|
|
|
208
219
|
* @param A BigInt Client public key.
|
|
209
220
|
* @param B BigInt Server public key.
|
|
210
221
|
* @param a BigInt Client private key.
|
|
222
|
+
* @returns Buffer The raw session-key digest (fixed length, may start
|
|
223
|
+
* with a zero byte — significant for the proof).
|
|
211
224
|
*/
|
|
212
|
-
function clientSession(user: string, password: string, salt: Buffer, A: bigint, B: bigint, a: bigint, hashAlgo: string = 'sha1'):
|
|
225
|
+
function clientSession(user: string, password: string, salt: Buffer, A: bigint, B: bigint, a: bigint, hashAlgo: string = 'sha1'): Buffer {
|
|
213
226
|
var u = getScramble(A, B, 'sha1');
|
|
214
227
|
var x = getUserHash(user, salt, password, 'sha1');
|
|
215
228
|
var gx = modPow(PRIME.g, x, PRIME.N);
|
|
@@ -227,7 +240,7 @@ function clientSession(user: string, password: string, salt: Buffer, A: bigint,
|
|
|
227
240
|
var ux = (u * x) % PRIME.N;
|
|
228
241
|
var aux = (a + ux) % PRIME.N;
|
|
229
242
|
var sessionSecret = modPow(diff, aux, PRIME.N);
|
|
230
|
-
var K =
|
|
243
|
+
var K = Buffer.from(getHash('sha1', toBuffer(sessionSecret)), 'hex');
|
|
231
244
|
|
|
232
245
|
dump('B', B);
|
|
233
246
|
dump('u', u);
|