@gjsify/crypto 0.1.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.
Files changed (87) hide show
  1. package/README.md +27 -0
  2. package/lib/esm/asn1.js +504 -0
  3. package/lib/esm/bigint-math.js +34 -0
  4. package/lib/esm/cipher.js +1272 -0
  5. package/lib/esm/constants.js +15 -0
  6. package/lib/esm/crypto-utils.js +47 -0
  7. package/lib/esm/dh.js +411 -0
  8. package/lib/esm/ecdh.js +356 -0
  9. package/lib/esm/ecdsa.js +125 -0
  10. package/lib/esm/hash.js +100 -0
  11. package/lib/esm/hkdf.js +58 -0
  12. package/lib/esm/hmac.js +93 -0
  13. package/lib/esm/index.js +158 -0
  14. package/lib/esm/key-object.js +330 -0
  15. package/lib/esm/mgf1.js +27 -0
  16. package/lib/esm/pbkdf2.js +68 -0
  17. package/lib/esm/public-encrypt.js +175 -0
  18. package/lib/esm/random.js +138 -0
  19. package/lib/esm/rsa-oaep.js +95 -0
  20. package/lib/esm/rsa-pss.js +100 -0
  21. package/lib/esm/scrypt.js +134 -0
  22. package/lib/esm/sign.js +248 -0
  23. package/lib/esm/timing-safe-equal.js +13 -0
  24. package/lib/esm/x509.js +214 -0
  25. package/lib/types/asn1.d.ts +87 -0
  26. package/lib/types/bigint-math.d.ts +13 -0
  27. package/lib/types/cipher.d.ts +84 -0
  28. package/lib/types/constants.d.ts +10 -0
  29. package/lib/types/crypto-utils.d.ts +22 -0
  30. package/lib/types/dh.d.ts +79 -0
  31. package/lib/types/ecdh.d.ts +96 -0
  32. package/lib/types/ecdsa.d.ts +21 -0
  33. package/lib/types/hash.d.ts +25 -0
  34. package/lib/types/hkdf.d.ts +9 -0
  35. package/lib/types/hmac.d.ts +20 -0
  36. package/lib/types/index.d.ts +105 -0
  37. package/lib/types/key-object.d.ts +36 -0
  38. package/lib/types/mgf1.d.ts +5 -0
  39. package/lib/types/pbkdf2.d.ts +9 -0
  40. package/lib/types/public-encrypt.d.ts +42 -0
  41. package/lib/types/random.d.ts +22 -0
  42. package/lib/types/rsa-oaep.d.ts +8 -0
  43. package/lib/types/rsa-pss.d.ts +8 -0
  44. package/lib/types/scrypt.d.ts +11 -0
  45. package/lib/types/sign.d.ts +61 -0
  46. package/lib/types/timing-safe-equal.d.ts +6 -0
  47. package/lib/types/x509.d.ts +72 -0
  48. package/package.json +45 -0
  49. package/src/asn1.ts +797 -0
  50. package/src/bigint-math.ts +45 -0
  51. package/src/cipher.spec.ts +332 -0
  52. package/src/cipher.ts +952 -0
  53. package/src/constants.ts +16 -0
  54. package/src/crypto-utils.ts +64 -0
  55. package/src/dh.spec.ts +111 -0
  56. package/src/dh.ts +761 -0
  57. package/src/ecdh.spec.ts +116 -0
  58. package/src/ecdh.ts +624 -0
  59. package/src/ecdsa.ts +243 -0
  60. package/src/extended.spec.ts +444 -0
  61. package/src/gcm.spec.ts +141 -0
  62. package/src/hash.spec.ts +86 -0
  63. package/src/hash.ts +119 -0
  64. package/src/hkdf.ts +99 -0
  65. package/src/hmac.spec.ts +64 -0
  66. package/src/hmac.ts +123 -0
  67. package/src/index.ts +93 -0
  68. package/src/key-object.spec.ts +202 -0
  69. package/src/key-object.ts +401 -0
  70. package/src/mgf1.ts +37 -0
  71. package/src/pbkdf2.spec.ts +76 -0
  72. package/src/pbkdf2.ts +106 -0
  73. package/src/public-encrypt.ts +288 -0
  74. package/src/random.spec.ts +133 -0
  75. package/src/random.ts +183 -0
  76. package/src/rsa-oaep.ts +167 -0
  77. package/src/rsa-pss.ts +190 -0
  78. package/src/scrypt.spec.ts +90 -0
  79. package/src/scrypt.ts +191 -0
  80. package/src/sign.spec.ts +160 -0
  81. package/src/sign.ts +319 -0
  82. package/src/test.mts +19 -0
  83. package/src/timing-safe-equal.ts +21 -0
  84. package/src/x509.spec.ts +210 -0
  85. package/src/x509.ts +262 -0
  86. package/tsconfig.json +31 -0
  87. package/tsconfig.tsbuildinfo +1 -0
@@ -0,0 +1,93 @@
1
+ import { Transform } from "node:stream";
2
+ import { Buffer } from "node:buffer";
3
+ import { normalizeEncoding } from "@gjsify/utils";
4
+ import { Hash } from "./hash.js";
5
+ import { normalizeAlgorithm, BLOCK_SIZES, SUPPORTED_ALGORITHMS } from "./crypto-utils.js";
6
+ class Hmac extends Transform {
7
+ _algorithm;
8
+ _innerHash;
9
+ _outerKeyPad;
10
+ _finalized = false;
11
+ constructor(algorithm, key) {
12
+ super();
13
+ const normalized = normalizeAlgorithm(algorithm);
14
+ if (!SUPPORTED_ALGORITHMS.has(normalized)) {
15
+ const err = new Error(`Unknown message digest: ${algorithm}`);
16
+ err.code = "ERR_CRYPTO_HASH_UNKNOWN";
17
+ throw err;
18
+ }
19
+ this._algorithm = normalized;
20
+ let keyBytes;
21
+ if (typeof key === "string") {
22
+ keyBytes = Buffer.from(key, "utf8");
23
+ } else {
24
+ keyBytes = key instanceof Uint8Array ? key : Buffer.from(key);
25
+ }
26
+ const blockSize = BLOCK_SIZES[normalized];
27
+ if (keyBytes.length > blockSize) {
28
+ const h = new Hash(normalized);
29
+ h.update(keyBytes);
30
+ keyBytes = h.digest();
31
+ }
32
+ const paddedKey = new Uint8Array(blockSize);
33
+ paddedKey.set(keyBytes);
34
+ const iKeyPad = new Uint8Array(blockSize);
35
+ const oKeyPad = new Uint8Array(blockSize);
36
+ for (let i = 0; i < blockSize; i++) {
37
+ iKeyPad[i] = paddedKey[i] ^ 54;
38
+ oKeyPad[i] = paddedKey[i] ^ 92;
39
+ }
40
+ this._outerKeyPad = oKeyPad;
41
+ this._innerHash = new Hash(normalized);
42
+ this._innerHash.update(iKeyPad);
43
+ }
44
+ /** Update the HMAC with data. */
45
+ update(data, inputEncoding) {
46
+ if (this._finalized) {
47
+ throw new Error("Digest already called");
48
+ }
49
+ let bytes;
50
+ if (typeof data === "string") {
51
+ const enc = normalizeEncoding(inputEncoding);
52
+ bytes = Buffer.from(data, enc);
53
+ } else {
54
+ bytes = data instanceof Uint8Array ? data : Buffer.from(data);
55
+ }
56
+ this._innerHash.update(bytes);
57
+ return this;
58
+ }
59
+ /** Calculate the HMAC digest. */
60
+ digest(encoding) {
61
+ if (this._finalized) {
62
+ throw new Error("Digest already called");
63
+ }
64
+ this._finalized = true;
65
+ const innerDigest = this._innerHash.digest();
66
+ const outerHash = new Hash(this._algorithm);
67
+ outerHash.update(this._outerKeyPad);
68
+ outerHash.update(innerDigest);
69
+ const result = outerHash.digest();
70
+ if (encoding) return result.toString(encoding);
71
+ return result;
72
+ }
73
+ // Transform stream interface
74
+ _transform(chunk, encoding, callback) {
75
+ try {
76
+ this.update(chunk, encoding);
77
+ callback();
78
+ } catch (err) {
79
+ callback(err);
80
+ }
81
+ }
82
+ _flush(callback) {
83
+ try {
84
+ this.push(this.digest());
85
+ callback();
86
+ } catch (err) {
87
+ callback(err);
88
+ }
89
+ }
90
+ }
91
+ export {
92
+ Hmac
93
+ };
@@ -0,0 +1,158 @@
1
+ import { Hash, getHashes, hash } from "./hash.js";
2
+ import { Hmac } from "./hmac.js";
3
+ import {
4
+ randomBytes,
5
+ randomFill,
6
+ randomFillSync,
7
+ randomUUID,
8
+ randomInt
9
+ } from "./random.js";
10
+ import { timingSafeEqual } from "./timing-safe-equal.js";
11
+ import { constants } from "./constants.js";
12
+ import { pbkdf2, pbkdf2Sync } from "./pbkdf2.js";
13
+ import { hkdf, hkdfSync } from "./hkdf.js";
14
+ import { scrypt, scryptSync } from "./scrypt.js";
15
+ import { Hash as Hash2 } from "./hash.js";
16
+ import { Hmac as Hmac2 } from "./hmac.js";
17
+ function createHash(algorithm) {
18
+ return new Hash2(algorithm);
19
+ }
20
+ function createHmac(algorithm, key) {
21
+ return new Hmac2(algorithm, key);
22
+ }
23
+ import { createCipher, createCipheriv, createDecipher, createDecipheriv, getCiphers } from "./cipher.js";
24
+ import { Sign, Verify, createSign, createVerify } from "./sign.js";
25
+ import { createDiffieHellman, getDiffieHellman, DiffieHellman, DiffieHellmanGroup, createDiffieHellmanGroup } from "./dh.js";
26
+ import { createECDH, getCurves } from "./ecdh.js";
27
+ import { ecdsaSign, ecdsaVerify } from "./ecdsa.js";
28
+ import { publicEncrypt, privateDecrypt, privateEncrypt, publicDecrypt } from "./public-encrypt.js";
29
+ import { rsaPssSign, rsaPssVerify } from "./rsa-pss.js";
30
+ import { rsaOaepEncrypt, rsaOaepDecrypt } from "./rsa-oaep.js";
31
+ import { mgf1 } from "./mgf1.js";
32
+ import { KeyObject, createSecretKey, createPublicKey, createPrivateKey } from "./key-object.js";
33
+ import { X509Certificate } from "./x509.js";
34
+ import { getHashes as getHashes2, hash as hash2 } from "./hash.js";
35
+ import { randomBytes as randomBytes2, randomFill as randomFill2, randomFillSync as randomFillSync2, randomUUID as randomUUID2, randomInt as randomInt2 } from "./random.js";
36
+ import { timingSafeEqual as timingSafeEqual2 } from "./timing-safe-equal.js";
37
+ import { constants as constants2 } from "./constants.js";
38
+ import { pbkdf2 as pbkdf22, pbkdf2Sync as pbkdf2Sync2 } from "./pbkdf2.js";
39
+ import { hkdf as hkdf2, hkdfSync as hkdfSync2 } from "./hkdf.js";
40
+ import { scrypt as scrypt2, scryptSync as scryptSync2 } from "./scrypt.js";
41
+ import { createCipher as createCipher2, createCipheriv as createCipheriv2, createDecipher as createDecipher2, createDecipheriv as createDecipheriv2, getCiphers as getCiphers2 } from "./cipher.js";
42
+ import { Sign as Sign2, Verify as Verify2, createSign as createSign2, createVerify as createVerify2 } from "./sign.js";
43
+ import { createDiffieHellman as createDiffieHellman2, getDiffieHellman as getDiffieHellman2, DiffieHellman as DiffieHellman2, DiffieHellmanGroup as DiffieHellmanGroup2, createDiffieHellmanGroup as createDiffieHellmanGroup2 } from "./dh.js";
44
+ import { createECDH as createECDH2, getCurves as getCurves2 } from "./ecdh.js";
45
+ import { ecdsaSign as ecdsaSign2, ecdsaVerify as ecdsaVerify2 } from "./ecdsa.js";
46
+ import { publicEncrypt as publicEncrypt2, privateDecrypt as privateDecrypt2, privateEncrypt as privateEncrypt2, publicDecrypt as publicDecrypt2 } from "./public-encrypt.js";
47
+ import { rsaPssSign as rsaPssSign2, rsaPssVerify as rsaPssVerify2 } from "./rsa-pss.js";
48
+ import { rsaOaepEncrypt as rsaOaepEncrypt2, rsaOaepDecrypt as rsaOaepDecrypt2 } from "./rsa-oaep.js";
49
+ import { mgf1 as mgf12 } from "./mgf1.js";
50
+ import { KeyObject as KeyObject2, createSecretKey as createSecretKey2, createPublicKey as createPublicKey2, createPrivateKey as createPrivateKey2 } from "./key-object.js";
51
+ import { X509Certificate as X509Certificate2 } from "./x509.js";
52
+ var index_default = {
53
+ Hash: Hash2,
54
+ getHashes: getHashes2,
55
+ hash: hash2,
56
+ Hmac: Hmac2,
57
+ randomBytes: randomBytes2,
58
+ randomFill: randomFill2,
59
+ randomFillSync: randomFillSync2,
60
+ randomUUID: randomUUID2,
61
+ randomInt: randomInt2,
62
+ timingSafeEqual: timingSafeEqual2,
63
+ constants: constants2,
64
+ pbkdf2: pbkdf22,
65
+ pbkdf2Sync: pbkdf2Sync2,
66
+ hkdf: hkdf2,
67
+ hkdfSync: hkdfSync2,
68
+ scrypt: scrypt2,
69
+ scryptSync: scryptSync2,
70
+ createHash,
71
+ createHmac,
72
+ createCipher: createCipher2,
73
+ createCipheriv: createCipheriv2,
74
+ createDecipher: createDecipher2,
75
+ createDecipheriv: createDecipheriv2,
76
+ getCiphers: getCiphers2,
77
+ Sign: Sign2,
78
+ Verify: Verify2,
79
+ createSign: createSign2,
80
+ createVerify: createVerify2,
81
+ createDiffieHellman: createDiffieHellman2,
82
+ getDiffieHellman: getDiffieHellman2,
83
+ DiffieHellman: DiffieHellman2,
84
+ DiffieHellmanGroup: DiffieHellmanGroup2,
85
+ createDiffieHellmanGroup: createDiffieHellmanGroup2,
86
+ createECDH: createECDH2,
87
+ getCurves: getCurves2,
88
+ ecdsaSign: ecdsaSign2,
89
+ ecdsaVerify: ecdsaVerify2,
90
+ publicEncrypt: publicEncrypt2,
91
+ privateDecrypt: privateDecrypt2,
92
+ privateEncrypt: privateEncrypt2,
93
+ publicDecrypt: publicDecrypt2,
94
+ rsaPssSign: rsaPssSign2,
95
+ rsaPssVerify: rsaPssVerify2,
96
+ rsaOaepEncrypt: rsaOaepEncrypt2,
97
+ rsaOaepDecrypt: rsaOaepDecrypt2,
98
+ mgf1: mgf12,
99
+ KeyObject: KeyObject2,
100
+ createSecretKey: createSecretKey2,
101
+ createPublicKey: createPublicKey2,
102
+ createPrivateKey: createPrivateKey2,
103
+ X509Certificate: X509Certificate2
104
+ };
105
+ export {
106
+ DiffieHellman,
107
+ DiffieHellmanGroup,
108
+ Hash,
109
+ Hmac,
110
+ KeyObject,
111
+ Sign,
112
+ Verify,
113
+ X509Certificate,
114
+ constants,
115
+ createCipher,
116
+ createCipheriv,
117
+ createDecipher,
118
+ createDecipheriv,
119
+ createDiffieHellman,
120
+ createDiffieHellmanGroup,
121
+ createECDH,
122
+ createHash,
123
+ createHmac,
124
+ createPrivateKey,
125
+ createPublicKey,
126
+ createSecretKey,
127
+ createSign,
128
+ createVerify,
129
+ index_default as default,
130
+ ecdsaSign,
131
+ ecdsaVerify,
132
+ getCiphers,
133
+ getCurves,
134
+ getDiffieHellman,
135
+ getHashes,
136
+ hash,
137
+ hkdf,
138
+ hkdfSync,
139
+ mgf1,
140
+ pbkdf2,
141
+ pbkdf2Sync,
142
+ privateDecrypt,
143
+ privateEncrypt,
144
+ publicDecrypt,
145
+ publicEncrypt,
146
+ randomBytes,
147
+ randomFill,
148
+ randomFillSync,
149
+ randomInt,
150
+ randomUUID,
151
+ rsaOaepDecrypt,
152
+ rsaOaepEncrypt,
153
+ rsaPssSign,
154
+ rsaPssVerify,
155
+ scrypt,
156
+ scryptSync,
157
+ timingSafeEqual
158
+ };
@@ -0,0 +1,330 @@
1
+ import { Buffer } from "node:buffer";
2
+ import {
3
+ parsePemKey,
4
+ rsaKeySize,
5
+ encodeSubjectPublicKeyInfo,
6
+ encodeRsaPublicKeyPkcs1,
7
+ encodeRsaPrivateKeyPkcs1,
8
+ encodePrivateKeyInfo,
9
+ derToPem
10
+ } from "./asn1.js";
11
+ function bigintToBase64url(value) {
12
+ if (value === 0n) return "AA";
13
+ const hex = value.toString(16);
14
+ const paddedHex = hex.length % 2 ? "0" + hex : hex;
15
+ const bytes = [];
16
+ for (let i = 0; i < paddedHex.length; i += 2) {
17
+ bytes.push(parseInt(paddedHex.substring(i, i + 2), 16));
18
+ }
19
+ return Buffer.from(bytes).toString("base64url");
20
+ }
21
+ function base64urlToBigint(b64) {
22
+ const buf = Buffer.from(b64, "base64url");
23
+ let result = 0n;
24
+ for (let i = 0; i < buf.length; i++) {
25
+ result = result << 8n | BigInt(buf[i]);
26
+ }
27
+ return result;
28
+ }
29
+ class KeyObject {
30
+ type;
31
+ /** @internal */
32
+ _handle;
33
+ constructor(type, handle) {
34
+ if (type !== "secret" && type !== "public" && type !== "private") {
35
+ throw new TypeError(`Invalid KeyObject type: ${type}`);
36
+ }
37
+ this.type = type;
38
+ this._handle = handle;
39
+ }
40
+ get symmetricKeySize() {
41
+ if (this.type !== "secret") return void 0;
42
+ return this._handle.byteLength;
43
+ }
44
+ get asymmetricKeyType() {
45
+ if (this.type === "secret") return void 0;
46
+ const handle = this._handle;
47
+ if (handle.parsed.type === "rsa-public" || handle.parsed.type === "rsa-private") {
48
+ return "rsa";
49
+ }
50
+ return void 0;
51
+ }
52
+ get asymmetricKeySize() {
53
+ if (this.type === "secret") return void 0;
54
+ const handle = this._handle;
55
+ if (handle.parsed.type === "rsa-public") {
56
+ return rsaKeySize(handle.parsed.components.n) / 8;
57
+ }
58
+ if (handle.parsed.type === "rsa-private") {
59
+ return rsaKeySize(handle.parsed.components.n) / 8;
60
+ }
61
+ return void 0;
62
+ }
63
+ equals(otherKeyObject) {
64
+ if (!(otherKeyObject instanceof KeyObject)) return false;
65
+ if (this.type !== otherKeyObject.type) return false;
66
+ if (this.type === "secret") {
67
+ const a2 = this._handle;
68
+ const b2 = otherKeyObject._handle;
69
+ if (a2.byteLength !== b2.byteLength) return false;
70
+ for (let i = 0; i < a2.byteLength; i++) {
71
+ if (a2[i] !== b2[i]) return false;
72
+ }
73
+ return true;
74
+ }
75
+ const a = this._handle;
76
+ const b = otherKeyObject._handle;
77
+ return a.pem === b.pem;
78
+ }
79
+ export(options) {
80
+ if (this.type === "secret") {
81
+ const key = this._handle;
82
+ if (options?.format === "jwk") {
83
+ return {
84
+ kty: "oct",
85
+ k: Buffer.from(key).toString("base64url")
86
+ };
87
+ }
88
+ return Buffer.from(key);
89
+ }
90
+ const handle = this._handle;
91
+ const format = options?.format ?? "pem";
92
+ const keyType = options?.type;
93
+ if (format === "jwk") {
94
+ return exportJwk(handle.parsed, this.type);
95
+ }
96
+ if (format === "pem") {
97
+ if (handle.pem && !handle.pem.startsWith("[")) {
98
+ return handle.pem;
99
+ }
100
+ return generatePem(handle.parsed, this.type, keyType);
101
+ }
102
+ if (format === "der") {
103
+ if (handle.pem && !handle.pem.startsWith("[")) {
104
+ const lines = handle.pem.trim().split(/\r?\n/);
105
+ const headerIdx = lines.findIndex((l) => l.startsWith("-----BEGIN "));
106
+ const footerIdx = lines.findIndex((l, i) => i > headerIdx && l.startsWith("-----END "));
107
+ const base64Body = lines.slice(headerIdx + 1, footerIdx).join("");
108
+ return Buffer.from(base64Body, "base64");
109
+ }
110
+ return generateDer(handle.parsed, this.type, keyType);
111
+ }
112
+ throw new TypeError(`Unsupported export format: ${format}`);
113
+ }
114
+ get [Symbol.toStringTag]() {
115
+ return "KeyObject";
116
+ }
117
+ }
118
+ function exportJwk(parsed, keyType) {
119
+ if (parsed.type === "rsa-public") {
120
+ return {
121
+ kty: "RSA",
122
+ n: bigintToBase64url(parsed.components.n),
123
+ e: bigintToBase64url(parsed.components.e)
124
+ };
125
+ }
126
+ if (parsed.type === "rsa-private") {
127
+ if (keyType === "public") {
128
+ return {
129
+ kty: "RSA",
130
+ n: bigintToBase64url(parsed.components.n),
131
+ e: bigintToBase64url(parsed.components.e)
132
+ };
133
+ }
134
+ const { n, e, d, p, q } = parsed.components;
135
+ const dp = d % (p - 1n);
136
+ const dq = d % (q - 1n);
137
+ const qi = modInverse(q, p);
138
+ return {
139
+ kty: "RSA",
140
+ n: bigintToBase64url(n),
141
+ e: bigintToBase64url(e),
142
+ d: bigintToBase64url(d),
143
+ p: bigintToBase64url(p),
144
+ q: bigintToBase64url(q),
145
+ dp: bigintToBase64url(dp),
146
+ dq: bigintToBase64url(dq),
147
+ qi: bigintToBase64url(qi)
148
+ };
149
+ }
150
+ throw new Error("Unsupported key type for JWK export");
151
+ }
152
+ function importJwkRsa(jwk) {
153
+ if (jwk.d) {
154
+ const components2 = {
155
+ n: base64urlToBigint(jwk.n),
156
+ e: base64urlToBigint(jwk.e),
157
+ d: base64urlToBigint(jwk.d),
158
+ p: base64urlToBigint(jwk.p),
159
+ q: base64urlToBigint(jwk.q)
160
+ };
161
+ const parsed2 = { type: "rsa-private", components: components2 };
162
+ const der2 = encodeRsaPrivateKeyPkcs1(components2);
163
+ const pem2 = derToPem(der2, "RSA PRIVATE KEY");
164
+ return { parsed: parsed2, pem: pem2 };
165
+ }
166
+ const components = {
167
+ n: base64urlToBigint(jwk.n),
168
+ e: base64urlToBigint(jwk.e)
169
+ };
170
+ const parsed = { type: "rsa-public", components };
171
+ const der = encodeSubjectPublicKeyInfo(components);
172
+ const pem = derToPem(der, "PUBLIC KEY");
173
+ return { parsed, pem };
174
+ }
175
+ function generatePem(parsed, keyType, type) {
176
+ if (parsed.type === "rsa-public") {
177
+ if (type === "pkcs1") {
178
+ const der2 = encodeRsaPublicKeyPkcs1(parsed.components);
179
+ return derToPem(der2, "RSA PUBLIC KEY");
180
+ }
181
+ const der = encodeSubjectPublicKeyInfo(parsed.components);
182
+ return derToPem(der, "PUBLIC KEY");
183
+ }
184
+ if (parsed.type === "rsa-private" && keyType === "public") {
185
+ const pubComponents = {
186
+ n: parsed.components.n,
187
+ e: parsed.components.e
188
+ };
189
+ if (type === "pkcs1") {
190
+ const der2 = encodeRsaPublicKeyPkcs1(pubComponents);
191
+ return derToPem(der2, "RSA PUBLIC KEY");
192
+ }
193
+ const der = encodeSubjectPublicKeyInfo(pubComponents);
194
+ return derToPem(der, "PUBLIC KEY");
195
+ }
196
+ if (parsed.type === "rsa-private") {
197
+ if (type === "pkcs8") {
198
+ const der2 = encodePrivateKeyInfo(parsed.components);
199
+ return derToPem(der2, "PRIVATE KEY");
200
+ }
201
+ const der = encodeRsaPrivateKeyPkcs1(parsed.components);
202
+ return derToPem(der, "RSA PRIVATE KEY");
203
+ }
204
+ throw new Error("Cannot generate PEM for this key type");
205
+ }
206
+ function generateDer(parsed, keyType, type) {
207
+ if (parsed.type === "rsa-public") {
208
+ if (type === "pkcs1") {
209
+ return Buffer.from(encodeRsaPublicKeyPkcs1(parsed.components));
210
+ }
211
+ return Buffer.from(encodeSubjectPublicKeyInfo(parsed.components));
212
+ }
213
+ if (parsed.type === "rsa-private" && keyType === "public") {
214
+ const pubComponents = {
215
+ n: parsed.components.n,
216
+ e: parsed.components.e
217
+ };
218
+ if (type === "pkcs1") {
219
+ return Buffer.from(encodeRsaPublicKeyPkcs1(pubComponents));
220
+ }
221
+ return Buffer.from(encodeSubjectPublicKeyInfo(pubComponents));
222
+ }
223
+ if (parsed.type === "rsa-private") {
224
+ if (type === "pkcs8") {
225
+ return Buffer.from(encodePrivateKeyInfo(parsed.components));
226
+ }
227
+ return Buffer.from(encodeRsaPrivateKeyPkcs1(parsed.components));
228
+ }
229
+ throw new Error("Cannot generate DER for this key type");
230
+ }
231
+ function modInverse(a, m) {
232
+ let [old_r, r] = [a % m, m];
233
+ let [old_s, s] = [1n, 0n];
234
+ while (r !== 0n) {
235
+ const q = old_r / r;
236
+ [old_r, r] = [r, old_r - q * r];
237
+ [old_s, s] = [s, old_s - q * s];
238
+ }
239
+ return (old_s % m + m) % m;
240
+ }
241
+ function createSecretKey(key, encoding) {
242
+ let keyBuf;
243
+ if (typeof key === "string") {
244
+ keyBuf = Buffer.from(key, encoding ?? "utf8");
245
+ } else {
246
+ keyBuf = new Uint8Array(key);
247
+ }
248
+ return new KeyObject("secret", keyBuf);
249
+ }
250
+ function createPublicKey(key) {
251
+ if (key instanceof KeyObject) {
252
+ if (key.type === "public") return key;
253
+ if (key.type === "private") {
254
+ const handle = key._handle;
255
+ if (handle.parsed.type === "rsa-private") {
256
+ const pubComponents = {
257
+ n: handle.parsed.components.n,
258
+ e: handle.parsed.components.e
259
+ };
260
+ const pubParsed = { type: "rsa-public", components: pubComponents };
261
+ const der = encodeSubjectPublicKeyInfo(pubComponents);
262
+ const pem2 = derToPem(der, "PUBLIC KEY");
263
+ return new KeyObject("public", { parsed: pubParsed, pem: pem2 });
264
+ }
265
+ }
266
+ throw new TypeError("Cannot create public key from secret key");
267
+ }
268
+ if (typeof key === "object" && !Buffer.isBuffer(key) && "key" in key) {
269
+ const input = key;
270
+ if (input.format === "jwk") {
271
+ const jwk = input.key;
272
+ if (jwk.kty === "RSA") {
273
+ const { parsed: parsed2, pem: pem2 } = importJwkRsa({ n: jwk.n, e: jwk.e });
274
+ return new KeyObject("public", { parsed: parsed2, pem: pem2 });
275
+ }
276
+ throw new Error(`Unsupported JWK key type: ${jwk.kty}`);
277
+ }
278
+ }
279
+ const pem = normalizePem(key);
280
+ const parsed = parsePemKey(pem);
281
+ if (parsed.type === "rsa-private") {
282
+ const pubComponents = {
283
+ n: parsed.components.n,
284
+ e: parsed.components.e
285
+ };
286
+ const pubParsed = { type: "rsa-public", components: pubComponents };
287
+ const der = encodeSubjectPublicKeyInfo(pubComponents);
288
+ const pubPem = derToPem(der, "PUBLIC KEY");
289
+ return new KeyObject("public", { parsed: pubParsed, pem: pubPem });
290
+ }
291
+ return new KeyObject("public", { parsed, pem });
292
+ }
293
+ function createPrivateKey(key) {
294
+ if (typeof key === "object" && !Buffer.isBuffer(key) && "key" in key) {
295
+ const input = key;
296
+ if (input.format === "jwk") {
297
+ const jwk = input.key;
298
+ if (jwk.kty === "RSA" && jwk.d) {
299
+ const { parsed: parsed2, pem: pem2 } = importJwkRsa(jwk);
300
+ return new KeyObject("private", { parsed: parsed2, pem: pem2 });
301
+ }
302
+ throw new Error("JWK does not contain a private key");
303
+ }
304
+ }
305
+ const pem = normalizePem(key);
306
+ const parsed = parsePemKey(pem);
307
+ if (parsed.type !== "rsa-private") {
308
+ throw new TypeError("Key is not a private key");
309
+ }
310
+ return new KeyObject("private", { parsed, pem });
311
+ }
312
+ function normalizePem(key) {
313
+ if (typeof key === "string") return key;
314
+ if (Buffer.isBuffer(key)) return key.toString("utf8");
315
+ if (key && typeof key === "object" && "key" in key) {
316
+ const input = key;
317
+ if (typeof input.key === "string") return input.key;
318
+ if (Buffer.isBuffer(input.key)) return input.key.toString(input.encoding ?? "utf8");
319
+ if (input.key instanceof KeyObject) {
320
+ return input.key.export({ format: "pem" });
321
+ }
322
+ }
323
+ throw new TypeError("Invalid key input");
324
+ }
325
+ export {
326
+ KeyObject,
327
+ createPrivateKey,
328
+ createPublicKey,
329
+ createSecretKey
330
+ };
@@ -0,0 +1,27 @@
1
+ import { Hash } from "./hash.js";
2
+ import { hashSize } from "./crypto-utils.js";
3
+ function mgf1(hashAlgo, seed, length) {
4
+ const hashLen = hashSize(hashAlgo);
5
+ const mask = new Uint8Array(length);
6
+ let offset = 0;
7
+ let counter = 0;
8
+ while (offset < length) {
9
+ const C = new Uint8Array(4);
10
+ C[0] = counter >>> 24 & 255;
11
+ C[1] = counter >>> 16 & 255;
12
+ C[2] = counter >>> 8 & 255;
13
+ C[3] = counter & 255;
14
+ const hash = new Hash(hashAlgo);
15
+ hash.update(seed);
16
+ hash.update(C);
17
+ const digest = new Uint8Array(hash.digest());
18
+ const toCopy = Math.min(digest.length, length - offset);
19
+ mask.set(digest.slice(0, toCopy), offset);
20
+ offset += toCopy;
21
+ counter++;
22
+ }
23
+ return mask;
24
+ }
25
+ export {
26
+ mgf1
27
+ };
@@ -0,0 +1,68 @@
1
+ import { Buffer } from "node:buffer";
2
+ import { Hmac } from "./hmac.js";
3
+ import { normalizeAlgorithm, DIGEST_SIZES, SUPPORTED_ALGORITHMS, toBuffer } from "./crypto-utils.js";
4
+ function hmacDigest(algo, key, data) {
5
+ const hmac = new Hmac(algo, key);
6
+ hmac.update(data);
7
+ return hmac.digest();
8
+ }
9
+ function validateParameters(iterations, keylen) {
10
+ if (typeof iterations !== "number" || iterations < 0 || !Number.isFinite(iterations)) {
11
+ throw new TypeError("iterations must be a positive number");
12
+ }
13
+ if (iterations === 0) {
14
+ throw new TypeError("iterations must be a positive number");
15
+ }
16
+ if (typeof keylen !== "number" || keylen < 0 || !Number.isFinite(keylen) || keylen > 2147483647) {
17
+ throw new TypeError("keylen must be a positive number");
18
+ }
19
+ }
20
+ function pbkdf2Sync(password, salt, iterations, keylen, digest) {
21
+ validateParameters(iterations, keylen);
22
+ const passwordBuf = toBuffer(password);
23
+ const saltBuf = toBuffer(salt);
24
+ const algo = normalizeAlgorithm(digest || "sha1");
25
+ const hashLen = DIGEST_SIZES[algo];
26
+ if (!SUPPORTED_ALGORITHMS.has(algo) || hashLen === void 0) {
27
+ throw new TypeError(`Unknown message digest: ${digest || "sha1"}`);
28
+ }
29
+ if (keylen === 0) {
30
+ return Buffer.alloc(0);
31
+ }
32
+ const numBlocks = Math.ceil(keylen / hashLen);
33
+ const dk = Buffer.allocUnsafe(numBlocks * hashLen);
34
+ for (let blockIndex = 1; blockIndex <= numBlocks; blockIndex++) {
35
+ const block = Buffer.allocUnsafe(saltBuf.length + 4);
36
+ saltBuf.copy(block, 0);
37
+ block.writeUInt32BE(blockIndex, saltBuf.length);
38
+ let u = hmacDigest(algo, passwordBuf, block);
39
+ let t = Buffer.from(u);
40
+ for (let iter = 1; iter < iterations; iter++) {
41
+ u = hmacDigest(algo, passwordBuf, u);
42
+ for (let k = 0; k < hashLen; k++) {
43
+ t[k] ^= u[k];
44
+ }
45
+ }
46
+ t.copy(dk, (blockIndex - 1) * hashLen);
47
+ }
48
+ return Buffer.from(dk.buffer, dk.byteOffset, keylen);
49
+ }
50
+ function pbkdf2(password, salt, iterations, keylen, digest, callback) {
51
+ try {
52
+ validateParameters(iterations, keylen);
53
+ } catch (err) {
54
+ throw err;
55
+ }
56
+ setTimeout(() => {
57
+ try {
58
+ const result = pbkdf2Sync(password, salt, iterations, keylen, digest);
59
+ callback(null, result);
60
+ } catch (err) {
61
+ callback(err instanceof Error ? err : new Error(String(err)));
62
+ }
63
+ }, 0);
64
+ }
65
+ export {
66
+ pbkdf2,
67
+ pbkdf2Sync
68
+ };