@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.
- package/README.md +27 -0
- package/lib/esm/asn1.js +504 -0
- package/lib/esm/bigint-math.js +34 -0
- package/lib/esm/cipher.js +1272 -0
- package/lib/esm/constants.js +15 -0
- package/lib/esm/crypto-utils.js +47 -0
- package/lib/esm/dh.js +411 -0
- package/lib/esm/ecdh.js +356 -0
- package/lib/esm/ecdsa.js +125 -0
- package/lib/esm/hash.js +100 -0
- package/lib/esm/hkdf.js +58 -0
- package/lib/esm/hmac.js +93 -0
- package/lib/esm/index.js +158 -0
- package/lib/esm/key-object.js +330 -0
- package/lib/esm/mgf1.js +27 -0
- package/lib/esm/pbkdf2.js +68 -0
- package/lib/esm/public-encrypt.js +175 -0
- package/lib/esm/random.js +138 -0
- package/lib/esm/rsa-oaep.js +95 -0
- package/lib/esm/rsa-pss.js +100 -0
- package/lib/esm/scrypt.js +134 -0
- package/lib/esm/sign.js +248 -0
- package/lib/esm/timing-safe-equal.js +13 -0
- package/lib/esm/x509.js +214 -0
- package/lib/types/asn1.d.ts +87 -0
- package/lib/types/bigint-math.d.ts +13 -0
- package/lib/types/cipher.d.ts +84 -0
- package/lib/types/constants.d.ts +10 -0
- package/lib/types/crypto-utils.d.ts +22 -0
- package/lib/types/dh.d.ts +79 -0
- package/lib/types/ecdh.d.ts +96 -0
- package/lib/types/ecdsa.d.ts +21 -0
- package/lib/types/hash.d.ts +25 -0
- package/lib/types/hkdf.d.ts +9 -0
- package/lib/types/hmac.d.ts +20 -0
- package/lib/types/index.d.ts +105 -0
- package/lib/types/key-object.d.ts +36 -0
- package/lib/types/mgf1.d.ts +5 -0
- package/lib/types/pbkdf2.d.ts +9 -0
- package/lib/types/public-encrypt.d.ts +42 -0
- package/lib/types/random.d.ts +22 -0
- package/lib/types/rsa-oaep.d.ts +8 -0
- package/lib/types/rsa-pss.d.ts +8 -0
- package/lib/types/scrypt.d.ts +11 -0
- package/lib/types/sign.d.ts +61 -0
- package/lib/types/timing-safe-equal.d.ts +6 -0
- package/lib/types/x509.d.ts +72 -0
- package/package.json +45 -0
- package/src/asn1.ts +797 -0
- package/src/bigint-math.ts +45 -0
- package/src/cipher.spec.ts +332 -0
- package/src/cipher.ts +952 -0
- package/src/constants.ts +16 -0
- package/src/crypto-utils.ts +64 -0
- package/src/dh.spec.ts +111 -0
- package/src/dh.ts +761 -0
- package/src/ecdh.spec.ts +116 -0
- package/src/ecdh.ts +624 -0
- package/src/ecdsa.ts +243 -0
- package/src/extended.spec.ts +444 -0
- package/src/gcm.spec.ts +141 -0
- package/src/hash.spec.ts +86 -0
- package/src/hash.ts +119 -0
- package/src/hkdf.ts +99 -0
- package/src/hmac.spec.ts +64 -0
- package/src/hmac.ts +123 -0
- package/src/index.ts +93 -0
- package/src/key-object.spec.ts +202 -0
- package/src/key-object.ts +401 -0
- package/src/mgf1.ts +37 -0
- package/src/pbkdf2.spec.ts +76 -0
- package/src/pbkdf2.ts +106 -0
- package/src/public-encrypt.ts +288 -0
- package/src/random.spec.ts +133 -0
- package/src/random.ts +183 -0
- package/src/rsa-oaep.ts +167 -0
- package/src/rsa-pss.ts +190 -0
- package/src/scrypt.spec.ts +90 -0
- package/src/scrypt.ts +191 -0
- package/src/sign.spec.ts +160 -0
- package/src/sign.ts +319 -0
- package/src/test.mts +19 -0
- package/src/timing-safe-equal.ts +21 -0
- package/src/x509.spec.ts +210 -0
- package/src/x509.ts +262 -0
- package/tsconfig.json +31 -0
- package/tsconfig.tsbuildinfo +1 -0
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
const constants = {
|
|
2
|
+
// RSA padding modes (stubs for compatibility)
|
|
3
|
+
RSA_PKCS1_PADDING: 1,
|
|
4
|
+
RSA_NO_PADDING: 3,
|
|
5
|
+
RSA_PKCS1_OAEP_PADDING: 4,
|
|
6
|
+
RSA_PKCS1_PSS_PADDING: 6,
|
|
7
|
+
// DiffieHellman error codes
|
|
8
|
+
DH_CHECK_P_NOT_SAFE_PRIME: 2,
|
|
9
|
+
DH_CHECK_P_NOT_PRIME: 1,
|
|
10
|
+
DH_UNABLE_TO_CHECK_GENERATOR: 4,
|
|
11
|
+
DH_NOT_SUITABLE_GENERATOR: 8
|
|
12
|
+
};
|
|
13
|
+
export {
|
|
14
|
+
constants
|
|
15
|
+
};
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { Buffer } from "node:buffer";
|
|
2
|
+
function normalizeAlgorithm(algorithm) {
|
|
3
|
+
return algorithm.toLowerCase().replace(/-/g, "");
|
|
4
|
+
}
|
|
5
|
+
const DIGEST_SIZES = {
|
|
6
|
+
md5: 16,
|
|
7
|
+
sha1: 20,
|
|
8
|
+
sha256: 32,
|
|
9
|
+
sha384: 48,
|
|
10
|
+
sha512: 64
|
|
11
|
+
};
|
|
12
|
+
const BLOCK_SIZES = {
|
|
13
|
+
md5: 64,
|
|
14
|
+
sha1: 64,
|
|
15
|
+
sha256: 64,
|
|
16
|
+
sha384: 128,
|
|
17
|
+
sha512: 128
|
|
18
|
+
};
|
|
19
|
+
const SUPPORTED_ALGORITHMS = /* @__PURE__ */ new Set(["md5", "sha1", "sha256", "sha384", "sha512"]);
|
|
20
|
+
function hashSize(algo) {
|
|
21
|
+
const normalized = normalizeAlgorithm(algo);
|
|
22
|
+
const size = DIGEST_SIZES[normalized];
|
|
23
|
+
if (size === void 0) {
|
|
24
|
+
throw new Error(`Unknown hash algorithm: ${algo}`);
|
|
25
|
+
}
|
|
26
|
+
return size;
|
|
27
|
+
}
|
|
28
|
+
function toBuffer(input, encoding) {
|
|
29
|
+
if (typeof input === "string") {
|
|
30
|
+
return Buffer.from(input, encoding || "utf8");
|
|
31
|
+
}
|
|
32
|
+
if (input instanceof DataView) {
|
|
33
|
+
return Buffer.from(input.buffer, input.byteOffset, input.byteLength);
|
|
34
|
+
}
|
|
35
|
+
if (input instanceof ArrayBuffer) {
|
|
36
|
+
return Buffer.from(input);
|
|
37
|
+
}
|
|
38
|
+
return Buffer.from(input);
|
|
39
|
+
}
|
|
40
|
+
export {
|
|
41
|
+
BLOCK_SIZES,
|
|
42
|
+
DIGEST_SIZES,
|
|
43
|
+
SUPPORTED_ALGORITHMS,
|
|
44
|
+
hashSize,
|
|
45
|
+
normalizeAlgorithm,
|
|
46
|
+
toBuffer
|
|
47
|
+
};
|
package/lib/esm/dh.js
ADDED
|
@@ -0,0 +1,411 @@
|
|
|
1
|
+
import { Buffer } from "node:buffer";
|
|
2
|
+
import { randomBytes } from "./random.js";
|
|
3
|
+
import { modPow } from "./bigint-math.js";
|
|
4
|
+
const PREDEFINED_GROUPS = {
|
|
5
|
+
// RFC 2409 Section 6.1 — 768-bit MODP Group
|
|
6
|
+
modp1: {
|
|
7
|
+
gen: "02",
|
|
8
|
+
prime: "ffffffffffffffffc90fdaa22168c234c4c6628b80dc1cd129024e088a67cc74020bbea63b139b22514a08798e3404ddef9519b3cd3a431b302b0a6df25f14374fe1356d6d51c245e485b576625e7ec6f44c42e9a63a3620ffffffffffffffff"
|
|
9
|
+
},
|
|
10
|
+
// RFC 2409 Section 6.2 — 1024-bit MODP Group
|
|
11
|
+
modp2: {
|
|
12
|
+
gen: "02",
|
|
13
|
+
prime: "ffffffffffffffffc90fdaa22168c234c4c6628b80dc1cd129024e088a67cc74020bbea63b139b22514a08798e3404ddef9519b3cd3a431b302b0a6df25f14374fe1356d6d51c245e485b576625e7ec6f44c42e9a637ed6b0bff5cb6f406b7edee386bfb5a899fa5ae9f24117c4b1fe649286651ece65381ffffffffffffffff"
|
|
14
|
+
},
|
|
15
|
+
// RFC 3526 Section 2 — 1536-bit MODP Group
|
|
16
|
+
modp5: {
|
|
17
|
+
gen: "02",
|
|
18
|
+
prime: "ffffffffffffffffc90fdaa22168c234c4c6628b80dc1cd129024e088a67cc74020bbea63b139b22514a08798e3404ddef9519b3cd3a431b302b0a6df25f14374fe1356d6d51c245e485b576625e7ec6f44c42e9a637ed6b0bff5cb6f406b7edee386bfb5a899fa5ae9f24117c4b1fe649286651ece45b3dc2007cb8a163bf0598da48361c55d39a69163fa8fd24cf5f83655d23dca3ad961c62f356208552bb9ed529077096966d670c354e4abc9804f1746c08ca237327ffffffffffffffff"
|
|
19
|
+
},
|
|
20
|
+
// RFC 3526 Section 3 — 2048-bit MODP Group
|
|
21
|
+
modp14: {
|
|
22
|
+
gen: "02",
|
|
23
|
+
prime: "ffffffffffffffffc90fdaa22168c234c4c6628b80dc1cd129024e088a67cc74020bbea63b139b22514a08798e3404ddef9519b3cd3a431b302b0a6df25f14374fe1356d6d51c245e485b576625e7ec6f44c42e9a637ed6b0bff5cb6f406b7edee386bfb5a899fa5ae9f24117c4b1fe649286651ece45b3dc2007cb8a163bf0598da48361c55d39a69163fa8fd24cf5f83655d23dca3ad961c62f356208552bb9ed529077096966d670c354e4abc9804f1746c08ca18217c32905e462e36ce3be39e772c180e86039b2783a2ec07a28fb5c55df06f4c52c9de2bcbf6955817183995497cea956ae515d2261898fa051015728e5a8aacaa68ffffffffffffffff"
|
|
24
|
+
},
|
|
25
|
+
// RFC 3526 Section 4 — 3072-bit MODP Group
|
|
26
|
+
modp15: {
|
|
27
|
+
gen: "02",
|
|
28
|
+
prime: "ffffffffffffffffc90fdaa22168c234c4c6628b80dc1cd129024e088a67cc74020bbea63b139b22514a08798e3404ddef9519b3cd3a431b302b0a6df25f14374fe1356d6d51c245e485b576625e7ec6f44c42e9a637ed6b0bff5cb6f406b7edee386bfb5a899fa5ae9f24117c4b1fe649286651ece45b3dc2007cb8a163bf0598da48361c55d39a69163fa8fd24cf5f83655d23dca3ad961c62f356208552bb9ed529077096966d670c354e4abc9804f1746c08ca18217c32905e462e36ce3be39e772c180e86039b2783a2ec07a28fb5c55df06f4c52c9de2bcbf6955817183995497cea956ae515d2261898fa051015728e5a8aaac42dad33170d04507a33a85521abdf1cba64ecfb850458dbef0a8aea71575d060c7db3970f85a6e1e4c7abf5ae8cdb0933d71e8c94e04a25619dcee3d2261ad2ee6bf12ffa06d98a0864d87602733ec86a64521f2b18177b200cbbe117577a615d6c770988c0bad946e208e24fa074e5ab3143db5bfce0fd108e4b82d120a93ad2caffffffffffffffff"
|
|
29
|
+
},
|
|
30
|
+
// RFC 3526 Section 5 — 4096-bit MODP Group
|
|
31
|
+
modp16: {
|
|
32
|
+
gen: "02",
|
|
33
|
+
prime: "ffffffffffffffffc90fdaa22168c234c4c6628b80dc1cd129024e088a67cc74020bbea63b139b22514a08798e3404ddef9519b3cd3a431b302b0a6df25f14374fe1356d6d51c245e485b576625e7ec6f44c42e9a637ed6b0bff5cb6f406b7edee386bfb5a899fa5ae9f24117c4b1fe649286651ece45b3dc2007cb8a163bf0598da48361c55d39a69163fa8fd24cf5f83655d23dca3ad961c62f356208552bb9ed529077096966d670c354e4abc9804f1746c08ca18217c32905e462e36ce3be39e772c180e86039b2783a2ec07a28fb5c55df06f4c52c9de2bcbf6955817183995497cea956ae515d2261898fa051015728e5a8aaac42dad33170d04507a33a85521abdf1cba64ecfb850458dbef0a8aea71575d060c7db3970f85a6e1e4c7abf5ae8cdb0933d71e8c94e04a25619dcee3d2261ad2ee6bf12ffa06d98a0864d87602733ec86a64521f2b18177b200cbbe117577a615d6c770988c0bad946e208e24fa074e5ab3143db5bfce0fd108e4b82d120a92108011a723c12a787e6d788719a10bdba5b2699c327186af4e23c1a946834b6150bda2583e9ca2ad44ce8dbbbc2db04de8ef92e8efc141fbecaa6287c59474e6bc05d99b2964fa090c3a2233ba186515be7ed1f612970cee2d7afb81bdd762170481cd0069127d5b05aa993b4ea988d8fddc186ffb7dc90a6c08f4df435c934063199ffffffffffffffff"
|
|
34
|
+
},
|
|
35
|
+
// RFC 3526 Section 6 — 6144-bit MODP Group
|
|
36
|
+
modp17: {
|
|
37
|
+
gen: "02",
|
|
38
|
+
prime: "ffffffffffffffffc90fdaa22168c234c4c6628b80dc1cd129024e088a67cc74020bbea63b139b22514a08798e3404ddef9519b3cd3a431b302b0a6df25f14374fe1356d6d51c245e485b576625e7ec6f44c42e9a637ed6b0bff5cb6f406b7edee386bfb5a899fa5ae9f24117c4b1fe649286651ece45b3dc2007cb8a163bf0598da48361c55d39a69163fa8fd24cf5f83655d23dca3ad961c62f356208552bb9ed529077096966d670c354e4abc9804f1746c08ca18217c32905e462e36ce3be39e772c180e86039b2783a2ec07a28fb5c55df06f4c52c9de2bcbf6955817183995497cea956ae515d2261898fa051015728e5a8aaac42dad33170d04507a33a85521abdf1cba64ecfb850458dbef0a8aea71575d060c7db3970f85a6e1e4c7abf5ae8cdb0933d71e8c94e04a25619dcee3d2261ad2ee6bf12ffa06d98a0864d87602733ec86a64521f2b18177b200cbbe117577a615d6c770988c0bad946e208e24fa074e5ab3143db5bfce0fd108e4b82d120a92108011a723c12a787e6d788719a10bdba5b2699c327186af4e23c1a946834b6150bda2583e9ca2ad44ce8dbbbc2db04de8ef92e8efc141fbecaa6287c59474e6bc05d99b2964fa090c3a2233ba186515be7ed1f612970cee2d7afb81bdd762170481cd0069127d5b05aa993b4ea988d8fddc186ffb7dc90a6c08f4df435c93402849236c3fab4d27c7026c1d4dcb2602646dec9751e763dba37bdf8ff9406ad9e530ee5db382f413001aeb06a53ed9027d831179727b0865a8918da3edbebcf9b14ed44ce6cbaced4bb1bdb7f1447e6cc254b332051512bd7af426fb8f401378cd2bf5983ca01c64b92ecf032ea15d1721d03f482d7ce6e74fef6d55e702f46980c82b5a84031900b1c9e59e7c97fbec7e8f323a97a7e36cc88be0f1d45b7ff585ac54bd407b22b4154aacc8f6d7ebf48e1d814cc5ed20f8037e0a79715eef29be32806a1d58bb7c5da76f550aa3d8a1fbff0eb19ccb1a313d55cda56c9ec2ef29632387fe8d76e3c0468043e8f663f4860ee12bf2d5b0b7474d6e694f91e6dcc4024ffffffffffffffff"
|
|
39
|
+
},
|
|
40
|
+
// RFC 3526 Section 7 — 8192-bit MODP Group
|
|
41
|
+
modp18: {
|
|
42
|
+
gen: "02",
|
|
43
|
+
prime: "ffffffffffffffffc90fdaa22168c234c4c6628b80dc1cd129024e088a67cc74020bbea63b139b22514a08798e3404ddef9519b3cd3a431b302b0a6df25f14374fe1356d6d51c245e485b576625e7ec6f44c42e9a637ed6b0bff5cb6f406b7edee386bfb5a899fa5ae9f24117c4b1fe649286651ece45b3dc2007cb8a163bf0598da48361c55d39a69163fa8fd24cf5f83655d23dca3ad961c62f356208552bb9ed529077096966d670c354e4abc9804f1746c08ca18217c32905e462e36ce3be39e772c180e86039b2783a2ec07a28fb5c55df06f4c52c9de2bcbf6955817183995497cea956ae515d2261898fa051015728e5a8aaac42dad33170d04507a33a85521abdf1cba64ecfb850458dbef0a8aea71575d060c7db3970f85a6e1e4c7abf5ae8cdb0933d71e8c94e04a25619dcee3d2261ad2ee6bf12ffa06d98a0864d87602733ec86a64521f2b18177b200cbbe117577a615d6c770988c0bad946e208e24fa074e5ab3143db5bfce0fd108e4b82d120a92108011a723c12a787e6d788719a10bdba5b2699c327186af4e23c1a946834b6150bda2583e9ca2ad44ce8dbbbc2db04de8ef92e8efc141fbecaa6287c59474e6bc05d99b2964fa090c3a2233ba186515be7ed1f612970cee2d7afb81bdd762170481cd0069127d5b05aa993b4ea988d8fddc186ffb7dc90a6c08f4df435c93402849236c3fab4d27c7026c1d4dcb2602646dec9751e763dba37bdf8ff9406ad9e530ee5db382f413001aeb06a53ed9027d831179727b0865a8918da3edbebcf9b14ed44ce6cbaced4bb1bdb7f1447e6cc254b332051512bd7af426fb8f401378cd2bf5983ca01c64b92ecf032ea15d1721d03f482d7ce6e74fef6d55e702f46980c82b5a84031900b1c9e59e7c97fbec7e8f323a97a7e36cc88be0f1d45b7ff585ac54bd407b22b4154aacc8f6d7ebf48e1d814cc5ed20f8037e0a79715eef29be32806a1d58bb7c5da76f550aa3d8a1fbff0eb19ccb1a313d55cda56c9ec2ef29632387fe8d76e3c0468043e8f663f4860ee12bf2d5b0b7474d6e694f91e6dbe115974a3926f12fee5e438777cb6a932df8cd8bec4d073b931ba3bc832b68d9dd300741fa7bf8afc47ed2576f6936ba424663aab639c5ae4f5683423b4742bf1c978238f16cbe39d652de3fdb8befc848ad922222e04a4037c0713eb57a81a23f0c73473fc646cea306b4bcbc8862f8385ddfa9d4b7fa2c087e879683303ed5bdd3a062b3cf5b3a278a66d2a13f83f44f82ddf310ee074ab6a364597e899a0255dc164f31cc50846851df9ab48195ded7ea1b1d510bd7ee74d73faf36bc31ecfa268359046f4eb879f924009438b481c6cd7889a002ed5ee382bc9190da6fc026e479558e4475677e9aa9e3050e2765694dfc81f56e880b96e7160c980dd98edd3dfffffffffffffffff"
|
|
44
|
+
}
|
|
45
|
+
};
|
|
46
|
+
function hexToBigInt(hex) {
|
|
47
|
+
if (hex.length === 0) return 0n;
|
|
48
|
+
return BigInt("0x" + hex);
|
|
49
|
+
}
|
|
50
|
+
function bigIntToBuffer(n) {
|
|
51
|
+
if (n === 0n) return Buffer.from([0]);
|
|
52
|
+
let hex = n.toString(16);
|
|
53
|
+
if (hex.length % 2 !== 0) {
|
|
54
|
+
hex = "0" + hex;
|
|
55
|
+
}
|
|
56
|
+
return Buffer.from(hex, "hex");
|
|
57
|
+
}
|
|
58
|
+
function bufferToBigInt(buf) {
|
|
59
|
+
if (buf.length === 0) return 0n;
|
|
60
|
+
const hex = Buffer.from(buf).toString("hex");
|
|
61
|
+
if (hex.length === 0) return 0n;
|
|
62
|
+
return BigInt("0x" + hex);
|
|
63
|
+
}
|
|
64
|
+
function bitLength(n) {
|
|
65
|
+
if (n === 0n) return 0;
|
|
66
|
+
return n.toString(2).length;
|
|
67
|
+
}
|
|
68
|
+
const SMALL_PRIMES = [];
|
|
69
|
+
{
|
|
70
|
+
const limit = 1e3;
|
|
71
|
+
const sieve = new Uint8Array(limit + 1);
|
|
72
|
+
for (let i = 2; i * i <= limit; i++) {
|
|
73
|
+
if (!sieve[i]) {
|
|
74
|
+
for (let j = i * i; j <= limit; j += i) {
|
|
75
|
+
sieve[j] = 1;
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
for (let i = 2; i <= limit; i++) {
|
|
80
|
+
if (!sieve[i]) SMALL_PRIMES.push(i);
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
function simpleSieve(n) {
|
|
84
|
+
for (const p of SMALL_PRIMES) {
|
|
85
|
+
const bp = BigInt(p);
|
|
86
|
+
if (n % bp === 0n) {
|
|
87
|
+
return n === bp;
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
return true;
|
|
91
|
+
}
|
|
92
|
+
function fermatTest(n) {
|
|
93
|
+
return modPow(2n, n - 1n, n) === 1n;
|
|
94
|
+
}
|
|
95
|
+
function millerRabinTest(n) {
|
|
96
|
+
if (n < 2n) return false;
|
|
97
|
+
if (n === 2n || n === 3n) return true;
|
|
98
|
+
if (n % 2n === 0n) return false;
|
|
99
|
+
let d = n - 1n;
|
|
100
|
+
let r = 0;
|
|
101
|
+
while (d % 2n === 0n) {
|
|
102
|
+
d /= 2n;
|
|
103
|
+
r++;
|
|
104
|
+
}
|
|
105
|
+
const witnesses = [2n, 3n, 5n, 7n, 11n, 13n];
|
|
106
|
+
for (const a of witnesses) {
|
|
107
|
+
if (a >= n) continue;
|
|
108
|
+
let x = modPow(a, d, n);
|
|
109
|
+
if (x === 1n || x === n - 1n) continue;
|
|
110
|
+
let composite = true;
|
|
111
|
+
for (let i = 0; i < r - 1; i++) {
|
|
112
|
+
x = modPow(x, 2n, n);
|
|
113
|
+
if (x === n - 1n) {
|
|
114
|
+
composite = false;
|
|
115
|
+
break;
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
if (composite) return false;
|
|
119
|
+
}
|
|
120
|
+
return true;
|
|
121
|
+
}
|
|
122
|
+
const DH_CHECK_P_NOT_PRIME = 1;
|
|
123
|
+
const DH_CHECK_P_NOT_SAFE_PRIME = 2;
|
|
124
|
+
const DH_NOT_SUITABLE_GENERATOR = 8;
|
|
125
|
+
const DH_UNABLE_TO_CHECK_GENERATOR = 4;
|
|
126
|
+
function checkPrime(prime, generatorBuf) {
|
|
127
|
+
const genHex = generatorBuf.toString("hex");
|
|
128
|
+
let error = 0;
|
|
129
|
+
if (prime % 2n === 0n || !simpleSieve(prime) || !fermatTest(prime) || !millerRabinTest(prime)) {
|
|
130
|
+
error += DH_CHECK_P_NOT_PRIME;
|
|
131
|
+
if (genHex === "02" || genHex === "05") {
|
|
132
|
+
error += DH_NOT_SUITABLE_GENERATOR;
|
|
133
|
+
} else {
|
|
134
|
+
error += DH_UNABLE_TO_CHECK_GENERATOR;
|
|
135
|
+
}
|
|
136
|
+
return error;
|
|
137
|
+
}
|
|
138
|
+
const halfPrime = prime >> 1n;
|
|
139
|
+
if (!millerRabinTest(halfPrime)) {
|
|
140
|
+
error += DH_CHECK_P_NOT_SAFE_PRIME;
|
|
141
|
+
}
|
|
142
|
+
switch (genHex) {
|
|
143
|
+
case "02":
|
|
144
|
+
if (prime % 24n !== 11n) {
|
|
145
|
+
error += DH_NOT_SUITABLE_GENERATOR;
|
|
146
|
+
}
|
|
147
|
+
break;
|
|
148
|
+
case "05":
|
|
149
|
+
{
|
|
150
|
+
const rem = prime % 10n;
|
|
151
|
+
if (rem !== 3n && rem !== 7n) {
|
|
152
|
+
error += DH_NOT_SUITABLE_GENERATOR;
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
break;
|
|
156
|
+
default:
|
|
157
|
+
error += DH_UNABLE_TO_CHECK_GENERATOR;
|
|
158
|
+
}
|
|
159
|
+
return error;
|
|
160
|
+
}
|
|
161
|
+
const primeCheckCache = {};
|
|
162
|
+
function getCachedCheckPrime(prime, generatorBuf) {
|
|
163
|
+
const key = generatorBuf.toString("hex") + "_" + prime.toString(16);
|
|
164
|
+
if (key in primeCheckCache) {
|
|
165
|
+
return primeCheckCache[key];
|
|
166
|
+
}
|
|
167
|
+
const result = checkPrime(prime, generatorBuf);
|
|
168
|
+
primeCheckCache[key] = result;
|
|
169
|
+
return result;
|
|
170
|
+
}
|
|
171
|
+
function toBuffer(value, encoding) {
|
|
172
|
+
if (Buffer.isBuffer(value)) return value;
|
|
173
|
+
if (value instanceof Uint8Array) return Buffer.from(value);
|
|
174
|
+
if (value instanceof ArrayBuffer) return Buffer.from(value);
|
|
175
|
+
if (typeof value === "string") return Buffer.from(value, encoding || "utf8");
|
|
176
|
+
if (typeof value === "number") {
|
|
177
|
+
const buf = Buffer.alloc(1);
|
|
178
|
+
buf[0] = value;
|
|
179
|
+
return buf;
|
|
180
|
+
}
|
|
181
|
+
throw new TypeError("Invalid input type");
|
|
182
|
+
}
|
|
183
|
+
function formatReturnValue(n, encoding) {
|
|
184
|
+
const buf = bigIntToBuffer(n);
|
|
185
|
+
if (!encoding) {
|
|
186
|
+
return buf;
|
|
187
|
+
}
|
|
188
|
+
return buf.toString(encoding);
|
|
189
|
+
}
|
|
190
|
+
class DiffieHellman {
|
|
191
|
+
_prime;
|
|
192
|
+
_generator;
|
|
193
|
+
_generatorBuf;
|
|
194
|
+
_primeByteLength;
|
|
195
|
+
_pubKey;
|
|
196
|
+
_privKey;
|
|
197
|
+
_primeCode;
|
|
198
|
+
_malleable;
|
|
199
|
+
constructor(prime, generator, malleable = false) {
|
|
200
|
+
this._prime = bufferToBigInt(prime);
|
|
201
|
+
this._generatorBuf = generator;
|
|
202
|
+
this._generator = bufferToBigInt(generator);
|
|
203
|
+
this._primeByteLength = prime.length;
|
|
204
|
+
this._pubKey = void 0;
|
|
205
|
+
this._privKey = void 0;
|
|
206
|
+
this._primeCode = void 0;
|
|
207
|
+
this._malleable = malleable;
|
|
208
|
+
if (!malleable) {
|
|
209
|
+
this._primeCode = 0;
|
|
210
|
+
this.setPublicKey = void 0;
|
|
211
|
+
this.setPrivateKey = void 0;
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
/**
|
|
215
|
+
* Error code from prime/generator validation.
|
|
216
|
+
* Lazily computed on first access.
|
|
217
|
+
*/
|
|
218
|
+
get verifyError() {
|
|
219
|
+
if (typeof this._primeCode !== "number") {
|
|
220
|
+
this._primeCode = getCachedCheckPrime(this._prime, this._generatorBuf);
|
|
221
|
+
}
|
|
222
|
+
return this._primeCode;
|
|
223
|
+
}
|
|
224
|
+
generateKeys(encoding) {
|
|
225
|
+
if (!this._privKey) {
|
|
226
|
+
const randBuf = randomBytes(this._primeByteLength);
|
|
227
|
+
this._privKey = bufferToBigInt(randBuf);
|
|
228
|
+
}
|
|
229
|
+
this._pubKey = modPow(this._generator, this._privKey, this._prime);
|
|
230
|
+
return this.getPublicKey(encoding);
|
|
231
|
+
}
|
|
232
|
+
computeSecret(otherPublicKey, inputEncoding, outputEncoding) {
|
|
233
|
+
let otherBuf;
|
|
234
|
+
if (typeof otherPublicKey === "string") {
|
|
235
|
+
otherBuf = Buffer.from(otherPublicKey, inputEncoding || "utf8");
|
|
236
|
+
} else {
|
|
237
|
+
otherBuf = Buffer.from(otherPublicKey);
|
|
238
|
+
}
|
|
239
|
+
const other = bufferToBigInt(otherBuf);
|
|
240
|
+
if (!this._privKey) {
|
|
241
|
+
throw new Error("You must generate keys before computing a secret");
|
|
242
|
+
}
|
|
243
|
+
if (other <= 0n || other >= this._prime) {
|
|
244
|
+
throw new Error("Supplied key is too large");
|
|
245
|
+
}
|
|
246
|
+
const secret = modPow(other, this._privKey, this._prime);
|
|
247
|
+
let out = bigIntToBuffer(secret);
|
|
248
|
+
const primeLen = this._primeByteLength;
|
|
249
|
+
if (out.length < primeLen) {
|
|
250
|
+
const padded = Buffer.alloc(primeLen);
|
|
251
|
+
out.copy(padded, primeLen - out.length);
|
|
252
|
+
out = padded;
|
|
253
|
+
}
|
|
254
|
+
if (outputEncoding) {
|
|
255
|
+
return out.toString(outputEncoding);
|
|
256
|
+
}
|
|
257
|
+
return out;
|
|
258
|
+
}
|
|
259
|
+
getPrime(encoding) {
|
|
260
|
+
return formatReturnValue(this._prime, encoding);
|
|
261
|
+
}
|
|
262
|
+
getGenerator(encoding) {
|
|
263
|
+
return formatReturnValue(this._generator, encoding);
|
|
264
|
+
}
|
|
265
|
+
getPublicKey(encoding) {
|
|
266
|
+
if (!this._pubKey) {
|
|
267
|
+
throw new Error("No public key - call generateKeys() first");
|
|
268
|
+
}
|
|
269
|
+
return formatReturnValue(this._pubKey, encoding);
|
|
270
|
+
}
|
|
271
|
+
getPrivateKey(encoding) {
|
|
272
|
+
if (!this._privKey) {
|
|
273
|
+
throw new Error("No private key - call generateKeys() first");
|
|
274
|
+
}
|
|
275
|
+
return formatReturnValue(this._privKey, encoding);
|
|
276
|
+
}
|
|
277
|
+
/**
|
|
278
|
+
* Set the public key. Only available for malleable DH instances
|
|
279
|
+
* (created via createDiffieHellman, not getDiffieHellman).
|
|
280
|
+
*/
|
|
281
|
+
setPublicKey(publicKey, encoding) {
|
|
282
|
+
if (!this._malleable) {
|
|
283
|
+
throw new Error("setPublicKey is not available for predefined DH groups");
|
|
284
|
+
}
|
|
285
|
+
const buf = typeof publicKey === "string" ? Buffer.from(publicKey, encoding || "utf8") : Buffer.from(publicKey);
|
|
286
|
+
this._pubKey = bufferToBigInt(buf);
|
|
287
|
+
}
|
|
288
|
+
/**
|
|
289
|
+
* Set the private key. Only available for malleable DH instances
|
|
290
|
+
* (created via createDiffieHellman, not getDiffieHellman).
|
|
291
|
+
*/
|
|
292
|
+
setPrivateKey(privateKey, encoding) {
|
|
293
|
+
if (!this._malleable) {
|
|
294
|
+
throw new Error("setPrivateKey is not available for predefined DH groups");
|
|
295
|
+
}
|
|
296
|
+
const buf = typeof privateKey === "string" ? Buffer.from(privateKey, encoding || "utf8") : Buffer.from(privateKey);
|
|
297
|
+
this._privKey = bufferToBigInt(buf);
|
|
298
|
+
}
|
|
299
|
+
}
|
|
300
|
+
function generatePrime(bits, generator) {
|
|
301
|
+
const gen = bufferToBigInt(generator);
|
|
302
|
+
if (bits < 16) {
|
|
303
|
+
if (gen === 2n || gen === 5n) {
|
|
304
|
+
return Buffer.from([140, 123]);
|
|
305
|
+
} else {
|
|
306
|
+
return Buffer.from([140, 39]);
|
|
307
|
+
}
|
|
308
|
+
}
|
|
309
|
+
const byteLen = Math.ceil(bits / 8);
|
|
310
|
+
const ONE = 1n;
|
|
311
|
+
const TWO = 2n;
|
|
312
|
+
const FOUR = 4n;
|
|
313
|
+
const TWENTYFOUR = 24n;
|
|
314
|
+
const ELEVEN = 11n;
|
|
315
|
+
const TEN = 10n;
|
|
316
|
+
const THREE = 3n;
|
|
317
|
+
while (true) {
|
|
318
|
+
const randBuf = randomBytes(byteLen);
|
|
319
|
+
let num = bufferToBigInt(randBuf);
|
|
320
|
+
while (bitLength(num) > bits) {
|
|
321
|
+
num >>= 1n;
|
|
322
|
+
}
|
|
323
|
+
if (num % TWO === 0n) {
|
|
324
|
+
num += ONE;
|
|
325
|
+
}
|
|
326
|
+
if (!(num & TWO)) {
|
|
327
|
+
num += TWO;
|
|
328
|
+
}
|
|
329
|
+
if (gen === TWO) {
|
|
330
|
+
while (num % TWENTYFOUR !== ELEVEN) {
|
|
331
|
+
num += FOUR;
|
|
332
|
+
}
|
|
333
|
+
} else if (gen === 5n) {
|
|
334
|
+
while (num % TEN !== THREE) {
|
|
335
|
+
num += FOUR;
|
|
336
|
+
}
|
|
337
|
+
}
|
|
338
|
+
const n2 = num >> 1n;
|
|
339
|
+
if (simpleSieve(n2) && simpleSieve(num) && fermatTest(n2) && fermatTest(num) && millerRabinTest(n2) && millerRabinTest(num)) {
|
|
340
|
+
return bigIntToBuffer(num);
|
|
341
|
+
}
|
|
342
|
+
}
|
|
343
|
+
}
|
|
344
|
+
const VALID_ENCODINGS = {
|
|
345
|
+
binary: true,
|
|
346
|
+
hex: true,
|
|
347
|
+
base64: true,
|
|
348
|
+
latin1: true,
|
|
349
|
+
utf8: true,
|
|
350
|
+
"utf-8": true,
|
|
351
|
+
base64url: true,
|
|
352
|
+
ascii: true,
|
|
353
|
+
ucs2: true,
|
|
354
|
+
"ucs-2": true,
|
|
355
|
+
utf16le: true,
|
|
356
|
+
"utf-16le": true
|
|
357
|
+
};
|
|
358
|
+
function createDiffieHellman(prime, primeEncoding, generator, generatorEncoding) {
|
|
359
|
+
if (primeEncoding !== void 0 && typeof primeEncoding !== "number" && (Buffer.isBuffer(primeEncoding) || primeEncoding instanceof Uint8Array || typeof primeEncoding === "string" && !(primeEncoding in VALID_ENCODINGS))) {
|
|
360
|
+
return createDiffieHellman(
|
|
361
|
+
prime,
|
|
362
|
+
"binary",
|
|
363
|
+
primeEncoding,
|
|
364
|
+
generator
|
|
365
|
+
);
|
|
366
|
+
}
|
|
367
|
+
const enc = primeEncoding || "binary";
|
|
368
|
+
const genc = generatorEncoding || "binary";
|
|
369
|
+
let genBuf = Buffer.from([2]);
|
|
370
|
+
if (generator !== void 0) {
|
|
371
|
+
if (typeof generator === "number") {
|
|
372
|
+
genBuf = Buffer.alloc(1);
|
|
373
|
+
genBuf[0] = generator;
|
|
374
|
+
} else if (!Buffer.isBuffer(generator)) {
|
|
375
|
+
genBuf = Buffer.from(generator, genc);
|
|
376
|
+
} else {
|
|
377
|
+
genBuf = generator;
|
|
378
|
+
}
|
|
379
|
+
}
|
|
380
|
+
if (typeof prime === "number") {
|
|
381
|
+
const primeBuf2 = generatePrime(prime, genBuf);
|
|
382
|
+
return new DiffieHellman(primeBuf2, genBuf, true);
|
|
383
|
+
}
|
|
384
|
+
let primeBuf;
|
|
385
|
+
if (Buffer.isBuffer(prime)) {
|
|
386
|
+
primeBuf = prime;
|
|
387
|
+
} else if (prime instanceof Uint8Array) {
|
|
388
|
+
primeBuf = Buffer.from(prime);
|
|
389
|
+
} else {
|
|
390
|
+
primeBuf = Buffer.from(prime, enc);
|
|
391
|
+
}
|
|
392
|
+
return new DiffieHellman(primeBuf, genBuf, true);
|
|
393
|
+
}
|
|
394
|
+
function getDiffieHellman(groupName) {
|
|
395
|
+
const group = PREDEFINED_GROUPS[groupName];
|
|
396
|
+
if (!group) {
|
|
397
|
+
throw new Error(`Unknown group: ${groupName}. Supported groups: ${Object.keys(PREDEFINED_GROUPS).join(", ")}`);
|
|
398
|
+
}
|
|
399
|
+
const primeBuf = Buffer.from(group.prime, "hex");
|
|
400
|
+
const genBuf = Buffer.from(group.gen, "hex");
|
|
401
|
+
return new DiffieHellman(primeBuf, genBuf, false);
|
|
402
|
+
}
|
|
403
|
+
const createDiffieHellmanGroup = getDiffieHellman;
|
|
404
|
+
const DiffieHellmanGroup = getDiffieHellman;
|
|
405
|
+
export {
|
|
406
|
+
DiffieHellman,
|
|
407
|
+
DiffieHellmanGroup,
|
|
408
|
+
createDiffieHellman,
|
|
409
|
+
createDiffieHellmanGroup,
|
|
410
|
+
getDiffieHellman
|
|
411
|
+
};
|