node-firebird 0.9.6 → 1.0.0
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/.github/workflows/node.js.yml +78 -0
- package/README.md +45 -8
- package/lib/gdscodes.d.ts +1524 -0
- package/lib/gdscodes.js +1531 -0
- package/lib/index.d.ts +218 -16
- package/lib/index.js +298 -105
- package/lib/messages.js +1 -1
- package/lib/serialize.js +13 -19
- package/lib/srp.js +281 -0
- package/package.json +2 -1
- package/.github/workflows/npmpublish.yml +0 -47
package/lib/messages.js
CHANGED
package/lib/serialize.js
CHANGED
|
@@ -111,11 +111,11 @@ BlrWriter.prototype.addBuffer = function (b) {
|
|
|
111
111
|
|
|
112
112
|
BlrWriter.prototype.addString2 = function (c, s, encoding) {
|
|
113
113
|
this.addByte(c);
|
|
114
|
-
|
|
114
|
+
|
|
115
115
|
var len = Buffer.byteLength(s, encoding);
|
|
116
116
|
if (len > MAX_STRING_SIZE* MAX_STRING_SIZE)
|
|
117
117
|
throw new Error('blr string is too big');
|
|
118
|
-
|
|
118
|
+
|
|
119
119
|
this.ensure(len + 2);
|
|
120
120
|
this.buffer.writeUInt16LE(len, this.pos);
|
|
121
121
|
this.pos += 2;
|
|
@@ -135,6 +135,7 @@ BlrWriter.prototype.addMultiblockPart = function (c, s, encoding) {
|
|
|
135
135
|
this.addByte(toWrite + 1);
|
|
136
136
|
this.addByte(step);
|
|
137
137
|
|
|
138
|
+
this.ensure(toWrite);
|
|
138
139
|
buff.copy(this.buffer, this.pos, step * 254, (step * 254) + toWrite);
|
|
139
140
|
|
|
140
141
|
step++;
|
|
@@ -468,12 +469,18 @@ BitSet.prototype.scale = function(index) {
|
|
|
468
469
|
};
|
|
469
470
|
|
|
470
471
|
BitSet.prototype.set = function(index, value) {
|
|
471
|
-
|
|
472
|
+
let pos = index >>> 3;
|
|
473
|
+
|
|
474
|
+
for (let i = this.data.length; pos >= i; pos--) {
|
|
475
|
+
this.data.push(BIT_OFF);
|
|
476
|
+
}
|
|
477
|
+
|
|
478
|
+
pos = index >>> 3;
|
|
472
479
|
|
|
473
480
|
if (value === undefined || value) {
|
|
474
|
-
this.data[
|
|
481
|
+
this.data[pos] |= (1 << (index % BUFFER_BITS));
|
|
475
482
|
} else {
|
|
476
|
-
this.data[
|
|
483
|
+
this.data[pos] &= ~(1 << (index % BUFFER_BITS));
|
|
477
484
|
}
|
|
478
485
|
};
|
|
479
486
|
|
|
@@ -488,18 +495,5 @@ BitSet.prototype.get = function(index) {
|
|
|
488
495
|
};
|
|
489
496
|
|
|
490
497
|
BitSet.prototype.toBuffer = function() {
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
for (var i = 0; i < this.data.length; i += BUFFER_BITS) {
|
|
494
|
-
tmp = this.data.slice(i, i + BUFFER_BITS);
|
|
495
|
-
int32 = 0;
|
|
496
|
-
|
|
497
|
-
for (var k = 0; k < tmp.length; k++) {
|
|
498
|
-
int32 = (int32 * 2) + tmp[k];
|
|
499
|
-
}
|
|
500
|
-
|
|
501
|
-
buf.push(int32);
|
|
502
|
-
}
|
|
503
|
-
|
|
504
|
-
return Buffer.from(buf)
|
|
498
|
+
return Buffer.from(this.data);
|
|
505
499
|
};
|
package/lib/srp.js
ADDED
|
@@ -0,0 +1,281 @@
|
|
|
1
|
+
var BigInt = require('big-integer'),
|
|
2
|
+
crypto = require('crypto');
|
|
3
|
+
|
|
4
|
+
const SRP_KEY_SIZE = 128,
|
|
5
|
+
SRP_KEY_MAX = BigInt('340282366920938463463374607431768211456'), // 1 << SRP_KEY_SIZE
|
|
6
|
+
SRP_SALT_SIZE = 32;
|
|
7
|
+
|
|
8
|
+
const DEBUG = false;
|
|
9
|
+
const DEBUG_PRIVATE_KEY = BigInt('84316857F47914F838918D5C12CE3A3E7A9B2D7C9486346809E9EEFCE8DE7CD4259D8BE4FD0BCC2D259553769E078FA61EE2977025E4DA42F7FD97914D8A33723DFAFBC00770B7DA0C2E3778A05790F0C0F33C32A19ED88A12928567749021B3FD45DCD1CE259C45325067E3DDC972F87867349BA82C303CCCAA9B207218007B', 16);
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Prime values.
|
|
13
|
+
*
|
|
14
|
+
* @type {{g: (bigInt.BigInteger), k: (bigInt.BigInteger), N: (bigInt.BigInteger)}}
|
|
15
|
+
*/
|
|
16
|
+
const PRIME = {
|
|
17
|
+
N: BigInt('E67D2E994B2F900C3F41F08F5BB2627ED0D49EE1FE767A52EFCD565CD6E768812C3E1E9CE8F0A8BEA6CB13CD29DDEBF7A96D4A93B55D488DF099A15C89DCB0640738EB2CBDD9A8F7BAB561AB1B0DC1C6CDABF303264A08D1BCA932D1F1EE428B619D970F342ABA9A65793B8B2F041AE5364350C16F735F56ECBCA87BD57B29E7', 16),
|
|
18
|
+
g: BigInt(2),
|
|
19
|
+
k: BigInt('1277432915985975349439481660349303019122249719989')
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Generate a client key pair.
|
|
24
|
+
*
|
|
25
|
+
* @param a bigInt.BigInteger Client private key.
|
|
26
|
+
* @returns {{private: bigInt.BigInteger, public: bigInt.BigInteger}}
|
|
27
|
+
*/
|
|
28
|
+
exports.clientSeed = function(a = toBigInt(crypto.randomBytes(SRP_KEY_SIZE))) {
|
|
29
|
+
var A = PRIME.g.modPow(a, PRIME.N);
|
|
30
|
+
|
|
31
|
+
dump('a', a);
|
|
32
|
+
dump('A', A);
|
|
33
|
+
|
|
34
|
+
return {
|
|
35
|
+
public: A,
|
|
36
|
+
private: a
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* Generate a server key pair.
|
|
42
|
+
*
|
|
43
|
+
* @param user string Connection username.
|
|
44
|
+
* @param password string Connection password.
|
|
45
|
+
* @param salt bigInt.BigInteger Connection salt.
|
|
46
|
+
* @param b bigInt.BigInteger Server private key.
|
|
47
|
+
* @returns {{private: bigInt.BigInteger, public: bigInt.BigInteger}}
|
|
48
|
+
*/
|
|
49
|
+
exports.serverSeed = function(user, password, salt, b = toBigInt(crypto.randomBytes(SRP_KEY_SIZE))) {
|
|
50
|
+
var v = getVerifier(user, password, salt);
|
|
51
|
+
var gb = PRIME.g.modPow(b, PRIME.N);
|
|
52
|
+
var kv = PRIME.k.multiply(v).mod(PRIME.N);
|
|
53
|
+
var B = kv.add(gb).mod(PRIME.N);
|
|
54
|
+
|
|
55
|
+
dump('v', v);
|
|
56
|
+
dump('b', b);
|
|
57
|
+
dump('gb', b);
|
|
58
|
+
dump('kv', v);
|
|
59
|
+
dump('B', B);
|
|
60
|
+
|
|
61
|
+
return {
|
|
62
|
+
public: B,
|
|
63
|
+
private: b
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* Server session secret.
|
|
69
|
+
*
|
|
70
|
+
* @param user string Connection username.
|
|
71
|
+
* @param password string Connection password.
|
|
72
|
+
* @param salt bigInt.BigInteger Connection salt.
|
|
73
|
+
* @param A bigInt.BigInteger Client public key.
|
|
74
|
+
* @param B bigInt.BigInteger Server public key.
|
|
75
|
+
* @param b bigInt.BigInteger Server private key.
|
|
76
|
+
* @returns {bigInt.BigInteger}
|
|
77
|
+
*/
|
|
78
|
+
exports.serverSession = function(user, password, salt, A, B, b) {
|
|
79
|
+
var u = getScramble(A, B);
|
|
80
|
+
var v = getVerifier(user, password, salt);
|
|
81
|
+
var vu = v.modPow(u, PRIME.N);
|
|
82
|
+
var Avu = A.multiply(vu).mod(PRIME.N);
|
|
83
|
+
var sessionSecret = Avu.modPow(b, PRIME.N);
|
|
84
|
+
var K = getHash('sha1', toBuffer(sessionSecret));
|
|
85
|
+
|
|
86
|
+
dump('server sessionSecret', sessionSecret);
|
|
87
|
+
dump('server K', K);
|
|
88
|
+
|
|
89
|
+
return BigInt(K, 16);
|
|
90
|
+
};
|
|
91
|
+
|
|
92
|
+
/**
|
|
93
|
+
* M = H(H(N) xor H(g), H(I), s, A, B, K)
|
|
94
|
+
*/
|
|
95
|
+
exports.clientProof = function(user, password, salt, A, B, a, hashAlgo) {
|
|
96
|
+
var K = clientSession(user, password, salt, A, B, a);
|
|
97
|
+
var n1, n2;
|
|
98
|
+
|
|
99
|
+
n1 = toBigInt(getHash('sha1', toBuffer(PRIME.N)));
|
|
100
|
+
n2 = toBigInt(getHash('sha1', toBuffer(PRIME.g)));
|
|
101
|
+
|
|
102
|
+
dump('n1', n1);
|
|
103
|
+
dump('n2', n2);
|
|
104
|
+
|
|
105
|
+
n1 = n1.modPow(n2, PRIME.N);
|
|
106
|
+
n2 = toBigInt(getHash('sha1', user));
|
|
107
|
+
var M = toBigInt(getHash(hashAlgo, toBuffer(n1), toBuffer(n2), salt, toBuffer(A), toBuffer(B), toBuffer(K)));
|
|
108
|
+
|
|
109
|
+
dump('n1-2', n1);
|
|
110
|
+
dump('n2-2', n2);
|
|
111
|
+
dump('proof:M', M);
|
|
112
|
+
|
|
113
|
+
return {
|
|
114
|
+
clientSessionKey: K,
|
|
115
|
+
authData: M,
|
|
116
|
+
};
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
/**
|
|
120
|
+
* Pad hex string.
|
|
121
|
+
*/
|
|
122
|
+
function hexPad(hex) {
|
|
123
|
+
if (hex.length % 2 !== 0) {
|
|
124
|
+
hex = '0' + hex;
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
return hex;
|
|
128
|
+
}
|
|
129
|
+
exports.hexPad = hexPad;
|
|
130
|
+
|
|
131
|
+
/**
|
|
132
|
+
* Pad key with SRP_KEY_SIZE.
|
|
133
|
+
*
|
|
134
|
+
* @param n BigInt Key to pad.
|
|
135
|
+
* @returns Buffer
|
|
136
|
+
*/
|
|
137
|
+
function pad(n) {
|
|
138
|
+
var buff = Buffer.from(hexPad(n.toString(16)), 'hex');
|
|
139
|
+
|
|
140
|
+
if (buff.length > SRP_KEY_SIZE) {
|
|
141
|
+
buff = buff.slice(buff.length - SRP_KEY_SIZE, buff.length);
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
return buff;
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
/**
|
|
148
|
+
* Scramble keys.
|
|
149
|
+
*
|
|
150
|
+
* @param A bigInt.BigInteger Client public key.
|
|
151
|
+
* @param B bigInt.BigInteger Server public key.
|
|
152
|
+
* @returns {bigInt.BigInteger}
|
|
153
|
+
*/
|
|
154
|
+
function getScramble(A, B) {
|
|
155
|
+
return BigInt(getHash('sha1', pad(A), pad(B)), 16);
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
/**
|
|
159
|
+
* Client session secret.
|
|
160
|
+
*
|
|
161
|
+
* Both: u = H(A, B)
|
|
162
|
+
* User: x = H(s, p) (user enters password)
|
|
163
|
+
* User: S = (B - kg^x) ^ (a + ux) (computes session key)
|
|
164
|
+
* User: K = H(S)
|
|
165
|
+
*
|
|
166
|
+
* @param user string Connection username.
|
|
167
|
+
* @param password string Connection password.
|
|
168
|
+
* @param salt bigInt.BigInteger Connection salt.
|
|
169
|
+
* @param A bigInt.BigInteger Client public key.
|
|
170
|
+
* @param B bigInt.BigInteger Server public key.
|
|
171
|
+
* @param a bigInt.BigInteger Client private key.
|
|
172
|
+
*/
|
|
173
|
+
function clientSession(user, password, salt, A, B, a) {
|
|
174
|
+
var u = getScramble(A, B);
|
|
175
|
+
var x = getUserHash(user, salt, password);
|
|
176
|
+
var gx = PRIME.g.modPow(x, PRIME.N);
|
|
177
|
+
var kgx = PRIME.k.multiply(gx).mod(PRIME.N);
|
|
178
|
+
var diff = B.subtract(kgx).mod(PRIME.N);
|
|
179
|
+
|
|
180
|
+
if (diff.lesser(0)) {
|
|
181
|
+
diff = diff.add(PRIME.N);
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
var ux = u.multiply(x).mod(PRIME.N);
|
|
185
|
+
var aux = a.add(ux).mod(PRIME.N);
|
|
186
|
+
var sessionSecret = diff.modPow(aux, PRIME.N);
|
|
187
|
+
var K = toBigInt(getHash('sha1', toBuffer(sessionSecret)));
|
|
188
|
+
|
|
189
|
+
dump('B', B);
|
|
190
|
+
dump('u', u);
|
|
191
|
+
dump('x', x);
|
|
192
|
+
dump('gx', gx);
|
|
193
|
+
dump('kgx', kgx);
|
|
194
|
+
dump('diff', diff);
|
|
195
|
+
dump('ux', ux);
|
|
196
|
+
dump('aux', aux);
|
|
197
|
+
dump('sessionSecret', sessionSecret);
|
|
198
|
+
dump('sessionKey(K)', K);
|
|
199
|
+
|
|
200
|
+
return K;
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
/**
|
|
204
|
+
* Compute user hash.
|
|
205
|
+
*
|
|
206
|
+
* @param user string Connection username.
|
|
207
|
+
* @param salt bigInt.BigInteger Connection salt.
|
|
208
|
+
* @param password string Connection password.
|
|
209
|
+
* @returns {bigInt.BigInteger}
|
|
210
|
+
*/
|
|
211
|
+
function getUserHash(user, salt, password) {
|
|
212
|
+
var hash1 = getHash('sha1', user.toUpperCase(), ':', password);
|
|
213
|
+
var hash2 = getHash('sha1', salt, toBuffer(hash1));
|
|
214
|
+
|
|
215
|
+
return toBigInt(hash2);
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
/**
|
|
219
|
+
* Verifier of user hash.
|
|
220
|
+
*
|
|
221
|
+
* @param user string Connection username.
|
|
222
|
+
* @param password string Connection password.
|
|
223
|
+
* @param salt bigInt.BigInteger Connection salt.
|
|
224
|
+
* @returns {bigInt.BigInteger}
|
|
225
|
+
*/
|
|
226
|
+
function getVerifier(user, password, salt) {
|
|
227
|
+
return PRIME.g.modPow(getUserHash(user, salt, password), PRIME.N);
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
/**
|
|
231
|
+
* Hash data and return hex string.
|
|
232
|
+
*
|
|
233
|
+
* @param algo string Algorithm to use.
|
|
234
|
+
* @param data any[] Data to hash.
|
|
235
|
+
* @returns {string}
|
|
236
|
+
*/
|
|
237
|
+
function getHash(algo, ...data) {
|
|
238
|
+
var hash = crypto.createHash(algo);
|
|
239
|
+
|
|
240
|
+
for (var d of data) {
|
|
241
|
+
hash.update(d);
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
return hash.digest('hex');
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
/**
|
|
248
|
+
* Convert BigInt to buffer.
|
|
249
|
+
*
|
|
250
|
+
* @param bigInt
|
|
251
|
+
* @returns {*}
|
|
252
|
+
*/
|
|
253
|
+
function toBuffer(bigInt) {
|
|
254
|
+
return Buffer.from(BigInt.isInstance(bigInt) ? hexPad(bigInt.toString(16)) : bigInt, 'hex');
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
/**
|
|
258
|
+
* Convert hex buffer or string to BigInt.
|
|
259
|
+
*
|
|
260
|
+
* @param hex
|
|
261
|
+
* @returns {bigInt.BigInteger}
|
|
262
|
+
*/
|
|
263
|
+
function toBigInt(hex) {
|
|
264
|
+
return BigInt(Buffer.isBuffer(hex) ? hex.toString('hex') : hex, 16);
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
/**
|
|
268
|
+
* Dump value in debug mode.
|
|
269
|
+
*
|
|
270
|
+
* @param key
|
|
271
|
+
* @param value
|
|
272
|
+
*/
|
|
273
|
+
function dump(key, value) {
|
|
274
|
+
if (DEBUG) {
|
|
275
|
+
if (BigInt.isInstance(value)) {
|
|
276
|
+
value = value.toString(16);
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
console.log(key + '=' + value);
|
|
280
|
+
}
|
|
281
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "node-firebird",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "1.0.0",
|
|
4
4
|
"description": "Pure JavaScript and Asynchronous Firebird client for Node.js.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"firebird",
|
|
@@ -33,6 +33,7 @@
|
|
|
33
33
|
"test": "mocha"
|
|
34
34
|
},
|
|
35
35
|
"dependencies": {
|
|
36
|
+
"big-integer": "^1.6.48",
|
|
36
37
|
"long": "^4.0.0"
|
|
37
38
|
},
|
|
38
39
|
"devDependencies": {
|
|
@@ -1,47 +0,0 @@
|
|
|
1
|
-
# This workflow will run tests using node and then publish a package to GitHub Packages when a release is created
|
|
2
|
-
# For more information see: https://help.github.com/actions/language-and-framework-guides/publishing-nodejs-packages
|
|
3
|
-
|
|
4
|
-
name: Node.js Package
|
|
5
|
-
|
|
6
|
-
on:
|
|
7
|
-
release:
|
|
8
|
-
types: [created]
|
|
9
|
-
|
|
10
|
-
jobs:
|
|
11
|
-
build:
|
|
12
|
-
runs-on: ubuntu-latest
|
|
13
|
-
steps:
|
|
14
|
-
- uses: actions/checkout@v2
|
|
15
|
-
- uses: actions/setup-node@v1
|
|
16
|
-
with:
|
|
17
|
-
node-version: 12
|
|
18
|
-
- run: npm ci
|
|
19
|
-
- run: npm test
|
|
20
|
-
|
|
21
|
-
publish-npm:
|
|
22
|
-
needs: build
|
|
23
|
-
runs-on: ubuntu-latest
|
|
24
|
-
steps:
|
|
25
|
-
- uses: actions/checkout@v2
|
|
26
|
-
- uses: actions/setup-node@v1
|
|
27
|
-
with:
|
|
28
|
-
node-version: 12
|
|
29
|
-
registry-url: https://registry.npmjs.org/
|
|
30
|
-
- run: npm ci
|
|
31
|
-
- run: npm publish
|
|
32
|
-
env:
|
|
33
|
-
NODE_AUTH_TOKEN: ${{secrets.npm_token}}
|
|
34
|
-
|
|
35
|
-
publish-gpr:
|
|
36
|
-
needs: build
|
|
37
|
-
runs-on: ubuntu-latest
|
|
38
|
-
steps:
|
|
39
|
-
- uses: actions/checkout@v2
|
|
40
|
-
- uses: actions/setup-node@v1
|
|
41
|
-
with:
|
|
42
|
-
node-version: 12
|
|
43
|
-
registry-url: https://npm.pkg.github.com/
|
|
44
|
-
- run: npm ci
|
|
45
|
-
- run: npm publish
|
|
46
|
-
env:
|
|
47
|
-
NODE_AUTH_TOKEN: ${{secrets.GITHUB_TOKEN}}
|