shogun-core 5.2.0 → 5.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/browser/defaultVendors-node_modules_hpke_chacha20poly1305_esm_mod_js.shogun-core.js +1220 -0
- package/dist/browser/defaultVendors-node_modules_hpke_chacha20poly1305_esm_mod_js.shogun-core.js.map +1 -0
- package/dist/browser/defaultVendors-node_modules_hpke_hybridkem-x-wing_esm_mod_js.shogun-core.js +844 -0
- package/dist/browser/defaultVendors-node_modules_hpke_hybridkem-x-wing_esm_mod_js.shogun-core.js.map +1 -0
- package/dist/browser/defaultVendors-node_modules_mlkem_esm_mod_js.shogun-core.js +2335 -0
- package/dist/browser/defaultVendors-node_modules_mlkem_esm_mod_js.shogun-core.js.map +1 -0
- package/dist/browser/defaultVendors-node_modules_noble_ciphers_chacha_js.shogun-core.js +999 -0
- package/dist/browser/defaultVendors-node_modules_noble_ciphers_chacha_js.shogun-core.js.map +1 -0
- package/dist/browser/defaultVendors-node_modules_noble_curves_esm_abstract_curve_js-node_modules_noble_curves_esm_-1ce4ed.shogun-core.js +1651 -0
- package/dist/browser/defaultVendors-node_modules_noble_curves_esm_abstract_curve_js-node_modules_noble_curves_esm_-1ce4ed.shogun-core.js.map +1 -0
- package/dist/browser/defaultVendors-node_modules_noble_curves_esm_abstract_edwards_js-node_modules_noble_curves_es-a82056.shogun-core.js +825 -0
- package/dist/browser/defaultVendors-node_modules_noble_curves_esm_abstract_edwards_js-node_modules_noble_curves_es-a82056.shogun-core.js.map +1 -0
- package/dist/browser/defaultVendors-node_modules_noble_curves_esm_ed25519_js.shogun-core.js +508 -0
- package/dist/browser/defaultVendors-node_modules_noble_curves_esm_ed25519_js.shogun-core.js.map +1 -0
- package/dist/browser/defaultVendors-node_modules_noble_curves_esm_ed448_js.shogun-core.js +747 -0
- package/dist/browser/defaultVendors-node_modules_noble_curves_esm_ed448_js.shogun-core.js.map +1 -0
- package/dist/browser/defaultVendors-node_modules_noble_curves_esm_nist_js.shogun-core.js +1608 -0
- package/dist/browser/defaultVendors-node_modules_noble_curves_esm_nist_js.shogun-core.js.map +1 -0
- package/dist/browser/defaultVendors-node_modules_noble_post-quantum_ml-dsa_js.shogun-core.js +2117 -0
- package/dist/browser/defaultVendors-node_modules_noble_post-quantum_ml-dsa_js.shogun-core.js.map +1 -0
- package/dist/browser/defaultVendors-node_modules_openpgp_dist_openpgp_min_mjs.shogun-core.js +86 -0
- package/dist/browser/defaultVendors-node_modules_openpgp_dist_openpgp_min_mjs.shogun-core.js.map +1 -0
- package/dist/browser/node_modules_hpke_ml-kem_esm_mod_js.shogun-core.js +539 -0
- package/dist/browser/node_modules_hpke_ml-kem_esm_mod_js.shogun-core.js.map +1 -0
- package/dist/browser/shogun-core.js +160386 -0
- package/dist/browser/shogun-core.js.map +1 -0
- package/dist/config/simplified-config.js +236 -0
- package/dist/core.js +329 -0
- package/dist/crypto/asymmetric.js +99 -0
- package/dist/crypto/double-ratchet.js +370 -0
- package/dist/crypto/file-encryption.js +213 -0
- package/dist/crypto/hashing.js +87 -0
- package/dist/crypto/index.js +34 -0
- package/dist/crypto/mls-codec.js +202 -0
- package/dist/crypto/mls.js +550 -0
- package/dist/crypto/pgp.js +390 -0
- package/dist/crypto/random-generation.js +341 -0
- package/dist/crypto/sframe.js +350 -0
- package/dist/crypto/signal-protocol.js +376 -0
- package/dist/crypto/symmetric.js +91 -0
- package/dist/crypto/types.js +2 -0
- package/dist/crypto/utils.js +140 -0
- package/dist/examples/auth-test.js +253 -0
- package/dist/examples/crypto-identity-example.js +151 -0
- package/dist/examples/crypto-working-test.js +83 -0
- package/dist/examples/double-ratchet-test.js +155 -0
- package/dist/examples/mls-advanced-example.js +294 -0
- package/dist/examples/mls-sframe-test.js +304 -0
- package/dist/examples/pgp-example.js +200 -0
- package/dist/examples/quick-auth-test.js +61 -0
- package/dist/examples/random-generation-test.js +151 -0
- package/dist/examples/signal-protocol-test.js +38 -0
- package/dist/examples/simple-api-test.js +114 -0
- package/dist/examples/simple-crypto-identity-example.js +84 -0
- package/dist/examples/timeout-test.js +227 -0
- package/dist/examples/zkproof-credentials-example.js +212 -0
- package/dist/examples/zkproof-example.js +201 -0
- package/dist/gundb/api.js +435 -0
- package/dist/gundb/crypto.js +283 -0
- package/dist/gundb/db.js +1946 -0
- package/dist/gundb/derive.js +232 -0
- package/dist/gundb/errors.js +76 -0
- package/dist/gundb/index.js +22 -0
- package/dist/gundb/rxjs.js +447 -0
- package/dist/gundb/types.js +5 -0
- package/dist/index.js +58 -0
- package/dist/interfaces/common.js +2 -0
- package/dist/interfaces/events.js +40 -0
- package/dist/interfaces/plugin.js +2 -0
- package/dist/interfaces/shogun.js +37 -0
- package/dist/managers/AuthManager.js +226 -0
- package/dist/managers/CoreInitializer.js +228 -0
- package/dist/managers/CryptoIdentityManager.js +366 -0
- package/dist/managers/EventManager.js +70 -0
- package/dist/managers/PluginManager.js +299 -0
- package/dist/plugins/base.js +50 -0
- package/dist/plugins/index.js +32 -0
- package/dist/plugins/nostr/index.js +20 -0
- package/dist/plugins/nostr/nostrConnector.js +419 -0
- package/dist/plugins/nostr/nostrConnectorPlugin.js +453 -0
- package/dist/plugins/nostr/nostrSigner.js +319 -0
- package/dist/plugins/nostr/types.js +2 -0
- package/dist/plugins/smartwallet/index.js +18 -0
- package/dist/plugins/smartwallet/smartWalletPlugin.js +511 -0
- package/dist/plugins/smartwallet/types.js +2 -0
- package/dist/plugins/web3/index.js +20 -0
- package/dist/plugins/web3/types.js +2 -0
- package/dist/plugins/web3/web3Connector.js +533 -0
- package/dist/plugins/web3/web3ConnectorPlugin.js +455 -0
- package/dist/plugins/web3/web3Signer.js +314 -0
- package/dist/plugins/webauthn/index.js +19 -0
- package/dist/plugins/webauthn/types.js +14 -0
- package/dist/plugins/webauthn/webauthn.js +496 -0
- package/dist/plugins/webauthn/webauthnPlugin.js +489 -0
- package/dist/plugins/webauthn/webauthnSigner.js +310 -0
- package/dist/plugins/zkproof/index.js +53 -0
- package/dist/plugins/zkproof/types.js +2 -0
- package/dist/plugins/zkproof/zkCredentials.js +213 -0
- package/dist/plugins/zkproof/zkProofConnector.js +198 -0
- package/dist/plugins/zkproof/zkProofPlugin.js +272 -0
- package/dist/storage/storage.js +145 -0
- package/dist/types/config/simplified-config.d.ts +114 -0
- package/dist/types/core.d.ts +305 -0
- package/dist/types/crypto/asymmetric.d.ts +6 -0
- package/dist/types/crypto/double-ratchet.d.ts +22 -0
- package/dist/types/crypto/file-encryption.d.ts +19 -0
- package/dist/types/crypto/hashing.d.ts +9 -0
- package/dist/types/crypto/index.d.ts +13 -0
- package/dist/types/crypto/mls-codec.d.ts +39 -0
- package/dist/types/crypto/mls.d.ts +130 -0
- package/dist/types/crypto/pgp.d.ts +95 -0
- package/dist/types/crypto/random-generation.d.ts +35 -0
- package/dist/types/crypto/sframe.d.ts +102 -0
- package/dist/types/crypto/signal-protocol.d.ts +26 -0
- package/dist/types/crypto/symmetric.d.ts +9 -0
- package/dist/types/crypto/types.d.ts +144 -0
- package/dist/types/crypto/utils.d.ts +22 -0
- package/dist/types/examples/auth-test.d.ts +8 -0
- package/dist/types/examples/crypto-identity-example.d.ts +5 -0
- package/dist/types/examples/crypto-working-test.d.ts +1 -0
- package/dist/types/examples/double-ratchet-test.d.ts +1 -0
- package/dist/types/examples/mls-advanced-example.d.ts +53 -0
- package/dist/types/examples/mls-sframe-test.d.ts +1 -0
- package/dist/types/examples/pgp-example.d.ts +75 -0
- package/dist/types/examples/quick-auth-test.d.ts +8 -0
- package/dist/types/examples/random-generation-test.d.ts +1 -0
- package/dist/types/examples/signal-protocol-test.d.ts +1 -0
- package/dist/types/examples/simple-api-test.d.ts +10 -0
- package/dist/types/examples/simple-crypto-identity-example.d.ts +6 -0
- package/dist/types/examples/timeout-test.d.ts +8 -0
- package/dist/types/examples/zkproof-credentials-example.d.ts +12 -0
- package/dist/types/examples/zkproof-example.d.ts +11 -0
- package/dist/types/gundb/api.d.ts +185 -0
- package/dist/types/gundb/crypto.d.ts +95 -0
- package/dist/types/gundb/db.d.ts +397 -0
- package/dist/types/gundb/derive.d.ts +21 -0
- package/dist/types/gundb/errors.d.ts +42 -0
- package/dist/types/gundb/index.d.ts +3 -0
- package/dist/types/gundb/rxjs.d.ts +110 -0
- package/dist/types/gundb/types.d.ts +255 -0
- package/dist/types/index.d.ts +16 -0
- package/dist/types/interfaces/common.d.ts +85 -0
- package/dist/types/interfaces/events.d.ts +131 -0
- package/dist/types/interfaces/plugin.d.ts +162 -0
- package/dist/types/interfaces/shogun.d.ts +208 -0
- package/dist/types/managers/AuthManager.d.ts +72 -0
- package/dist/types/managers/CoreInitializer.d.ts +40 -0
- package/dist/types/managers/CryptoIdentityManager.d.ts +102 -0
- package/dist/types/managers/EventManager.d.ts +49 -0
- package/dist/types/managers/PluginManager.d.ts +145 -0
- package/dist/types/plugins/base.d.ts +35 -0
- package/dist/types/plugins/index.d.ts +18 -0
- package/dist/types/plugins/nostr/index.d.ts +4 -0
- package/dist/types/plugins/nostr/nostrConnector.d.ts +119 -0
- package/dist/types/plugins/nostr/nostrConnectorPlugin.d.ts +163 -0
- package/dist/types/plugins/nostr/nostrSigner.d.ts +105 -0
- package/dist/types/plugins/nostr/types.d.ts +122 -0
- package/dist/types/plugins/smartwallet/index.d.ts +2 -0
- package/dist/types/plugins/smartwallet/smartWalletPlugin.d.ts +67 -0
- package/dist/types/plugins/smartwallet/types.d.ts +80 -0
- package/dist/types/plugins/web3/index.d.ts +4 -0
- package/dist/types/plugins/web3/types.d.ts +107 -0
- package/dist/types/plugins/web3/web3Connector.d.ts +129 -0
- package/dist/types/plugins/web3/web3ConnectorPlugin.d.ts +160 -0
- package/dist/types/plugins/web3/web3Signer.d.ts +114 -0
- package/dist/types/plugins/webauthn/index.d.ts +3 -0
- package/dist/types/plugins/webauthn/types.d.ts +183 -0
- package/dist/types/plugins/webauthn/webauthn.d.ts +129 -0
- package/dist/types/plugins/webauthn/webauthnPlugin.d.ts +179 -0
- package/dist/types/plugins/webauthn/webauthnSigner.d.ts +91 -0
- package/dist/types/plugins/zkproof/index.d.ts +48 -0
- package/dist/types/plugins/zkproof/types.d.ts +123 -0
- package/dist/types/plugins/zkproof/zkCredentials.d.ts +112 -0
- package/dist/types/plugins/zkproof/zkProofConnector.d.ts +46 -0
- package/dist/types/plugins/zkproof/zkProofPlugin.d.ts +76 -0
- package/dist/types/storage/storage.d.ts +51 -0
- package/dist/types/utils/errorHandler.d.ts +119 -0
- package/dist/types/utils/eventEmitter.d.ts +39 -0
- package/dist/types/utils/seedPhrase.d.ts +50 -0
- package/dist/types/utils/validation.d.ts +27 -0
- package/dist/utils/errorHandler.js +246 -0
- package/dist/utils/eventEmitter.js +79 -0
- package/dist/utils/seedPhrase.js +97 -0
- package/dist/utils/validation.js +81 -0
- package/package.json +10 -1
|
@@ -0,0 +1,2335 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
(this["webpackChunkShogunCore"] = this["webpackChunkShogunCore"] || []).push([["defaultVendors-node_modules_mlkem_esm_mod_js"],{
|
|
3
|
+
|
|
4
|
+
/***/ "./node_modules/mlkem/esm/mod.js":
|
|
5
|
+
/*!****************************************************!*\
|
|
6
|
+
!*** ./node_modules/mlkem/esm/mod.js + 12 modules ***!
|
|
7
|
+
\****************************************************/
|
|
8
|
+
/***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => {
|
|
9
|
+
|
|
10
|
+
// ESM COMPAT FLAG
|
|
11
|
+
__webpack_require__.r(__webpack_exports__);
|
|
12
|
+
|
|
13
|
+
// EXPORTS
|
|
14
|
+
__webpack_require__.d(__webpack_exports__, {
|
|
15
|
+
MlKem1024: () => (/* reexport */ MlKem1024),
|
|
16
|
+
MlKem512: () => (/* reexport */ MlKem512),
|
|
17
|
+
MlKem768: () => (/* reexport */ MlKem768),
|
|
18
|
+
MlKemError: () => (/* reexport */ MlKemError),
|
|
19
|
+
sha3_256: () => (/* reexport */ sha3_256),
|
|
20
|
+
sha3_512: () => (/* reexport */ sha3_512),
|
|
21
|
+
shake128: () => (/* reexport */ shake128),
|
|
22
|
+
shake256: () => (/* reexport */ shake256)
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
;// ./node_modules/mlkem/esm/src/errors.js
|
|
26
|
+
/**
|
|
27
|
+
* The base error class of kyber-ts.
|
|
28
|
+
*/
|
|
29
|
+
class MlKemError extends Error {
|
|
30
|
+
constructor(e) {
|
|
31
|
+
let message;
|
|
32
|
+
if (e instanceof Error) {
|
|
33
|
+
message = e.message;
|
|
34
|
+
}
|
|
35
|
+
else if (typeof e === "string") {
|
|
36
|
+
message = e;
|
|
37
|
+
}
|
|
38
|
+
else {
|
|
39
|
+
message = "";
|
|
40
|
+
}
|
|
41
|
+
super(message);
|
|
42
|
+
this.name = this.constructor.name;
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
;// ./node_modules/mlkem/esm/src/consts.js
|
|
47
|
+
/**
|
|
48
|
+
* This implementation is based on https://github.com/antontutoveanu/crystals-kyber-javascript,
|
|
49
|
+
* which was deveploped under the MIT licence below:
|
|
50
|
+
* https://github.com/antontutoveanu/crystals-kyber-javascript/blob/main/LICENSE
|
|
51
|
+
*/
|
|
52
|
+
const N = 256;
|
|
53
|
+
const Q = 3329;
|
|
54
|
+
const Q_INV = 62209;
|
|
55
|
+
// deno-fmt-ignore
|
|
56
|
+
const NTT_ZETAS = [
|
|
57
|
+
2285, 2571, 2970, 1812, 1493, 1422, 287, 202, 3158, 622, 1577, 182, 962,
|
|
58
|
+
2127, 1855, 1468, 573, 2004, 264, 383, 2500, 1458, 1727, 3199, 2648, 1017,
|
|
59
|
+
732, 608, 1787, 411, 3124, 1758, 1223, 652, 2777, 1015, 2036, 1491, 3047,
|
|
60
|
+
1785, 516, 3321, 3009, 2663, 1711, 2167, 126, 1469, 2476, 3239, 3058, 830,
|
|
61
|
+
107, 1908, 3082, 2378, 2931, 961, 1821, 2604, 448, 2264, 677, 2054, 2226,
|
|
62
|
+
430, 555, 843, 2078, 871, 1550, 105, 422, 587, 177, 3094, 3038, 2869, 1574,
|
|
63
|
+
1653, 3083, 778, 1159, 3182, 2552, 1483, 2727, 1119, 1739, 644, 2457, 349,
|
|
64
|
+
418, 329, 3173, 3254, 817, 1097, 603, 610, 1322, 2044, 1864, 384, 2114, 3193,
|
|
65
|
+
1218, 1994, 2455, 220, 2142, 1670, 2144, 1799, 2051, 794, 1819, 2475, 2459,
|
|
66
|
+
478, 3221, 3021, 996, 991, 958, 1869, 1522, 1628,
|
|
67
|
+
];
|
|
68
|
+
// deno-fmt-ignore
|
|
69
|
+
const NTT_ZETAS_INV = [
|
|
70
|
+
1701, 1807, 1460, 2371, 2338, 2333, 308, 108, 2851, 870, 854, 1510, 2535,
|
|
71
|
+
1278, 1530, 1185, 1659, 1187, 3109, 874, 1335, 2111, 136, 1215, 2945, 1465,
|
|
72
|
+
1285, 2007, 2719, 2726, 2232, 2512, 75, 156, 3000, 2911, 2980, 872, 2685,
|
|
73
|
+
1590, 2210, 602, 1846, 777, 147, 2170, 2551, 246, 1676, 1755, 460, 291, 235,
|
|
74
|
+
3152, 2742, 2907, 3224, 1779, 2458, 1251, 2486, 2774, 2899, 1103, 1275, 2652,
|
|
75
|
+
1065, 2881, 725, 1508, 2368, 398, 951, 247, 1421, 3222, 2499, 271, 90, 853,
|
|
76
|
+
1860, 3203, 1162, 1618, 666, 320, 8, 2813, 1544, 282, 1838, 1293, 2314, 552,
|
|
77
|
+
2677, 2106, 1571, 205, 2918, 1542, 2721, 2597, 2312, 681, 130, 1602, 1871,
|
|
78
|
+
829, 2946, 3065, 1325, 2756, 1861, 1474, 1202, 2367, 3147, 1752, 2707, 171,
|
|
79
|
+
3127, 3042, 1907, 1836, 1517, 359, 758, 1441,
|
|
80
|
+
];
|
|
81
|
+
|
|
82
|
+
;// ./node_modules/mlkem/esm/src/sha3/_u64.js
|
|
83
|
+
/**
|
|
84
|
+
* This file is based on noble-hashes (https://github.com/paulmillr/noble-hashes).
|
|
85
|
+
*
|
|
86
|
+
* noble-hashes - MIT License (c) 2022 Paul Miller (paulmillr.com)
|
|
87
|
+
*
|
|
88
|
+
* The original file is located at:
|
|
89
|
+
* https://github.com/paulmillr/noble-hashes/blob/4e358a46d682adfb005ae6314ec999f2513086b9/src/_u64.ts
|
|
90
|
+
*/
|
|
91
|
+
/**
|
|
92
|
+
* Internal helpers for u64. BigUint64Array is too slow as per 2025, so we implement it using Uint32Array.
|
|
93
|
+
* @todo re-check https://issues.chromium.org/issues/42212588
|
|
94
|
+
* @module
|
|
95
|
+
*/
|
|
96
|
+
const U32_MASK64 = /* @__PURE__ */ BigInt(2 ** 32 - 1);
|
|
97
|
+
const _32n = /* @__PURE__ */ BigInt(32);
|
|
98
|
+
function fromBig(n, le = false) {
|
|
99
|
+
if (le) {
|
|
100
|
+
return { h: Number(n & U32_MASK64), l: Number((n >> _32n) & U32_MASK64) };
|
|
101
|
+
}
|
|
102
|
+
return {
|
|
103
|
+
h: Number((n >> _32n) & U32_MASK64) | 0,
|
|
104
|
+
l: Number(n & U32_MASK64) | 0,
|
|
105
|
+
};
|
|
106
|
+
}
|
|
107
|
+
function split(lst, le = false) {
|
|
108
|
+
const len = lst.length;
|
|
109
|
+
const Ah = new Uint32Array(len);
|
|
110
|
+
const Al = new Uint32Array(len);
|
|
111
|
+
for (let i = 0; i < len; i++) {
|
|
112
|
+
const { h, l } = fromBig(lst[i], le);
|
|
113
|
+
[Ah[i], Al[i]] = [h, l];
|
|
114
|
+
}
|
|
115
|
+
return [Ah, Al];
|
|
116
|
+
}
|
|
117
|
+
const toBig = (h, l) => (BigInt(h >>> 0) << _32n) | BigInt(l >>> 0);
|
|
118
|
+
// for Shift in [0, 32)
|
|
119
|
+
const shrSH = (h, _l, s) => h >>> s;
|
|
120
|
+
const shrSL = (h, l, s) => (h << (32 - s)) | (l >>> s);
|
|
121
|
+
// Right rotate for Shift in [1, 32)
|
|
122
|
+
const rotrSH = (h, l, s) => (h >>> s) | (l << (32 - s));
|
|
123
|
+
const rotrSL = (h, l, s) => (h << (32 - s)) | (l >>> s);
|
|
124
|
+
// Right rotate for Shift in (32, 64), NOTE: 32 is special case.
|
|
125
|
+
const rotrBH = (h, l, s) => (h << (64 - s)) | (l >>> (s - 32));
|
|
126
|
+
const rotrBL = (h, l, s) => (h >>> (s - 32)) | (l << (64 - s));
|
|
127
|
+
// Right rotate for shift===32 (just swaps l&h)
|
|
128
|
+
const rotr32H = (_h, l) => l;
|
|
129
|
+
const rotr32L = (h, _l) => h;
|
|
130
|
+
// Left rotate for Shift in [1, 32)
|
|
131
|
+
const rotlSH = (h, l, s) => (h << s) | (l >>> (32 - s));
|
|
132
|
+
const rotlSL = (h, l, s) => (l << s) | (h >>> (32 - s));
|
|
133
|
+
// Left rotate for Shift in (32, 64), NOTE: 32 is special case.
|
|
134
|
+
const rotlBH = (h, l, s) => (l << (s - 32)) | (h >>> (64 - s));
|
|
135
|
+
const rotlBL = (h, l, s) => (h << (s - 32)) | (l >>> (64 - s));
|
|
136
|
+
// JS uses 32-bit signed integers for bitwise operations which means we cannot
|
|
137
|
+
// simple take carry out of low bit sum by shift, we need to use division.
|
|
138
|
+
function add(Ah, Al, Bh, Bl) {
|
|
139
|
+
const l = (Al >>> 0) + (Bl >>> 0);
|
|
140
|
+
return { h: (Ah + Bh + ((l / 2 ** 32) | 0)) | 0, l: l | 0 };
|
|
141
|
+
}
|
|
142
|
+
// Addition with more than 2 elements
|
|
143
|
+
const add3L = (Al, Bl, Cl) => (Al >>> 0) + (Bl >>> 0) + (Cl >>> 0);
|
|
144
|
+
const add3H = (low, Ah, Bh, Ch) => (Ah + Bh + Ch + ((low / 2 ** 32) | 0)) | 0;
|
|
145
|
+
const add4L = (Al, Bl, Cl, Dl) => (Al >>> 0) + (Bl >>> 0) + (Cl >>> 0) + (Dl >>> 0);
|
|
146
|
+
const add4H = (low, Ah, Bh, Ch, Dh) => (Ah + Bh + Ch + Dh + ((low / 2 ** 32) | 0)) | 0;
|
|
147
|
+
const add5L = (Al, Bl, Cl, Dl, El) => (Al >>> 0) + (Bl >>> 0) + (Cl >>> 0) + (Dl >>> 0) + (El >>> 0);
|
|
148
|
+
const add5H = (low, Ah, Bh, Ch, Dh, Eh) => (Ah + Bh + Ch + Dh + Eh + ((low / 2 ** 32) | 0)) | 0;
|
|
149
|
+
// prettier-ignore
|
|
150
|
+
|
|
151
|
+
// prettier-ignore
|
|
152
|
+
const u64 = {
|
|
153
|
+
fromBig,
|
|
154
|
+
split,
|
|
155
|
+
toBig,
|
|
156
|
+
shrSH,
|
|
157
|
+
shrSL,
|
|
158
|
+
rotrSH,
|
|
159
|
+
rotrSL,
|
|
160
|
+
rotrBH,
|
|
161
|
+
rotrBL,
|
|
162
|
+
rotr32H,
|
|
163
|
+
rotr32L,
|
|
164
|
+
rotlSH,
|
|
165
|
+
rotlSL,
|
|
166
|
+
rotlBH,
|
|
167
|
+
rotlBL,
|
|
168
|
+
add,
|
|
169
|
+
add3L,
|
|
170
|
+
add3H,
|
|
171
|
+
add4L,
|
|
172
|
+
add4H,
|
|
173
|
+
add5H,
|
|
174
|
+
add5L,
|
|
175
|
+
};
|
|
176
|
+
/* harmony default export */ const _u64 = (u64);
|
|
177
|
+
|
|
178
|
+
;// ./node_modules/mlkem/esm/src/sha3/utils.js
|
|
179
|
+
// deno-lint-ignore-file no-explicit-any
|
|
180
|
+
/**
|
|
181
|
+
* This file is based on noble-hashes (https://github.com/paulmillr/noble-hashes).
|
|
182
|
+
*
|
|
183
|
+
* noble-hashes - MIT License (c) 2022 Paul Miller (paulmillr.com)
|
|
184
|
+
*
|
|
185
|
+
* The original file is located at:
|
|
186
|
+
* https://github.com/paulmillr/noble-hashes/blob/4e358a46d682adfb005ae6314ec999f2513086b9/src/utils.ts
|
|
187
|
+
*/
|
|
188
|
+
/**
|
|
189
|
+
* Utilities for hex, bytes, CSPRNG.
|
|
190
|
+
* @module
|
|
191
|
+
*/
|
|
192
|
+
/*! noble-hashes - MIT License (c) 2022 Paul Miller (paulmillr.com) */
|
|
193
|
+
/** Checks if something is Uint8Array. Be careful: nodejs Buffer will return true. */
|
|
194
|
+
function isBytes(a) {
|
|
195
|
+
return a instanceof Uint8Array ||
|
|
196
|
+
(ArrayBuffer.isView(a) && a.constructor.name === "Uint8Array");
|
|
197
|
+
}
|
|
198
|
+
/** Asserts something is positive integer. */
|
|
199
|
+
function anumber(n, title = "") {
|
|
200
|
+
if (!Number.isSafeInteger(n) || n < 0) {
|
|
201
|
+
const prefix = title && `"${title}" `;
|
|
202
|
+
throw new Error(`${prefix}expected integer >0, got ${n}`);
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
/** Asserts something is Uint8Array. */
|
|
206
|
+
function abytes(value, length, title = "") {
|
|
207
|
+
const bytes = isBytes(value);
|
|
208
|
+
const len = value?.length;
|
|
209
|
+
const needsLen = length !== undefined;
|
|
210
|
+
if (!bytes || (needsLen && len !== length)) {
|
|
211
|
+
const prefix = title && `"${title}" `;
|
|
212
|
+
const ofLen = needsLen ? ` of length ${length}` : "";
|
|
213
|
+
const got = bytes ? `length=${len}` : `type=${typeof value}`;
|
|
214
|
+
throw new Error(prefix + "expected Uint8Array" + ofLen + ", got " + got);
|
|
215
|
+
}
|
|
216
|
+
return value;
|
|
217
|
+
}
|
|
218
|
+
/** Asserts a hash instance has not been destroyed / finished */
|
|
219
|
+
function aexists(instance, checkFinished = true) {
|
|
220
|
+
if (instance.destroyed)
|
|
221
|
+
throw new Error("Hash instance has been destroyed");
|
|
222
|
+
if (checkFinished && instance.finished) {
|
|
223
|
+
throw new Error("Hash#digest() has already been called");
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
/** Asserts output is properly-sized byte array */
|
|
227
|
+
function aoutput(out, instance) {
|
|
228
|
+
abytes(out, undefined, "digestInto() output");
|
|
229
|
+
const min = instance.outputLen;
|
|
230
|
+
if (out.length < min) {
|
|
231
|
+
throw new Error('"digestInto() output" expected to be of length >=' + min);
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
/** Cast u8 / u16 / u32 to u32. */
|
|
235
|
+
function u32(arr) {
|
|
236
|
+
return new Uint32Array(arr.buffer, arr.byteOffset, Math.floor(arr.byteLength / 4));
|
|
237
|
+
}
|
|
238
|
+
/** Zeroize a byte array. Warning: JS provides no guarantees. */
|
|
239
|
+
function clean(...arrays) {
|
|
240
|
+
for (let i = 0; i < arrays.length; i++) {
|
|
241
|
+
arrays[i].fill(0);
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
/** Is current platform little-endian? Most are. Big-Endian platform: IBM */
|
|
245
|
+
const isLE =
|
|
246
|
+
/* @__PURE__ */ (() => new Uint8Array(new Uint32Array([0x11223344]).buffer)[0] === 0x44)();
|
|
247
|
+
/** The byte swap operation for uint32 */
|
|
248
|
+
function byteSwap(word) {
|
|
249
|
+
return (((word << 24) & 0xff000000) |
|
|
250
|
+
((word << 8) & 0xff0000) |
|
|
251
|
+
((word >>> 8) & 0xff00) |
|
|
252
|
+
((word >>> 24) & 0xff));
|
|
253
|
+
}
|
|
254
|
+
/** Conditionally byte swap if on a big-endian platform */
|
|
255
|
+
const swap8IfBE = isLE
|
|
256
|
+
? (n) => n
|
|
257
|
+
: (n) => byteSwap(n);
|
|
258
|
+
/** @deprecated */
|
|
259
|
+
const byteSwapIfBE = swap8IfBE;
|
|
260
|
+
/** In place byte swap for Uint32Array */
|
|
261
|
+
function byteSwap32(arr) {
|
|
262
|
+
for (let i = 0; i < arr.length; i++) {
|
|
263
|
+
arr[i] = byteSwap(arr[i]);
|
|
264
|
+
}
|
|
265
|
+
return arr;
|
|
266
|
+
}
|
|
267
|
+
const swap32IfBE = isLE
|
|
268
|
+
? (u) => u
|
|
269
|
+
: byteSwap32;
|
|
270
|
+
// Built-in hex conversion https://caniuse.com/mdn-javascript_builtins_uint8array_fromhex
|
|
271
|
+
const hasHexBuiltin = /* @__PURE__ */ (() =>
|
|
272
|
+
// @ts-ignore: to check the existence of the method
|
|
273
|
+
typeof Uint8Array.from([]).toHex === "function" &&
|
|
274
|
+
// @ts-ignore: to check the existence of the method
|
|
275
|
+
typeof Uint8Array.fromHex === "function")();
|
|
276
|
+
// We use optimized technique to convert hex string to byte array
|
|
277
|
+
const asciis = { _0: 48, _9: 57, A: 65, F: 70, a: 97, f: 102 };
|
|
278
|
+
function asciiToBase16(ch) {
|
|
279
|
+
if (ch >= asciis._0 && ch <= asciis._9)
|
|
280
|
+
return ch - asciis._0; // '2' => 50-48
|
|
281
|
+
if (ch >= asciis.A && ch <= asciis.F)
|
|
282
|
+
return ch - (asciis.A - 10); // 'B' => 66-(65-10)
|
|
283
|
+
if (ch >= asciis.a && ch <= asciis.f)
|
|
284
|
+
return ch - (asciis.a - 10); // 'b' => 98-(97-10)
|
|
285
|
+
return;
|
|
286
|
+
}
|
|
287
|
+
/**
|
|
288
|
+
* Convert hex string to byte array. Uses built-in function, when available.
|
|
289
|
+
* @example hexToBytes('cafe0123') // Uint8Array.from([0xca, 0xfe, 0x01, 0x23])
|
|
290
|
+
*/
|
|
291
|
+
function hexToBytes(hex) {
|
|
292
|
+
if (typeof hex !== "string") {
|
|
293
|
+
throw new Error("hex string expected, got " + typeof hex);
|
|
294
|
+
}
|
|
295
|
+
// @ts-ignore: to check the existence of the method
|
|
296
|
+
if (hasHexBuiltin)
|
|
297
|
+
return Uint8Array.fromHex(hex);
|
|
298
|
+
const hl = hex.length;
|
|
299
|
+
const al = hl / 2;
|
|
300
|
+
if (hl % 2) {
|
|
301
|
+
throw new Error("hex string expected, got unpadded hex of length " + hl);
|
|
302
|
+
}
|
|
303
|
+
const array = new Uint8Array(al);
|
|
304
|
+
for (let ai = 0, hi = 0; ai < al; ai++, hi += 2) {
|
|
305
|
+
const n1 = asciiToBase16(hex.charCodeAt(hi));
|
|
306
|
+
const n2 = asciiToBase16(hex.charCodeAt(hi + 1));
|
|
307
|
+
if (n1 === undefined || n2 === undefined) {
|
|
308
|
+
const char = hex[hi] + hex[hi + 1];
|
|
309
|
+
throw new Error('hex string expected, got non-hex character "' + char + '" at index ' +
|
|
310
|
+
hi);
|
|
311
|
+
}
|
|
312
|
+
array[ai] = n1 * 16 + n2; // multiply first octet, e.g. 'a3' => 10*16+3 => 160 + 3 => 163
|
|
313
|
+
}
|
|
314
|
+
return array;
|
|
315
|
+
}
|
|
316
|
+
/**
|
|
317
|
+
* Converts string to bytes using UTF8 encoding.
|
|
318
|
+
* @example utf8ToBytes('abc') // Uint8Array.from([97, 98, 99])
|
|
319
|
+
*/
|
|
320
|
+
function utf8ToBytes(str) {
|
|
321
|
+
if (typeof str !== "string")
|
|
322
|
+
throw new Error("string expected");
|
|
323
|
+
return new Uint8Array(new TextEncoder().encode(str)); // https://bugzil.la/1681809
|
|
324
|
+
}
|
|
325
|
+
/**
|
|
326
|
+
* Converts bytes to string using UTF8 encoding.
|
|
327
|
+
* @example bytesToUtf8(Uint8Array.from([97, 98, 99])) // 'abc'
|
|
328
|
+
*/
|
|
329
|
+
function bytesToUtf8(bytes) {
|
|
330
|
+
return new TextDecoder().decode(bytes);
|
|
331
|
+
}
|
|
332
|
+
/** Copies several Uint8Arrays into one. */
|
|
333
|
+
function concatBytes(...arrays) {
|
|
334
|
+
let sum = 0;
|
|
335
|
+
for (let i = 0; i < arrays.length; i++) {
|
|
336
|
+
const a = arrays[i];
|
|
337
|
+
abytes(a);
|
|
338
|
+
sum += a.length;
|
|
339
|
+
}
|
|
340
|
+
const res = new Uint8Array(sum);
|
|
341
|
+
for (let i = 0, pad = 0; i < arrays.length; i++) {
|
|
342
|
+
const a = arrays[i];
|
|
343
|
+
res.set(a, pad);
|
|
344
|
+
pad += a.length;
|
|
345
|
+
}
|
|
346
|
+
return res;
|
|
347
|
+
}
|
|
348
|
+
function createHasher(hashCons, info = {}) {
|
|
349
|
+
const hashC = (msg, opts) => hashCons(opts).update(msg).digest();
|
|
350
|
+
const tmp = hashCons(undefined);
|
|
351
|
+
hashC.outputLen = tmp.outputLen;
|
|
352
|
+
hashC.blockLen = tmp.blockLen;
|
|
353
|
+
hashC.create = (opts) => hashCons(opts);
|
|
354
|
+
Object.assign(hashC, info);
|
|
355
|
+
return Object.freeze(hashC);
|
|
356
|
+
}
|
|
357
|
+
// 06 09 60 86 48 01 65 03 04 02
|
|
358
|
+
const oidNist = (suffix) => ({
|
|
359
|
+
oid: Uint8Array.from([
|
|
360
|
+
0x06,
|
|
361
|
+
0x09,
|
|
362
|
+
0x60,
|
|
363
|
+
0x86,
|
|
364
|
+
0x48,
|
|
365
|
+
0x01,
|
|
366
|
+
0x65,
|
|
367
|
+
0x03,
|
|
368
|
+
0x04,
|
|
369
|
+
0x02,
|
|
370
|
+
suffix,
|
|
371
|
+
]),
|
|
372
|
+
});
|
|
373
|
+
|
|
374
|
+
;// ./node_modules/mlkem/esm/src/sha3/sha3.js
|
|
375
|
+
/**
|
|
376
|
+
* This file is based on noble-hashes (https://github.com/paulmillr/noble-hashes).
|
|
377
|
+
*
|
|
378
|
+
* noble-hashes - MIT License (c) 2022 Paul Miller (paulmillr.com)
|
|
379
|
+
*
|
|
380
|
+
* The original file is located at:
|
|
381
|
+
* https://github.com/paulmillr/noble-hashes/blob/4e358a46d682adfb005ae6314ec999f2513086b9/src/sha3.ts
|
|
382
|
+
*/
|
|
383
|
+
/**
|
|
384
|
+
* SHA3 (keccak) hash function, based on a new "Sponge function" design.
|
|
385
|
+
* Different from older hashes, the internal state is bigger than output size.
|
|
386
|
+
*
|
|
387
|
+
* Check out [FIPS-202](https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.202.pdf),
|
|
388
|
+
* [Website](https://keccak.team/keccak.html),
|
|
389
|
+
* [the differences between SHA-3 and Keccak](https://crypto.stackexchange.com/questions/15727/what-are-the-key-differences-between-the-draft-sha-3-standard-and-the-keccak-sub).
|
|
390
|
+
*
|
|
391
|
+
* Check out `sha3-addons` module for cSHAKE, k12, and others.
|
|
392
|
+
* @module
|
|
393
|
+
*/
|
|
394
|
+
|
|
395
|
+
// prettier-ignore
|
|
396
|
+
|
|
397
|
+
// No __PURE__ annotations in sha3 header:
|
|
398
|
+
// EVERYTHING is in fact used on every export.
|
|
399
|
+
// Various per round constants calculations
|
|
400
|
+
const _0n = BigInt(0);
|
|
401
|
+
const _1n = BigInt(1);
|
|
402
|
+
const _2n = BigInt(2);
|
|
403
|
+
const _7n = BigInt(7);
|
|
404
|
+
const _256n = BigInt(256);
|
|
405
|
+
const _0x71n = BigInt(0x71);
|
|
406
|
+
const SHA3_PI = [];
|
|
407
|
+
const SHA3_ROTL = [];
|
|
408
|
+
const _SHA3_IOTA = []; // no pure annotation: var is always used
|
|
409
|
+
for (let round = 0, R = _1n, x = 1, y = 0; round < 24; round++) {
|
|
410
|
+
// Pi
|
|
411
|
+
[x, y] = [y, (2 * x + 3 * y) % 5];
|
|
412
|
+
SHA3_PI.push(2 * (5 * y + x));
|
|
413
|
+
// Rotational
|
|
414
|
+
SHA3_ROTL.push((((round + 1) * (round + 2)) / 2) % 64);
|
|
415
|
+
// Iota
|
|
416
|
+
let t = _0n;
|
|
417
|
+
for (let j = 0; j < 7; j++) {
|
|
418
|
+
R = ((R << _1n) ^ ((R >> _7n) * _0x71n)) % _256n;
|
|
419
|
+
if (R & _2n)
|
|
420
|
+
t ^= _1n << ((_1n << BigInt(j)) - _1n);
|
|
421
|
+
}
|
|
422
|
+
_SHA3_IOTA.push(t);
|
|
423
|
+
}
|
|
424
|
+
const IOTAS = split(_SHA3_IOTA, true);
|
|
425
|
+
const SHA3_IOTA_H = IOTAS[0];
|
|
426
|
+
const SHA3_IOTA_L = IOTAS[1];
|
|
427
|
+
// Left rotation (without 0, 32, 64)
|
|
428
|
+
const rotlH = (h, l, s) => (s > 32 ? rotlBH(h, l, s) : rotlSH(h, l, s));
|
|
429
|
+
const rotlL = (h, l, s) => (s > 32 ? rotlBL(h, l, s) : rotlSL(h, l, s));
|
|
430
|
+
/** `keccakf1600` internal function, additionally allows to adjust round count. */
|
|
431
|
+
function keccakP(s, rounds = 24) {
|
|
432
|
+
const B = new Uint32Array(5 * 2);
|
|
433
|
+
// NOTE: all indices are x2 since we store state as u32 instead of u64 (bigints to slow in js)
|
|
434
|
+
for (let round = 24 - rounds; round < 24; round++) {
|
|
435
|
+
// Theta θ
|
|
436
|
+
for (let x = 0; x < 10; x++) {
|
|
437
|
+
B[x] = s[x] ^ s[x + 10] ^ s[x + 20] ^ s[x + 30] ^ s[x + 40];
|
|
438
|
+
}
|
|
439
|
+
for (let x = 0; x < 10; x += 2) {
|
|
440
|
+
const idx1 = (x + 8) % 10;
|
|
441
|
+
const idx0 = (x + 2) % 10;
|
|
442
|
+
const B0 = B[idx0];
|
|
443
|
+
const B1 = B[idx0 + 1];
|
|
444
|
+
const Th = rotlH(B0, B1, 1) ^ B[idx1];
|
|
445
|
+
const Tl = rotlL(B0, B1, 1) ^ B[idx1 + 1];
|
|
446
|
+
for (let y = 0; y < 50; y += 10) {
|
|
447
|
+
s[x + y] ^= Th;
|
|
448
|
+
s[x + y + 1] ^= Tl;
|
|
449
|
+
}
|
|
450
|
+
}
|
|
451
|
+
// Rho (ρ) and Pi (π)
|
|
452
|
+
let curH = s[2];
|
|
453
|
+
let curL = s[3];
|
|
454
|
+
for (let t = 0; t < 24; t++) {
|
|
455
|
+
const shift = SHA3_ROTL[t];
|
|
456
|
+
const Th = rotlH(curH, curL, shift);
|
|
457
|
+
const Tl = rotlL(curH, curL, shift);
|
|
458
|
+
const PI = SHA3_PI[t];
|
|
459
|
+
curH = s[PI];
|
|
460
|
+
curL = s[PI + 1];
|
|
461
|
+
s[PI] = Th;
|
|
462
|
+
s[PI + 1] = Tl;
|
|
463
|
+
}
|
|
464
|
+
// Chi (χ)
|
|
465
|
+
for (let y = 0; y < 50; y += 10) {
|
|
466
|
+
for (let x = 0; x < 10; x++)
|
|
467
|
+
B[x] = s[y + x];
|
|
468
|
+
for (let x = 0; x < 10; x++) {
|
|
469
|
+
s[y + x] ^= ~B[(x + 2) % 10] & B[(x + 4) % 10];
|
|
470
|
+
}
|
|
471
|
+
}
|
|
472
|
+
// Iota (ι)
|
|
473
|
+
s[0] ^= SHA3_IOTA_H[round];
|
|
474
|
+
s[1] ^= SHA3_IOTA_L[round];
|
|
475
|
+
}
|
|
476
|
+
clean(B);
|
|
477
|
+
}
|
|
478
|
+
/** Keccak sponge function. */
|
|
479
|
+
class Keccak {
|
|
480
|
+
// NOTE: we accept arguments in bytes instead of bits here.
|
|
481
|
+
constructor(blockLen, suffix, outputLen, enableXOF = false, rounds = 24) {
|
|
482
|
+
Object.defineProperty(this, "state", {
|
|
483
|
+
enumerable: true,
|
|
484
|
+
configurable: true,
|
|
485
|
+
writable: true,
|
|
486
|
+
value: void 0
|
|
487
|
+
});
|
|
488
|
+
Object.defineProperty(this, "pos", {
|
|
489
|
+
enumerable: true,
|
|
490
|
+
configurable: true,
|
|
491
|
+
writable: true,
|
|
492
|
+
value: 0
|
|
493
|
+
});
|
|
494
|
+
Object.defineProperty(this, "posOut", {
|
|
495
|
+
enumerable: true,
|
|
496
|
+
configurable: true,
|
|
497
|
+
writable: true,
|
|
498
|
+
value: 0
|
|
499
|
+
});
|
|
500
|
+
Object.defineProperty(this, "finished", {
|
|
501
|
+
enumerable: true,
|
|
502
|
+
configurable: true,
|
|
503
|
+
writable: true,
|
|
504
|
+
value: false
|
|
505
|
+
});
|
|
506
|
+
Object.defineProperty(this, "state32", {
|
|
507
|
+
enumerable: true,
|
|
508
|
+
configurable: true,
|
|
509
|
+
writable: true,
|
|
510
|
+
value: void 0
|
|
511
|
+
});
|
|
512
|
+
Object.defineProperty(this, "destroyed", {
|
|
513
|
+
enumerable: true,
|
|
514
|
+
configurable: true,
|
|
515
|
+
writable: true,
|
|
516
|
+
value: false
|
|
517
|
+
});
|
|
518
|
+
Object.defineProperty(this, "blockLen", {
|
|
519
|
+
enumerable: true,
|
|
520
|
+
configurable: true,
|
|
521
|
+
writable: true,
|
|
522
|
+
value: void 0
|
|
523
|
+
});
|
|
524
|
+
Object.defineProperty(this, "suffix", {
|
|
525
|
+
enumerable: true,
|
|
526
|
+
configurable: true,
|
|
527
|
+
writable: true,
|
|
528
|
+
value: void 0
|
|
529
|
+
});
|
|
530
|
+
Object.defineProperty(this, "outputLen", {
|
|
531
|
+
enumerable: true,
|
|
532
|
+
configurable: true,
|
|
533
|
+
writable: true,
|
|
534
|
+
value: void 0
|
|
535
|
+
});
|
|
536
|
+
Object.defineProperty(this, "enableXOF", {
|
|
537
|
+
enumerable: true,
|
|
538
|
+
configurable: true,
|
|
539
|
+
writable: true,
|
|
540
|
+
value: false
|
|
541
|
+
});
|
|
542
|
+
Object.defineProperty(this, "rounds", {
|
|
543
|
+
enumerable: true,
|
|
544
|
+
configurable: true,
|
|
545
|
+
writable: true,
|
|
546
|
+
value: void 0
|
|
547
|
+
});
|
|
548
|
+
this.blockLen = blockLen;
|
|
549
|
+
this.suffix = suffix;
|
|
550
|
+
this.outputLen = outputLen;
|
|
551
|
+
this.enableXOF = enableXOF;
|
|
552
|
+
this.rounds = rounds;
|
|
553
|
+
// Can be passed from user as dkLen
|
|
554
|
+
anumber(outputLen, "outputLen");
|
|
555
|
+
// 1600 = 5x5 matrix of 64bit. 1600 bits === 200 bytes
|
|
556
|
+
// 0 < blockLen < 200
|
|
557
|
+
if (!(0 < blockLen && blockLen < 200)) {
|
|
558
|
+
throw new Error("only keccak-f1600 function is supported");
|
|
559
|
+
}
|
|
560
|
+
this.state = new Uint8Array(200);
|
|
561
|
+
this.state32 = u32(this.state);
|
|
562
|
+
}
|
|
563
|
+
clone() {
|
|
564
|
+
return this._cloneInto();
|
|
565
|
+
}
|
|
566
|
+
keccak() {
|
|
567
|
+
swap32IfBE(this.state32);
|
|
568
|
+
keccakP(this.state32, this.rounds);
|
|
569
|
+
swap32IfBE(this.state32);
|
|
570
|
+
this.posOut = 0;
|
|
571
|
+
this.pos = 0;
|
|
572
|
+
}
|
|
573
|
+
update(data) {
|
|
574
|
+
aexists(this);
|
|
575
|
+
abytes(data);
|
|
576
|
+
const { blockLen, state } = this;
|
|
577
|
+
const len = data.length;
|
|
578
|
+
for (let pos = 0; pos < len;) {
|
|
579
|
+
const take = Math.min(blockLen - this.pos, len - pos);
|
|
580
|
+
for (let i = 0; i < take; i++)
|
|
581
|
+
state[this.pos++] ^= data[pos++];
|
|
582
|
+
if (this.pos === blockLen)
|
|
583
|
+
this.keccak();
|
|
584
|
+
}
|
|
585
|
+
return this;
|
|
586
|
+
}
|
|
587
|
+
finish() {
|
|
588
|
+
if (this.finished)
|
|
589
|
+
return;
|
|
590
|
+
this.finished = true;
|
|
591
|
+
const { state, suffix, pos, blockLen } = this;
|
|
592
|
+
// Do the padding
|
|
593
|
+
state[pos] ^= suffix;
|
|
594
|
+
if ((suffix & 0x80) !== 0 && pos === blockLen - 1)
|
|
595
|
+
this.keccak();
|
|
596
|
+
state[blockLen - 1] ^= 0x80;
|
|
597
|
+
this.keccak();
|
|
598
|
+
}
|
|
599
|
+
writeInto(out) {
|
|
600
|
+
aexists(this, false);
|
|
601
|
+
abytes(out);
|
|
602
|
+
this.finish();
|
|
603
|
+
const bufferOut = this.state;
|
|
604
|
+
const { blockLen } = this;
|
|
605
|
+
for (let pos = 0, len = out.length; pos < len;) {
|
|
606
|
+
if (this.posOut >= blockLen)
|
|
607
|
+
this.keccak();
|
|
608
|
+
const take = Math.min(blockLen - this.posOut, len - pos);
|
|
609
|
+
out.set(bufferOut.subarray(this.posOut, this.posOut + take), pos);
|
|
610
|
+
this.posOut += take;
|
|
611
|
+
pos += take;
|
|
612
|
+
}
|
|
613
|
+
return out;
|
|
614
|
+
}
|
|
615
|
+
xofInto(out) {
|
|
616
|
+
// Sha3/Keccak usage with XOF is probably mistake, only SHAKE instances can do XOF
|
|
617
|
+
if (!this.enableXOF) {
|
|
618
|
+
throw new Error("XOF is not possible for this instance");
|
|
619
|
+
}
|
|
620
|
+
return this.writeInto(out);
|
|
621
|
+
}
|
|
622
|
+
xof(bytes) {
|
|
623
|
+
anumber(bytes);
|
|
624
|
+
return this.xofInto(new Uint8Array(bytes));
|
|
625
|
+
}
|
|
626
|
+
digestInto(out) {
|
|
627
|
+
aoutput(out, this);
|
|
628
|
+
if (this.finished)
|
|
629
|
+
throw new Error("digest() was already called");
|
|
630
|
+
this.writeInto(out);
|
|
631
|
+
this.destroy();
|
|
632
|
+
return out;
|
|
633
|
+
}
|
|
634
|
+
digest() {
|
|
635
|
+
return this.digestInto(new Uint8Array(this.outputLen));
|
|
636
|
+
}
|
|
637
|
+
destroy() {
|
|
638
|
+
this.destroyed = true;
|
|
639
|
+
clean(this.state);
|
|
640
|
+
}
|
|
641
|
+
_cloneInto(to) {
|
|
642
|
+
const { blockLen, suffix, outputLen, rounds, enableXOF } = this;
|
|
643
|
+
to ||= new Keccak(blockLen, suffix, outputLen, enableXOF, rounds);
|
|
644
|
+
to.state32.set(this.state32);
|
|
645
|
+
to.pos = this.pos;
|
|
646
|
+
to.posOut = this.posOut;
|
|
647
|
+
to.finished = this.finished;
|
|
648
|
+
to.rounds = rounds;
|
|
649
|
+
// Suffix can change in cSHAKE
|
|
650
|
+
to.suffix = suffix;
|
|
651
|
+
to.outputLen = outputLen;
|
|
652
|
+
to.enableXOF = enableXOF;
|
|
653
|
+
to.destroyed = this.destroyed;
|
|
654
|
+
return to;
|
|
655
|
+
}
|
|
656
|
+
}
|
|
657
|
+
const genKeccak = (suffix, blockLen, outputLen, info = {}) => createHasher(() => new Keccak(blockLen, suffix, outputLen), info);
|
|
658
|
+
// /** SHA3-224 hash function. */
|
|
659
|
+
// export const sha3_224: CHash = /* @__PURE__ */ genKeccak(
|
|
660
|
+
// 0x06,
|
|
661
|
+
// 144,
|
|
662
|
+
// 28,
|
|
663
|
+
// /* @__PURE__ */ oidNist(0x07),
|
|
664
|
+
// );
|
|
665
|
+
/** SHA3-256 hash function. Different from keccak-256. */
|
|
666
|
+
const sha3_256 = /* @__PURE__ */ genKeccak(0x06, 136, 32,
|
|
667
|
+
/* @__PURE__ */ oidNist(0x08));
|
|
668
|
+
// /** SHA3-384 hash function. */
|
|
669
|
+
// export const sha3_384: CHash = /* @__PURE__ */ genKeccak(
|
|
670
|
+
// 0x06,
|
|
671
|
+
// 104,
|
|
672
|
+
// 48,
|
|
673
|
+
// /* @__PURE__ */ oidNist(0x09),
|
|
674
|
+
// );
|
|
675
|
+
/** SHA3-512 hash function. */
|
|
676
|
+
const sha3_512 = /* @__PURE__ */ genKeccak(0x06, 72, 64,
|
|
677
|
+
/* @__PURE__ */ oidNist(0x0a));
|
|
678
|
+
/** keccak-224 hash function. */
|
|
679
|
+
const keccak_224 = /* @__PURE__ */ genKeccak(0x01, 144, 28);
|
|
680
|
+
/** keccak-256 hash function. Different from SHA3-256. */
|
|
681
|
+
const keccak_256 = /* @__PURE__ */ genKeccak(0x01, 136, 32);
|
|
682
|
+
/** keccak-384 hash function. */
|
|
683
|
+
const keccak_384 = /* @__PURE__ */ genKeccak(0x01, 104, 48);
|
|
684
|
+
/** keccak-512 hash function. */
|
|
685
|
+
const keccak_512 = /* @__PURE__ */ genKeccak(0x01, 72, 64);
|
|
686
|
+
const genShake = (suffix, blockLen, outputLen, info = {}) => createHasher((opts = {}) => new Keccak(blockLen, suffix, opts.dkLen === undefined ? outputLen : opts.dkLen, true), info);
|
|
687
|
+
/** SHAKE128 XOF with 128-bit security. */
|
|
688
|
+
const shake128 =
|
|
689
|
+
/* @__PURE__ */
|
|
690
|
+
genShake(0x1f, 168, 16, /* @__PURE__ */ oidNist(0x0b));
|
|
691
|
+
/** SHAKE256 XOF with 256-bit security. */
|
|
692
|
+
const shake256 =
|
|
693
|
+
/* @__PURE__ */
|
|
694
|
+
genShake(0x1f, 136, 32, /* @__PURE__ */ oidNist(0x0c));
|
|
695
|
+
// /** SHAKE128 XOF with 256-bit output (NIST version). */
|
|
696
|
+
// export const shake128_32: CHashXOF<Keccak, ShakeOpts> =
|
|
697
|
+
// /* @__PURE__ */
|
|
698
|
+
// genShake(0x1f, 168, 32, /* @__PURE__ */ oidNist(0x0b));
|
|
699
|
+
// /** SHAKE256 XOF with 512-bit output (NIST version). */
|
|
700
|
+
// export const shake256_64: CHashXOF<Keccak, ShakeOpts> =
|
|
701
|
+
// /* @__PURE__ */
|
|
702
|
+
// genShake(0x1f, 136, 64, /* @__PURE__ */ oidNist(0x0c));
|
|
703
|
+
|
|
704
|
+
;// ./node_modules/mlkem/esm/src/deps.js
|
|
705
|
+
|
|
706
|
+
|
|
707
|
+
;// ./node_modules/mlkem/esm/_dnt.shims.js
|
|
708
|
+
const dntGlobals = {};
|
|
709
|
+
const dntGlobalThis = createMergeProxy(globalThis, dntGlobals);
|
|
710
|
+
function createMergeProxy(baseObj, extObj) {
|
|
711
|
+
return new Proxy(baseObj, {
|
|
712
|
+
get(_target, prop, _receiver) {
|
|
713
|
+
if (prop in extObj) {
|
|
714
|
+
return extObj[prop];
|
|
715
|
+
}
|
|
716
|
+
else {
|
|
717
|
+
return baseObj[prop];
|
|
718
|
+
}
|
|
719
|
+
},
|
|
720
|
+
set(_target, prop, value) {
|
|
721
|
+
if (prop in extObj) {
|
|
722
|
+
delete extObj[prop];
|
|
723
|
+
}
|
|
724
|
+
baseObj[prop] = value;
|
|
725
|
+
return true;
|
|
726
|
+
},
|
|
727
|
+
deleteProperty(_target, prop) {
|
|
728
|
+
let success = false;
|
|
729
|
+
if (prop in extObj) {
|
|
730
|
+
delete extObj[prop];
|
|
731
|
+
success = true;
|
|
732
|
+
}
|
|
733
|
+
if (prop in baseObj) {
|
|
734
|
+
delete baseObj[prop];
|
|
735
|
+
success = true;
|
|
736
|
+
}
|
|
737
|
+
return success;
|
|
738
|
+
},
|
|
739
|
+
ownKeys(_target) {
|
|
740
|
+
const baseKeys = Reflect.ownKeys(baseObj);
|
|
741
|
+
const extKeys = Reflect.ownKeys(extObj);
|
|
742
|
+
const extKeysSet = new Set(extKeys);
|
|
743
|
+
return [...baseKeys.filter((k) => !extKeysSet.has(k)), ...extKeys];
|
|
744
|
+
},
|
|
745
|
+
defineProperty(_target, prop, desc) {
|
|
746
|
+
if (prop in extObj) {
|
|
747
|
+
delete extObj[prop];
|
|
748
|
+
}
|
|
749
|
+
Reflect.defineProperty(baseObj, prop, desc);
|
|
750
|
+
return true;
|
|
751
|
+
},
|
|
752
|
+
getOwnPropertyDescriptor(_target, prop) {
|
|
753
|
+
if (prop in extObj) {
|
|
754
|
+
return Reflect.getOwnPropertyDescriptor(extObj, prop);
|
|
755
|
+
}
|
|
756
|
+
else {
|
|
757
|
+
return Reflect.getOwnPropertyDescriptor(baseObj, prop);
|
|
758
|
+
}
|
|
759
|
+
},
|
|
760
|
+
has(_target, prop) {
|
|
761
|
+
return prop in extObj || prop in baseObj;
|
|
762
|
+
},
|
|
763
|
+
});
|
|
764
|
+
}
|
|
765
|
+
|
|
766
|
+
;// ./node_modules/mlkem/esm/src/utils.js
|
|
767
|
+
|
|
768
|
+
|
|
769
|
+
function utils_byte(n) {
|
|
770
|
+
return n % 256;
|
|
771
|
+
}
|
|
772
|
+
function int16(n) {
|
|
773
|
+
const end = -32768;
|
|
774
|
+
const start = 32767;
|
|
775
|
+
if (n >= end && n <= start) {
|
|
776
|
+
return n;
|
|
777
|
+
}
|
|
778
|
+
if (n < end) {
|
|
779
|
+
n = n + 32769;
|
|
780
|
+
n = n % 65536;
|
|
781
|
+
return start + n;
|
|
782
|
+
}
|
|
783
|
+
// if (n > start) {
|
|
784
|
+
n = n - 32768;
|
|
785
|
+
n = n % 65536;
|
|
786
|
+
return end + n;
|
|
787
|
+
}
|
|
788
|
+
function uint16(n) {
|
|
789
|
+
return n % 65536;
|
|
790
|
+
}
|
|
791
|
+
function int32(n) {
|
|
792
|
+
const end = -2147483648;
|
|
793
|
+
const start = 2147483647;
|
|
794
|
+
if (n >= end && n <= start) {
|
|
795
|
+
return n;
|
|
796
|
+
}
|
|
797
|
+
if (n < end) {
|
|
798
|
+
n = n + 2147483649;
|
|
799
|
+
n = n % 4294967296;
|
|
800
|
+
return start + n;
|
|
801
|
+
}
|
|
802
|
+
// if (n > start) {
|
|
803
|
+
n = n - 2147483648;
|
|
804
|
+
n = n % 4294967296;
|
|
805
|
+
return end + n;
|
|
806
|
+
}
|
|
807
|
+
// any bit operations to be done in uint32 must have >>> 0
|
|
808
|
+
// javascript calculates bitwise in SIGNED 32 bit so you need to convert
|
|
809
|
+
function uint32(n) {
|
|
810
|
+
return n % 4294967296;
|
|
811
|
+
}
|
|
812
|
+
/**
|
|
813
|
+
* compares two arrays
|
|
814
|
+
* @returns 1 if they are the same or 0 if not
|
|
815
|
+
*/
|
|
816
|
+
function constantTimeCompare(x, y) {
|
|
817
|
+
// check array lengths
|
|
818
|
+
if (x.length != y.length) {
|
|
819
|
+
return 0;
|
|
820
|
+
}
|
|
821
|
+
const v = new Uint8Array([0]);
|
|
822
|
+
for (let i = 0; i < x.length; i++) {
|
|
823
|
+
v[0] |= x[i] ^ y[i];
|
|
824
|
+
}
|
|
825
|
+
// constantTimeByteEq
|
|
826
|
+
const z = new Uint8Array([0]);
|
|
827
|
+
z[0] = ~(v[0] ^ z[0]);
|
|
828
|
+
z[0] &= z[0] >> 4;
|
|
829
|
+
z[0] &= z[0] >> 2;
|
|
830
|
+
z[0] &= z[0] >> 1;
|
|
831
|
+
return z[0];
|
|
832
|
+
}
|
|
833
|
+
function equalUint8Array(x, y) {
|
|
834
|
+
if (x.length != y.length) {
|
|
835
|
+
return false;
|
|
836
|
+
}
|
|
837
|
+
for (let i = 0; i < x.length; i++) {
|
|
838
|
+
if (x[i] !== y[i]) {
|
|
839
|
+
return false;
|
|
840
|
+
}
|
|
841
|
+
}
|
|
842
|
+
return true;
|
|
843
|
+
}
|
|
844
|
+
async function loadCrypto() {
|
|
845
|
+
if (typeof dntGlobalThis !== "undefined" && globalThis.crypto !== undefined) {
|
|
846
|
+
// Browsers, Node.js >= v19, Cloudflare Workers, Bun, etc.
|
|
847
|
+
return globalThis.crypto;
|
|
848
|
+
}
|
|
849
|
+
// Node.js <= v18
|
|
850
|
+
try {
|
|
851
|
+
// @ts-ignore: to ignore "crypto"
|
|
852
|
+
const { webcrypto } = await Promise.resolve(/*! import() */).then(__webpack_require__.t.bind(__webpack_require__, /*! crypto */ "./node_modules/crypto-browserify/index.js", 19)); // node:crypto
|
|
853
|
+
return webcrypto;
|
|
854
|
+
}
|
|
855
|
+
catch (_e) {
|
|
856
|
+
throw new Error("failed to load Crypto");
|
|
857
|
+
}
|
|
858
|
+
}
|
|
859
|
+
// prf provides a pseudo-random function (PRF) which returns
|
|
860
|
+
// a byte array of length `l`, using the provided key and nonce
|
|
861
|
+
// to instantiate the PRF's underlying hash function.
|
|
862
|
+
function prf(len, seed, nonce) {
|
|
863
|
+
return shake256.create({ dkLen: len }).update(seed).update(new Uint8Array([nonce])).digest();
|
|
864
|
+
}
|
|
865
|
+
// byteopsLoad24 returns a 32-bit unsigned integer loaded from byte x.
|
|
866
|
+
function byteopsLoad24(x) {
|
|
867
|
+
let r = uint32(x[0]);
|
|
868
|
+
r |= uint32(x[1]) << 8;
|
|
869
|
+
r |= uint32(x[2]) << 16;
|
|
870
|
+
return r;
|
|
871
|
+
}
|
|
872
|
+
// byteopsLoad32 returns a 32-bit unsigned integer loaded from byte x.
|
|
873
|
+
function byteopsLoad32(x) {
|
|
874
|
+
let r = uint32(x[0]);
|
|
875
|
+
r |= uint32(x[1]) << 8;
|
|
876
|
+
r |= uint32(x[2]) << 16;
|
|
877
|
+
r |= uint32(x[3]) << 24;
|
|
878
|
+
return uint32(r);
|
|
879
|
+
}
|
|
880
|
+
|
|
881
|
+
;// ./node_modules/mlkem/esm/src/mlKemBase.js
|
|
882
|
+
/**
|
|
883
|
+
* This implementation is based on https://github.com/antontutoveanu/crystals-kyber-javascript,
|
|
884
|
+
* which was deveploped under the MIT licence below:
|
|
885
|
+
* https://github.com/antontutoveanu/crystals-kyber-javascript/blob/main/LICENSE
|
|
886
|
+
*/
|
|
887
|
+
|
|
888
|
+
|
|
889
|
+
|
|
890
|
+
|
|
891
|
+
/**
|
|
892
|
+
* Represents the base class for the ML-KEM key encapsulation mechanism.
|
|
893
|
+
*
|
|
894
|
+
* This class provides the base implementation for the ML-KEM key encapsulation mechanism.
|
|
895
|
+
*
|
|
896
|
+
* @remarks
|
|
897
|
+
*
|
|
898
|
+
* This class is not intended to be used directly. Instead, use one of the subclasses:
|
|
899
|
+
*
|
|
900
|
+
* @example
|
|
901
|
+
*
|
|
902
|
+
* ```ts
|
|
903
|
+
* // Using jsr:
|
|
904
|
+
* import { MlKemBase } from "@dajiaji/mlkem";
|
|
905
|
+
* // Using npm:
|
|
906
|
+
* // import { MlKemBase } from "mlkem"; // or "crystals-kyber-js"
|
|
907
|
+
*
|
|
908
|
+
* class MlKem768 extends MlKemBase {
|
|
909
|
+
* protected _k = 3;
|
|
910
|
+
* protected _du = 10;
|
|
911
|
+
* protected _dv = 4;
|
|
912
|
+
* protected _eta1 = 2;
|
|
913
|
+
* protected _eta2 = 2;
|
|
914
|
+
*
|
|
915
|
+
* constructor() {
|
|
916
|
+
* super();
|
|
917
|
+
* this._skSize = 12 * this._k * N / 8;
|
|
918
|
+
* this._pkSize = this._skSize + 32;
|
|
919
|
+
* this._compressedUSize = this._k * this._du * N / 8;
|
|
920
|
+
* this._compressedVSize = this._dv * N / 8;
|
|
921
|
+
* }
|
|
922
|
+
* }
|
|
923
|
+
*
|
|
924
|
+
* const kyber = new MlKem768();
|
|
925
|
+
* ```
|
|
926
|
+
*/
|
|
927
|
+
class MlKemBase {
|
|
928
|
+
/**
|
|
929
|
+
* Creates a new instance of the MlKemBase class.
|
|
930
|
+
*/
|
|
931
|
+
constructor() {
|
|
932
|
+
Object.defineProperty(this, "_api", {
|
|
933
|
+
enumerable: true,
|
|
934
|
+
configurable: true,
|
|
935
|
+
writable: true,
|
|
936
|
+
value: undefined
|
|
937
|
+
});
|
|
938
|
+
Object.defineProperty(this, "_k", {
|
|
939
|
+
enumerable: true,
|
|
940
|
+
configurable: true,
|
|
941
|
+
writable: true,
|
|
942
|
+
value: 0
|
|
943
|
+
});
|
|
944
|
+
Object.defineProperty(this, "_du", {
|
|
945
|
+
enumerable: true,
|
|
946
|
+
configurable: true,
|
|
947
|
+
writable: true,
|
|
948
|
+
value: 0
|
|
949
|
+
});
|
|
950
|
+
Object.defineProperty(this, "_dv", {
|
|
951
|
+
enumerable: true,
|
|
952
|
+
configurable: true,
|
|
953
|
+
writable: true,
|
|
954
|
+
value: 0
|
|
955
|
+
});
|
|
956
|
+
Object.defineProperty(this, "_eta1", {
|
|
957
|
+
enumerable: true,
|
|
958
|
+
configurable: true,
|
|
959
|
+
writable: true,
|
|
960
|
+
value: 0
|
|
961
|
+
});
|
|
962
|
+
Object.defineProperty(this, "_eta2", {
|
|
963
|
+
enumerable: true,
|
|
964
|
+
configurable: true,
|
|
965
|
+
writable: true,
|
|
966
|
+
value: 0
|
|
967
|
+
});
|
|
968
|
+
Object.defineProperty(this, "_skSize", {
|
|
969
|
+
enumerable: true,
|
|
970
|
+
configurable: true,
|
|
971
|
+
writable: true,
|
|
972
|
+
value: 0
|
|
973
|
+
});
|
|
974
|
+
Object.defineProperty(this, "_pkSize", {
|
|
975
|
+
enumerable: true,
|
|
976
|
+
configurable: true,
|
|
977
|
+
writable: true,
|
|
978
|
+
value: 0
|
|
979
|
+
});
|
|
980
|
+
Object.defineProperty(this, "_compressedUSize", {
|
|
981
|
+
enumerable: true,
|
|
982
|
+
configurable: true,
|
|
983
|
+
writable: true,
|
|
984
|
+
value: 0
|
|
985
|
+
});
|
|
986
|
+
Object.defineProperty(this, "_compressedVSize", {
|
|
987
|
+
enumerable: true,
|
|
988
|
+
configurable: true,
|
|
989
|
+
writable: true,
|
|
990
|
+
value: 0
|
|
991
|
+
});
|
|
992
|
+
}
|
|
993
|
+
/**
|
|
994
|
+
* Generates a keypair [publicKey, privateKey].
|
|
995
|
+
*
|
|
996
|
+
* If an error occurred, throws {@link MlKemError}.
|
|
997
|
+
*
|
|
998
|
+
* @returns A kaypair [publicKey, privateKey].
|
|
999
|
+
* @throws {@link MlKemError}
|
|
1000
|
+
*
|
|
1001
|
+
* @example Generates a {@link MlKem768} keypair.
|
|
1002
|
+
*
|
|
1003
|
+
* ```ts
|
|
1004
|
+
* // Using jsr:
|
|
1005
|
+
* import { MlKem768 } from "@dajiaji/mlkem";
|
|
1006
|
+
* // Using npm:
|
|
1007
|
+
* // import { MlKem768 } from "mlkem"; // or "crystals-kyber-js"
|
|
1008
|
+
*
|
|
1009
|
+
* const kyber = new MlKem768();
|
|
1010
|
+
* const [pk, sk] = await kyber.generateKeyPair();
|
|
1011
|
+
* ```
|
|
1012
|
+
*/
|
|
1013
|
+
async generateKeyPair() {
|
|
1014
|
+
await this._setup();
|
|
1015
|
+
try {
|
|
1016
|
+
const rnd = new Uint8Array(64);
|
|
1017
|
+
this._api.getRandomValues(rnd);
|
|
1018
|
+
return this._deriveKeyPair(rnd);
|
|
1019
|
+
}
|
|
1020
|
+
catch (e) {
|
|
1021
|
+
throw new MlKemError(e);
|
|
1022
|
+
}
|
|
1023
|
+
}
|
|
1024
|
+
/**
|
|
1025
|
+
* Derives a keypair [publicKey, privateKey] deterministically from a 64-octet seed.
|
|
1026
|
+
*
|
|
1027
|
+
* If an error occurred, throws {@link MlKemError}.
|
|
1028
|
+
*
|
|
1029
|
+
* @param seed A 64-octet seed for the deterministic key generation.
|
|
1030
|
+
* @returns A kaypair [publicKey, privateKey].
|
|
1031
|
+
* @throws {@link MlKemError}
|
|
1032
|
+
*
|
|
1033
|
+
* @example Derives a {@link MlKem768} keypair deterministically.
|
|
1034
|
+
*
|
|
1035
|
+
* ```ts
|
|
1036
|
+
* // Using jsr:
|
|
1037
|
+
* import { MlKem768 } from "@dajiaji/mlkem";
|
|
1038
|
+
* // Using npm:
|
|
1039
|
+
* // import { MlKem768 } from "mlkem"; // or "crystals-kyber-js"
|
|
1040
|
+
*
|
|
1041
|
+
* const kyber = new MlKem768();
|
|
1042
|
+
* const seed = new Uint8Array(64);
|
|
1043
|
+
* globalThis.crypto.getRandomValues(seed);
|
|
1044
|
+
* const [pk, sk] = await kyber.deriveKeyPair(seed);
|
|
1045
|
+
* ```
|
|
1046
|
+
*/
|
|
1047
|
+
async deriveKeyPair(seed) {
|
|
1048
|
+
await this._setup();
|
|
1049
|
+
try {
|
|
1050
|
+
if (seed.byteLength !== 64) {
|
|
1051
|
+
throw new Error("seed must be 64 bytes in length");
|
|
1052
|
+
}
|
|
1053
|
+
return this._deriveKeyPair(seed);
|
|
1054
|
+
}
|
|
1055
|
+
catch (e) {
|
|
1056
|
+
throw new MlKemError(e);
|
|
1057
|
+
}
|
|
1058
|
+
}
|
|
1059
|
+
/**
|
|
1060
|
+
* Generates a shared secret from the encapsulated ciphertext and the private key.
|
|
1061
|
+
*
|
|
1062
|
+
* If an error occurred, throws {@link MlKemError}.
|
|
1063
|
+
*
|
|
1064
|
+
* @param pk A public key.
|
|
1065
|
+
* @param seed An optional 32-octet seed for the deterministic shared secret generation.
|
|
1066
|
+
* @returns A ciphertext (encapsulated public key) and a shared secret.
|
|
1067
|
+
* @throws {@link MlKemError}
|
|
1068
|
+
*
|
|
1069
|
+
* @example The {@link MlKem768} encapsulation.
|
|
1070
|
+
*
|
|
1071
|
+
* ```ts
|
|
1072
|
+
* // Using jsr:
|
|
1073
|
+
* import { MlKem768 } from "@dajiaji/mlkem";
|
|
1074
|
+
* // Using npm:
|
|
1075
|
+
* // import { MlKem768 } from "mlkem"; // or "crystals-kyber-js"
|
|
1076
|
+
*
|
|
1077
|
+
* const kyber = new MlKem768();
|
|
1078
|
+
* const [pk, sk] = await kyber.generateKeyPair();
|
|
1079
|
+
* const [ct, ss] = await kyber.encap(pk);
|
|
1080
|
+
* ```
|
|
1081
|
+
*/
|
|
1082
|
+
async encap(pk, seed) {
|
|
1083
|
+
await this._setup();
|
|
1084
|
+
try {
|
|
1085
|
+
// validate key type; the modulo is checked in `_encap`.
|
|
1086
|
+
if (pk.length !== 384 * this._k + 32) {
|
|
1087
|
+
throw new Error("invalid encapsulation key");
|
|
1088
|
+
}
|
|
1089
|
+
const m = this._getSeed(seed);
|
|
1090
|
+
const [k, r] = g(m, h(pk));
|
|
1091
|
+
const ct = this._encap(pk, m, r);
|
|
1092
|
+
return [ct, k];
|
|
1093
|
+
}
|
|
1094
|
+
catch (e) {
|
|
1095
|
+
throw new MlKemError(e);
|
|
1096
|
+
}
|
|
1097
|
+
}
|
|
1098
|
+
/**
|
|
1099
|
+
* Generates a ciphertext for the public key and a shared secret.
|
|
1100
|
+
*
|
|
1101
|
+
* If an error occurred, throws {@link MlKemError}.
|
|
1102
|
+
*
|
|
1103
|
+
* @param ct A ciphertext generated by {@link encap}.
|
|
1104
|
+
* @param sk A private key.
|
|
1105
|
+
* @returns A shared secret.
|
|
1106
|
+
* @throws {@link MlKemError}
|
|
1107
|
+
*
|
|
1108
|
+
* @example The {@link MlKem768} decapsulation.
|
|
1109
|
+
*
|
|
1110
|
+
* ```ts
|
|
1111
|
+
* // Using jsr:
|
|
1112
|
+
* import { MlKem768 } from "@dajiaji/mlkem";
|
|
1113
|
+
* // Using npm:
|
|
1114
|
+
* // import { MlKem768 } from "mlkem"; // or "crystals-kyber-js"
|
|
1115
|
+
*
|
|
1116
|
+
* const kyber = new MlKem768();
|
|
1117
|
+
* const [pk, sk] = await kyber.generateKeyPair();
|
|
1118
|
+
* const [ct, ssS] = await kyber.encap(pk);
|
|
1119
|
+
* const ssR = await kyber.decap(ct, sk);
|
|
1120
|
+
* // ssS === ssR
|
|
1121
|
+
* ```
|
|
1122
|
+
*/
|
|
1123
|
+
async decap(ct, sk) {
|
|
1124
|
+
await this._setup();
|
|
1125
|
+
try {
|
|
1126
|
+
// ciphertext type check
|
|
1127
|
+
if (ct.byteLength !== this._compressedUSize + this._compressedVSize) {
|
|
1128
|
+
throw new Error("Invalid ct size");
|
|
1129
|
+
}
|
|
1130
|
+
// decapsulation key type check
|
|
1131
|
+
if (sk.length !== 768 * this._k + 96) {
|
|
1132
|
+
throw new Error("Invalid decapsulation key");
|
|
1133
|
+
}
|
|
1134
|
+
const sk2 = sk.subarray(0, this._skSize);
|
|
1135
|
+
const pk = sk.subarray(this._skSize, this._skSize + this._pkSize);
|
|
1136
|
+
const hpk = sk.subarray(this._skSize + this._pkSize, this._skSize + this._pkSize + 32);
|
|
1137
|
+
const z = sk.subarray(this._skSize + this._pkSize + 32, this._skSize + this._pkSize + 64);
|
|
1138
|
+
const m2 = this._decap(ct, sk2);
|
|
1139
|
+
const [k2, r2] = g(m2, hpk);
|
|
1140
|
+
const kBar = kdf(z, ct);
|
|
1141
|
+
const ct2 = this._encap(pk, m2, r2);
|
|
1142
|
+
return constantTimeCompare(ct, ct2) === 1 ? k2 : kBar;
|
|
1143
|
+
}
|
|
1144
|
+
catch (e) {
|
|
1145
|
+
throw new MlKemError(e);
|
|
1146
|
+
}
|
|
1147
|
+
}
|
|
1148
|
+
/**
|
|
1149
|
+
* Sets up the MlKemBase instance by loading the necessary crypto library.
|
|
1150
|
+
* If the crypto library is already loaded, this method does nothing.
|
|
1151
|
+
* @returns {Promise<void>} A promise that resolves when the setup is complete.
|
|
1152
|
+
*/
|
|
1153
|
+
async _setup() {
|
|
1154
|
+
if (this._api !== undefined) {
|
|
1155
|
+
return;
|
|
1156
|
+
}
|
|
1157
|
+
this._api = await loadCrypto();
|
|
1158
|
+
}
|
|
1159
|
+
/**
|
|
1160
|
+
* Returns a Uint8Array seed for cryptographic operations.
|
|
1161
|
+
* If no seed is provided, a random seed of length 32 bytes is generated.
|
|
1162
|
+
* If a seed is provided, it must be exactly 32 bytes in length.
|
|
1163
|
+
*
|
|
1164
|
+
* @param seed - Optional seed for cryptographic operations.
|
|
1165
|
+
* @returns A Uint8Array seed.
|
|
1166
|
+
* @throws Error if the provided seed is not 32 bytes in length.
|
|
1167
|
+
*/
|
|
1168
|
+
_getSeed(seed) {
|
|
1169
|
+
if (seed == undefined) {
|
|
1170
|
+
const s = new Uint8Array(32);
|
|
1171
|
+
this._api.getRandomValues(s);
|
|
1172
|
+
return s;
|
|
1173
|
+
}
|
|
1174
|
+
if (seed.byteLength !== 32) {
|
|
1175
|
+
throw new Error("seed must be 32 bytes in length");
|
|
1176
|
+
}
|
|
1177
|
+
return seed;
|
|
1178
|
+
}
|
|
1179
|
+
/**
|
|
1180
|
+
* Derives a key pair from a given seed.
|
|
1181
|
+
*
|
|
1182
|
+
* @param seed - The seed used for key derivation.
|
|
1183
|
+
* @returns An array containing the public key and secret key.
|
|
1184
|
+
*/
|
|
1185
|
+
_deriveKeyPair(seed) {
|
|
1186
|
+
const cpaSeed = seed.subarray(0, 32);
|
|
1187
|
+
const z = seed.subarray(32, 64);
|
|
1188
|
+
const [pk, skBody] = this._deriveCpaKeyPair(cpaSeed);
|
|
1189
|
+
const pkh = h(pk);
|
|
1190
|
+
const sk = new Uint8Array(this._skSize + this._pkSize + 64);
|
|
1191
|
+
sk.set(skBody, 0);
|
|
1192
|
+
sk.set(pk, this._skSize);
|
|
1193
|
+
sk.set(pkh, this._skSize + this._pkSize);
|
|
1194
|
+
sk.set(z, this._skSize + this._pkSize + 32);
|
|
1195
|
+
return [pk, sk];
|
|
1196
|
+
}
|
|
1197
|
+
// indcpaKeyGen generates public and private keys for the CPA-secure
|
|
1198
|
+
// public-key encryption scheme underlying ML-KEM.
|
|
1199
|
+
/**
|
|
1200
|
+
* Derives a CPA key pair using the provided CPA seed.
|
|
1201
|
+
*
|
|
1202
|
+
* @param cpaSeed - The CPA seed used for key derivation.
|
|
1203
|
+
* @returns An array containing the public key and private key.
|
|
1204
|
+
*/
|
|
1205
|
+
_deriveCpaKeyPair(cpaSeed) {
|
|
1206
|
+
const [publicSeed, noiseSeed] = g(cpaSeed, new Uint8Array([this._k]));
|
|
1207
|
+
const a = this._sampleMatrix(publicSeed, false);
|
|
1208
|
+
const s = this._sampleNoise1(noiseSeed, 0, this._k);
|
|
1209
|
+
const e = this._sampleNoise1(noiseSeed, this._k, this._k);
|
|
1210
|
+
// perform number theoretic transform on secret s
|
|
1211
|
+
for (let i = 0; i < this._k; i++) {
|
|
1212
|
+
s[i] = ntt(s[i]);
|
|
1213
|
+
s[i] = reduce(s[i]);
|
|
1214
|
+
e[i] = ntt(e[i]);
|
|
1215
|
+
}
|
|
1216
|
+
// KEY COMPUTATION
|
|
1217
|
+
// pk = A*s + e
|
|
1218
|
+
const pk = new Array(this._k);
|
|
1219
|
+
for (let i = 0; i < this._k; i++) {
|
|
1220
|
+
pk[i] = polyToMont(multiply(a[i], s));
|
|
1221
|
+
pk[i] = mlKemBase_add(pk[i], e[i]);
|
|
1222
|
+
pk[i] = reduce(pk[i]);
|
|
1223
|
+
}
|
|
1224
|
+
// PUBLIC KEY
|
|
1225
|
+
// turn polynomials into byte arrays
|
|
1226
|
+
const pubKey = new Uint8Array(this._pkSize);
|
|
1227
|
+
for (let i = 0; i < this._k; i++) {
|
|
1228
|
+
pubKey.set(polyToBytes(pk[i]), i * 384);
|
|
1229
|
+
}
|
|
1230
|
+
// append public seed
|
|
1231
|
+
pubKey.set(publicSeed, this._skSize);
|
|
1232
|
+
// PRIVATE KEY
|
|
1233
|
+
// turn polynomials into byte arrays
|
|
1234
|
+
const privKey = new Uint8Array(this._skSize);
|
|
1235
|
+
for (let i = 0; i < this._k; i++) {
|
|
1236
|
+
privKey.set(polyToBytes(s[i]), i * 384);
|
|
1237
|
+
}
|
|
1238
|
+
return [pubKey, privKey];
|
|
1239
|
+
}
|
|
1240
|
+
// _encap is the encapsulation function of the CPA-secure
|
|
1241
|
+
// public-key encryption scheme underlying ML-KEM.
|
|
1242
|
+
/**
|
|
1243
|
+
* Encapsulates a message using the ML-KEM encryption scheme.
|
|
1244
|
+
*
|
|
1245
|
+
* @param pk - The public key.
|
|
1246
|
+
* @param msg - The message to be encapsulated.
|
|
1247
|
+
* @param seed - The seed used for generating random values.
|
|
1248
|
+
* @returns The encapsulated message as a Uint8Array.
|
|
1249
|
+
*/
|
|
1250
|
+
_encap(pk, msg, seed) {
|
|
1251
|
+
const tHat = new Array(this._k);
|
|
1252
|
+
const pkCheck = new Uint8Array(384 * this._k); // to validate the pk modulo (see input validation at NIST draft 6.2)
|
|
1253
|
+
for (let i = 0; i < this._k; i++) {
|
|
1254
|
+
tHat[i] = polyFromBytes(pk.subarray(i * 384, (i + 1) * 384));
|
|
1255
|
+
pkCheck.set(polyToBytes(tHat[i]), i * 384);
|
|
1256
|
+
}
|
|
1257
|
+
if (!equalUint8Array(pk.subarray(0, pkCheck.length), pkCheck)) {
|
|
1258
|
+
throw new Error("invalid encapsulation key");
|
|
1259
|
+
}
|
|
1260
|
+
const rho = pk.subarray(this._skSize);
|
|
1261
|
+
const a = this._sampleMatrix(rho, true);
|
|
1262
|
+
const r = this._sampleNoise1(seed, 0, this._k);
|
|
1263
|
+
const e1 = this._sampleNoise2(seed, this._k, this._k);
|
|
1264
|
+
const e2 = this._sampleNoise2(seed, this._k * 2, 1)[0];
|
|
1265
|
+
// perform number theoretic transform on random vector r
|
|
1266
|
+
for (let i = 0; i < this._k; i++) {
|
|
1267
|
+
r[i] = ntt(r[i]);
|
|
1268
|
+
r[i] = reduce(r[i]);
|
|
1269
|
+
}
|
|
1270
|
+
// u = A*r + e1
|
|
1271
|
+
const u = new Array(this._k);
|
|
1272
|
+
for (let i = 0; i < this._k; i++) {
|
|
1273
|
+
u[i] = multiply(a[i], r);
|
|
1274
|
+
u[i] = nttInverse(u[i]);
|
|
1275
|
+
u[i] = mlKemBase_add(u[i], e1[i]);
|
|
1276
|
+
u[i] = reduce(u[i]);
|
|
1277
|
+
}
|
|
1278
|
+
// v = tHat*r + e2 + m
|
|
1279
|
+
const m = polyFromMsg(msg);
|
|
1280
|
+
let v = multiply(tHat, r);
|
|
1281
|
+
v = nttInverse(v);
|
|
1282
|
+
v = mlKemBase_add(v, e2);
|
|
1283
|
+
v = mlKemBase_add(v, m);
|
|
1284
|
+
v = reduce(v);
|
|
1285
|
+
// compress
|
|
1286
|
+
const ret = new Uint8Array(this._compressedUSize + this._compressedVSize);
|
|
1287
|
+
this._compressU(ret.subarray(0, this._compressedUSize), u);
|
|
1288
|
+
this._compressV(ret.subarray(this._compressedUSize), v);
|
|
1289
|
+
return ret;
|
|
1290
|
+
}
|
|
1291
|
+
// indcpaDecrypt is the decryption function of the CPA-secure
|
|
1292
|
+
// public-key encryption scheme underlying ML-KEM.
|
|
1293
|
+
/**
|
|
1294
|
+
* Decapsulates the ciphertext using the provided secret key.
|
|
1295
|
+
*
|
|
1296
|
+
* @param ct - The ciphertext to be decapsulated.
|
|
1297
|
+
* @param sk - The secret key used for decapsulation.
|
|
1298
|
+
* @returns The decapsulated message as a Uint8Array.
|
|
1299
|
+
*/
|
|
1300
|
+
_decap(ct, sk) {
|
|
1301
|
+
// extract ciphertext
|
|
1302
|
+
const u = this._decompressU(ct.subarray(0, this._compressedUSize));
|
|
1303
|
+
const v = this._decompressV(ct.subarray(this._compressedUSize));
|
|
1304
|
+
const privateKeyPolyvec = this._polyvecFromBytes(sk);
|
|
1305
|
+
for (let i = 0; i < this._k; i++) {
|
|
1306
|
+
u[i] = ntt(u[i]);
|
|
1307
|
+
}
|
|
1308
|
+
let mp = multiply(privateKeyPolyvec, u);
|
|
1309
|
+
mp = nttInverse(mp);
|
|
1310
|
+
mp = subtract(v, mp);
|
|
1311
|
+
mp = reduce(mp);
|
|
1312
|
+
return polyToMsg(mp);
|
|
1313
|
+
}
|
|
1314
|
+
// generateMatrixA deterministically generates a matrix `A` (or the transpose of `A`)
|
|
1315
|
+
// from a seed. Entries of the matrix are polynomials that look uniformly random.
|
|
1316
|
+
// Performs rejection sampling on the output of an extendable-output function (XOF).
|
|
1317
|
+
/**
|
|
1318
|
+
* Generates a sample matrix based on the provided seed and transposition flag.
|
|
1319
|
+
*
|
|
1320
|
+
* @param seed - The seed used for generating the matrix.
|
|
1321
|
+
* @param transposed - A flag indicating whether the matrix should be transposed or not.
|
|
1322
|
+
* @returns The generated sample matrix.
|
|
1323
|
+
*/
|
|
1324
|
+
_sampleMatrix(seed, transposed) {
|
|
1325
|
+
const a = new Array(this._k);
|
|
1326
|
+
const transpose = new Uint8Array(2);
|
|
1327
|
+
for (let ctr = 0, i = 0; i < this._k; i++) {
|
|
1328
|
+
a[i] = new Array(this._k);
|
|
1329
|
+
for (let j = 0; j < this._k; j++) {
|
|
1330
|
+
// set if transposed matrix or not
|
|
1331
|
+
if (transposed) {
|
|
1332
|
+
transpose[0] = i;
|
|
1333
|
+
transpose[1] = j;
|
|
1334
|
+
}
|
|
1335
|
+
else {
|
|
1336
|
+
transpose[0] = j;
|
|
1337
|
+
transpose[1] = i;
|
|
1338
|
+
}
|
|
1339
|
+
const output = xof(seed, transpose);
|
|
1340
|
+
// run rejection sampling on the output from above
|
|
1341
|
+
const result = indcpaRejUniform(output.subarray(0, 504), 504, N);
|
|
1342
|
+
a[i][j] = result[0]; // the result here is an NTT-representation
|
|
1343
|
+
ctr = result[1]; // keeps track of index of output array from sampling function
|
|
1344
|
+
while (ctr < N) { // if the polynomial hasnt been filled yet with mod q entries
|
|
1345
|
+
const outputn = output.subarray(504, 672); // take last 168 bytes of byte array from xof
|
|
1346
|
+
const result1 = indcpaRejUniform(outputn, 168, N - ctr); // run sampling function again
|
|
1347
|
+
const missing = result1[0]; // here is additional mod q polynomial coefficients
|
|
1348
|
+
const ctrn = result1[1]; // how many coefficients were accepted and are in the output
|
|
1349
|
+
// starting at last position of output array from first sampling function until 256 is reached
|
|
1350
|
+
for (let k = ctr; k < N; k++) {
|
|
1351
|
+
a[i][j][k] = missing[k - ctr]; // fill rest of array with the additional coefficients until full
|
|
1352
|
+
}
|
|
1353
|
+
ctr = ctr + ctrn; // update index
|
|
1354
|
+
}
|
|
1355
|
+
}
|
|
1356
|
+
}
|
|
1357
|
+
return a;
|
|
1358
|
+
}
|
|
1359
|
+
/**
|
|
1360
|
+
* Generates a 2D array of noise samples.
|
|
1361
|
+
*
|
|
1362
|
+
* @param sigma - The noise parameter.
|
|
1363
|
+
* @param offset - The offset value.
|
|
1364
|
+
* @param size - The size of the array.
|
|
1365
|
+
* @returns The generated 2D array of noise samples.
|
|
1366
|
+
*/
|
|
1367
|
+
_sampleNoise1(sigma, offset, size) {
|
|
1368
|
+
const r = new Array(size);
|
|
1369
|
+
for (let i = 0; i < size; i++) {
|
|
1370
|
+
r[i] = byteopsCbd(prf(this._eta1 * N / 4, sigma, offset), this._eta1);
|
|
1371
|
+
offset++;
|
|
1372
|
+
}
|
|
1373
|
+
return r;
|
|
1374
|
+
}
|
|
1375
|
+
/**
|
|
1376
|
+
* Generates a 2-dimensional array of noise samples.
|
|
1377
|
+
*
|
|
1378
|
+
* @param sigma - The noise parameter.
|
|
1379
|
+
* @param offset - The offset value.
|
|
1380
|
+
* @param size - The size of the array.
|
|
1381
|
+
* @returns The generated 2-dimensional array of noise samples.
|
|
1382
|
+
*/
|
|
1383
|
+
_sampleNoise2(sigma, offset, size) {
|
|
1384
|
+
const r = new Array(size);
|
|
1385
|
+
for (let i = 0; i < size; i++) {
|
|
1386
|
+
r[i] = byteopsCbd(prf(this._eta2 * N / 4, sigma, offset), this._eta2);
|
|
1387
|
+
offset++;
|
|
1388
|
+
}
|
|
1389
|
+
return r;
|
|
1390
|
+
}
|
|
1391
|
+
// polyvecFromBytes deserializes a vector of polynomials.
|
|
1392
|
+
/**
|
|
1393
|
+
* Converts a Uint8Array to a 2D array of numbers representing a polynomial vector.
|
|
1394
|
+
* Each element in the resulting array represents a polynomial.
|
|
1395
|
+
* @param a The Uint8Array to convert.
|
|
1396
|
+
* @returns The 2D array of numbers representing the polynomial vector.
|
|
1397
|
+
*/
|
|
1398
|
+
_polyvecFromBytes(a) {
|
|
1399
|
+
const r = new Array(this._k);
|
|
1400
|
+
for (let i = 0; i < this._k; i++) {
|
|
1401
|
+
r[i] = polyFromBytes(a.subarray(i * 384, (i + 1) * 384));
|
|
1402
|
+
}
|
|
1403
|
+
return r;
|
|
1404
|
+
}
|
|
1405
|
+
// compressU lossily compresses and serializes a vector of polynomials.
|
|
1406
|
+
/**
|
|
1407
|
+
* Compresses the given array of coefficients into a Uint8Array.
|
|
1408
|
+
*
|
|
1409
|
+
* @param r - The output Uint8Array.
|
|
1410
|
+
* @param u - The array of coefficients.
|
|
1411
|
+
* @returns The compressed Uint8Array.
|
|
1412
|
+
*/
|
|
1413
|
+
_compressU(r, u) {
|
|
1414
|
+
const t = new Array(4);
|
|
1415
|
+
for (let rr = 0, i = 0; i < this._k; i++) {
|
|
1416
|
+
for (let j = 0; j < N / 4; j++) {
|
|
1417
|
+
for (let k = 0; k < 4; k++) {
|
|
1418
|
+
// parse {0,...,3328} to {0,...,1023}
|
|
1419
|
+
t[k] = (((u[i][4 * j + k] << 10) + Q / 2) / Q) &
|
|
1420
|
+
0b1111111111;
|
|
1421
|
+
}
|
|
1422
|
+
// converts 4 12-bit coefficients {0,...,3328} to 5 8-bit bytes {0,...,255}
|
|
1423
|
+
// 48 bits down to 40 bits per block
|
|
1424
|
+
r[rr++] = utils_byte(t[0] >> 0);
|
|
1425
|
+
r[rr++] = utils_byte((t[0] >> 8) | (t[1] << 2));
|
|
1426
|
+
r[rr++] = utils_byte((t[1] >> 6) | (t[2] << 4));
|
|
1427
|
+
r[rr++] = utils_byte((t[2] >> 4) | (t[3] << 6));
|
|
1428
|
+
r[rr++] = utils_byte(t[3] >> 2);
|
|
1429
|
+
}
|
|
1430
|
+
}
|
|
1431
|
+
return r;
|
|
1432
|
+
}
|
|
1433
|
+
// compressV lossily compresses and subsequently serializes a polynomial.
|
|
1434
|
+
/**
|
|
1435
|
+
* Compresses the given array of numbers into a Uint8Array.
|
|
1436
|
+
*
|
|
1437
|
+
* @param r - The Uint8Array to store the compressed values.
|
|
1438
|
+
* @param v - The array of numbers to compress.
|
|
1439
|
+
* @returns The compressed Uint8Array.
|
|
1440
|
+
*/
|
|
1441
|
+
_compressV(r, v) {
|
|
1442
|
+
// const r = new Uint8Array(128);
|
|
1443
|
+
const t = new Uint8Array(8);
|
|
1444
|
+
for (let rr = 0, i = 0; i < N / 8; i++) {
|
|
1445
|
+
for (let j = 0; j < 8; j++) {
|
|
1446
|
+
t[j] = utils_byte(((v[8 * i + j] << 4) + Q / 2) / Q) & 0b1111;
|
|
1447
|
+
}
|
|
1448
|
+
r[rr++] = t[0] | (t[1] << 4);
|
|
1449
|
+
r[rr++] = t[2] | (t[3] << 4);
|
|
1450
|
+
r[rr++] = t[4] | (t[5] << 4);
|
|
1451
|
+
r[rr++] = t[6] | (t[7] << 4);
|
|
1452
|
+
}
|
|
1453
|
+
return r;
|
|
1454
|
+
}
|
|
1455
|
+
// decompressU de-serializes and decompresses a vector of polynomials and
|
|
1456
|
+
// represents the approximate inverse of compress1. Since compression is lossy,
|
|
1457
|
+
// the results of decompression will may not match the original vector of polynomials.
|
|
1458
|
+
/**
|
|
1459
|
+
* Decompresses a Uint8Array into a two-dimensional array of numbers.
|
|
1460
|
+
*
|
|
1461
|
+
* @param a The Uint8Array to decompress.
|
|
1462
|
+
* @returns The decompressed two-dimensional array.
|
|
1463
|
+
*/
|
|
1464
|
+
_decompressU(a) {
|
|
1465
|
+
const r = new Array(this._k);
|
|
1466
|
+
for (let i = 0; i < this._k; i++) {
|
|
1467
|
+
r[i] = new Array(384);
|
|
1468
|
+
}
|
|
1469
|
+
const t = new Array(4);
|
|
1470
|
+
for (let aa = 0, i = 0; i < this._k; i++) {
|
|
1471
|
+
for (let j = 0; j < N / 4; j++) {
|
|
1472
|
+
t[0] = (uint16(a[aa + 0]) >> 0) | (uint16(a[aa + 1]) << 8);
|
|
1473
|
+
t[1] = (uint16(a[aa + 1]) >> 2) | (uint16(a[aa + 2]) << 6);
|
|
1474
|
+
t[2] = (uint16(a[aa + 2]) >> 4) | (uint16(a[aa + 3]) << 4);
|
|
1475
|
+
t[3] = (uint16(a[aa + 3]) >> 6) | (uint16(a[aa + 4]) << 2);
|
|
1476
|
+
aa = aa + 5;
|
|
1477
|
+
for (let k = 0; k < 4; k++) {
|
|
1478
|
+
r[i][4 * j + k] = int16((((uint32(t[k] & 0x3FF)) * (uint32(Q))) + 512) >> 10);
|
|
1479
|
+
}
|
|
1480
|
+
}
|
|
1481
|
+
}
|
|
1482
|
+
return r;
|
|
1483
|
+
}
|
|
1484
|
+
// decompressV de-serializes and subsequently decompresses a polynomial,
|
|
1485
|
+
// representing the approximate inverse of compress2.
|
|
1486
|
+
// Note that compression is lossy, and thus decompression will not match the
|
|
1487
|
+
// original input.
|
|
1488
|
+
/**
|
|
1489
|
+
* Decompresses a Uint8Array into an array of numbers.
|
|
1490
|
+
*
|
|
1491
|
+
* @param a - The Uint8Array to decompress.
|
|
1492
|
+
* @returns An array of numbers.
|
|
1493
|
+
*/
|
|
1494
|
+
_decompressV(a) {
|
|
1495
|
+
const r = new Array(384);
|
|
1496
|
+
for (let aa = 0, i = 0; i < N / 2; i++, aa++) {
|
|
1497
|
+
r[2 * i + 0] = int16(((uint16(a[aa] & 15) * uint16(Q)) + 8) >> 4);
|
|
1498
|
+
r[2 * i + 1] = int16(((uint16(a[aa] >> 4) * uint16(Q)) + 8) >> 4);
|
|
1499
|
+
}
|
|
1500
|
+
return r;
|
|
1501
|
+
}
|
|
1502
|
+
}
|
|
1503
|
+
/**
|
|
1504
|
+
* Computes the hash of the input array `a` and an optional input array `b`.
|
|
1505
|
+
* Returns an array containing two Uint8Arrays, representing the first 32 bytes and the next 32 bytes of the hash digest.
|
|
1506
|
+
* @param a - The input array to be hashed.
|
|
1507
|
+
* @param b - An optional input array to be hashed along with `a`.
|
|
1508
|
+
* @returns An array containing two Uint8Arrays representing the hash digest.
|
|
1509
|
+
*/
|
|
1510
|
+
function g(a, b) {
|
|
1511
|
+
const hash = sha3_512.create().update(a);
|
|
1512
|
+
if (b !== undefined) {
|
|
1513
|
+
hash.update(b);
|
|
1514
|
+
}
|
|
1515
|
+
const res = hash.digest();
|
|
1516
|
+
return [res.subarray(0, 32), res.subarray(32, 64)];
|
|
1517
|
+
}
|
|
1518
|
+
/**
|
|
1519
|
+
* Computes the SHA3-256 hash of the given message.
|
|
1520
|
+
*
|
|
1521
|
+
* @param msg - The input message as a Uint8Array.
|
|
1522
|
+
* @returns The computed hash as a Uint8Array.
|
|
1523
|
+
*/
|
|
1524
|
+
function h(msg) {
|
|
1525
|
+
return sha3_256.create().update(msg).digest();
|
|
1526
|
+
}
|
|
1527
|
+
/**
|
|
1528
|
+
* Key Derivation Function (KDF) that takes an input array `a` and an optional input array `b`.
|
|
1529
|
+
* It uses the SHAKE256 hash function to derive a 32-byte output.
|
|
1530
|
+
*
|
|
1531
|
+
* @param a - The input array.
|
|
1532
|
+
* @param b - The optional input array.
|
|
1533
|
+
* @returns The derived key as a Uint8Array.
|
|
1534
|
+
*/
|
|
1535
|
+
function kdf(a, b) {
|
|
1536
|
+
const hash = shake256.create({ dkLen: 32 }).update(a);
|
|
1537
|
+
if (b !== undefined) {
|
|
1538
|
+
hash.update(b);
|
|
1539
|
+
}
|
|
1540
|
+
return hash.digest();
|
|
1541
|
+
}
|
|
1542
|
+
/**
|
|
1543
|
+
* Computes the extendable-output function (XOF) using the SHAKE128 algorithm.
|
|
1544
|
+
*
|
|
1545
|
+
* @param seed - The seed value for the XOF.
|
|
1546
|
+
* @param transpose - The transpose value for the XOF.
|
|
1547
|
+
* @returns The computed XOF value as a Uint8Array.
|
|
1548
|
+
*/
|
|
1549
|
+
function xof(seed, transpose) {
|
|
1550
|
+
return shake128.create({ dkLen: 672 }).update(seed).update(transpose)
|
|
1551
|
+
.digest();
|
|
1552
|
+
}
|
|
1553
|
+
// polyToBytes serializes a polynomial into an array of bytes.
|
|
1554
|
+
/**
|
|
1555
|
+
* Converts a polynomial represented by an array of numbers to a Uint8Array.
|
|
1556
|
+
* Each coefficient of the polynomial is reduced modulo q.
|
|
1557
|
+
*
|
|
1558
|
+
* @param a - The array representing the polynomial.
|
|
1559
|
+
* @returns The Uint8Array representation of the polynomial.
|
|
1560
|
+
*/
|
|
1561
|
+
function polyToBytes(a) {
|
|
1562
|
+
let t0 = 0;
|
|
1563
|
+
let t1 = 0;
|
|
1564
|
+
const r = new Uint8Array(384);
|
|
1565
|
+
const a2 = subtractQ(a); // Returns: a - q if a >= q, else a (each coefficient of the polynomial)
|
|
1566
|
+
// for 0-127
|
|
1567
|
+
for (let i = 0; i < N / 2; i++) {
|
|
1568
|
+
// get two coefficient entries in the polynomial
|
|
1569
|
+
t0 = uint16(a2[2 * i]);
|
|
1570
|
+
t1 = uint16(a2[2 * i + 1]);
|
|
1571
|
+
// convert the 2 coefficient into 3 bytes
|
|
1572
|
+
r[3 * i + 0] = utils_byte(t0 >> 0); // byte() does mod 256 of the input (output value 0-255)
|
|
1573
|
+
r[3 * i + 1] = utils_byte(t0 >> 8) | utils_byte(t1 << 4);
|
|
1574
|
+
r[3 * i + 2] = utils_byte(t1 >> 4);
|
|
1575
|
+
}
|
|
1576
|
+
return r;
|
|
1577
|
+
}
|
|
1578
|
+
// polyFromBytes de-serialises an array of bytes into a polynomial,
|
|
1579
|
+
// and represents the inverse of polyToBytes.
|
|
1580
|
+
/**
|
|
1581
|
+
* Converts a Uint8Array to an array of numbers representing a polynomial.
|
|
1582
|
+
* Each element in the array represents a coefficient of the polynomial.
|
|
1583
|
+
* The input array `a` should have a length of 384.
|
|
1584
|
+
* The function performs bitwise operations to extract the coefficients from the input array.
|
|
1585
|
+
* @param a The Uint8Array to convert to a polynomial.
|
|
1586
|
+
* @returns An array of numbers representing the polynomial.
|
|
1587
|
+
*/
|
|
1588
|
+
function polyFromBytes(a) {
|
|
1589
|
+
const r = new Array(384).fill(0);
|
|
1590
|
+
for (let i = 0; i < N / 2; i++) {
|
|
1591
|
+
r[2 * i] = int16(((uint16(a[3 * i + 0]) >> 0) | (uint16(a[3 * i + 1]) << 8)) & 0xFFF);
|
|
1592
|
+
r[2 * i + 1] = int16(((uint16(a[3 * i + 1]) >> 4) | (uint16(a[3 * i + 2]) << 4)) & 0xFFF);
|
|
1593
|
+
}
|
|
1594
|
+
return r;
|
|
1595
|
+
}
|
|
1596
|
+
// polyToMsg converts a polynomial to a 32-byte message
|
|
1597
|
+
// and represents the inverse of polyFromMsg.
|
|
1598
|
+
/**
|
|
1599
|
+
* Converts a polynomial to a message represented as a Uint8Array.
|
|
1600
|
+
* @param a - The polynomial to convert.
|
|
1601
|
+
* @returns The message as a Uint8Array.
|
|
1602
|
+
*/
|
|
1603
|
+
function polyToMsg(a) {
|
|
1604
|
+
const msg = new Uint8Array(32);
|
|
1605
|
+
let t;
|
|
1606
|
+
const a2 = subtractQ(a);
|
|
1607
|
+
for (let i = 0; i < N / 8; i++) {
|
|
1608
|
+
msg[i] = 0;
|
|
1609
|
+
for (let j = 0; j < 8; j++) {
|
|
1610
|
+
t = (((uint16(a2[8 * i + j]) << 1) + uint16(Q / 2)) /
|
|
1611
|
+
uint16(Q)) & 1;
|
|
1612
|
+
msg[i] |= utils_byte(t << j);
|
|
1613
|
+
}
|
|
1614
|
+
}
|
|
1615
|
+
return msg;
|
|
1616
|
+
}
|
|
1617
|
+
// polyFromMsg converts a 32-byte message to a polynomial.
|
|
1618
|
+
/**
|
|
1619
|
+
* Converts a Uint8Array message to an array of numbers representing a polynomial.
|
|
1620
|
+
* Each element in the array is an int16 (0-65535).
|
|
1621
|
+
*
|
|
1622
|
+
* @param msg - The Uint8Array message to convert.
|
|
1623
|
+
* @returns An array of numbers representing the polynomial.
|
|
1624
|
+
*/
|
|
1625
|
+
function polyFromMsg(msg) {
|
|
1626
|
+
const r = new Array(384).fill(0); // each element is int16 (0-65535)
|
|
1627
|
+
let mask; // int16
|
|
1628
|
+
for (let i = 0; i < N / 8; i++) {
|
|
1629
|
+
for (let j = 0; j < 8; j++) {
|
|
1630
|
+
mask = -1 * int16((msg[i] >> j) & 1);
|
|
1631
|
+
r[8 * i + j] = mask & int16((Q + 1) / 2);
|
|
1632
|
+
}
|
|
1633
|
+
}
|
|
1634
|
+
return r;
|
|
1635
|
+
}
|
|
1636
|
+
// indcpaRejUniform runs rejection sampling on uniform random bytes
|
|
1637
|
+
// to generate uniform random integers modulo `Q`.
|
|
1638
|
+
/**
|
|
1639
|
+
* Generates an array of random numbers from a given buffer, rejecting values greater than a specified threshold.
|
|
1640
|
+
*
|
|
1641
|
+
* @param buf - The input buffer containing random bytes.
|
|
1642
|
+
* @param bufl - The length of the input buffer.
|
|
1643
|
+
* @param len - The desired length of the output array.
|
|
1644
|
+
* @returns An array of random numbers and the actual length of the output array.
|
|
1645
|
+
*/
|
|
1646
|
+
function indcpaRejUniform(buf, bufl, len) {
|
|
1647
|
+
const r = new Array(384).fill(0);
|
|
1648
|
+
let ctr = 0;
|
|
1649
|
+
let val0, val1; // d1, d2 in kyber documentation
|
|
1650
|
+
for (let pos = 0; ctr < len && pos + 3 <= bufl;) {
|
|
1651
|
+
// compute d1 and d2
|
|
1652
|
+
val0 = (uint16((buf[pos]) >> 0) | (uint16(buf[pos + 1]) << 8)) & 0xFFF;
|
|
1653
|
+
val1 = (uint16((buf[pos + 1]) >> 4) | (uint16(buf[pos + 2]) << 4)) & 0xFFF;
|
|
1654
|
+
// increment input buffer index by 3
|
|
1655
|
+
pos = pos + 3;
|
|
1656
|
+
// if d1 is less than 3329
|
|
1657
|
+
if (val0 < Q) {
|
|
1658
|
+
// assign to d1
|
|
1659
|
+
r[ctr] = val0;
|
|
1660
|
+
// increment position of output array
|
|
1661
|
+
ctr = ctr + 1;
|
|
1662
|
+
}
|
|
1663
|
+
if (ctr < len && val1 < Q) {
|
|
1664
|
+
r[ctr] = val1;
|
|
1665
|
+
ctr = ctr + 1;
|
|
1666
|
+
}
|
|
1667
|
+
}
|
|
1668
|
+
return [r, ctr];
|
|
1669
|
+
}
|
|
1670
|
+
// byteopsCbd computes a polynomial with coefficients distributed
|
|
1671
|
+
// according to a centered binomial distribution with parameter PARAMS_ETA,
|
|
1672
|
+
// given an array of uniformly random bytes.
|
|
1673
|
+
/**
|
|
1674
|
+
* Converts a Uint8Array buffer to an array of numbers using the CBD operation.
|
|
1675
|
+
* @param buf - The input Uint8Array buffer.
|
|
1676
|
+
* @param eta - The value used in the CBD operation.
|
|
1677
|
+
* @returns An array of numbers obtained from the CBD operation.
|
|
1678
|
+
*/
|
|
1679
|
+
function byteopsCbd(buf, eta) {
|
|
1680
|
+
let t, d;
|
|
1681
|
+
let a, b;
|
|
1682
|
+
const r = new Array(384).fill(0);
|
|
1683
|
+
for (let i = 0; i < N / 8; i++) {
|
|
1684
|
+
t = byteopsLoad32(buf.subarray(4 * i, buf.length));
|
|
1685
|
+
d = t & 0x55555555;
|
|
1686
|
+
d = d + ((t >> 1) & 0x55555555);
|
|
1687
|
+
for (let j = 0; j < 8; j++) {
|
|
1688
|
+
a = int16((d >> (4 * j + 0)) & 0x3);
|
|
1689
|
+
b = int16((d >> (4 * j + eta)) & 0x3);
|
|
1690
|
+
r[8 * i + j] = a - b;
|
|
1691
|
+
}
|
|
1692
|
+
}
|
|
1693
|
+
return r;
|
|
1694
|
+
}
|
|
1695
|
+
// ntt performs an inplace number-theoretic transform (NTT) in `Rq`.
|
|
1696
|
+
// The input is in standard order, the output is in bit-reversed order.
|
|
1697
|
+
/**
|
|
1698
|
+
* Performs the Number Theoretic Transform (NTT) on an array of numbers.
|
|
1699
|
+
*
|
|
1700
|
+
* @param r - The input array of numbers.
|
|
1701
|
+
* @returns The transformed array of numbers.
|
|
1702
|
+
*/
|
|
1703
|
+
function ntt(r) {
|
|
1704
|
+
// 128, 64, 32, 16, 8, 4, 2
|
|
1705
|
+
for (let j = 0, k = 1, l = 128; l >= 2; l >>= 1) {
|
|
1706
|
+
// 0,
|
|
1707
|
+
for (let start = 0; start < 256; start = j + l) {
|
|
1708
|
+
const zeta = NTT_ZETAS[k];
|
|
1709
|
+
k = k + 1;
|
|
1710
|
+
// for each element in the subsections (128, 64, 32, 16, 8, 4, 2) starting at an offset
|
|
1711
|
+
for (j = start; j < start + l; j++) {
|
|
1712
|
+
// compute the modular multiplication of the zeta and each element in the subsection
|
|
1713
|
+
const t = nttFqMul(zeta, r[j + l]); // t is mod q
|
|
1714
|
+
// overwrite each element in the subsection as the opposite subsection element minus t
|
|
1715
|
+
r[j + l] = r[j] - t;
|
|
1716
|
+
// add t back again to the opposite subsection
|
|
1717
|
+
r[j] = r[j] + t;
|
|
1718
|
+
}
|
|
1719
|
+
}
|
|
1720
|
+
}
|
|
1721
|
+
return r;
|
|
1722
|
+
}
|
|
1723
|
+
// nttFqMul performs multiplication followed by Montgomery reduction
|
|
1724
|
+
// and returns a 16-bit integer congruent to `a*b*R^{-1} mod Q`.
|
|
1725
|
+
/**
|
|
1726
|
+
* Performs an NTT (Number Theoretic Transform) multiplication on two numbers in Fq.
|
|
1727
|
+
* @param a The first number.
|
|
1728
|
+
* @param b The second number.
|
|
1729
|
+
* @returns The result of the NTT multiplication.
|
|
1730
|
+
*/
|
|
1731
|
+
function nttFqMul(a, b) {
|
|
1732
|
+
return byteopsMontgomeryReduce(a * b);
|
|
1733
|
+
}
|
|
1734
|
+
// reduce applies Barrett reduction to all coefficients of a polynomial.
|
|
1735
|
+
/**
|
|
1736
|
+
* Reduces each element in the given array using the barrett function.
|
|
1737
|
+
*
|
|
1738
|
+
* @param r - The array to be reduced.
|
|
1739
|
+
* @returns The reduced array.
|
|
1740
|
+
*/
|
|
1741
|
+
function reduce(r) {
|
|
1742
|
+
for (let i = 0; i < N; i++) {
|
|
1743
|
+
r[i] = barrett(r[i]);
|
|
1744
|
+
}
|
|
1745
|
+
return r;
|
|
1746
|
+
}
|
|
1747
|
+
// barrett computes a Barrett reduction; given
|
|
1748
|
+
// a integer `a`, returns a integer congruent to
|
|
1749
|
+
// `a mod Q` in {0,...,Q}.
|
|
1750
|
+
/**
|
|
1751
|
+
* Performs the Barrett reduction algorithm on the given number.
|
|
1752
|
+
*
|
|
1753
|
+
* @param a - The number to be reduced.
|
|
1754
|
+
* @returns The result of the reduction.
|
|
1755
|
+
*/
|
|
1756
|
+
function barrett(a) {
|
|
1757
|
+
const v = ((1 << 24) + Q / 2) / Q;
|
|
1758
|
+
let t = v * a >> 24;
|
|
1759
|
+
t = t * Q;
|
|
1760
|
+
return a - t;
|
|
1761
|
+
}
|
|
1762
|
+
// byteopsMontgomeryReduce computes a Montgomery reduction; given
|
|
1763
|
+
// a 32-bit integer `a`, returns `a * R^-1 mod Q` where `R=2^16`.
|
|
1764
|
+
/**
|
|
1765
|
+
* Performs Montgomery reduction on a given number.
|
|
1766
|
+
* @param a - The number to be reduced.
|
|
1767
|
+
* @returns The reduced number.
|
|
1768
|
+
*/
|
|
1769
|
+
function byteopsMontgomeryReduce(a) {
|
|
1770
|
+
const u = int16(int32(a) * Q_INV);
|
|
1771
|
+
let t = u * Q;
|
|
1772
|
+
t = a - t;
|
|
1773
|
+
t >>= 16;
|
|
1774
|
+
return int16(t);
|
|
1775
|
+
}
|
|
1776
|
+
// polyToMont performs the in-place conversion of all coefficients
|
|
1777
|
+
// of a polynomial from the normal domain to the Montgomery domain.
|
|
1778
|
+
/**
|
|
1779
|
+
* Converts a polynomial to the Montgomery domain.
|
|
1780
|
+
*
|
|
1781
|
+
* @param r - The polynomial to be converted.
|
|
1782
|
+
* @returns The polynomial in the Montgomery domain.
|
|
1783
|
+
*/
|
|
1784
|
+
function polyToMont(r) {
|
|
1785
|
+
// let f = int16(((uint64(1) << 32)) % uint64(Q));
|
|
1786
|
+
const f = 1353; // if Q changes then this needs to be updated
|
|
1787
|
+
for (let i = 0; i < N; i++) {
|
|
1788
|
+
r[i] = byteopsMontgomeryReduce(int32(r[i]) * int32(f));
|
|
1789
|
+
}
|
|
1790
|
+
return r;
|
|
1791
|
+
}
|
|
1792
|
+
// pointwise-multiplies elements of polynomial-vectors
|
|
1793
|
+
// `a` and `b`, accumulates the results into `r`, and then multiplies by `2^-16`.
|
|
1794
|
+
/**
|
|
1795
|
+
* Multiplies two matrices element-wise and returns the result.
|
|
1796
|
+
* @param a - The first matrix.
|
|
1797
|
+
* @param b - The second matrix.
|
|
1798
|
+
* @returns The resulting matrix after element-wise multiplication.
|
|
1799
|
+
*/
|
|
1800
|
+
function multiply(a, b) {
|
|
1801
|
+
let r = polyBaseMulMontgomery(a[0], b[0]);
|
|
1802
|
+
let t;
|
|
1803
|
+
for (let i = 1; i < a.length; i++) {
|
|
1804
|
+
t = polyBaseMulMontgomery(a[i], b[i]);
|
|
1805
|
+
r = mlKemBase_add(r, t);
|
|
1806
|
+
}
|
|
1807
|
+
return reduce(r);
|
|
1808
|
+
}
|
|
1809
|
+
// polyBaseMulMontgomery performs the multiplication of two polynomials
|
|
1810
|
+
// in the number-theoretic transform (NTT) domain.
|
|
1811
|
+
/**
|
|
1812
|
+
* Performs polynomial base multiplication in Montgomery domain.
|
|
1813
|
+
* @param a - The first polynomial array.
|
|
1814
|
+
* @param b - The second polynomial array.
|
|
1815
|
+
* @returns The result of the polynomial base multiplication.
|
|
1816
|
+
*/
|
|
1817
|
+
function polyBaseMulMontgomery(a, b) {
|
|
1818
|
+
let rx, ry;
|
|
1819
|
+
for (let i = 0; i < N / 4; i++) {
|
|
1820
|
+
rx = nttBaseMul(a[4 * i + 0], a[4 * i + 1], b[4 * i + 0], b[4 * i + 1], NTT_ZETAS[64 + i]);
|
|
1821
|
+
ry = nttBaseMul(a[4 * i + 2], a[4 * i + 3], b[4 * i + 2], b[4 * i + 3], -NTT_ZETAS[64 + i]);
|
|
1822
|
+
a[4 * i + 0] = rx[0];
|
|
1823
|
+
a[4 * i + 1] = rx[1];
|
|
1824
|
+
a[4 * i + 2] = ry[0];
|
|
1825
|
+
a[4 * i + 3] = ry[1];
|
|
1826
|
+
}
|
|
1827
|
+
return a;
|
|
1828
|
+
}
|
|
1829
|
+
// nttBaseMul performs the multiplication of polynomials
|
|
1830
|
+
// in `Zq[X]/(X^2-zeta)`. Used for multiplication of elements
|
|
1831
|
+
// in `Rq` in the number-theoretic transformation domain.
|
|
1832
|
+
/**
|
|
1833
|
+
* Performs NTT base multiplication.
|
|
1834
|
+
*
|
|
1835
|
+
* @param a0 - The first coefficient of the first polynomial.
|
|
1836
|
+
* @param a1 - The second coefficient of the first polynomial.
|
|
1837
|
+
* @param b0 - The first coefficient of the second polynomial.
|
|
1838
|
+
* @param b1 - The second coefficient of the second polynomial.
|
|
1839
|
+
* @param zeta - The zeta value used in the multiplication.
|
|
1840
|
+
* @returns An array containing the result of the multiplication.
|
|
1841
|
+
*/
|
|
1842
|
+
function nttBaseMul(a0, a1, b0, b1, zeta) {
|
|
1843
|
+
const r = new Array(2);
|
|
1844
|
+
r[0] = nttFqMul(a1, b1);
|
|
1845
|
+
r[0] = nttFqMul(r[0], zeta);
|
|
1846
|
+
r[0] += nttFqMul(a0, b0);
|
|
1847
|
+
r[1] = nttFqMul(a0, b1);
|
|
1848
|
+
r[1] += nttFqMul(a1, b0);
|
|
1849
|
+
return r;
|
|
1850
|
+
}
|
|
1851
|
+
// adds two polynomials.
|
|
1852
|
+
/**
|
|
1853
|
+
* Adds two arrays element-wise.
|
|
1854
|
+
* @param a - The first array.
|
|
1855
|
+
* @param b - The second array.
|
|
1856
|
+
* @returns The resulting array after element-wise addition.
|
|
1857
|
+
*/
|
|
1858
|
+
function mlKemBase_add(a, b) {
|
|
1859
|
+
const c = new Array(384);
|
|
1860
|
+
for (let i = 0; i < N; i++) {
|
|
1861
|
+
c[i] = a[i] + b[i];
|
|
1862
|
+
}
|
|
1863
|
+
return c;
|
|
1864
|
+
}
|
|
1865
|
+
// subtracts two polynomials.
|
|
1866
|
+
/**
|
|
1867
|
+
* Subtracts the elements of array b from array a.
|
|
1868
|
+
*
|
|
1869
|
+
* @param a - The array from which to subtract.
|
|
1870
|
+
* @param b - The array to subtract.
|
|
1871
|
+
* @returns The resulting array after subtraction.
|
|
1872
|
+
*/
|
|
1873
|
+
function subtract(a, b) {
|
|
1874
|
+
for (let i = 0; i < N; i++) {
|
|
1875
|
+
a[i] -= b[i];
|
|
1876
|
+
}
|
|
1877
|
+
return a;
|
|
1878
|
+
}
|
|
1879
|
+
// nttInverse performs an inplace inverse number-theoretic transform (NTT)
|
|
1880
|
+
// in `Rq` and multiplication by Montgomery factor 2^16.
|
|
1881
|
+
// The input is in bit-reversed order, the output is in standard order.
|
|
1882
|
+
/**
|
|
1883
|
+
* Performs the inverse Number Theoretic Transform (NTT) on the given array.
|
|
1884
|
+
*
|
|
1885
|
+
* @param r - The input array to perform the inverse NTT on.
|
|
1886
|
+
* @returns The array after performing the inverse NTT.
|
|
1887
|
+
*/
|
|
1888
|
+
function nttInverse(r) {
|
|
1889
|
+
let j = 0;
|
|
1890
|
+
for (let k = 0, l = 2; l <= 128; l <<= 1) {
|
|
1891
|
+
for (let start = 0; start < 256; start = j + l) {
|
|
1892
|
+
const zeta = NTT_ZETAS_INV[k];
|
|
1893
|
+
k = k + 1;
|
|
1894
|
+
for (j = start; j < start + l; j++) {
|
|
1895
|
+
const t = r[j];
|
|
1896
|
+
r[j] = barrett(t + r[j + l]);
|
|
1897
|
+
r[j + l] = t - r[j + l];
|
|
1898
|
+
r[j + l] = nttFqMul(zeta, r[j + l]);
|
|
1899
|
+
}
|
|
1900
|
+
}
|
|
1901
|
+
}
|
|
1902
|
+
for (j = 0; j < 256; j++) {
|
|
1903
|
+
r[j] = nttFqMul(r[j], NTT_ZETAS_INV[127]);
|
|
1904
|
+
}
|
|
1905
|
+
return r;
|
|
1906
|
+
}
|
|
1907
|
+
// subtractQ applies the conditional subtraction of q to each coefficient of a polynomial.
|
|
1908
|
+
// if a is 3329 then convert to 0
|
|
1909
|
+
// Returns: a - q if a >= q, else a
|
|
1910
|
+
/**
|
|
1911
|
+
* Subtracts the value of Q from each element in the given array.
|
|
1912
|
+
* The result should be a negative integer for each element.
|
|
1913
|
+
* If the leftmost bit is 0 (positive number), the value of Q is added back.
|
|
1914
|
+
*
|
|
1915
|
+
* @param r - The array to subtract Q from.
|
|
1916
|
+
* @returns The resulting array after the subtraction.
|
|
1917
|
+
*/
|
|
1918
|
+
function subtractQ(r) {
|
|
1919
|
+
for (let i = 0; i < N; i++) {
|
|
1920
|
+
r[i] -= Q; // should result in a negative integer
|
|
1921
|
+
// push left most signed bit to right most position
|
|
1922
|
+
// javascript does bitwise operations in signed 32 bit
|
|
1923
|
+
// add q back again if left most bit was 0 (positive number)
|
|
1924
|
+
r[i] += (r[i] >> 31) & Q;
|
|
1925
|
+
}
|
|
1926
|
+
return r;
|
|
1927
|
+
}
|
|
1928
|
+
|
|
1929
|
+
;// ./node_modules/mlkem/esm/src/mlKem512.js
|
|
1930
|
+
/**
|
|
1931
|
+
* This implementation is based on https://github.com/antontutoveanu/crystals-kyber-javascript,
|
|
1932
|
+
* which was deveploped under the MIT licence below:
|
|
1933
|
+
* https://github.com/antontutoveanu/crystals-kyber-javascript/blob/main/LICENSE
|
|
1934
|
+
*/
|
|
1935
|
+
|
|
1936
|
+
|
|
1937
|
+
|
|
1938
|
+
/**
|
|
1939
|
+
* Represents the MlKem512 class.
|
|
1940
|
+
*
|
|
1941
|
+
* This class extends the MlKemBase class and provides specific implementation for MlKem512.
|
|
1942
|
+
*
|
|
1943
|
+
* @remarks
|
|
1944
|
+
*
|
|
1945
|
+
* MlKem512 is a specific implementation of the ML-KEM key encapsulation mechanism.
|
|
1946
|
+
*
|
|
1947
|
+
* @example
|
|
1948
|
+
*
|
|
1949
|
+
* ```ts
|
|
1950
|
+
* // Using jsr:
|
|
1951
|
+
* import { MlKem512 } from "@dajiaji/mlkem";
|
|
1952
|
+
* // Using npm:
|
|
1953
|
+
* // import { MlKem512 } from "mlkem"; // or "crystals-kyber-js"
|
|
1954
|
+
*
|
|
1955
|
+
* const recipient = new MlKem512();
|
|
1956
|
+
* const [pkR, skR] = await recipient.generateKeyPair();
|
|
1957
|
+
*
|
|
1958
|
+
* const sender = new MlKem512();
|
|
1959
|
+
* const [ct, ssS] = await sender.encap(pkR);
|
|
1960
|
+
*
|
|
1961
|
+
* const ssR = await recipient.decap(ct, skR);
|
|
1962
|
+
* // ssS === ssR
|
|
1963
|
+
* ```
|
|
1964
|
+
*/
|
|
1965
|
+
class MlKem512 extends MlKemBase {
|
|
1966
|
+
/**
|
|
1967
|
+
* Constructs a new instance of the MlKem512 class.
|
|
1968
|
+
*/
|
|
1969
|
+
constructor() {
|
|
1970
|
+
super();
|
|
1971
|
+
Object.defineProperty(this, "_k", {
|
|
1972
|
+
enumerable: true,
|
|
1973
|
+
configurable: true,
|
|
1974
|
+
writable: true,
|
|
1975
|
+
value: 2
|
|
1976
|
+
});
|
|
1977
|
+
Object.defineProperty(this, "_du", {
|
|
1978
|
+
enumerable: true,
|
|
1979
|
+
configurable: true,
|
|
1980
|
+
writable: true,
|
|
1981
|
+
value: 10
|
|
1982
|
+
});
|
|
1983
|
+
Object.defineProperty(this, "_dv", {
|
|
1984
|
+
enumerable: true,
|
|
1985
|
+
configurable: true,
|
|
1986
|
+
writable: true,
|
|
1987
|
+
value: 4
|
|
1988
|
+
});
|
|
1989
|
+
Object.defineProperty(this, "_eta1", {
|
|
1990
|
+
enumerable: true,
|
|
1991
|
+
configurable: true,
|
|
1992
|
+
writable: true,
|
|
1993
|
+
value: 3
|
|
1994
|
+
});
|
|
1995
|
+
Object.defineProperty(this, "_eta2", {
|
|
1996
|
+
enumerable: true,
|
|
1997
|
+
configurable: true,
|
|
1998
|
+
writable: true,
|
|
1999
|
+
value: 2
|
|
2000
|
+
});
|
|
2001
|
+
this._skSize = 12 * this._k * N / 8;
|
|
2002
|
+
this._pkSize = this._skSize + 32;
|
|
2003
|
+
this._compressedUSize = this._k * this._du * N / 8;
|
|
2004
|
+
this._compressedVSize = this._dv * N / 8;
|
|
2005
|
+
}
|
|
2006
|
+
/**
|
|
2007
|
+
* Samples a vector of polynomials from a seed.
|
|
2008
|
+
* @internal
|
|
2009
|
+
* @param sigma - The seed.
|
|
2010
|
+
* @param offset - The offset.
|
|
2011
|
+
* @param size - The size.
|
|
2012
|
+
* @returns The sampled vector of polynomials.
|
|
2013
|
+
*/
|
|
2014
|
+
_sampleNoise1(sigma, offset, size) {
|
|
2015
|
+
const r = new Array(size);
|
|
2016
|
+
for (let i = 0; i < size; i++) {
|
|
2017
|
+
r[i] = mlKem512_byteopsCbd(prf(this._eta1 * N / 4, sigma, offset), this._eta1);
|
|
2018
|
+
offset++;
|
|
2019
|
+
}
|
|
2020
|
+
return r;
|
|
2021
|
+
}
|
|
2022
|
+
}
|
|
2023
|
+
/**
|
|
2024
|
+
* Performs the byte operations for the Cbd function.
|
|
2025
|
+
*
|
|
2026
|
+
* @param buf - The input buffer.
|
|
2027
|
+
* @param eta - The value of eta.
|
|
2028
|
+
* @returns An array of numbers representing the result of the byte operations.
|
|
2029
|
+
*/
|
|
2030
|
+
function mlKem512_byteopsCbd(buf, eta) {
|
|
2031
|
+
let t, d;
|
|
2032
|
+
let a, b;
|
|
2033
|
+
const r = new Array(384).fill(0);
|
|
2034
|
+
for (let i = 0; i < N / 4; i++) {
|
|
2035
|
+
t = byteopsLoad24(buf.subarray(3 * i, buf.length));
|
|
2036
|
+
d = t & 0x00249249;
|
|
2037
|
+
d = d + ((t >> 1) & 0x00249249);
|
|
2038
|
+
d = d + ((t >> 2) & 0x00249249);
|
|
2039
|
+
for (let j = 0; j < 4; j++) {
|
|
2040
|
+
a = int16((d >> (6 * j + 0)) & 0x7);
|
|
2041
|
+
b = int16((d >> (6 * j + eta)) & 0x7);
|
|
2042
|
+
r[4 * i + j] = a - b;
|
|
2043
|
+
}
|
|
2044
|
+
}
|
|
2045
|
+
return r;
|
|
2046
|
+
}
|
|
2047
|
+
|
|
2048
|
+
;// ./node_modules/mlkem/esm/src/mlKem768.js
|
|
2049
|
+
/**
|
|
2050
|
+
* This implementation is based on https://github.com/antontutoveanu/crystals-kyber-javascript,
|
|
2051
|
+
* which was deveploped under the MIT licence below:
|
|
2052
|
+
* https://github.com/antontutoveanu/crystals-kyber-javascript/blob/main/LICENSE
|
|
2053
|
+
*/
|
|
2054
|
+
|
|
2055
|
+
|
|
2056
|
+
/**
|
|
2057
|
+
* Represents the MlKem768 class, which extends the MlKemBase class.
|
|
2058
|
+
*
|
|
2059
|
+
* This class extends the MlKemBase class and provides specific implementation for MlKem768.
|
|
2060
|
+
*
|
|
2061
|
+
* @remarks
|
|
2062
|
+
*
|
|
2063
|
+
* MlKem768 is a specific implementation of the ML-KEM key encapsulation mechanism.
|
|
2064
|
+
*
|
|
2065
|
+
* @example
|
|
2066
|
+
*
|
|
2067
|
+
* ```ts
|
|
2068
|
+
* // Using jsr:
|
|
2069
|
+
* import { MlKem768 } from "@dajiaji/mlkem";
|
|
2070
|
+
* // Using npm:
|
|
2071
|
+
* // import { MlKem768 } from "mlkem"; // or "crystals-kyber-js"
|
|
2072
|
+
*
|
|
2073
|
+
* const recipient = new MlKem768();
|
|
2074
|
+
* const [pkR, skR] = await recipient.generateKeyPair();
|
|
2075
|
+
*
|
|
2076
|
+
* const sender = new MlKem768();
|
|
2077
|
+
* const [ct, ssS] = await sender.encap(pkR);
|
|
2078
|
+
*
|
|
2079
|
+
* const ssR = await recipient.decap(ct, skR);
|
|
2080
|
+
* // ssS === ssR
|
|
2081
|
+
* ```
|
|
2082
|
+
*/
|
|
2083
|
+
class MlKem768 extends MlKemBase {
|
|
2084
|
+
constructor() {
|
|
2085
|
+
super();
|
|
2086
|
+
Object.defineProperty(this, "_k", {
|
|
2087
|
+
enumerable: true,
|
|
2088
|
+
configurable: true,
|
|
2089
|
+
writable: true,
|
|
2090
|
+
value: 3
|
|
2091
|
+
});
|
|
2092
|
+
Object.defineProperty(this, "_du", {
|
|
2093
|
+
enumerable: true,
|
|
2094
|
+
configurable: true,
|
|
2095
|
+
writable: true,
|
|
2096
|
+
value: 10
|
|
2097
|
+
});
|
|
2098
|
+
Object.defineProperty(this, "_dv", {
|
|
2099
|
+
enumerable: true,
|
|
2100
|
+
configurable: true,
|
|
2101
|
+
writable: true,
|
|
2102
|
+
value: 4
|
|
2103
|
+
});
|
|
2104
|
+
Object.defineProperty(this, "_eta1", {
|
|
2105
|
+
enumerable: true,
|
|
2106
|
+
configurable: true,
|
|
2107
|
+
writable: true,
|
|
2108
|
+
value: 2
|
|
2109
|
+
});
|
|
2110
|
+
Object.defineProperty(this, "_eta2", {
|
|
2111
|
+
enumerable: true,
|
|
2112
|
+
configurable: true,
|
|
2113
|
+
writable: true,
|
|
2114
|
+
value: 2
|
|
2115
|
+
});
|
|
2116
|
+
this._skSize = 12 * this._k * N / 8;
|
|
2117
|
+
this._pkSize = this._skSize + 32;
|
|
2118
|
+
this._compressedUSize = this._k * this._du * N / 8;
|
|
2119
|
+
this._compressedVSize = this._dv * N / 8;
|
|
2120
|
+
}
|
|
2121
|
+
}
|
|
2122
|
+
|
|
2123
|
+
;// ./node_modules/mlkem/esm/src/mlKem1024.js
|
|
2124
|
+
/**
|
|
2125
|
+
* This implementation is based on https://github.com/antontutoveanu/crystals-kyber-javascript,
|
|
2126
|
+
* which was deveploped under the MIT licence below:
|
|
2127
|
+
* https://github.com/antontutoveanu/crystals-kyber-javascript/blob/main/LICENSE
|
|
2128
|
+
*/
|
|
2129
|
+
|
|
2130
|
+
|
|
2131
|
+
|
|
2132
|
+
/**
|
|
2133
|
+
* Represents the MlKem1024 class, which extends the MlKemBase class.
|
|
2134
|
+
*
|
|
2135
|
+
* This class extends the MlKemBase class and provides specific implementation for MlKem1024.
|
|
2136
|
+
*
|
|
2137
|
+
* @remarks
|
|
2138
|
+
*
|
|
2139
|
+
* MlKem1024 is a specific implementation of the ML-KEM key encapsulation mechanism.
|
|
2140
|
+
*
|
|
2141
|
+
* @example
|
|
2142
|
+
*
|
|
2143
|
+
* ```ts
|
|
2144
|
+
* // Using jsr:
|
|
2145
|
+
* import { MlKem1024 } from "@dajiaji/mlkem";
|
|
2146
|
+
* // Using npm:
|
|
2147
|
+
* // import { MlKem1024 } from "mlkem"; // or "crystals-kyber-js"
|
|
2148
|
+
*
|
|
2149
|
+
* const recipient = new MlKem1024();
|
|
2150
|
+
* const [pkR, skR] = await recipient.generateKeyPair();
|
|
2151
|
+
*
|
|
2152
|
+
* const sender = new MlKem1024();
|
|
2153
|
+
* const [ct, ssS] = await sender.encap(pkR);
|
|
2154
|
+
*
|
|
2155
|
+
* const ssR = await recipient.decap(ct, skR);
|
|
2156
|
+
* // ssS === ssR
|
|
2157
|
+
* ```
|
|
2158
|
+
*/
|
|
2159
|
+
class MlKem1024 extends MlKemBase {
|
|
2160
|
+
/**
|
|
2161
|
+
* Constructs a new instance of the MlKem1024 class.
|
|
2162
|
+
*/
|
|
2163
|
+
constructor() {
|
|
2164
|
+
super();
|
|
2165
|
+
Object.defineProperty(this, "_k", {
|
|
2166
|
+
enumerable: true,
|
|
2167
|
+
configurable: true,
|
|
2168
|
+
writable: true,
|
|
2169
|
+
value: 4
|
|
2170
|
+
});
|
|
2171
|
+
Object.defineProperty(this, "_du", {
|
|
2172
|
+
enumerable: true,
|
|
2173
|
+
configurable: true,
|
|
2174
|
+
writable: true,
|
|
2175
|
+
value: 11
|
|
2176
|
+
});
|
|
2177
|
+
Object.defineProperty(this, "_dv", {
|
|
2178
|
+
enumerable: true,
|
|
2179
|
+
configurable: true,
|
|
2180
|
+
writable: true,
|
|
2181
|
+
value: 5
|
|
2182
|
+
});
|
|
2183
|
+
Object.defineProperty(this, "_eta1", {
|
|
2184
|
+
enumerable: true,
|
|
2185
|
+
configurable: true,
|
|
2186
|
+
writable: true,
|
|
2187
|
+
value: 2
|
|
2188
|
+
});
|
|
2189
|
+
Object.defineProperty(this, "_eta2", {
|
|
2190
|
+
enumerable: true,
|
|
2191
|
+
configurable: true,
|
|
2192
|
+
writable: true,
|
|
2193
|
+
value: 2
|
|
2194
|
+
});
|
|
2195
|
+
this._skSize = 12 * this._k * N / 8;
|
|
2196
|
+
this._pkSize = this._skSize + 32;
|
|
2197
|
+
this._compressedUSize = this._k * this._du * N / 8;
|
|
2198
|
+
this._compressedVSize = this._dv * N / 8;
|
|
2199
|
+
}
|
|
2200
|
+
// compressU lossily compresses and serializes a vector of polynomials.
|
|
2201
|
+
/**
|
|
2202
|
+
* Lossily compresses and serializes a vector of polynomials.
|
|
2203
|
+
*
|
|
2204
|
+
* @param u - The vector of polynomials to compress.
|
|
2205
|
+
* @returns The compressed and serialized data as a Uint8Array.
|
|
2206
|
+
*/
|
|
2207
|
+
_compressU(r, u) {
|
|
2208
|
+
const t = new Array(8);
|
|
2209
|
+
for (let rr = 0, i = 0; i < this._k; i++) {
|
|
2210
|
+
for (let j = 0; j < N / 8; j++) {
|
|
2211
|
+
for (let k = 0; k < 8; k++) {
|
|
2212
|
+
t[k] = uint16((((uint32(u[i][8 * j + k]) << 11) + uint32(Q / 2)) /
|
|
2213
|
+
uint32(Q)) & 0x7ff);
|
|
2214
|
+
}
|
|
2215
|
+
r[rr++] = utils_byte(t[0] >> 0);
|
|
2216
|
+
r[rr++] = utils_byte((t[0] >> 8) | (t[1] << 3));
|
|
2217
|
+
r[rr++] = utils_byte((t[1] >> 5) | (t[2] << 6));
|
|
2218
|
+
r[rr++] = utils_byte(t[2] >> 2);
|
|
2219
|
+
r[rr++] = utils_byte((t[2] >> 10) | (t[3] << 1));
|
|
2220
|
+
r[rr++] = utils_byte((t[3] >> 7) | (t[4] << 4));
|
|
2221
|
+
r[rr++] = utils_byte((t[4] >> 4) | (t[5] << 7));
|
|
2222
|
+
r[rr++] = utils_byte(t[5] >> 1);
|
|
2223
|
+
r[rr++] = utils_byte((t[5] >> 9) | (t[6] << 2));
|
|
2224
|
+
r[rr++] = utils_byte((t[6] >> 6) | (t[7] << 5));
|
|
2225
|
+
r[rr++] = utils_byte(t[7] >> 3);
|
|
2226
|
+
}
|
|
2227
|
+
}
|
|
2228
|
+
return r;
|
|
2229
|
+
}
|
|
2230
|
+
// compressV lossily compresses and subsequently serializes a polynomial.
|
|
2231
|
+
/**
|
|
2232
|
+
* Lossily compresses and serializes a polynomial.
|
|
2233
|
+
*
|
|
2234
|
+
* @param r - The output buffer to store the compressed data.
|
|
2235
|
+
* @param v - The polynomial to compress.
|
|
2236
|
+
* @returns The compressed and serialized data as a Uint8Array.
|
|
2237
|
+
*/
|
|
2238
|
+
_compressV(r, v) {
|
|
2239
|
+
const t = new Uint8Array(8);
|
|
2240
|
+
for (let rr = 0, i = 0; i < N / 8; i++) {
|
|
2241
|
+
for (let j = 0; j < 8; j++) {
|
|
2242
|
+
t[j] = utils_byte(((uint32(v[8 * i + j]) << 5) + uint32(Q / 2)) / uint32(Q)) & 31;
|
|
2243
|
+
}
|
|
2244
|
+
r[rr++] = utils_byte((t[0] >> 0) | (t[1] << 5));
|
|
2245
|
+
r[rr++] = utils_byte((t[1] >> 3) | (t[2] << 2) | (t[3] << 7));
|
|
2246
|
+
r[rr++] = utils_byte((t[3] >> 1) | (t[4] << 4));
|
|
2247
|
+
r[rr++] = utils_byte((t[4] >> 4) | (t[5] << 1) | (t[6] << 6));
|
|
2248
|
+
r[rr++] = utils_byte((t[6] >> 2) | (t[7] << 3));
|
|
2249
|
+
}
|
|
2250
|
+
return r;
|
|
2251
|
+
}
|
|
2252
|
+
// decompressU de-serializes and decompresses a vector of polynomials and
|
|
2253
|
+
// represents the approximate inverse of compress1. Since compression is lossy,
|
|
2254
|
+
// the results of decompression will may not match the original vector of polynomials.
|
|
2255
|
+
/**
|
|
2256
|
+
* Deserializes and decompresses a vector of polynomials.
|
|
2257
|
+
* This is the approximate inverse of the `_compressU` method.
|
|
2258
|
+
* Since compression is lossy, the decompressed data may not match the original vector of polynomials.
|
|
2259
|
+
*
|
|
2260
|
+
* @param a - The compressed and serialized data as a Uint8Array.
|
|
2261
|
+
* @returns The decompressed vector of polynomials.
|
|
2262
|
+
*/
|
|
2263
|
+
_decompressU(a) {
|
|
2264
|
+
const r = new Array(this._k);
|
|
2265
|
+
for (let i = 0; i < this._k; i++) {
|
|
2266
|
+
r[i] = new Array(384);
|
|
2267
|
+
}
|
|
2268
|
+
const t = new Array(8);
|
|
2269
|
+
for (let aa = 0, i = 0; i < this._k; i++) {
|
|
2270
|
+
for (let j = 0; j < N / 8; j++) {
|
|
2271
|
+
t[0] = (uint16(a[aa + 0]) >> 0) | (uint16(a[aa + 1]) << 8);
|
|
2272
|
+
t[1] = (uint16(a[aa + 1]) >> 3) | (uint16(a[aa + 2]) << 5);
|
|
2273
|
+
t[2] = (uint16(a[aa + 2]) >> 6) | (uint16(a[aa + 3]) << 2) |
|
|
2274
|
+
(uint16(a[aa + 4]) << 10);
|
|
2275
|
+
t[3] = (uint16(a[aa + 4]) >> 1) | (uint16(a[aa + 5]) << 7);
|
|
2276
|
+
t[4] = (uint16(a[aa + 5]) >> 4) | (uint16(a[aa + 6]) << 4);
|
|
2277
|
+
t[5] = (uint16(a[aa + 6]) >> 7) | (uint16(a[aa + 7]) << 1) |
|
|
2278
|
+
(uint16(a[aa + 8]) << 9);
|
|
2279
|
+
t[6] = (uint16(a[aa + 8]) >> 2) | (uint16(a[aa + 9]) << 6);
|
|
2280
|
+
t[7] = (uint16(a[aa + 9]) >> 5) | (uint16(a[aa + 10]) << 3);
|
|
2281
|
+
aa = aa + 11;
|
|
2282
|
+
for (let k = 0; k < 8; k++) {
|
|
2283
|
+
r[i][8 * j + k] = (uint32(t[k] & 0x7FF) * Q + 1024) >> 11;
|
|
2284
|
+
}
|
|
2285
|
+
}
|
|
2286
|
+
}
|
|
2287
|
+
return r;
|
|
2288
|
+
}
|
|
2289
|
+
// decompressV de-serializes and subsequently decompresses a polynomial,
|
|
2290
|
+
// representing the approximate inverse of compress2.
|
|
2291
|
+
// Note that compression is lossy, and thus decompression will not match the
|
|
2292
|
+
// original input.
|
|
2293
|
+
/**
|
|
2294
|
+
* Decompresses a given polynomial, representing the approximate inverse of
|
|
2295
|
+
* compress2, in Uint8Array into an array of numbers.
|
|
2296
|
+
*
|
|
2297
|
+
* Note that compression is lossy, and thus decompression will not match the
|
|
2298
|
+
* original input.
|
|
2299
|
+
*
|
|
2300
|
+
* @param a - The Uint8Array to decompress.
|
|
2301
|
+
* @returns An array of numbers obtained from the decompression process.
|
|
2302
|
+
*/
|
|
2303
|
+
_decompressV(a) {
|
|
2304
|
+
const r = new Array(384);
|
|
2305
|
+
const t = new Array(8);
|
|
2306
|
+
for (let aa = 0, i = 0; i < N / 8; i++) {
|
|
2307
|
+
t[0] = a[aa + 0] >> 0;
|
|
2308
|
+
t[1] = (a[aa + 0] >> 5) | (a[aa + 1] << 3);
|
|
2309
|
+
t[2] = a[aa + 1] >> 2;
|
|
2310
|
+
t[3] = (a[aa + 1] >> 7) | (a[aa + 2] << 1);
|
|
2311
|
+
t[4] = (a[aa + 2] >> 4) | (a[aa + 3] << 4);
|
|
2312
|
+
t[5] = a[aa + 3] >> 1;
|
|
2313
|
+
t[6] = (a[aa + 3] >> 6) | (a[aa + 4] << 2);
|
|
2314
|
+
t[7] = a[aa + 4] >> 3;
|
|
2315
|
+
aa = aa + 5;
|
|
2316
|
+
for (let j = 0; j < 8; j++) {
|
|
2317
|
+
r[8 * i + j] = int16(((uint32(t[j] & 31) * uint32(Q)) + 16) >> 5);
|
|
2318
|
+
}
|
|
2319
|
+
}
|
|
2320
|
+
return r;
|
|
2321
|
+
}
|
|
2322
|
+
}
|
|
2323
|
+
|
|
2324
|
+
;// ./node_modules/mlkem/esm/mod.js
|
|
2325
|
+
|
|
2326
|
+
|
|
2327
|
+
|
|
2328
|
+
|
|
2329
|
+
|
|
2330
|
+
|
|
2331
|
+
|
|
2332
|
+
/***/ })
|
|
2333
|
+
|
|
2334
|
+
}]);
|
|
2335
|
+
//# sourceMappingURL=defaultVendors-node_modules_mlkem_esm_mod_js.shogun-core.js.map
|