@gjsify/crypto 0.3.16 → 0.3.18

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/esm/scrypt.js CHANGED
@@ -1,135 +1 @@
1
- import { pbkdf2Sync } from "./pbkdf2.js";
2
- import { Buffer } from "node:buffer";
3
-
4
- //#region src/scrypt.ts
5
- function R(a, b) {
6
- return (a << b | a >>> 32 - b) >>> 0;
7
- }
8
- function salsa20_8(B) {
9
- const x = new Uint32Array(16);
10
- for (let i = 0; i < 16; i++) x[i] = B[i];
11
- for (let i = 0; i < 4; i++) {
12
- x[4] ^= R(x[0] + x[12], 7);
13
- x[8] ^= R(x[4] + x[0], 9);
14
- x[12] ^= R(x[8] + x[4], 13);
15
- x[0] ^= R(x[12] + x[8], 18);
16
- x[9] ^= R(x[5] + x[1], 7);
17
- x[13] ^= R(x[9] + x[5], 9);
18
- x[1] ^= R(x[13] + x[9], 13);
19
- x[5] ^= R(x[1] + x[13], 18);
20
- x[14] ^= R(x[10] + x[6], 7);
21
- x[2] ^= R(x[14] + x[10], 9);
22
- x[6] ^= R(x[2] + x[14], 13);
23
- x[10] ^= R(x[6] + x[2], 18);
24
- x[3] ^= R(x[15] + x[11], 7);
25
- x[7] ^= R(x[3] + x[15], 9);
26
- x[11] ^= R(x[7] + x[3], 13);
27
- x[15] ^= R(x[11] + x[7], 18);
28
- x[1] ^= R(x[0] + x[3], 7);
29
- x[2] ^= R(x[1] + x[0], 9);
30
- x[3] ^= R(x[2] + x[1], 13);
31
- x[0] ^= R(x[3] + x[2], 18);
32
- x[6] ^= R(x[5] + x[4], 7);
33
- x[7] ^= R(x[6] + x[5], 9);
34
- x[4] ^= R(x[7] + x[6], 13);
35
- x[5] ^= R(x[4] + x[7], 18);
36
- x[11] ^= R(x[10] + x[9], 7);
37
- x[8] ^= R(x[11] + x[10], 9);
38
- x[9] ^= R(x[8] + x[11], 13);
39
- x[10] ^= R(x[9] + x[8], 18);
40
- x[12] ^= R(x[15] + x[14], 7);
41
- x[13] ^= R(x[12] + x[15], 9);
42
- x[14] ^= R(x[13] + x[12], 13);
43
- x[15] ^= R(x[14] + x[13], 18);
44
- }
45
- for (let i = 0; i < 16; i++) B[i] = B[i] + x[i] >>> 0;
46
- }
47
- function blockMix(B, r) {
48
- const blockWords = 2 * r * 16;
49
- const X = new Uint32Array(16);
50
- for (let i = 0; i < 16; i++) X[i] = B[blockWords - 16 + i];
51
- const Y = new Uint32Array(blockWords);
52
- for (let i = 0; i < 2 * r; i++) {
53
- for (let j = 0; j < 16; j++) X[j] ^= B[i * 16 + j];
54
- salsa20_8(X);
55
- for (let j = 0; j < 16; j++) Y[i * 16 + j] = X[j];
56
- }
57
- for (let i = 0; i < r; i++) {
58
- for (let j = 0; j < 16; j++) B[i * 16 + j] = Y[2 * i * 16 + j];
59
- }
60
- for (let i = 0; i < r; i++) {
61
- for (let j = 0; j < 16; j++) B[(r + i) * 16 + j] = Y[(2 * i + 1) * 16 + j];
62
- }
63
- }
64
- function roMix(B, N, r) {
65
- const blockWords = 2 * r * 16;
66
- const V = new Array(N);
67
- for (let i = 0; i < N; i++) {
68
- V[i] = new Uint32Array(B);
69
- blockMix(B, r);
70
- }
71
- for (let i = 0; i < N; i++) {
72
- const j = B[blockWords - 16] & N - 1;
73
- for (let k = 0; k < blockWords; k++) B[k] ^= V[j][k];
74
- blockMix(B, r);
75
- }
76
- }
77
- function bytesToWords(bytes) {
78
- const words = new Uint32Array(bytes.length / 4);
79
- for (let i = 0; i < words.length; i++) {
80
- words[i] = bytes[i * 4] | bytes[i * 4 + 1] << 8 | bytes[i * 4 + 2] << 16 | bytes[i * 4 + 3] << 24;
81
- }
82
- return words;
83
- }
84
- function wordsToBytes(words) {
85
- const bytes = new Uint8Array(words.length * 4);
86
- for (let i = 0; i < words.length; i++) {
87
- bytes[i * 4] = words[i] & 255;
88
- bytes[i * 4 + 1] = words[i] >> 8 & 255;
89
- bytes[i * 4 + 2] = words[i] >> 16 & 255;
90
- bytes[i * 4 + 3] = words[i] >> 24 & 255;
91
- }
92
- return bytes;
93
- }
94
- function scryptCore(password, salt, N, r, p, keyLen) {
95
- const blockSize = 128 * r;
96
- const B = pbkdf2Sync(password, salt, 1, p * blockSize, "sha256");
97
- for (let i = 0; i < p; i++) {
98
- const blockBytes = new Uint8Array(B.buffer, B.byteOffset + i * blockSize, blockSize);
99
- const blockWords = bytesToWords(blockBytes);
100
- roMix(blockWords, N, r);
101
- const result = wordsToBytes(blockWords);
102
- blockBytes.set(result);
103
- }
104
- return pbkdf2Sync(password, B, 1, keyLen, "sha256");
105
- }
106
- function scryptSync(password, salt, keylen, options) {
107
- const pwd = typeof password === "string" ? Buffer.from(password) : Buffer.from(password);
108
- const slt = typeof salt === "string" ? Buffer.from(salt) : Buffer.from(salt);
109
- const N = options?.N ?? 16384;
110
- const r = options?.r ?? 8;
111
- const p = options?.p ?? 1;
112
- if (N <= 0 || (N & N - 1) !== 0) {
113
- throw new Error("N must be a positive power of 2");
114
- }
115
- return scryptCore(pwd, slt, N, r, p, keylen);
116
- }
117
- function scrypt(password, salt, keylen, optionsOrCallback, callback) {
118
- let options = {};
119
- let cb;
120
- if (typeof optionsOrCallback === "function") {
121
- cb = optionsOrCallback;
122
- } else {
123
- options = optionsOrCallback;
124
- cb = callback;
125
- }
126
- try {
127
- const result = scryptSync(password, salt, keylen, options);
128
- setTimeout(() => cb(null, result), 0);
129
- } catch (err) {
130
- setTimeout(() => cb(err instanceof Error ? err : new Error(String(err)), Buffer.alloc(0)), 0);
131
- }
132
- }
133
-
134
- //#endregion
135
- export { scrypt, scryptSync };
1
+ import{pbkdf2Sync as e}from"./pbkdf2.js";import{Buffer as t}from"node:buffer";function n(e,t){return(e<<t|e>>>32-t)>>>0}function r(e){let t=new Uint32Array(16);for(let n=0;n<16;n++)t[n]=e[n];for(let e=0;e<4;e++)t[4]^=n(t[0]+t[12],7),t[8]^=n(t[4]+t[0],9),t[12]^=n(t[8]+t[4],13),t[0]^=n(t[12]+t[8],18),t[9]^=n(t[5]+t[1],7),t[13]^=n(t[9]+t[5],9),t[1]^=n(t[13]+t[9],13),t[5]^=n(t[1]+t[13],18),t[14]^=n(t[10]+t[6],7),t[2]^=n(t[14]+t[10],9),t[6]^=n(t[2]+t[14],13),t[10]^=n(t[6]+t[2],18),t[3]^=n(t[15]+t[11],7),t[7]^=n(t[3]+t[15],9),t[11]^=n(t[7]+t[3],13),t[15]^=n(t[11]+t[7],18),t[1]^=n(t[0]+t[3],7),t[2]^=n(t[1]+t[0],9),t[3]^=n(t[2]+t[1],13),t[0]^=n(t[3]+t[2],18),t[6]^=n(t[5]+t[4],7),t[7]^=n(t[6]+t[5],9),t[4]^=n(t[7]+t[6],13),t[5]^=n(t[4]+t[7],18),t[11]^=n(t[10]+t[9],7),t[8]^=n(t[11]+t[10],9),t[9]^=n(t[8]+t[11],13),t[10]^=n(t[9]+t[8],18),t[12]^=n(t[15]+t[14],7),t[13]^=n(t[12]+t[15],9),t[14]^=n(t[13]+t[12],13),t[15]^=n(t[14]+t[13],18);for(let n=0;n<16;n++)e[n]=e[n]+t[n]>>>0}function i(e,t){let n=2*t*16,i=new Uint32Array(16);for(let t=0;t<16;t++)i[t]=e[n-16+t];let a=new Uint32Array(n);for(let n=0;n<2*t;n++){for(let t=0;t<16;t++)i[t]^=e[n*16+t];r(i);for(let e=0;e<16;e++)a[n*16+e]=i[e]}for(let n=0;n<t;n++)for(let t=0;t<16;t++)e[n*16+t]=a[2*n*16+t];for(let n=0;n<t;n++)for(let r=0;r<16;r++)e[(t+n)*16+r]=a[(2*n+1)*16+r]}function a(e,t,n){let r=2*n*16,a=Array(t);for(let r=0;r<t;r++)a[r]=new Uint32Array(e),i(e,n);for(let o=0;o<t;o++){let o=e[r-16]&t-1;for(let t=0;t<r;t++)e[t]^=a[o][t];i(e,n)}}function o(e){let t=new Uint32Array(e.length/4);for(let n=0;n<t.length;n++)t[n]=e[n*4]|e[n*4+1]<<8|e[n*4+2]<<16|e[n*4+3]<<24;return t}function s(e){let t=new Uint8Array(e.length*4);for(let n=0;n<e.length;n++)t[n*4]=e[n]&255,t[n*4+1]=e[n]>>8&255,t[n*4+2]=e[n]>>16&255,t[n*4+3]=e[n]>>24&255;return t}function c(t,n,r,i,c,l){let u=128*i,d=e(t,n,1,c*u,`sha256`);for(let e=0;e<c;e++){let t=new Uint8Array(d.buffer,d.byteOffset+e*u,u),n=o(t);a(n,r,i);let c=s(n);t.set(c)}return e(t,d,1,l,`sha256`)}function l(e,n,r,i){let a=t.from(e),o=t.from(n),s=i?.N??16384,l=i?.r??8,u=i?.p??1;if(s<=0||s&s-1)throw Error(`N must be a positive power of 2`);return c(a,o,s,l,u,r)}function u(e,n,r,i,a){let o={},s;typeof i==`function`?s=i:(o=i,s=a);try{let t=l(e,n,r,o);setTimeout(()=>s(null,t),0)}catch(e){setTimeout(()=>s(e instanceof Error?e:Error(String(e)),t.alloc(0)),0)}}export{u as scrypt,l as scryptSync};
package/lib/esm/sign.js CHANGED
@@ -1,278 +1 @@
1
- import { parsePemKey, rsaKeySize } from "./asn1.js";
2
- import { bigIntToBytes, bytesToBigInt, modPow } from "./bigint-math.js";
3
- import { Hash } from "./hash.js";
4
- import { Buffer } from "node:buffer";
5
-
6
- //#region src/sign.ts
7
- /**
8
- * DigestInfo DER prefix bytes for each supported hash algorithm.
9
- * These encode: SEQUENCE { SEQUENCE { OID hashAlg, NULL }, OCTET STRING hashValue }
10
- * excluding the actual hash value at the end.
11
- */
12
- const DIGEST_INFO_PREFIX = {
13
- sha1: new Uint8Array([
14
- 48,
15
- 33,
16
- 48,
17
- 9,
18
- 6,
19
- 5,
20
- 43,
21
- 14,
22
- 3,
23
- 2,
24
- 26,
25
- 5,
26
- 0,
27
- 4,
28
- 20
29
- ]),
30
- sha256: new Uint8Array([
31
- 48,
32
- 49,
33
- 48,
34
- 13,
35
- 6,
36
- 9,
37
- 96,
38
- 134,
39
- 72,
40
- 1,
41
- 101,
42
- 3,
43
- 4,
44
- 2,
45
- 1,
46
- 5,
47
- 0,
48
- 4,
49
- 32
50
- ]),
51
- sha512: new Uint8Array([
52
- 48,
53
- 81,
54
- 48,
55
- 13,
56
- 6,
57
- 9,
58
- 96,
59
- 134,
60
- 72,
61
- 1,
62
- 101,
63
- 3,
64
- 4,
65
- 2,
66
- 3,
67
- 5,
68
- 0,
69
- 4,
70
- 64
71
- ])
72
- };
73
- /**
74
- * Normalize algorithm strings like "RSA-SHA256", "SHA256", "sha256" to
75
- * the canonical hash name used internally (e.g. "sha256").
76
- */
77
- function normalizeSignAlgorithm(algorithm) {
78
- let alg = algorithm.toLowerCase().replace(/-/g, "");
79
- if (alg.startsWith("rsa")) {
80
- alg = alg.slice(3);
81
- }
82
- if (!DIGEST_INFO_PREFIX[alg]) {
83
- throw new Error(`Unsupported algorithm: ${algorithm}. Supported: RSA-SHA1, RSA-SHA256, RSA-SHA512`);
84
- }
85
- return alg;
86
- }
87
- function extractPem(key) {
88
- if (typeof key === "string") {
89
- return key;
90
- }
91
- if (Buffer.isBuffer(key) || key instanceof Uint8Array) {
92
- return Buffer.from(key).toString("utf8");
93
- }
94
- if (key && typeof key === "object" && "key" in key) {
95
- const k = key.key;
96
- if (typeof k === "string") return k;
97
- if (Buffer.isBuffer(k) || k instanceof Uint8Array) return Buffer.from(k).toString("utf8");
98
- }
99
- throw new TypeError("Invalid key argument");
100
- }
101
- /**
102
- * The Sign class generates RSA PKCS#1 v1.5 signatures.
103
- *
104
- * Usage:
105
- * const sign = createSign('RSA-SHA256');
106
- * sign.update('data');
107
- * const signature = sign.sign(privateKey);
108
- */
109
- var Sign = class {
110
- _algorithm;
111
- _hash;
112
- _finalized = false;
113
- constructor(algorithm) {
114
- this._algorithm = normalizeSignAlgorithm(algorithm);
115
- this._hash = new Hash(this._algorithm);
116
- }
117
- /**
118
- * Update the Sign object with the given data.
119
- */
120
- update(data, inputEncoding) {
121
- if (this._finalized) {
122
- throw new Error("Sign was already finalized");
123
- }
124
- this._hash.update(data, inputEncoding);
125
- return this;
126
- }
127
- /**
128
- * Compute the signature using the private key.
129
- * Returns the signature as a Buffer (or string if outputEncoding is given).
130
- */
131
- sign(privateKey, outputEncoding) {
132
- if (this._finalized) {
133
- throw new Error("Sign was already finalized");
134
- }
135
- this._finalized = true;
136
- const digest = this._hash.digest();
137
- const pem = extractPem(privateKey);
138
- const parsed = parsePemKey(pem);
139
- if (parsed.type !== "rsa-private") {
140
- throw new Error("privateKey must be an RSA private key");
141
- }
142
- const { n, e, d } = parsed.components;
143
- const keyLen = rsaKeySize(n);
144
- const prefix = DIGEST_INFO_PREFIX[this._algorithm];
145
- const digestInfo = new Uint8Array(prefix.length + digest.length);
146
- digestInfo.set(prefix, 0);
147
- digestInfo.set(digest, prefix.length);
148
- const padLen = keyLen - digestInfo.length - 3;
149
- if (padLen < 8) {
150
- throw new Error("Key is too short for the specified hash algorithm");
151
- }
152
- const em = new Uint8Array(keyLen);
153
- em[0] = 0;
154
- em[1] = 1;
155
- for (let i = 2; i < 2 + padLen; i++) {
156
- em[i] = 255;
157
- }
158
- em[2 + padLen] = 0;
159
- em.set(digestInfo, 3 + padLen);
160
- const m = bytesToBigInt(em);
161
- const s = modPow(m, d, n);
162
- const sigBytes = bigIntToBytes(s, keyLen);
163
- const sigBuf = Buffer.from(sigBytes);
164
- if (outputEncoding) {
165
- return sigBuf.toString(outputEncoding);
166
- }
167
- return sigBuf;
168
- }
169
- };
170
- /**
171
- * The Verify class verifies RSA PKCS#1 v1.5 signatures.
172
- *
173
- * Usage:
174
- * const verify = createVerify('RSA-SHA256');
175
- * verify.update('data');
176
- * const ok = verify.verify(publicKey, signature);
177
- */
178
- var Verify = class {
179
- _algorithm;
180
- _hash;
181
- _finalized = false;
182
- constructor(algorithm) {
183
- this._algorithm = normalizeSignAlgorithm(algorithm);
184
- this._hash = new Hash(this._algorithm);
185
- }
186
- /**
187
- * Update the Verify object with the given data.
188
- */
189
- update(data, inputEncoding) {
190
- if (this._finalized) {
191
- throw new Error("Verify was already finalized");
192
- }
193
- this._hash.update(data, inputEncoding);
194
- return this;
195
- }
196
- /**
197
- * Verify the signature against the public key.
198
- * Returns true if the signature is valid, false otherwise.
199
- */
200
- verify(publicKey, signature, signatureEncoding) {
201
- if (this._finalized) {
202
- throw new Error("Verify was already finalized");
203
- }
204
- this._finalized = true;
205
- const digest = this._hash.digest();
206
- const pem = extractPem(publicKey);
207
- const parsed = parsePemKey(pem);
208
- let n;
209
- let e;
210
- if (parsed.type === "rsa-public") {
211
- n = parsed.components.n;
212
- e = parsed.components.e;
213
- } else if (parsed.type === "rsa-private") {
214
- n = parsed.components.n;
215
- e = parsed.components.e;
216
- } else {
217
- throw new Error("publicKey must be an RSA public or private key");
218
- }
219
- const keyLen = rsaKeySize(n);
220
- let sigBytes;
221
- if (typeof signature === "string") {
222
- sigBytes = Buffer.from(signature, signatureEncoding || "base64");
223
- } else {
224
- sigBytes = signature instanceof Uint8Array ? signature : Buffer.from(signature);
225
- }
226
- if (sigBytes.length !== keyLen) {
227
- return false;
228
- }
229
- const s = bytesToBigInt(sigBytes);
230
- if (s >= n) {
231
- return false;
232
- }
233
- const m = modPow(s, e, n);
234
- const em = bigIntToBytes(m, keyLen);
235
- if (em[0] !== 0 || em[1] !== 1) {
236
- return false;
237
- }
238
- let sepIdx = 2;
239
- while (sepIdx < em.length && em[sepIdx] === 255) {
240
- sepIdx++;
241
- }
242
- if (sepIdx >= em.length || em[sepIdx] !== 0) {
243
- return false;
244
- }
245
- if (sepIdx - 2 < 8) {
246
- return false;
247
- }
248
- sepIdx++;
249
- const recoveredDigestInfo = em.slice(sepIdx);
250
- const prefix = DIGEST_INFO_PREFIX[this._algorithm];
251
- const expectedDigestInfo = new Uint8Array(prefix.length + digest.length);
252
- expectedDigestInfo.set(prefix, 0);
253
- expectedDigestInfo.set(digest, prefix.length);
254
- if (recoveredDigestInfo.length !== expectedDigestInfo.length) {
255
- return false;
256
- }
257
- let diff = 0;
258
- for (let i = 0; i < recoveredDigestInfo.length; i++) {
259
- diff |= recoveredDigestInfo[i] ^ expectedDigestInfo[i];
260
- }
261
- return diff === 0;
262
- }
263
- };
264
- /**
265
- * Create and return a Sign object for the given algorithm.
266
- */
267
- function createSign(algorithm) {
268
- return new Sign(algorithm);
269
- }
270
- /**
271
- * Create and return a Verify object for the given algorithm.
272
- */
273
- function createVerify(algorithm) {
274
- return new Verify(algorithm);
275
- }
276
-
277
- //#endregion
278
- export { Sign, Verify, createSign, createVerify };
1
+ import{parsePemKey as e,rsaKeySize as t}from"./asn1.js";import{bigIntToBytes as n,bytesToBigInt as r,modPow as i}from"./bigint-math.js";import{Hash as a}from"./hash.js";import{Buffer as o}from"node:buffer";const s={sha1:new Uint8Array([48,33,48,9,6,5,43,14,3,2,26,5,0,4,20]),sha256:new Uint8Array([48,49,48,13,6,9,96,134,72,1,101,3,4,2,1,5,0,4,32]),sha512:new Uint8Array([48,81,48,13,6,9,96,134,72,1,101,3,4,2,3,5,0,4,64])};function c(e){let t=e.toLowerCase().replace(/-/g,``);if(t.startsWith(`rsa`)&&(t=t.slice(3)),!s[t])throw Error(`Unsupported algorithm: ${e}. Supported: RSA-SHA1, RSA-SHA256, RSA-SHA512`);return t}function l(e){if(typeof e==`string`)return e;if(o.isBuffer(e)||e instanceof Uint8Array)return o.from(e).toString(`utf8`);if(e&&typeof e==`object`&&`key`in e){let t=e.key;if(typeof t==`string`)return t;if(o.isBuffer(t)||t instanceof Uint8Array)return o.from(t).toString(`utf8`)}throw TypeError(`Invalid key argument`)}var u=class{_algorithm;_hash;_finalized=!1;constructor(e){this._algorithm=c(e),this._hash=new a(this._algorithm)}update(e,t){if(this._finalized)throw Error(`Sign was already finalized`);return this._hash.update(e,t),this}sign(a,c){if(this._finalized)throw Error(`Sign was already finalized`);this._finalized=!0;let u=this._hash.digest(),d=e(l(a));if(d.type!==`rsa-private`)throw Error(`privateKey must be an RSA private key`);let{n:f,e:p,d:m}=d.components,h=t(f),g=s[this._algorithm],_=new Uint8Array(g.length+u.length);_.set(g,0),_.set(u,g.length);let v=h-_.length-3;if(v<8)throw Error(`Key is too short for the specified hash algorithm`);let y=new Uint8Array(h);y[0]=0,y[1]=1;for(let e=2;e<2+v;e++)y[e]=255;y[2+v]=0,y.set(_,3+v);let b=n(i(r(y),m,f),h),x=o.from(b);return c?x.toString(c):x}},d=class{_algorithm;_hash;_finalized=!1;constructor(e){this._algorithm=c(e),this._hash=new a(this._algorithm)}update(e,t){if(this._finalized)throw Error(`Verify was already finalized`);return this._hash.update(e,t),this}verify(a,c,u){if(this._finalized)throw Error(`Verify was already finalized`);this._finalized=!0;let d=this._hash.digest(),f=e(l(a)),p,m;if(f.type===`rsa-public`)p=f.components.n,m=f.components.e;else if(f.type===`rsa-private`)p=f.components.n,m=f.components.e;else throw Error(`publicKey must be an RSA public or private key`);let h=t(p),g;if(g=typeof c==`string`?o.from(c,u||`base64`):c instanceof Uint8Array?c:o.from(c),g.length!==h)return!1;let _=r(g);if(_>=p)return!1;let v=n(i(_,m,p),h);if(v[0]!==0||v[1]!==1)return!1;let y=2;for(;y<v.length&&v[y]===255;)y++;if(y>=v.length||v[y]!==0||y-2<8)return!1;y++;let b=v.slice(y),x=s[this._algorithm],S=new Uint8Array(x.length+d.length);if(S.set(x,0),S.set(d,x.length),b.length!==S.length)return!1;let C=0;for(let e=0;e<b.length;e++)C|=b[e]^S[e];return C===0}};function f(e){return new u(e)}function p(e){return new d(e)}export{u as Sign,d as Verify,f as createSign,p as createVerify};
@@ -1,18 +1 @@
1
- //#region src/timing-safe-equal.ts
2
- /**
3
- * Compare two buffers in constant time to prevent timing attacks.
4
- * Both buffers must have the same length.
5
- */
6
- function timingSafeEqual(a, b) {
7
- if (a.length !== b.length) {
8
- throw new RangeError("Input buffers must have the same byte length");
9
- }
10
- let result = 0;
11
- for (let i = 0; i < a.length; i++) {
12
- result |= a[i] ^ b[i];
13
- }
14
- return result === 0;
15
- }
16
-
17
- //#endregion
18
- export { timingSafeEqual };
1
+ function e(e,t){if(e.length!==t.length)throw RangeError(`Input buffers must have the same byte length`);let n=0;for(let r=0;r<e.length;r++)n|=e[r]^t[r];return n===0}export{e as timingSafeEqual};
package/lib/esm/x509.js CHANGED
@@ -1,223 +1 @@
1
- import { derToPem, encodeSubjectPublicKeyInfo, parseX509, parseX509Der } from "./asn1.js";
2
- import { KeyObject } from "./key-object.js";
3
- import { createHash } from "./index.js";
4
- import { Buffer } from "node:buffer";
5
-
6
- //#region src/x509.ts
7
- /**
8
- * X509Certificate encapsulates an X.509 certificate and provides
9
- * read-only access to its information.
10
- */
11
- var X509Certificate = class {
12
- _components;
13
- _pem;
14
- constructor(buf) {
15
- if (typeof buf === "string") {
16
- this._pem = buf;
17
- this._components = parseX509(buf);
18
- } else {
19
- const bufData = Buffer.isBuffer(buf) ? buf : Buffer.from(buf);
20
- const str = bufData.toString("utf8");
21
- if (str.includes("-----BEGIN CERTIFICATE-----")) {
22
- this._pem = str;
23
- this._components = parseX509(str);
24
- } else {
25
- this._components = parseX509Der(new Uint8Array(bufData.buffer, bufData.byteOffset, bufData.byteLength));
26
- this._pem = derToPem(this._components.raw, "CERTIFICATE");
27
- }
28
- }
29
- }
30
- /** The DER encoded certificate data. */
31
- get raw() {
32
- return Buffer.from(this._components.raw);
33
- }
34
- /** The serial number of the certificate as a hex string. */
35
- get serialNumber() {
36
- return this._components.serialNumber.toString(16).toUpperCase();
37
- }
38
- /** The subject of the certificate. */
39
- get subject() {
40
- return this._components.subject;
41
- }
42
- /** The issuer of the certificate. */
43
- get issuer() {
44
- return this._components.issuer;
45
- }
46
- /** The start date of the certificate validity period. */
47
- get validFrom() {
48
- return this._components.validFrom.toUTCString();
49
- }
50
- /** The end date of the certificate validity period. */
51
- get validTo() {
52
- return this._components.validTo.toUTCString();
53
- }
54
- /** SHA-1 fingerprint of the certificate. */
55
- get fingerprint() {
56
- const hash = createHash("sha1").update(this._components.raw).digest();
57
- return formatFingerprint(hash);
58
- }
59
- /** SHA-256 fingerprint of the certificate. */
60
- get fingerprint256() {
61
- const hash = createHash("sha256").update(this._components.raw).digest();
62
- return formatFingerprint(hash);
63
- }
64
- /** SHA-512 fingerprint of the certificate. */
65
- get fingerprint512() {
66
- const hash = createHash("sha512").update(this._components.raw).digest();
67
- return formatFingerprint(hash);
68
- }
69
- /** The public key of the certificate as a KeyObject. */
70
- get publicKey() {
71
- if (!this._components.publicKey) {
72
- throw new Error("Certificate does not contain a supported public key type");
73
- }
74
- const der = encodeSubjectPublicKeyInfo(this._components.publicKey);
75
- const pem = derToPem(der, "PUBLIC KEY");
76
- return new KeyObject("public", {
77
- parsed: {
78
- type: "rsa-public",
79
- components: this._components.publicKey
80
- },
81
- pem
82
- });
83
- }
84
- /** The Subject Alternative Name extension, if present. */
85
- get subjectAltName() {
86
- if (!this._components.subjectAltName || this._components.subjectAltName.length === 0) {
87
- return undefined;
88
- }
89
- return this._components.subjectAltName.join(", ");
90
- }
91
- /** The key usage extension (stub — returns undefined). */
92
- get keyUsage() {
93
- return undefined;
94
- }
95
- /** Information access extension (stub — returns undefined). */
96
- get infoAccess() {
97
- return undefined;
98
- }
99
- /** Whether this certificate is a CA certificate. */
100
- get ca() {
101
- return false;
102
- }
103
- /**
104
- * Check whether the certificate matches the given hostname.
105
- */
106
- checkHost(name) {
107
- const cnMatch = this._components.subject.match(/CN=([^,]+)/);
108
- if (cnMatch) {
109
- const cn = cnMatch[1].trim();
110
- if (matchHostname(cn, name)) return cn;
111
- }
112
- if (this._components.subjectAltName) {
113
- for (const san of this._components.subjectAltName) {
114
- if (san.startsWith("DNS:")) {
115
- const dnsName = san.substring(4);
116
- if (matchHostname(dnsName, name)) return dnsName;
117
- }
118
- }
119
- }
120
- return undefined;
121
- }
122
- /**
123
- * Check whether the certificate matches the given email address.
124
- */
125
- checkEmail(email) {
126
- const emailLower = email.toLowerCase();
127
- const emailMatch = this._components.subject.match(/emailAddress=([^,]+)/);
128
- if (emailMatch && emailMatch[1].toLowerCase() === emailLower) {
129
- return emailMatch[1];
130
- }
131
- return undefined;
132
- }
133
- /**
134
- * Check whether the certificate matches the given IP address.
135
- */
136
- checkIP(ip) {
137
- if (this._components.subjectAltName) {
138
- for (const san of this._components.subjectAltName) {
139
- if (san.startsWith("IP Address:") && san.substring(11) === ip) {
140
- return ip;
141
- }
142
- }
143
- }
144
- return undefined;
145
- }
146
- /**
147
- * Verify the certificate signature using the given public key.
148
- */
149
- verify(_publicKey) {
150
- return true;
151
- }
152
- /**
153
- * Check whether this certificate was issued by the given issuer certificate.
154
- */
155
- checkIssued(otherCert) {
156
- return this.issuer === otherCert.subject;
157
- }
158
- /**
159
- * Returns a legacy certificate object for compatibility.
160
- */
161
- toLegacyObject() {
162
- return {
163
- subject: parseDNToObject(this._components.subject),
164
- issuer: parseDNToObject(this._components.issuer),
165
- valid_from: this.validFrom,
166
- valid_to: this.validTo,
167
- serialNumber: this.serialNumber,
168
- fingerprint: this.fingerprint,
169
- fingerprint256: this.fingerprint256
170
- };
171
- }
172
- /**
173
- * Returns the PEM-encoded certificate.
174
- */
175
- toString() {
176
- return this._pem;
177
- }
178
- /**
179
- * Returns the PEM-encoded certificate in JSON context.
180
- */
181
- toJSON() {
182
- return this._pem;
183
- }
184
- get [Symbol.toStringTag]() {
185
- return "X509Certificate";
186
- }
187
- };
188
- function formatFingerprint(hash) {
189
- const hex = hash.toString("hex").toUpperCase();
190
- const parts = [];
191
- for (let i = 0; i < hex.length; i += 2) {
192
- parts.push(hex.substring(i, i + 2));
193
- }
194
- return parts.join(":");
195
- }
196
- function matchHostname(pattern, hostname) {
197
- const patternLower = pattern.toLowerCase();
198
- const hostLower = hostname.toLowerCase();
199
- if (patternLower === hostLower) return true;
200
- if (patternLower.startsWith("*.")) {
201
- const suffix = patternLower.substring(2);
202
- const hostParts = hostLower.split(".");
203
- if (hostParts.length >= 2) {
204
- const hostSuffix = hostParts.slice(1).join(".");
205
- return hostSuffix === suffix;
206
- }
207
- }
208
- return false;
209
- }
210
- function parseDNToObject(dn) {
211
- const result = {};
212
- const parts = dn.split(", ");
213
- for (const part of parts) {
214
- const eqIdx = part.indexOf("=");
215
- if (eqIdx > 0) {
216
- result[part.substring(0, eqIdx)] = part.substring(eqIdx + 1);
217
- }
218
- }
219
- return result;
220
- }
221
-
222
- //#endregion
223
- export { X509Certificate };
1
+ import{derToPem as e,encodeSubjectPublicKeyInfo as t,parseX509 as n,parseX509Der as r}from"./asn1.js";import{KeyObject as i}from"./key-object.js";import{createHash as a}from"./index.js";import{Buffer as o}from"node:buffer";var s=class{_components;_pem;constructor(t){if(typeof t==`string`)this._pem=t,this._components=n(t);else{let i=o.isBuffer(t)?t:o.from(t),a=i.toString(`utf8`);a.includes(`-----BEGIN CERTIFICATE-----`)?(this._pem=a,this._components=n(a)):(this._components=r(new Uint8Array(i.buffer,i.byteOffset,i.byteLength)),this._pem=e(this._components.raw,`CERTIFICATE`))}}get raw(){return o.from(this._components.raw)}get serialNumber(){return this._components.serialNumber.toString(16).toUpperCase()}get subject(){return this._components.subject}get issuer(){return this._components.issuer}get validFrom(){return this._components.validFrom.toUTCString()}get validTo(){return this._components.validTo.toUTCString()}get fingerprint(){return c(a(`sha1`).update(this._components.raw).digest())}get fingerprint256(){return c(a(`sha256`).update(this._components.raw).digest())}get fingerprint512(){return c(a(`sha512`).update(this._components.raw).digest())}get publicKey(){if(!this._components.publicKey)throw Error(`Certificate does not contain a supported public key type`);let n=e(t(this._components.publicKey),`PUBLIC KEY`);return new i(`public`,{parsed:{type:`rsa-public`,components:this._components.publicKey},pem:n})}get subjectAltName(){if(!(!this._components.subjectAltName||this._components.subjectAltName.length===0))return this._components.subjectAltName.join(`, `)}get keyUsage(){}get infoAccess(){}get ca(){return!1}checkHost(e){let t=this._components.subject.match(/CN=([^,]+)/);if(t){let n=t[1].trim();if(l(n,e))return n}if(this._components.subjectAltName){for(let t of this._components.subjectAltName)if(t.startsWith(`DNS:`)){let n=t.substring(4);if(l(n,e))return n}}}checkEmail(e){let t=e.toLowerCase(),n=this._components.subject.match(/emailAddress=([^,]+)/);if(n&&n[1].toLowerCase()===t)return n[1]}checkIP(e){if(this._components.subjectAltName){for(let t of this._components.subjectAltName)if(t.startsWith(`IP Address:`)&&t.substring(11)===e)return e}}verify(e){return!0}checkIssued(e){return this.issuer===e.subject}toLegacyObject(){return{subject:u(this._components.subject),issuer:u(this._components.issuer),valid_from:this.validFrom,valid_to:this.validTo,serialNumber:this.serialNumber,fingerprint:this.fingerprint,fingerprint256:this.fingerprint256}}toString(){return this._pem}toJSON(){return this._pem}get[Symbol.toStringTag](){return`X509Certificate`}};function c(e){let t=e.toString(`hex`).toUpperCase(),n=[];for(let e=0;e<t.length;e+=2)n.push(t.substring(e,e+2));return n.join(`:`)}function l(e,t){let n=e.toLowerCase(),r=t.toLowerCase();if(n===r)return!0;if(n.startsWith(`*.`)){let e=n.substring(2),t=r.split(`.`);if(t.length>=2)return t.slice(1).join(`.`)===e}return!1}function u(e){let t={},n=e.split(`, `);for(let e of n){let n=e.indexOf(`=`);n>0&&(t[e.substring(0,n)]=e.substring(n+1))}return t}export{s as X509Certificate};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@gjsify/crypto",
3
- "version": "0.3.16",
3
+ "version": "0.3.18",
4
4
  "description": "Node.js crypto module for Gjs",
5
5
  "type": "module",
6
6
  "module": "lib/esm/index.js",
@@ -30,16 +30,16 @@
30
30
  "crypto"
31
31
  ],
32
32
  "devDependencies": {
33
- "@gjsify/cli": "^0.3.16",
34
- "@gjsify/unit": "^0.3.16",
33
+ "@gjsify/cli": "^0.3.18",
34
+ "@gjsify/unit": "^0.3.18",
35
35
  "@types/diffie-hellman": "^5.0.3",
36
- "@types/node": "^25.6.0",
36
+ "@types/node": "^25.6.2",
37
37
  "typescript": "^6.0.3"
38
38
  },
39
39
  "dependencies": {
40
- "@girs/glib-2.0": "2.88.0-4.0.0-rc.9",
41
- "@gjsify/buffer": "^0.3.16",
42
- "@gjsify/stream": "^0.3.16",
43
- "@gjsify/utils": "^0.3.16"
40
+ "@girs/glib-2.0": "2.88.0-4.0.0-rc.14",
41
+ "@gjsify/buffer": "^0.3.18",
42
+ "@gjsify/stream": "^0.3.18",
43
+ "@gjsify/utils": "^0.3.18"
44
44
  }
45
45
  }