@twin.org/crypto 0.0.2-next.9 → 0.0.3-next.2
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/es/address/bech32.js +72 -0
- package/dist/es/address/bech32.js.map +1 -0
- package/dist/es/address/bip44.js +113 -0
- package/dist/es/address/bip44.js.map +1 -0
- package/dist/es/ciphers/chaCha20Poly1305.js +48 -0
- package/dist/es/ciphers/chaCha20Poly1305.js.map +1 -0
- package/dist/es/curves/ed25519.js +114 -0
- package/dist/es/curves/ed25519.js.map +1 -0
- package/dist/es/curves/secp256k1.js +82 -0
- package/dist/es/curves/secp256k1.js.map +1 -0
- package/dist/es/curves/x25519.js +34 -0
- package/dist/es/curves/x25519.js.map +1 -0
- package/dist/es/curves/zip215.js +33 -0
- package/dist/es/curves/zip215.js.map +1 -0
- package/dist/es/hashes/blake2b.js +90 -0
- package/dist/es/hashes/blake2b.js.map +1 -0
- package/dist/es/hashes/blake3.js +76 -0
- package/dist/es/hashes/blake3.js.map +1 -0
- package/dist/es/hashes/hmacSha1.js +56 -0
- package/dist/es/hashes/hmacSha1.js.map +1 -0
- package/dist/es/hashes/hmacSha256.js +83 -0
- package/dist/es/hashes/hmacSha256.js.map +1 -0
- package/dist/es/hashes/hmacSha512.js +132 -0
- package/dist/es/hashes/hmacSha512.js.map +1 -0
- package/dist/es/hashes/pbkdf2.js +45 -0
- package/dist/es/hashes/pbkdf2.js.map +1 -0
- package/dist/es/hashes/sha1.js +52 -0
- package/dist/es/hashes/sha1.js.map +1 -0
- package/dist/es/hashes/sha256.js +75 -0
- package/dist/es/hashes/sha256.js.map +1 -0
- package/dist/es/hashes/sha3.js +122 -0
- package/dist/es/hashes/sha3.js.map +1 -0
- package/dist/es/hashes/sha512.js +118 -0
- package/dist/es/hashes/sha512.js.map +1 -0
- package/dist/es/helpers/pemHelper.js +42 -0
- package/dist/es/helpers/pemHelper.js.map +1 -0
- package/dist/es/index.js +29 -0
- package/dist/es/index.js.map +1 -0
- package/dist/es/keys/bip32Path.js +72 -0
- package/dist/es/keys/bip32Path.js.map +1 -0
- package/dist/es/keys/bip39.js +83 -0
- package/dist/es/keys/bip39.js.map +1 -0
- package/dist/es/keys/slip0010.js +83 -0
- package/dist/es/keys/slip0010.js.map +1 -0
- package/dist/es/models/keyType.js +17 -0
- package/dist/es/models/keyType.js.map +1 -0
- package/dist/es/otp/hotp.js +27 -0
- package/dist/es/otp/hotp.js.map +1 -0
- package/dist/es/otp/totp.js +75 -0
- package/dist/es/otp/totp.js.map +1 -0
- package/dist/es/passwords/passwordGenerator.js +28 -0
- package/dist/es/passwords/passwordGenerator.js.map +1 -0
- package/dist/es/passwords/passwordValidator.js +81 -0
- package/dist/es/passwords/passwordValidator.js.map +1 -0
- package/dist/types/address/bech32.d.ts +4 -0
- package/dist/types/address/bip44.d.ts +6 -2
- package/dist/types/ciphers/chaCha20Poly1305.d.ts +4 -0
- package/dist/types/curves/ed25519.d.ts +4 -0
- package/dist/types/curves/secp256k1.d.ts +4 -0
- package/dist/types/curves/x25519.d.ts +4 -0
- package/dist/types/curves/zip215.d.ts +4 -0
- package/dist/types/hashes/blake2b.d.ts +4 -0
- package/dist/types/hashes/blake3.d.ts +4 -0
- package/dist/types/hashes/hmacSha1.d.ts +4 -0
- package/dist/types/hashes/hmacSha256.d.ts +4 -0
- package/dist/types/hashes/hmacSha512.d.ts +4 -0
- package/dist/types/hashes/pbkdf2.d.ts +4 -0
- package/dist/types/hashes/sha1.d.ts +4 -0
- package/dist/types/hashes/sha256.d.ts +4 -0
- package/dist/types/hashes/sha3.d.ts +4 -0
- package/dist/types/hashes/sha512.d.ts +4 -0
- package/dist/types/helpers/pemHelper.d.ts +4 -0
- package/dist/types/index.d.ts +26 -26
- package/dist/types/keys/bip39.d.ts +4 -0
- package/dist/types/keys/slip0010.d.ts +6 -2
- package/dist/types/otp/hotp.d.ts +4 -0
- package/docs/changelog.md +286 -0
- package/docs/reference/classes/Bech32.md +8 -0
- package/docs/reference/classes/Bip39.md +8 -0
- package/docs/reference/classes/Bip44.md +8 -0
- package/docs/reference/classes/Blake2b.md +8 -0
- package/docs/reference/classes/Blake3.md +8 -0
- package/docs/reference/classes/ChaCha20Poly1305.md +8 -0
- package/docs/reference/classes/Ed25519.md +8 -0
- package/docs/reference/classes/HmacSha1.md +8 -0
- package/docs/reference/classes/HmacSha256.md +8 -0
- package/docs/reference/classes/HmacSha512.md +8 -0
- package/docs/reference/classes/Hotp.md +8 -0
- package/docs/reference/classes/Pbkdf2.md +8 -0
- package/docs/reference/classes/PemHelper.md +8 -0
- package/docs/reference/classes/Secp256k1.md +8 -0
- package/docs/reference/classes/Sha1.md +8 -0
- package/docs/reference/classes/Sha256.md +8 -0
- package/docs/reference/classes/Sha3.md +8 -0
- package/docs/reference/classes/Sha512.md +8 -0
- package/docs/reference/classes/Slip0010.md +8 -0
- package/docs/reference/classes/Totp.md +2 -2
- package/docs/reference/classes/X25519.md +8 -0
- package/docs/reference/classes/Zip215.md +8 -0
- package/locales/en.json +9 -28
- package/package.json +29 -16
- package/dist/cjs/index.cjs +0 -1876
- package/dist/esm/index.mjs +0 -1829
package/dist/esm/index.mjs
DELETED
|
@@ -1,1829 +0,0 @@
|
|
|
1
|
-
import { bech32 } from '@scure/base';
|
|
2
|
-
import { Guards, BaseError, GeneralError, Is, Uint8ArrayHelper, Converter, GuardError, Base32, RandomHelper, Validation } from '@twin.org/core';
|
|
3
|
-
import { ed25519 } from '@noble/curves/ed25519.js';
|
|
4
|
-
import { secp256k1 } from '@noble/curves/secp256k1.js';
|
|
5
|
-
import { blake2b } from '@noble/hashes/blake2.js';
|
|
6
|
-
import { HDKey as HDKey$1 } from '@scure/bip32';
|
|
7
|
-
import { HDKey } from 'micro-key-producer/slip10.js';
|
|
8
|
-
import { chacha20poly1305 } from '@noble/ciphers/chacha.js';
|
|
9
|
-
import { blake3 } from '@noble/hashes/blake3.js';
|
|
10
|
-
import { hmac } from '@noble/hashes/hmac.js';
|
|
11
|
-
import { sha1 } from '@noble/hashes/legacy.js';
|
|
12
|
-
import { sha256, sha224, sha512_224, sha512_256, sha384, sha512 } from '@noble/hashes/sha2.js';
|
|
13
|
-
import { pbkdf2 } from '@noble/hashes/pbkdf2.js';
|
|
14
|
-
import { sha3_224, sha3_256, sha3_384, sha3_512 } from '@noble/hashes/sha3.js';
|
|
15
|
-
import * as bip39 from '@scure/bip39';
|
|
16
|
-
import { wordlist } from '@scure/bip39/wordlists/english.js';
|
|
17
|
-
import * as otp from 'micro-key-producer/otp.js';
|
|
18
|
-
|
|
19
|
-
// Copyright 2024 IOTA Stiftung.
|
|
20
|
-
// SPDX-License-Identifier: Apache-2.0.
|
|
21
|
-
/**
|
|
22
|
-
* Bech32 encoding and decoding.
|
|
23
|
-
*/
|
|
24
|
-
class Bech32 {
|
|
25
|
-
/**
|
|
26
|
-
* Runtime name for the class.
|
|
27
|
-
* @internal
|
|
28
|
-
*/
|
|
29
|
-
static _CLASS_NAME = "Bech32";
|
|
30
|
-
/**
|
|
31
|
-
* Encode the buffer.
|
|
32
|
-
* @param humanReadablePart The header.
|
|
33
|
-
* @param data The data to encode.
|
|
34
|
-
* @returns The encoded data.
|
|
35
|
-
*/
|
|
36
|
-
static encode(humanReadablePart, data) {
|
|
37
|
-
Guards.stringValue(Bech32._CLASS_NAME, "humanReadablePart", humanReadablePart);
|
|
38
|
-
Guards.uint8Array(Bech32._CLASS_NAME, "data", data);
|
|
39
|
-
return bech32.encode(humanReadablePart, bech32.toWords(data));
|
|
40
|
-
}
|
|
41
|
-
/**
|
|
42
|
-
* Decode a bech32 string.
|
|
43
|
-
* @param bech The text to decode.
|
|
44
|
-
* @returns The decoded data or undefined if it could not be decoded.
|
|
45
|
-
* @throws An error if the decoding fails.
|
|
46
|
-
*/
|
|
47
|
-
static decode(bech) {
|
|
48
|
-
Guards.stringValue(Bech32._CLASS_NAME, "bech", bech);
|
|
49
|
-
try {
|
|
50
|
-
const result = bech32.decodeToBytes(bech);
|
|
51
|
-
return {
|
|
52
|
-
humanReadablePart: result.prefix,
|
|
53
|
-
data: result.bytes
|
|
54
|
-
};
|
|
55
|
-
}
|
|
56
|
-
catch (err) {
|
|
57
|
-
if (BaseError.isErrorMessage(err, /checksum/)) {
|
|
58
|
-
throw new GeneralError(Bech32._CLASS_NAME, "invalidChecksum", { bech: bech32 });
|
|
59
|
-
}
|
|
60
|
-
else if (BaseError.isErrorMessage(err, /between prefix and data only/i)) {
|
|
61
|
-
throw new GeneralError(Bech32._CLASS_NAME, "separatorMisused", { bech: bech32 });
|
|
62
|
-
}
|
|
63
|
-
else if (BaseError.isErrorMessage(err, /lowercase or uppercase/i)) {
|
|
64
|
-
throw new GeneralError(Bech32._CLASS_NAME, "lowerUpper", { bech: bech32 });
|
|
65
|
-
}
|
|
66
|
-
else if (BaseError.isErrorMessage(err, /must be at least/i) ||
|
|
67
|
-
BaseError.isErrorMessage(err, /wrong string length/i)) {
|
|
68
|
-
throw new GeneralError(Bech32._CLASS_NAME, "dataTooShort", { bech: bech32 });
|
|
69
|
-
}
|
|
70
|
-
throw new GeneralError(Bech32._CLASS_NAME, "decodeFailed", { bech: bech32 }, err);
|
|
71
|
-
}
|
|
72
|
-
}
|
|
73
|
-
/**
|
|
74
|
-
* Is the input a bech 32 address.
|
|
75
|
-
* @param bech The value to test.
|
|
76
|
-
* @returns True if this is potentially a match.
|
|
77
|
-
*/
|
|
78
|
-
static isBech32(bech) {
|
|
79
|
-
try {
|
|
80
|
-
if (Is.stringValue(bech)) {
|
|
81
|
-
const result = bech32.decodeToBytes(bech);
|
|
82
|
-
return (Is.stringValue(result.prefix) && Is.uint8Array(result.bytes) && result.bytes.length > 0);
|
|
83
|
-
}
|
|
84
|
-
}
|
|
85
|
-
catch { }
|
|
86
|
-
return false;
|
|
87
|
-
}
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
// Copyright 2024 IOTA Stiftung.
|
|
91
|
-
// SPDX-License-Identifier: Apache-2.0.
|
|
92
|
-
/**
|
|
93
|
-
* Implementation of Ed25519.
|
|
94
|
-
*/
|
|
95
|
-
class Ed25519 {
|
|
96
|
-
/**
|
|
97
|
-
* Private Key Size is the size, in bytes, of private keys as used in this package.
|
|
98
|
-
*/
|
|
99
|
-
static PRIVATE_KEY_SIZE = 32;
|
|
100
|
-
/**
|
|
101
|
-
* Public Key Size is the size, in bytes, of public keys as used in this package.
|
|
102
|
-
*/
|
|
103
|
-
static PUBLIC_KEY_SIZE = 32;
|
|
104
|
-
/**
|
|
105
|
-
* Runtime name for the class.
|
|
106
|
-
* @internal
|
|
107
|
-
*/
|
|
108
|
-
static _CLASS_NAME = "Ed25519";
|
|
109
|
-
/**
|
|
110
|
-
* Public returns the PublicKey corresponding to private.
|
|
111
|
-
* @param privateKey The private key to get the corresponding public key.
|
|
112
|
-
* @returns The public key.
|
|
113
|
-
* @throws Error if the private key is not the correct length.
|
|
114
|
-
*/
|
|
115
|
-
static publicKeyFromPrivateKey(privateKey) {
|
|
116
|
-
Guards.uint8Array(Ed25519._CLASS_NAME, "privateKey", privateKey);
|
|
117
|
-
if (privateKey.length !== Ed25519.PRIVATE_KEY_SIZE) {
|
|
118
|
-
throw new GeneralError(Ed25519._CLASS_NAME, "privateKeyLength", {
|
|
119
|
-
requiredSize: Ed25519.PRIVATE_KEY_SIZE,
|
|
120
|
-
actualSize: privateKey.length
|
|
121
|
-
});
|
|
122
|
-
}
|
|
123
|
-
return ed25519.getPublicKey(privateKey);
|
|
124
|
-
}
|
|
125
|
-
/**
|
|
126
|
-
* Sign the block with privateKey and returns a signature.
|
|
127
|
-
* @param privateKey The private key.
|
|
128
|
-
* @param block The block to sign.
|
|
129
|
-
* @returns The signature.
|
|
130
|
-
* @throws Error if the private key is not the correct length.
|
|
131
|
-
*/
|
|
132
|
-
static sign(privateKey, block) {
|
|
133
|
-
Guards.uint8Array(Ed25519._CLASS_NAME, "privateKey", privateKey);
|
|
134
|
-
Guards.uint8Array(Ed25519._CLASS_NAME, "block", block);
|
|
135
|
-
if (privateKey.length !== Ed25519.PRIVATE_KEY_SIZE) {
|
|
136
|
-
throw new GeneralError(Ed25519._CLASS_NAME, "privateKeyLength", {
|
|
137
|
-
requiredSize: Ed25519.PRIVATE_KEY_SIZE,
|
|
138
|
-
actualSize: privateKey ? privateKey.length : 0
|
|
139
|
-
});
|
|
140
|
-
}
|
|
141
|
-
return ed25519.sign(block, privateKey);
|
|
142
|
-
}
|
|
143
|
-
/**
|
|
144
|
-
* Verify reports whether sig is a valid signature of block by publicKey.
|
|
145
|
-
* @param publicKey The public key to verify the signature.
|
|
146
|
-
* @param block The block for the signature.
|
|
147
|
-
* @param signature The signature.
|
|
148
|
-
* @returns True if the signature matches.
|
|
149
|
-
* @throws Error if the public key is not the correct length.
|
|
150
|
-
*/
|
|
151
|
-
static verify(publicKey, block, signature) {
|
|
152
|
-
Guards.uint8Array(Ed25519._CLASS_NAME, "publicKey", publicKey);
|
|
153
|
-
Guards.uint8Array(Ed25519._CLASS_NAME, "block", block);
|
|
154
|
-
Guards.uint8Array(Ed25519._CLASS_NAME, "signature", signature);
|
|
155
|
-
if (publicKey.length !== Ed25519.PUBLIC_KEY_SIZE) {
|
|
156
|
-
throw new GeneralError(Ed25519._CLASS_NAME, "publicKeyLength", {
|
|
157
|
-
requiredSize: Ed25519.PUBLIC_KEY_SIZE,
|
|
158
|
-
actualSize: publicKey ? publicKey.length : 0
|
|
159
|
-
});
|
|
160
|
-
}
|
|
161
|
-
try {
|
|
162
|
-
return ed25519.verify(signature, block, publicKey);
|
|
163
|
-
}
|
|
164
|
-
catch {
|
|
165
|
-
return false;
|
|
166
|
-
}
|
|
167
|
-
}
|
|
168
|
-
/**
|
|
169
|
-
* Convert a private key in PKCS8 format.
|
|
170
|
-
* @param privateKey The private key to convert.
|
|
171
|
-
* @returns The private key in PKCS8 format.
|
|
172
|
-
*/
|
|
173
|
-
static async privateKeyToPkcs8(privateKey) {
|
|
174
|
-
Guards.uint8Array(Ed25519._CLASS_NAME, "privateKey", privateKey);
|
|
175
|
-
if (privateKey.length !== Ed25519.PRIVATE_KEY_SIZE) {
|
|
176
|
-
throw new GeneralError(Ed25519._CLASS_NAME, "privateKeyLength", {
|
|
177
|
-
requiredSize: Ed25519.PRIVATE_KEY_SIZE,
|
|
178
|
-
actualSize: privateKey.length
|
|
179
|
-
});
|
|
180
|
-
}
|
|
181
|
-
// crypto.subtle.importKey does not support Ed25519 keys in raw format.
|
|
182
|
-
// We need to convert the key to PKCS8 format before importing.
|
|
183
|
-
// The PKCS8 format is the raw key prefixed with the ASN.1 sequence for an Ed25519 private key.
|
|
184
|
-
// The ASN.1 sequence is 48 46 02 01 00 30 05 06 03 2b 65 70 04 20 04 20 (0x302e020100300506032b657004220420)
|
|
185
|
-
const pkcs8Prefix = new Uint8Array([48, 46, 2, 1, 0, 48, 5, 6, 3, 43, 101, 112, 4, 34, 4, 32]);
|
|
186
|
-
const fullKey = Uint8ArrayHelper.concat([pkcs8Prefix, privateKey]);
|
|
187
|
-
return crypto.subtle.importKey("pkcs8", new Uint8Array(fullKey), "Ed25519", true, ["sign"]);
|
|
188
|
-
}
|
|
189
|
-
/**
|
|
190
|
-
* Convert a crypto key to raw private key.
|
|
191
|
-
* @param cryptoKey The crypto key to convert.
|
|
192
|
-
* @returns The raw private key.
|
|
193
|
-
*/
|
|
194
|
-
static async pkcs8ToPrivateKey(cryptoKey) {
|
|
195
|
-
Guards.defined(Ed25519._CLASS_NAME, "cryptoKey", cryptoKey);
|
|
196
|
-
// crypto.subtle.exportKey does not support Ed25519 keys in raw format.
|
|
197
|
-
// so we export as PKCS8 and remove the ASN.1 sequence prefix.
|
|
198
|
-
const pkcs8Bytes = await crypto.subtle.exportKey("pkcs8", cryptoKey);
|
|
199
|
-
return new Uint8Array(pkcs8Bytes.slice(16));
|
|
200
|
-
}
|
|
201
|
-
}
|
|
202
|
-
|
|
203
|
-
// Copyright 2024 IOTA Stiftung.
|
|
204
|
-
// SPDX-License-Identifier: Apache-2.0.
|
|
205
|
-
/**
|
|
206
|
-
* Implementation of secp256k1.
|
|
207
|
-
*/
|
|
208
|
-
class Secp256k1 {
|
|
209
|
-
/**
|
|
210
|
-
* Private Key Size is the size, in bytes, of private keys as used in this package.
|
|
211
|
-
*/
|
|
212
|
-
static PRIVATE_KEY_SIZE = 32;
|
|
213
|
-
/**
|
|
214
|
-
* Public Key Size is the size, in bytes, of public keys as used in this package.
|
|
215
|
-
*/
|
|
216
|
-
static PUBLIC_KEY_SIZE = 33;
|
|
217
|
-
/**
|
|
218
|
-
* Runtime name for the class.
|
|
219
|
-
* @internal
|
|
220
|
-
*/
|
|
221
|
-
static _CLASS_NAME = "Secp256k1";
|
|
222
|
-
/**
|
|
223
|
-
* Public returns the PublicKey corresponding to private.
|
|
224
|
-
* @param privateKey The private key to get the corresponding public key.
|
|
225
|
-
* @returns The public key.
|
|
226
|
-
* @throws Error if the private key is not the correct length.
|
|
227
|
-
*/
|
|
228
|
-
static publicKeyFromPrivateKey(privateKey) {
|
|
229
|
-
Guards.uint8Array(Secp256k1._CLASS_NAME, "privateKey", privateKey);
|
|
230
|
-
if (privateKey.length !== Secp256k1.PRIVATE_KEY_SIZE) {
|
|
231
|
-
throw new GeneralError(Secp256k1._CLASS_NAME, "privateKeyLength", {
|
|
232
|
-
requiredSize: Secp256k1.PRIVATE_KEY_SIZE,
|
|
233
|
-
actualSize: privateKey.length
|
|
234
|
-
});
|
|
235
|
-
}
|
|
236
|
-
return secp256k1.getPublicKey(privateKey);
|
|
237
|
-
}
|
|
238
|
-
/**
|
|
239
|
-
* Sign the block with privateKey and returns a signature.
|
|
240
|
-
* @param privateKey The private key.
|
|
241
|
-
* @param block The block to sign.
|
|
242
|
-
* @returns The signature.
|
|
243
|
-
* @throws Error if the private key is not the correct length.
|
|
244
|
-
*/
|
|
245
|
-
static sign(privateKey, block) {
|
|
246
|
-
Guards.uint8Array(Secp256k1._CLASS_NAME, "privateKey", privateKey);
|
|
247
|
-
Guards.uint8Array(Secp256k1._CLASS_NAME, "block", block);
|
|
248
|
-
if (privateKey.length !== Secp256k1.PRIVATE_KEY_SIZE) {
|
|
249
|
-
throw new GeneralError(Secp256k1._CLASS_NAME, "privateKeyLength", {
|
|
250
|
-
requiredSize: Secp256k1.PRIVATE_KEY_SIZE,
|
|
251
|
-
actualSize: privateKey.length
|
|
252
|
-
});
|
|
253
|
-
}
|
|
254
|
-
const res = secp256k1.sign(block, privateKey, { prehash: false });
|
|
255
|
-
return res;
|
|
256
|
-
}
|
|
257
|
-
/**
|
|
258
|
-
* Verify reports whether sig is a valid signature of block by publicKey.
|
|
259
|
-
* @param publicKey The public key to verify the signature.
|
|
260
|
-
* @param block The block for the signature.
|
|
261
|
-
* @param signature The signature.
|
|
262
|
-
* @returns True if the signature matches.
|
|
263
|
-
* @throws Error if the public key is not the correct length.
|
|
264
|
-
*/
|
|
265
|
-
static verify(publicKey, block, signature) {
|
|
266
|
-
Guards.uint8Array(Secp256k1._CLASS_NAME, "publicKey", publicKey);
|
|
267
|
-
Guards.uint8Array(Secp256k1._CLASS_NAME, "block", block);
|
|
268
|
-
Guards.uint8Array(Secp256k1._CLASS_NAME, "signature", signature);
|
|
269
|
-
if (publicKey.length !== Secp256k1.PUBLIC_KEY_SIZE) {
|
|
270
|
-
throw new GeneralError(Secp256k1._CLASS_NAME, "publicKeyLength", {
|
|
271
|
-
requiredSize: Secp256k1.PUBLIC_KEY_SIZE,
|
|
272
|
-
actualSize: publicKey ? publicKey.length : 0
|
|
273
|
-
});
|
|
274
|
-
}
|
|
275
|
-
try {
|
|
276
|
-
return secp256k1.verify(signature, block, publicKey, { prehash: false });
|
|
277
|
-
}
|
|
278
|
-
catch {
|
|
279
|
-
return false;
|
|
280
|
-
}
|
|
281
|
-
}
|
|
282
|
-
}
|
|
283
|
-
|
|
284
|
-
// Copyright 2024 IOTA Stiftung.
|
|
285
|
-
// SPDX-License-Identifier: Apache-2.0.
|
|
286
|
-
/**
|
|
287
|
-
* Class to help with Blake2B Signature scheme.
|
|
288
|
-
*/
|
|
289
|
-
class Blake2b {
|
|
290
|
-
/**
|
|
291
|
-
* Blake2b 160.
|
|
292
|
-
*/
|
|
293
|
-
static SIZE_160 = 20;
|
|
294
|
-
/**
|
|
295
|
-
* Blake2b 256.
|
|
296
|
-
*/
|
|
297
|
-
static SIZE_256 = 32;
|
|
298
|
-
/**
|
|
299
|
-
* Blake2b 512.
|
|
300
|
-
*/
|
|
301
|
-
static SIZE_512 = 64;
|
|
302
|
-
/**
|
|
303
|
-
* Runtime name for the class.
|
|
304
|
-
* @internal
|
|
305
|
-
*/
|
|
306
|
-
static _CLASS_NAME = "Blake2b";
|
|
307
|
-
/**
|
|
308
|
-
* The instance of the hash.
|
|
309
|
-
* @internal
|
|
310
|
-
*/
|
|
311
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
312
|
-
_instance;
|
|
313
|
-
/**
|
|
314
|
-
* Create a new instance of Blake2b.
|
|
315
|
-
* @param outputLength The output length.
|
|
316
|
-
* @param key Optional key for the hash.
|
|
317
|
-
*/
|
|
318
|
-
constructor(outputLength, key) {
|
|
319
|
-
this._instance = blake2b.create({
|
|
320
|
-
dkLen: outputLength,
|
|
321
|
-
key
|
|
322
|
-
});
|
|
323
|
-
}
|
|
324
|
-
/**
|
|
325
|
-
* Perform Sum 160 on the block.
|
|
326
|
-
* @param block The block to operate on.
|
|
327
|
-
* @param key Optional key for the hash.
|
|
328
|
-
* @returns The sum 160 of the block.
|
|
329
|
-
*/
|
|
330
|
-
static sum160(block, key) {
|
|
331
|
-
Guards.uint8Array(Blake2b._CLASS_NAME, "block", block);
|
|
332
|
-
return new Blake2b(Blake2b.SIZE_160, key).update(block).digest();
|
|
333
|
-
}
|
|
334
|
-
/**
|
|
335
|
-
* Perform Sum 256 on the block.
|
|
336
|
-
* @param block The block to operate on.
|
|
337
|
-
* @param key Optional key for the hash.
|
|
338
|
-
* @returns The sum 256 of the block.
|
|
339
|
-
*/
|
|
340
|
-
static sum256(block, key) {
|
|
341
|
-
Guards.uint8Array(Blake2b._CLASS_NAME, "block", block);
|
|
342
|
-
return new Blake2b(Blake2b.SIZE_256, key).update(block).digest();
|
|
343
|
-
}
|
|
344
|
-
/**
|
|
345
|
-
* Perform Sum 512 on the block.
|
|
346
|
-
* @param block The block to operate on.
|
|
347
|
-
* @param key Optional key for the hash.
|
|
348
|
-
* @returns The sum 512 of the block.
|
|
349
|
-
*/
|
|
350
|
-
static sum512(block, key) {
|
|
351
|
-
Guards.uint8Array(Blake2b._CLASS_NAME, "block", block);
|
|
352
|
-
return new Blake2b(Blake2b.SIZE_512, key).update(block).digest();
|
|
353
|
-
}
|
|
354
|
-
/**
|
|
355
|
-
* Update the hash with the block.
|
|
356
|
-
* @param block The block to update the hash with.
|
|
357
|
-
* @returns The instance for chaining.
|
|
358
|
-
*/
|
|
359
|
-
update(block) {
|
|
360
|
-
Guards.uint8Array(Blake2b._CLASS_NAME, "block", block);
|
|
361
|
-
this._instance.update(block);
|
|
362
|
-
return this;
|
|
363
|
-
}
|
|
364
|
-
/**
|
|
365
|
-
* Get the digest for the hash.
|
|
366
|
-
* @returns The instance for chaining.
|
|
367
|
-
*/
|
|
368
|
-
digest() {
|
|
369
|
-
return this._instance.digest();
|
|
370
|
-
}
|
|
371
|
-
}
|
|
372
|
-
|
|
373
|
-
// Copyright 2024 IOTA Stiftung.
|
|
374
|
-
// SPDX-License-Identifier: Apache-2.0.
|
|
375
|
-
/**
|
|
376
|
-
* Class to help with bip32 paths.
|
|
377
|
-
*/
|
|
378
|
-
class Bip32Path {
|
|
379
|
-
/**
|
|
380
|
-
* The path.
|
|
381
|
-
* @internal
|
|
382
|
-
*/
|
|
383
|
-
_path;
|
|
384
|
-
/**
|
|
385
|
-
* Create a new instance of Bip32Path.
|
|
386
|
-
* @param initialPath Initial path to create.
|
|
387
|
-
*/
|
|
388
|
-
constructor(initialPath) {
|
|
389
|
-
if (initialPath) {
|
|
390
|
-
this._path = initialPath.split("/");
|
|
391
|
-
if (this._path[0] === "m") {
|
|
392
|
-
this._path.shift();
|
|
393
|
-
}
|
|
394
|
-
}
|
|
395
|
-
else {
|
|
396
|
-
this._path = [];
|
|
397
|
-
}
|
|
398
|
-
}
|
|
399
|
-
/**
|
|
400
|
-
* Construct a new path by cloning an existing one.
|
|
401
|
-
* @param bip32Path The path to clone.
|
|
402
|
-
* @returns A new instance of Bip32Path.
|
|
403
|
-
*/
|
|
404
|
-
static fromPath(bip32Path) {
|
|
405
|
-
const p = new Bip32Path();
|
|
406
|
-
p._path = bip32Path._path.slice();
|
|
407
|
-
return p;
|
|
408
|
-
}
|
|
409
|
-
/**
|
|
410
|
-
* Converts the path to a string.
|
|
411
|
-
* @returns The path as a string.
|
|
412
|
-
*/
|
|
413
|
-
toString() {
|
|
414
|
-
return this._path.length > 0 ? `m/${this._path.join("/")}` : "m";
|
|
415
|
-
}
|
|
416
|
-
/**
|
|
417
|
-
* Push a new index on to the path.
|
|
418
|
-
* @param index The index to add to the path.
|
|
419
|
-
*/
|
|
420
|
-
push(index) {
|
|
421
|
-
this._path.push(`${index}`);
|
|
422
|
-
}
|
|
423
|
-
/**
|
|
424
|
-
* Push a new hardened index on to the path.
|
|
425
|
-
* @param index The index to add to the path.
|
|
426
|
-
*/
|
|
427
|
-
pushHardened(index) {
|
|
428
|
-
this._path.push(`${index}'`);
|
|
429
|
-
}
|
|
430
|
-
/**
|
|
431
|
-
* Pop an index from the path.
|
|
432
|
-
*/
|
|
433
|
-
pop() {
|
|
434
|
-
this._path.pop();
|
|
435
|
-
}
|
|
436
|
-
/**
|
|
437
|
-
* Get the segments.
|
|
438
|
-
* @returns The segments as numbers.
|
|
439
|
-
*/
|
|
440
|
-
numberSegments() {
|
|
441
|
-
return this._path.map(p => Number.parseInt(p, 10));
|
|
442
|
-
}
|
|
443
|
-
}
|
|
444
|
-
|
|
445
|
-
// Copyright 2024 IOTA Stiftung.
|
|
446
|
-
// SPDX-License-Identifier: Apache-2.0.
|
|
447
|
-
/**
|
|
448
|
-
* The names of the key types.
|
|
449
|
-
*/
|
|
450
|
-
// eslint-disable-next-line @typescript-eslint/naming-convention
|
|
451
|
-
const KeyType = {
|
|
452
|
-
/**
|
|
453
|
-
* Ed25519.
|
|
454
|
-
*/
|
|
455
|
-
Ed25519: 0,
|
|
456
|
-
/**
|
|
457
|
-
* Secp256k1.
|
|
458
|
-
*/
|
|
459
|
-
Secp256k1: 1
|
|
460
|
-
};
|
|
461
|
-
|
|
462
|
-
// Copyright 2024 IOTA Stiftung.
|
|
463
|
-
// SPDX-License-Identifier: Apache-2.0.
|
|
464
|
-
/**
|
|
465
|
-
* Class to help with slip0010 key derivation
|
|
466
|
-
* https://github.com/satoshilabs/slips/blob/master/slip-0010.md.
|
|
467
|
-
*/
|
|
468
|
-
class Slip0010 {
|
|
469
|
-
/**
|
|
470
|
-
* Runtime name for the class.
|
|
471
|
-
* @internal
|
|
472
|
-
*/
|
|
473
|
-
static _CLASS_NAME = "Slip0010";
|
|
474
|
-
/**
|
|
475
|
-
* Get the master key from the seed.
|
|
476
|
-
* @param seed The seed to generate the master key from.
|
|
477
|
-
* @param keyType The key type.
|
|
478
|
-
* @returns The key and chain code.
|
|
479
|
-
* @throws If the seed is invalid.
|
|
480
|
-
*/
|
|
481
|
-
static getMasterKeyFromSeed(seed, keyType = KeyType.Ed25519) {
|
|
482
|
-
try {
|
|
483
|
-
const masterKey = keyType === KeyType.Ed25519
|
|
484
|
-
? HDKey.fromMasterSeed(seed)
|
|
485
|
-
: HDKey$1.fromMasterSeed(seed);
|
|
486
|
-
return {
|
|
487
|
-
privateKey: masterKey.privateKey ?? new Uint8Array(),
|
|
488
|
-
chainCode: masterKey.chainCode ?? new Uint8Array()
|
|
489
|
-
};
|
|
490
|
-
}
|
|
491
|
-
catch (error) {
|
|
492
|
-
throw new GeneralError(Slip0010._CLASS_NAME, "invalidSeed", { seed: Converter.bytesToUtf8(seed) }, error);
|
|
493
|
-
}
|
|
494
|
-
}
|
|
495
|
-
/**
|
|
496
|
-
* Derive a key from the path.
|
|
497
|
-
* @param seed The seed.
|
|
498
|
-
* @param path The path.
|
|
499
|
-
* @param keyType The key type.
|
|
500
|
-
* @returns The key and chain code.
|
|
501
|
-
*/
|
|
502
|
-
static derivePath(seed, path, keyType = KeyType.Ed25519) {
|
|
503
|
-
const keyOpts = Slip0010.getMasterKeyFromSeed(seed, keyType);
|
|
504
|
-
if (keyType === KeyType.Ed25519) {
|
|
505
|
-
const hdKey = new HDKey(keyOpts);
|
|
506
|
-
const derivedKey = hdKey.derive(path.toString());
|
|
507
|
-
return {
|
|
508
|
-
privateKey: derivedKey.privateKey,
|
|
509
|
-
chainCode: derivedKey.chainCode
|
|
510
|
-
};
|
|
511
|
-
}
|
|
512
|
-
const hdKey = new HDKey$1(keyOpts);
|
|
513
|
-
const derivedKey = hdKey.derive(path.toString());
|
|
514
|
-
return {
|
|
515
|
-
privateKey: derivedKey.privateKey ?? new Uint8Array(),
|
|
516
|
-
chainCode: derivedKey.chainCode ?? new Uint8Array()
|
|
517
|
-
};
|
|
518
|
-
}
|
|
519
|
-
/**
|
|
520
|
-
* Get the public key from the private key.
|
|
521
|
-
* @param privateKey The private key.
|
|
522
|
-
* @param keyType The key type.
|
|
523
|
-
* @param withZeroByte Include a zero bute prefix.
|
|
524
|
-
* @returns The public key.
|
|
525
|
-
*/
|
|
526
|
-
static getPublicKey(privateKey, keyType = KeyType.Ed25519, withZeroByte = true) {
|
|
527
|
-
const signPk = keyType === KeyType.Ed25519
|
|
528
|
-
? Ed25519.publicKeyFromPrivateKey(privateKey)
|
|
529
|
-
: Secp256k1.publicKeyFromPrivateKey(privateKey);
|
|
530
|
-
if (withZeroByte) {
|
|
531
|
-
const arr = new Uint8Array(1 + signPk.length);
|
|
532
|
-
arr[0] = 0;
|
|
533
|
-
arr.set(signPk, 1);
|
|
534
|
-
return arr;
|
|
535
|
-
}
|
|
536
|
-
return signPk;
|
|
537
|
-
}
|
|
538
|
-
}
|
|
539
|
-
|
|
540
|
-
// Copyright 2024 IOTA Stiftung.
|
|
541
|
-
// SPDX-License-Identifier: Apache-2.0.
|
|
542
|
-
/**
|
|
543
|
-
* Implementation of Bip44 for address generation.
|
|
544
|
-
*/
|
|
545
|
-
class Bip44 {
|
|
546
|
-
/**
|
|
547
|
-
* Runtime name for the class.
|
|
548
|
-
* @internal
|
|
549
|
-
*/
|
|
550
|
-
static _CLASS_NAME = "Bip44";
|
|
551
|
-
/**
|
|
552
|
-
* Generate a bip44 key pair from the seed and parts.
|
|
553
|
-
* @param seed The account seed.
|
|
554
|
-
* @param keyType The key type.
|
|
555
|
-
* @param coinType The coin type.
|
|
556
|
-
* @param accountIndex The account index.
|
|
557
|
-
* @param isInternal Is this an internal address.
|
|
558
|
-
* @param addressIndex The address index.
|
|
559
|
-
* @returns The key pair.
|
|
560
|
-
* @throws Error if the address type is not supported.
|
|
561
|
-
*/
|
|
562
|
-
static keyPair(seed, keyType, coinType, accountIndex, isInternal, addressIndex) {
|
|
563
|
-
const bip44Path = Bip44.path(coinType, accountIndex, isInternal, addressIndex);
|
|
564
|
-
const keys = Slip0010.derivePath(seed, bip44Path);
|
|
565
|
-
if (keyType === KeyType.Ed25519) {
|
|
566
|
-
const publicKey = Ed25519.publicKeyFromPrivateKey(keys.privateKey);
|
|
567
|
-
return {
|
|
568
|
-
privateKey: keys.privateKey,
|
|
569
|
-
publicKey
|
|
570
|
-
};
|
|
571
|
-
}
|
|
572
|
-
else if (keyType === KeyType.Secp256k1) {
|
|
573
|
-
const publicKey = Secp256k1.publicKeyFromPrivateKey(keys.privateKey);
|
|
574
|
-
return {
|
|
575
|
-
privateKey: keys.privateKey,
|
|
576
|
-
publicKey
|
|
577
|
-
};
|
|
578
|
-
}
|
|
579
|
-
throw new GeneralError(Bip44._CLASS_NAME, "unsupportedKeyType", { keyType });
|
|
580
|
-
}
|
|
581
|
-
/**
|
|
582
|
-
* Generate a bip44 path based on all its parts.
|
|
583
|
-
* @param coinType The coin type.
|
|
584
|
-
* @param accountIndex The account index.
|
|
585
|
-
* @param isInternal Is this an internal address.
|
|
586
|
-
* @param addressIndex The address index.
|
|
587
|
-
* @returns The generated path.
|
|
588
|
-
*/
|
|
589
|
-
static path(coinType, accountIndex, isInternal, addressIndex) {
|
|
590
|
-
const bip32Path = new Bip32Path(Bip44.basePath(coinType));
|
|
591
|
-
bip32Path.pushHardened(accountIndex);
|
|
592
|
-
bip32Path.pushHardened(isInternal ? 1 : 0);
|
|
593
|
-
bip32Path.pushHardened(addressIndex);
|
|
594
|
-
return bip32Path;
|
|
595
|
-
}
|
|
596
|
-
/**
|
|
597
|
-
* Create a bip44 base path for the provided coin type.
|
|
598
|
-
* @param coinType The coin type.
|
|
599
|
-
* @returns The bip44 address base path.
|
|
600
|
-
*/
|
|
601
|
-
static basePath(coinType) {
|
|
602
|
-
return `m/44'/${coinType}'`;
|
|
603
|
-
}
|
|
604
|
-
/**
|
|
605
|
-
* Generate an address from the seed and parts.
|
|
606
|
-
* @param seed The account seed.
|
|
607
|
-
* @param keyType The key type.
|
|
608
|
-
* @param coinType The coin type.
|
|
609
|
-
* @param accountIndex The account index.
|
|
610
|
-
* @param isInternal Is this an internal address.
|
|
611
|
-
* @param addressIndex The address index.
|
|
612
|
-
* @returns The generated path and the associated keypair.
|
|
613
|
-
*/
|
|
614
|
-
static address(seed, keyType, coinType, accountIndex, isInternal, addressIndex) {
|
|
615
|
-
const keyPair = Bip44.keyPair(seed, keyType, coinType, accountIndex, isInternal, addressIndex);
|
|
616
|
-
const addressData = Blake2b.sum256(keyPair.publicKey);
|
|
617
|
-
return {
|
|
618
|
-
address: Converter.bytesToHex(addressData, true),
|
|
619
|
-
...keyPair
|
|
620
|
-
};
|
|
621
|
-
}
|
|
622
|
-
/**
|
|
623
|
-
* Generate a bech32 address from the seed and parts.
|
|
624
|
-
* @param seed The account seed.
|
|
625
|
-
* @param keyType The key type.
|
|
626
|
-
* @param hrp The human readable part of the address.
|
|
627
|
-
* @param coinType The coin type.
|
|
628
|
-
* @param accountIndex The account index.
|
|
629
|
-
* @param isInternal Is this an internal address.
|
|
630
|
-
* @param addressIndex The address index.
|
|
631
|
-
* @returns The generated path and the associated keypair.
|
|
632
|
-
*/
|
|
633
|
-
static addressBech32(seed, keyType, hrp, coinType, accountIndex, isInternal, addressIndex) {
|
|
634
|
-
const keyPair = Bip44.keyPair(seed, keyType, coinType, accountIndex, isInternal, addressIndex);
|
|
635
|
-
const addressData = Blake2b.sum256(keyPair.publicKey);
|
|
636
|
-
const bech32Data = new Uint8Array(1 + addressData.length);
|
|
637
|
-
bech32Data[0] = keyType;
|
|
638
|
-
bech32Data.set(addressData, 1);
|
|
639
|
-
return {
|
|
640
|
-
address: Bech32.encode(hrp, bech32Data),
|
|
641
|
-
...keyPair
|
|
642
|
-
};
|
|
643
|
-
}
|
|
644
|
-
}
|
|
645
|
-
|
|
646
|
-
// Copyright 2024 IOTA Stiftung.
|
|
647
|
-
// SPDX-License-Identifier: Apache-2.0.
|
|
648
|
-
/**
|
|
649
|
-
* Implementation of the ChaCha20Poly1305 cipher.
|
|
650
|
-
*/
|
|
651
|
-
class ChaCha20Poly1305 {
|
|
652
|
-
/**
|
|
653
|
-
* Runtime name for the class.
|
|
654
|
-
* @internal
|
|
655
|
-
*/
|
|
656
|
-
static _CLASS_NAME = "ChaCha20Poly1305";
|
|
657
|
-
/**
|
|
658
|
-
* The cipher instance.
|
|
659
|
-
* @internal
|
|
660
|
-
*/
|
|
661
|
-
_instance;
|
|
662
|
-
/**
|
|
663
|
-
* Create a new instance of ChaCha20Poly1305.
|
|
664
|
-
* @param key The key.
|
|
665
|
-
* @param nonce The nonce.
|
|
666
|
-
* @param aad The additional authenticated data.
|
|
667
|
-
*/
|
|
668
|
-
constructor(key, nonce, aad) {
|
|
669
|
-
Guards.uint8Array(ChaCha20Poly1305._CLASS_NAME, "key", key);
|
|
670
|
-
Guards.uint8Array(ChaCha20Poly1305._CLASS_NAME, "nonce", nonce);
|
|
671
|
-
this._instance = chacha20poly1305(key, nonce, aad);
|
|
672
|
-
}
|
|
673
|
-
/**
|
|
674
|
-
* Encrypt the block.
|
|
675
|
-
* @param block The block to encrypt.
|
|
676
|
-
* @returns The block encrypted.
|
|
677
|
-
*/
|
|
678
|
-
encrypt(block) {
|
|
679
|
-
Guards.uint8Array(ChaCha20Poly1305._CLASS_NAME, "block", block);
|
|
680
|
-
return this._instance.encrypt(block);
|
|
681
|
-
}
|
|
682
|
-
/**
|
|
683
|
-
* Decrypt the block.
|
|
684
|
-
* @param block The block to decrypt.
|
|
685
|
-
* @returns The block decrypted.
|
|
686
|
-
*/
|
|
687
|
-
decrypt(block) {
|
|
688
|
-
Guards.uint8Array(ChaCha20Poly1305._CLASS_NAME, "block", block);
|
|
689
|
-
return this._instance.decrypt(block);
|
|
690
|
-
}
|
|
691
|
-
}
|
|
692
|
-
|
|
693
|
-
// Copyright 2024 IOTA Stiftung.
|
|
694
|
-
// SPDX-License-Identifier: Apache-2.0.
|
|
695
|
-
/**
|
|
696
|
-
* Implementation of X25519.
|
|
697
|
-
*/
|
|
698
|
-
class X25519 {
|
|
699
|
-
/**
|
|
700
|
-
* Runtime name for the class.
|
|
701
|
-
* @internal
|
|
702
|
-
*/
|
|
703
|
-
static _CLASS_NAME = "X25519";
|
|
704
|
-
/**
|
|
705
|
-
* Convert Ed25519 private key to X25519 private key.
|
|
706
|
-
* @param ed25519PrivateKey The ed25519 private key to convert.
|
|
707
|
-
* @returns The x25519 private key.
|
|
708
|
-
*/
|
|
709
|
-
static convertPrivateKeyToX25519(ed25519PrivateKey) {
|
|
710
|
-
Guards.uint8Array(X25519._CLASS_NAME, "ed25519PrivateKey", ed25519PrivateKey);
|
|
711
|
-
return ed25519.utils.toMontgomerySecret(ed25519PrivateKey.slice(0, Ed25519.PRIVATE_KEY_SIZE));
|
|
712
|
-
}
|
|
713
|
-
/**
|
|
714
|
-
* Convert Ed25519 public key to X25519 public key.
|
|
715
|
-
* @param ed25519PublicKey The ed25519 public key to convert.
|
|
716
|
-
* @returns The x25519 public key.
|
|
717
|
-
* @throws GeneralError On invalid public key.
|
|
718
|
-
*/
|
|
719
|
-
static convertPublicKeyToX25519(ed25519PublicKey) {
|
|
720
|
-
Guards.uint8Array(X25519._CLASS_NAME, "ed25519PublicKey", ed25519PublicKey);
|
|
721
|
-
return ed25519.utils.toMontgomery(ed25519PublicKey);
|
|
722
|
-
}
|
|
723
|
-
}
|
|
724
|
-
|
|
725
|
-
// Copyright 2024 IOTA Stiftung.
|
|
726
|
-
// SPDX-License-Identifier: Apache-2.0.
|
|
727
|
-
/**
|
|
728
|
-
* Implementation of Zip215.
|
|
729
|
-
*/
|
|
730
|
-
class Zip215 {
|
|
731
|
-
/**
|
|
732
|
-
* Runtime name for the class.
|
|
733
|
-
* @internal
|
|
734
|
-
*/
|
|
735
|
-
static _CLASS_NAME = "Zip215";
|
|
736
|
-
/**
|
|
737
|
-
* Verify reports whether sig is a valid signature of block by
|
|
738
|
-
* publicKey, using precisely-specified validation criteria (ZIP 215) suitable
|
|
739
|
-
* for use in consensus-critical contexts.
|
|
740
|
-
* @param publicKey The public key for the block.
|
|
741
|
-
* @param block The block content to validate.
|
|
742
|
-
* @param sig The signature to verify.
|
|
743
|
-
* @returns True if the signature is valid.
|
|
744
|
-
*/
|
|
745
|
-
static verify(publicKey, block, sig) {
|
|
746
|
-
Guards.uint8Array(Zip215._CLASS_NAME, "publicKey", publicKey);
|
|
747
|
-
Guards.uint8Array(Zip215._CLASS_NAME, "block", block);
|
|
748
|
-
Guards.uint8Array(Zip215._CLASS_NAME, "sig", sig);
|
|
749
|
-
if (publicKey.length !== Ed25519.PUBLIC_KEY_SIZE) {
|
|
750
|
-
return false;
|
|
751
|
-
}
|
|
752
|
-
return ed25519.verify(sig, block, publicKey, { zip215: true });
|
|
753
|
-
}
|
|
754
|
-
}
|
|
755
|
-
|
|
756
|
-
// Copyright 2024 IOTA Stiftung.
|
|
757
|
-
// SPDX-License-Identifier: Apache-2.0.
|
|
758
|
-
/**
|
|
759
|
-
* Class to help with Blake3 Signature scheme.
|
|
760
|
-
*/
|
|
761
|
-
class Blake3 {
|
|
762
|
-
/**
|
|
763
|
-
* Blake3 256.
|
|
764
|
-
*/
|
|
765
|
-
static SIZE_256 = 32;
|
|
766
|
-
/**
|
|
767
|
-
* Blake3 512.
|
|
768
|
-
*/
|
|
769
|
-
static SIZE_512 = 64;
|
|
770
|
-
/**
|
|
771
|
-
* Runtime name for the class.
|
|
772
|
-
* @internal
|
|
773
|
-
*/
|
|
774
|
-
static _CLASS_NAME = "Blake3";
|
|
775
|
-
/**
|
|
776
|
-
* The instance of the hash.
|
|
777
|
-
* @internal
|
|
778
|
-
*/
|
|
779
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
780
|
-
_instance;
|
|
781
|
-
/**
|
|
782
|
-
* Create a new instance of Blake3.
|
|
783
|
-
* @param outputLength The output length.
|
|
784
|
-
* @param key Optional key for the hash.
|
|
785
|
-
*/
|
|
786
|
-
constructor(outputLength, key) {
|
|
787
|
-
this._instance = blake3.create({
|
|
788
|
-
dkLen: outputLength,
|
|
789
|
-
key
|
|
790
|
-
});
|
|
791
|
-
}
|
|
792
|
-
/**
|
|
793
|
-
* Perform Sum 256 on the block.
|
|
794
|
-
* @param block The block to operate on.
|
|
795
|
-
* @param key Optional key for the hash.
|
|
796
|
-
* @returns The sum 256 of the block.
|
|
797
|
-
*/
|
|
798
|
-
static sum256(block, key) {
|
|
799
|
-
Guards.uint8Array(Blake3._CLASS_NAME, "block", block);
|
|
800
|
-
return new Blake3(Blake3.SIZE_256, key).update(block).digest();
|
|
801
|
-
}
|
|
802
|
-
/**
|
|
803
|
-
* Perform Sum 512 on the block.
|
|
804
|
-
* @param block The block to operate on.
|
|
805
|
-
* @param key Optional key for the hash.
|
|
806
|
-
* @returns The sum 512 of the block.
|
|
807
|
-
*/
|
|
808
|
-
static sum512(block, key) {
|
|
809
|
-
Guards.uint8Array(Blake3._CLASS_NAME, "block", block);
|
|
810
|
-
return new Blake3(Blake3.SIZE_512, key).update(block).digest();
|
|
811
|
-
}
|
|
812
|
-
/**
|
|
813
|
-
* Update the hash with the block.
|
|
814
|
-
* @param block The block to update the hash with.
|
|
815
|
-
* @returns The instance for chaining.
|
|
816
|
-
*/
|
|
817
|
-
update(block) {
|
|
818
|
-
Guards.uint8Array(Blake3._CLASS_NAME, "block", block);
|
|
819
|
-
this._instance.update(block);
|
|
820
|
-
return this;
|
|
821
|
-
}
|
|
822
|
-
/**
|
|
823
|
-
* Get the digest for the hash.
|
|
824
|
-
* @returns The instance for chaining.
|
|
825
|
-
*/
|
|
826
|
-
digest() {
|
|
827
|
-
return this._instance.digest();
|
|
828
|
-
}
|
|
829
|
-
}
|
|
830
|
-
|
|
831
|
-
// Copyright 2024 IOTA Stiftung.
|
|
832
|
-
// SPDX-License-Identifier: Apache-2.0.
|
|
833
|
-
/**
|
|
834
|
-
* Class to help with HmacSha1 scheme.
|
|
835
|
-
*/
|
|
836
|
-
class HmacSha1 {
|
|
837
|
-
/**
|
|
838
|
-
* Runtime name for the class.
|
|
839
|
-
* @internal
|
|
840
|
-
*/
|
|
841
|
-
static _CLASS_NAME = "HmacSha1";
|
|
842
|
-
/**
|
|
843
|
-
* The instance of the hash.
|
|
844
|
-
* @internal
|
|
845
|
-
*/
|
|
846
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
847
|
-
_instance;
|
|
848
|
-
/**
|
|
849
|
-
* Create a new instance of HmacSha1.
|
|
850
|
-
* @param key The key for the hmac.
|
|
851
|
-
*/
|
|
852
|
-
constructor(key) {
|
|
853
|
-
this._instance = hmac.create(sha1, key);
|
|
854
|
-
}
|
|
855
|
-
/**
|
|
856
|
-
* Perform Sum on the block.
|
|
857
|
-
* @param key The key for the hmac.
|
|
858
|
-
* @param block The block to operate on.
|
|
859
|
-
* @returns The sum of the block.
|
|
860
|
-
*/
|
|
861
|
-
static sum(key, block) {
|
|
862
|
-
Guards.uint8Array(HmacSha1._CLASS_NAME, "key", key);
|
|
863
|
-
Guards.uint8Array(HmacSha1._CLASS_NAME, "block", block);
|
|
864
|
-
return new HmacSha1(key).update(block).digest();
|
|
865
|
-
}
|
|
866
|
-
/**
|
|
867
|
-
* Update the hash with the block.
|
|
868
|
-
* @param block The block to update the hash with.
|
|
869
|
-
* @returns The instance for chaining.
|
|
870
|
-
*/
|
|
871
|
-
update(block) {
|
|
872
|
-
Guards.uint8Array(HmacSha1._CLASS_NAME, "block", block);
|
|
873
|
-
this._instance.update(block);
|
|
874
|
-
return this;
|
|
875
|
-
}
|
|
876
|
-
/**
|
|
877
|
-
* Get the digest for the hash.
|
|
878
|
-
* @returns The instance for chaining.
|
|
879
|
-
*/
|
|
880
|
-
digest() {
|
|
881
|
-
return this._instance.digest();
|
|
882
|
-
}
|
|
883
|
-
}
|
|
884
|
-
|
|
885
|
-
// Copyright 2024 IOTA Stiftung.
|
|
886
|
-
// SPDX-License-Identifier: Apache-2.0.
|
|
887
|
-
/**
|
|
888
|
-
* Class to help with HmacSha256 scheme.
|
|
889
|
-
*/
|
|
890
|
-
class HmacSha256 {
|
|
891
|
-
/**
|
|
892
|
-
* Sha256 256.
|
|
893
|
-
*/
|
|
894
|
-
static SIZE_256 = 256;
|
|
895
|
-
/**
|
|
896
|
-
* Sha256 224.
|
|
897
|
-
*/
|
|
898
|
-
static SIZE_224 = 224;
|
|
899
|
-
/**
|
|
900
|
-
* Runtime name for the class.
|
|
901
|
-
* @internal
|
|
902
|
-
*/
|
|
903
|
-
static _CLASS_NAME = "HmacSha256";
|
|
904
|
-
/**
|
|
905
|
-
* The instance of the hash.
|
|
906
|
-
* @internal
|
|
907
|
-
*/
|
|
908
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
909
|
-
_instance;
|
|
910
|
-
/**
|
|
911
|
-
* Create a new instance of HmacSha256.
|
|
912
|
-
* @param key The key for the hmac.
|
|
913
|
-
* @param bits The number of bits.
|
|
914
|
-
*/
|
|
915
|
-
constructor(key, bits = HmacSha256.SIZE_256) {
|
|
916
|
-
if (bits !== HmacSha256.SIZE_224 && bits !== HmacSha256.SIZE_256) {
|
|
917
|
-
throw new GeneralError(HmacSha256._CLASS_NAME, "bitSize", { bitSize: bits });
|
|
918
|
-
}
|
|
919
|
-
this._instance = hmac.create(bits === HmacSha256.SIZE_256 ? sha256 : sha224, key);
|
|
920
|
-
}
|
|
921
|
-
/**
|
|
922
|
-
* Perform Sum 224 on the block.
|
|
923
|
-
* @param key The key for the hmac.
|
|
924
|
-
* @param block The block to operate on.
|
|
925
|
-
* @returns The sum 224 of the block.
|
|
926
|
-
*/
|
|
927
|
-
static sum224(key, block) {
|
|
928
|
-
Guards.uint8Array(HmacSha256._CLASS_NAME, "key", key);
|
|
929
|
-
Guards.uint8Array(HmacSha256._CLASS_NAME, "block", block);
|
|
930
|
-
const instance = new HmacSha256(key, HmacSha256.SIZE_224);
|
|
931
|
-
instance.update(block);
|
|
932
|
-
return instance.digest();
|
|
933
|
-
}
|
|
934
|
-
/**
|
|
935
|
-
* Perform Sum 256 on the block.
|
|
936
|
-
* @param key The key for the hmac.
|
|
937
|
-
* @param block The block to operate on.
|
|
938
|
-
* @returns The sum 256 of the block.
|
|
939
|
-
*/
|
|
940
|
-
static sum256(key, block) {
|
|
941
|
-
Guards.uint8Array(HmacSha256._CLASS_NAME, "key", key);
|
|
942
|
-
Guards.uint8Array(HmacSha256._CLASS_NAME, "block", block);
|
|
943
|
-
const instance = new HmacSha256(key, HmacSha256.SIZE_256);
|
|
944
|
-
instance.update(block);
|
|
945
|
-
return instance.digest();
|
|
946
|
-
}
|
|
947
|
-
/**
|
|
948
|
-
* Update the hash with the block.
|
|
949
|
-
* @param block The block to update the hash with.
|
|
950
|
-
* @returns The instance for chaining.
|
|
951
|
-
*/
|
|
952
|
-
update(block) {
|
|
953
|
-
Guards.uint8Array(HmacSha256._CLASS_NAME, "block", block);
|
|
954
|
-
this._instance.update(block);
|
|
955
|
-
return this;
|
|
956
|
-
}
|
|
957
|
-
/**
|
|
958
|
-
* Get the digest for the hash.
|
|
959
|
-
* @returns The instance for chaining.
|
|
960
|
-
*/
|
|
961
|
-
digest() {
|
|
962
|
-
return this._instance.digest();
|
|
963
|
-
}
|
|
964
|
-
}
|
|
965
|
-
|
|
966
|
-
// Copyright 2024 IOTA Stiftung.
|
|
967
|
-
// SPDX-License-Identifier: Apache-2.0.
|
|
968
|
-
/* eslint-disable camelcase */
|
|
969
|
-
/**
|
|
970
|
-
* Class to help with HmacSha512 scheme.
|
|
971
|
-
*/
|
|
972
|
-
class HmacSha512 {
|
|
973
|
-
/**
|
|
974
|
-
* Sha512 224.
|
|
975
|
-
*/
|
|
976
|
-
static SIZE_224 = 224;
|
|
977
|
-
/**
|
|
978
|
-
* Sha512 256.
|
|
979
|
-
*/
|
|
980
|
-
static SIZE_256 = 256;
|
|
981
|
-
/**
|
|
982
|
-
* Sha512 384.
|
|
983
|
-
*/
|
|
984
|
-
static SIZE_384 = 384;
|
|
985
|
-
/**
|
|
986
|
-
* Sha512 512.
|
|
987
|
-
*/
|
|
988
|
-
static SIZE_512 = 512;
|
|
989
|
-
/**
|
|
990
|
-
* Runtime name for the class.
|
|
991
|
-
* @internal
|
|
992
|
-
*/
|
|
993
|
-
static _CLASS_NAME = "HmacSha512";
|
|
994
|
-
/**
|
|
995
|
-
* The instance of the hash.
|
|
996
|
-
* @internal
|
|
997
|
-
*/
|
|
998
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
999
|
-
_instance;
|
|
1000
|
-
/**
|
|
1001
|
-
* Create a new instance of HmacSha512.
|
|
1002
|
-
* @param key The key for the hmac.
|
|
1003
|
-
* @param bits The number of bits.
|
|
1004
|
-
*/
|
|
1005
|
-
constructor(key, bits = HmacSha512.SIZE_512) {
|
|
1006
|
-
if (bits !== HmacSha512.SIZE_224 &&
|
|
1007
|
-
bits !== HmacSha512.SIZE_256 &&
|
|
1008
|
-
bits !== HmacSha512.SIZE_384 &&
|
|
1009
|
-
bits !== HmacSha512.SIZE_512) {
|
|
1010
|
-
throw new GeneralError(HmacSha512._CLASS_NAME, "bitSize", { bitSize: bits });
|
|
1011
|
-
}
|
|
1012
|
-
if (bits === HmacSha512.SIZE_224) {
|
|
1013
|
-
this._instance = hmac.create(sha512_224, key);
|
|
1014
|
-
}
|
|
1015
|
-
else if (bits === HmacSha512.SIZE_256) {
|
|
1016
|
-
this._instance = hmac.create(sha512_256, key);
|
|
1017
|
-
}
|
|
1018
|
-
else if (bits === HmacSha512.SIZE_384) {
|
|
1019
|
-
this._instance = hmac.create(sha384, key);
|
|
1020
|
-
}
|
|
1021
|
-
else {
|
|
1022
|
-
this._instance = hmac.create(sha512, key);
|
|
1023
|
-
}
|
|
1024
|
-
}
|
|
1025
|
-
/**
|
|
1026
|
-
* Perform Sum 512 on the block.
|
|
1027
|
-
* @param key The key for the hmac.
|
|
1028
|
-
* @param block The block to operate on.
|
|
1029
|
-
* @returns The sum 512 of the block.
|
|
1030
|
-
*/
|
|
1031
|
-
static sum512(key, block) {
|
|
1032
|
-
Guards.uint8Array(HmacSha512._CLASS_NAME, "key", key);
|
|
1033
|
-
Guards.uint8Array(HmacSha512._CLASS_NAME, "block", block);
|
|
1034
|
-
const instance = new HmacSha512(key, HmacSha512.SIZE_512);
|
|
1035
|
-
instance.update(block);
|
|
1036
|
-
return instance.digest();
|
|
1037
|
-
}
|
|
1038
|
-
/**
|
|
1039
|
-
* Perform Sum 384 on the block.
|
|
1040
|
-
* @param key The key for the hmac.
|
|
1041
|
-
* @param block The block to operate on.
|
|
1042
|
-
* @returns The sum 384 of the block.
|
|
1043
|
-
*/
|
|
1044
|
-
static sum384(key, block) {
|
|
1045
|
-
Guards.uint8Array(HmacSha512._CLASS_NAME, "key", key);
|
|
1046
|
-
Guards.uint8Array(HmacSha512._CLASS_NAME, "block", block);
|
|
1047
|
-
const instance = new HmacSha512(key, HmacSha512.SIZE_384);
|
|
1048
|
-
instance.update(block);
|
|
1049
|
-
return instance.digest();
|
|
1050
|
-
}
|
|
1051
|
-
/**
|
|
1052
|
-
* Perform Sum 256 on the block.
|
|
1053
|
-
* @param key The key for the hmac.
|
|
1054
|
-
* @param block The block to operate on.
|
|
1055
|
-
* @returns The sum 256 of the block.
|
|
1056
|
-
*/
|
|
1057
|
-
static sum256(key, block) {
|
|
1058
|
-
Guards.uint8Array(HmacSha512._CLASS_NAME, "key", key);
|
|
1059
|
-
Guards.uint8Array(HmacSha512._CLASS_NAME, "block", block);
|
|
1060
|
-
const instance = new HmacSha512(key, HmacSha512.SIZE_256);
|
|
1061
|
-
instance.update(block);
|
|
1062
|
-
return instance.digest();
|
|
1063
|
-
}
|
|
1064
|
-
/**
|
|
1065
|
-
* Perform Sum 224 on the block.
|
|
1066
|
-
* @param key The key for the hmac.
|
|
1067
|
-
* @param block The block to operate on.
|
|
1068
|
-
* @returns The sum 224 of the block.
|
|
1069
|
-
*/
|
|
1070
|
-
static sum224(key, block) {
|
|
1071
|
-
Guards.uint8Array(HmacSha512._CLASS_NAME, "key", key);
|
|
1072
|
-
Guards.uint8Array(HmacSha512._CLASS_NAME, "block", block);
|
|
1073
|
-
const instance = new HmacSha512(key, HmacSha512.SIZE_224);
|
|
1074
|
-
instance.update(block);
|
|
1075
|
-
return instance.digest();
|
|
1076
|
-
}
|
|
1077
|
-
/**
|
|
1078
|
-
* Update the hash with the block.
|
|
1079
|
-
* @param block The block to update the hash with.
|
|
1080
|
-
* @returns The instance for chaining.
|
|
1081
|
-
*/
|
|
1082
|
-
update(block) {
|
|
1083
|
-
Guards.uint8Array(HmacSha512._CLASS_NAME, "block", block);
|
|
1084
|
-
this._instance.update(block);
|
|
1085
|
-
return this;
|
|
1086
|
-
}
|
|
1087
|
-
/**
|
|
1088
|
-
* Get the digest for the hash.
|
|
1089
|
-
* @returns The instance for chaining.
|
|
1090
|
-
*/
|
|
1091
|
-
digest() {
|
|
1092
|
-
return this._instance.digest();
|
|
1093
|
-
}
|
|
1094
|
-
}
|
|
1095
|
-
|
|
1096
|
-
// Copyright 2024 IOTA Stiftung.
|
|
1097
|
-
// SPDX-License-Identifier: Apache-2.0.
|
|
1098
|
-
/**
|
|
1099
|
-
* Implementation of the password based key derivation function 2.
|
|
1100
|
-
*/
|
|
1101
|
-
class Pbkdf2 {
|
|
1102
|
-
/**
|
|
1103
|
-
* Runtime name for the class.
|
|
1104
|
-
* @internal
|
|
1105
|
-
*/
|
|
1106
|
-
static _CLASS_NAME = "Pbkdf2";
|
|
1107
|
-
/**
|
|
1108
|
-
* Derive a key from the parameters using Sha256.
|
|
1109
|
-
* @param password The password to derive the key from.
|
|
1110
|
-
* @param salt The salt for the derivation.
|
|
1111
|
-
* @param iterations Number of iterations to perform.
|
|
1112
|
-
* @param keyLength The length of the key to derive.
|
|
1113
|
-
* @returns The derived key.
|
|
1114
|
-
*/
|
|
1115
|
-
static sha256(password, salt, iterations, keyLength) {
|
|
1116
|
-
Guards.uint8Array(Pbkdf2._CLASS_NAME, "password", password);
|
|
1117
|
-
Guards.uint8Array(Pbkdf2._CLASS_NAME, "salt", salt);
|
|
1118
|
-
Guards.number(Pbkdf2._CLASS_NAME, "iterations", iterations);
|
|
1119
|
-
Guards.number(Pbkdf2._CLASS_NAME, "keyLength", keyLength);
|
|
1120
|
-
return pbkdf2(sha256, password, salt, { c: iterations, dkLen: keyLength });
|
|
1121
|
-
}
|
|
1122
|
-
/**
|
|
1123
|
-
* Derive a key from the parameters using Sha512.
|
|
1124
|
-
* @param password The password to derive the key from.
|
|
1125
|
-
* @param salt The salt for the derivation.
|
|
1126
|
-
* @param iterations Number of iterations to perform.
|
|
1127
|
-
* @param keyLength The length of the key to derive.
|
|
1128
|
-
* @returns The derived key.
|
|
1129
|
-
*/
|
|
1130
|
-
static sha512(password, salt, iterations, keyLength) {
|
|
1131
|
-
Guards.uint8Array(Pbkdf2._CLASS_NAME, "password", password);
|
|
1132
|
-
Guards.uint8Array(Pbkdf2._CLASS_NAME, "salt", salt);
|
|
1133
|
-
Guards.number(Pbkdf2._CLASS_NAME, "iterations", iterations);
|
|
1134
|
-
Guards.number(Pbkdf2._CLASS_NAME, "keyLength", keyLength);
|
|
1135
|
-
return pbkdf2(sha512, password, salt, { c: iterations, dkLen: keyLength });
|
|
1136
|
-
}
|
|
1137
|
-
}
|
|
1138
|
-
|
|
1139
|
-
// Copyright 2024 IOTA Stiftung.
|
|
1140
|
-
// SPDX-License-Identifier: Apache-2.0.
|
|
1141
|
-
/**
|
|
1142
|
-
* Perform a SHA-1 hash on the block.
|
|
1143
|
-
*/
|
|
1144
|
-
class Sha1 {
|
|
1145
|
-
/**
|
|
1146
|
-
* Runtime name for the class.
|
|
1147
|
-
* @internal
|
|
1148
|
-
*/
|
|
1149
|
-
static _CLASS_NAME = "Sha1";
|
|
1150
|
-
/**
|
|
1151
|
-
* The instance of the hash.
|
|
1152
|
-
* @internal
|
|
1153
|
-
*/
|
|
1154
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
1155
|
-
_instance;
|
|
1156
|
-
/**
|
|
1157
|
-
* Create a new instance of Sha1.
|
|
1158
|
-
*/
|
|
1159
|
-
constructor() {
|
|
1160
|
-
this._instance = sha1.create();
|
|
1161
|
-
}
|
|
1162
|
-
/**
|
|
1163
|
-
* Perform Sum on the block.
|
|
1164
|
-
* @param block The block to operate on.
|
|
1165
|
-
* @returns The sum of the block.
|
|
1166
|
-
*/
|
|
1167
|
-
static sum(block) {
|
|
1168
|
-
Guards.uint8Array(Sha1._CLASS_NAME, "block", block);
|
|
1169
|
-
return new Sha1().update(block).digest();
|
|
1170
|
-
}
|
|
1171
|
-
/**
|
|
1172
|
-
* Update the hash with the block.
|
|
1173
|
-
* @param block The block to update the hash with.
|
|
1174
|
-
* @returns The instance for chaining.
|
|
1175
|
-
*/
|
|
1176
|
-
update(block) {
|
|
1177
|
-
Guards.uint8Array(Sha1._CLASS_NAME, "block", block);
|
|
1178
|
-
this._instance.update(block);
|
|
1179
|
-
return this;
|
|
1180
|
-
}
|
|
1181
|
-
/**
|
|
1182
|
-
* Get the digest for the hash.
|
|
1183
|
-
* @returns The instance for chaining.
|
|
1184
|
-
*/
|
|
1185
|
-
digest() {
|
|
1186
|
-
return this._instance.digest();
|
|
1187
|
-
}
|
|
1188
|
-
}
|
|
1189
|
-
|
|
1190
|
-
// Copyright 2024 IOTA Stiftung.
|
|
1191
|
-
// SPDX-License-Identifier: Apache-2.0.
|
|
1192
|
-
/**
|
|
1193
|
-
* Perform a SHA-256 hash on the block.
|
|
1194
|
-
*/
|
|
1195
|
-
class Sha256 {
|
|
1196
|
-
/**
|
|
1197
|
-
* Sha256 256.
|
|
1198
|
-
*/
|
|
1199
|
-
static SIZE_256 = 256;
|
|
1200
|
-
/**
|
|
1201
|
-
* Sha256 224.
|
|
1202
|
-
*/
|
|
1203
|
-
static SIZE_224 = 224;
|
|
1204
|
-
/**
|
|
1205
|
-
* Runtime name for the class.
|
|
1206
|
-
* @internal
|
|
1207
|
-
*/
|
|
1208
|
-
static _CLASS_NAME = "Sha256";
|
|
1209
|
-
/**
|
|
1210
|
-
* The instance of the hash.
|
|
1211
|
-
* @internal
|
|
1212
|
-
*/
|
|
1213
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
1214
|
-
_instance;
|
|
1215
|
-
/**
|
|
1216
|
-
* Create a new instance of Sha256.
|
|
1217
|
-
* @param bits The number of bits.
|
|
1218
|
-
*/
|
|
1219
|
-
constructor(bits = Sha256.SIZE_256) {
|
|
1220
|
-
if (bits !== Sha256.SIZE_224 && bits !== Sha256.SIZE_256) {
|
|
1221
|
-
throw new GeneralError(Sha256._CLASS_NAME, "bitSize", { bitSize: bits });
|
|
1222
|
-
}
|
|
1223
|
-
this._instance = bits === Sha256.SIZE_256 ? sha256.create() : sha224.create();
|
|
1224
|
-
}
|
|
1225
|
-
/**
|
|
1226
|
-
* Perform Sum 256 on the block.
|
|
1227
|
-
* @param block The block to operate on.
|
|
1228
|
-
* @returns The sum 256 of the block.
|
|
1229
|
-
*/
|
|
1230
|
-
static sum256(block) {
|
|
1231
|
-
const b2b = new Sha256(Sha256.SIZE_256);
|
|
1232
|
-
b2b.update(block);
|
|
1233
|
-
return b2b.digest();
|
|
1234
|
-
}
|
|
1235
|
-
/**
|
|
1236
|
-
* Perform Sum 224 on the block.
|
|
1237
|
-
* @param block The block to operate on.
|
|
1238
|
-
* @returns The sum 224 of the block.
|
|
1239
|
-
*/
|
|
1240
|
-
static sum224(block) {
|
|
1241
|
-
const b2b = new Sha256(Sha256.SIZE_224);
|
|
1242
|
-
b2b.update(block);
|
|
1243
|
-
return b2b.digest();
|
|
1244
|
-
}
|
|
1245
|
-
/**
|
|
1246
|
-
* Update the hash with the block.
|
|
1247
|
-
* @param block The block to update the hash with.
|
|
1248
|
-
* @returns The instance for chaining.
|
|
1249
|
-
*/
|
|
1250
|
-
update(block) {
|
|
1251
|
-
Guards.uint8Array(Sha256._CLASS_NAME, "block", block);
|
|
1252
|
-
this._instance.update(block);
|
|
1253
|
-
return this;
|
|
1254
|
-
}
|
|
1255
|
-
/**
|
|
1256
|
-
* Get the digest for the hash.
|
|
1257
|
-
* @returns The instance for chaining.
|
|
1258
|
-
*/
|
|
1259
|
-
digest() {
|
|
1260
|
-
return this._instance.digest();
|
|
1261
|
-
}
|
|
1262
|
-
}
|
|
1263
|
-
|
|
1264
|
-
// Copyright 2024 IOTA Stiftung.
|
|
1265
|
-
// SPDX-License-Identifier: Apache-2.0.
|
|
1266
|
-
// eslint-disable-next-line camelcase
|
|
1267
|
-
/**
|
|
1268
|
-
* Perform a SHA-3 hash on the block.
|
|
1269
|
-
*/
|
|
1270
|
-
class Sha3 {
|
|
1271
|
-
/**
|
|
1272
|
-
* Sha3 224.
|
|
1273
|
-
*/
|
|
1274
|
-
static SIZE_224 = 224;
|
|
1275
|
-
/**
|
|
1276
|
-
* Sha3 256.
|
|
1277
|
-
*/
|
|
1278
|
-
static SIZE_256 = 256;
|
|
1279
|
-
/**
|
|
1280
|
-
* Sha3 384.
|
|
1281
|
-
*/
|
|
1282
|
-
static SIZE_384 = 384;
|
|
1283
|
-
/**
|
|
1284
|
-
* Sha3 512.
|
|
1285
|
-
*/
|
|
1286
|
-
static SIZE_512 = 512;
|
|
1287
|
-
/**
|
|
1288
|
-
* Runtime name for the class.
|
|
1289
|
-
* @internal
|
|
1290
|
-
*/
|
|
1291
|
-
static _CLASS_NAME = "Sha3";
|
|
1292
|
-
/**
|
|
1293
|
-
* The instance of the hash.
|
|
1294
|
-
* @internal
|
|
1295
|
-
*/
|
|
1296
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
1297
|
-
_instance;
|
|
1298
|
-
/**
|
|
1299
|
-
* Create a new instance of Sha3.
|
|
1300
|
-
* @param bits The number of bits.
|
|
1301
|
-
*/
|
|
1302
|
-
constructor(bits = Sha3.SIZE_256) {
|
|
1303
|
-
if (bits !== Sha3.SIZE_224 &&
|
|
1304
|
-
bits !== Sha3.SIZE_256 &&
|
|
1305
|
-
bits !== Sha3.SIZE_384 &&
|
|
1306
|
-
bits !== Sha3.SIZE_512) {
|
|
1307
|
-
throw new GeneralError(Sha3._CLASS_NAME, "bitSize", { bitSize: bits });
|
|
1308
|
-
}
|
|
1309
|
-
if (bits === Sha3.SIZE_224) {
|
|
1310
|
-
// eslint-disable-next-line camelcase
|
|
1311
|
-
this._instance = sha3_224.create();
|
|
1312
|
-
}
|
|
1313
|
-
else if (bits === Sha3.SIZE_256) {
|
|
1314
|
-
// eslint-disable-next-line camelcase
|
|
1315
|
-
this._instance = sha3_256.create();
|
|
1316
|
-
}
|
|
1317
|
-
else if (bits === Sha3.SIZE_384) {
|
|
1318
|
-
// eslint-disable-next-line camelcase
|
|
1319
|
-
this._instance = sha3_384.create();
|
|
1320
|
-
}
|
|
1321
|
-
else {
|
|
1322
|
-
// eslint-disable-next-line camelcase
|
|
1323
|
-
this._instance = sha3_512.create();
|
|
1324
|
-
}
|
|
1325
|
-
}
|
|
1326
|
-
/**
|
|
1327
|
-
* Perform Sum 256 on the block.
|
|
1328
|
-
* @param block The block to operate on.
|
|
1329
|
-
* @returns The sum 256 of the block.
|
|
1330
|
-
*/
|
|
1331
|
-
static sum256(block) {
|
|
1332
|
-
const b2b = new Sha3(Sha3.SIZE_256);
|
|
1333
|
-
b2b.update(block);
|
|
1334
|
-
return b2b.digest();
|
|
1335
|
-
}
|
|
1336
|
-
/**
|
|
1337
|
-
* Perform Sum 224 on the block.
|
|
1338
|
-
* @param block The block to operate on.
|
|
1339
|
-
* @returns The sum 224 of the block.
|
|
1340
|
-
*/
|
|
1341
|
-
static sum224(block) {
|
|
1342
|
-
const b2b = new Sha3(Sha3.SIZE_224);
|
|
1343
|
-
b2b.update(block);
|
|
1344
|
-
return b2b.digest();
|
|
1345
|
-
}
|
|
1346
|
-
/**
|
|
1347
|
-
* Perform Sum 384 on the block.
|
|
1348
|
-
* @param block The block to operate on.
|
|
1349
|
-
* @returns The sum 384 of the block.
|
|
1350
|
-
*/
|
|
1351
|
-
static sum384(block) {
|
|
1352
|
-
const b2b = new Sha3(Sha3.SIZE_384);
|
|
1353
|
-
b2b.update(block);
|
|
1354
|
-
return b2b.digest();
|
|
1355
|
-
}
|
|
1356
|
-
/**
|
|
1357
|
-
* Perform Sum 512 on the block.
|
|
1358
|
-
* @param block The block to operate on.
|
|
1359
|
-
* @returns The sum 512 of the block.
|
|
1360
|
-
*/
|
|
1361
|
-
static sum512(block) {
|
|
1362
|
-
const b2b = new Sha3(Sha3.SIZE_512);
|
|
1363
|
-
b2b.update(block);
|
|
1364
|
-
return b2b.digest();
|
|
1365
|
-
}
|
|
1366
|
-
/**
|
|
1367
|
-
* Update the hash with the block.
|
|
1368
|
-
* @param block The block to update the hash with.
|
|
1369
|
-
* @returns The instance for chaining.
|
|
1370
|
-
*/
|
|
1371
|
-
update(block) {
|
|
1372
|
-
Guards.uint8Array(Sha3._CLASS_NAME, "block", block);
|
|
1373
|
-
this._instance.update(block);
|
|
1374
|
-
return this;
|
|
1375
|
-
}
|
|
1376
|
-
/**
|
|
1377
|
-
* Get the digest for the hash.
|
|
1378
|
-
* @returns The instance for chaining.
|
|
1379
|
-
*/
|
|
1380
|
-
digest() {
|
|
1381
|
-
return this._instance.digest();
|
|
1382
|
-
}
|
|
1383
|
-
}
|
|
1384
|
-
|
|
1385
|
-
// Copyright 2024 IOTA Stiftung.
|
|
1386
|
-
// SPDX-License-Identifier: Apache-2.0.
|
|
1387
|
-
/* eslint-disable camelcase */
|
|
1388
|
-
/**
|
|
1389
|
-
* Perform a SHA-512 hash on the block.
|
|
1390
|
-
*/
|
|
1391
|
-
class Sha512 {
|
|
1392
|
-
/**
|
|
1393
|
-
* Sha512 224.
|
|
1394
|
-
*/
|
|
1395
|
-
static SIZE_224 = 224;
|
|
1396
|
-
/**
|
|
1397
|
-
* Sha512 256.
|
|
1398
|
-
*/
|
|
1399
|
-
static SIZE_256 = 256;
|
|
1400
|
-
/**
|
|
1401
|
-
* Sha512 384.
|
|
1402
|
-
*/
|
|
1403
|
-
static SIZE_384 = 384;
|
|
1404
|
-
/**
|
|
1405
|
-
* Sha512 512.
|
|
1406
|
-
*/
|
|
1407
|
-
static SIZE_512 = 512;
|
|
1408
|
-
/**
|
|
1409
|
-
* Runtime name for the class.
|
|
1410
|
-
* @internal
|
|
1411
|
-
*/
|
|
1412
|
-
static _CLASS_NAME = "Sha512";
|
|
1413
|
-
/**
|
|
1414
|
-
* The instance of the hash.
|
|
1415
|
-
* @internal
|
|
1416
|
-
*/
|
|
1417
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
1418
|
-
_instance;
|
|
1419
|
-
/**
|
|
1420
|
-
* Create a new instance of Sha512.
|
|
1421
|
-
* @param bits The number of bits.
|
|
1422
|
-
*/
|
|
1423
|
-
constructor(bits = Sha512.SIZE_512) {
|
|
1424
|
-
if (bits !== Sha512.SIZE_224 &&
|
|
1425
|
-
bits !== Sha512.SIZE_256 &&
|
|
1426
|
-
bits !== Sha512.SIZE_384 &&
|
|
1427
|
-
bits !== Sha512.SIZE_512) {
|
|
1428
|
-
throw new GeneralError(Sha512._CLASS_NAME, "bitSize", { bitSize: bits });
|
|
1429
|
-
}
|
|
1430
|
-
if (bits === Sha512.SIZE_224) {
|
|
1431
|
-
this._instance = sha512_224.create();
|
|
1432
|
-
}
|
|
1433
|
-
else if (bits === Sha512.SIZE_256) {
|
|
1434
|
-
this._instance = sha512_256.create();
|
|
1435
|
-
}
|
|
1436
|
-
else if (bits === Sha512.SIZE_384) {
|
|
1437
|
-
this._instance = sha384.create();
|
|
1438
|
-
}
|
|
1439
|
-
else {
|
|
1440
|
-
this._instance = sha512.create();
|
|
1441
|
-
}
|
|
1442
|
-
}
|
|
1443
|
-
/**
|
|
1444
|
-
* Perform Sum 512 on the block.
|
|
1445
|
-
* @param block The block to operate on.
|
|
1446
|
-
* @returns The sum 512 of the block.
|
|
1447
|
-
*/
|
|
1448
|
-
static sum512(block) {
|
|
1449
|
-
const b2b = new Sha512(Sha512.SIZE_512);
|
|
1450
|
-
b2b.update(block);
|
|
1451
|
-
return b2b.digest();
|
|
1452
|
-
}
|
|
1453
|
-
/**
|
|
1454
|
-
* Perform Sum 384 on the block.
|
|
1455
|
-
* @param block The block to operate on.
|
|
1456
|
-
* @returns The sum 384 of the block.
|
|
1457
|
-
*/
|
|
1458
|
-
static sum384(block) {
|
|
1459
|
-
const b2b = new Sha512(Sha512.SIZE_384);
|
|
1460
|
-
b2b.update(block);
|
|
1461
|
-
return b2b.digest();
|
|
1462
|
-
}
|
|
1463
|
-
/**
|
|
1464
|
-
* Perform Sum 256 on the block.
|
|
1465
|
-
* @param block The block to operate on.
|
|
1466
|
-
* @returns The sum 256 of the block.
|
|
1467
|
-
*/
|
|
1468
|
-
static sum256(block) {
|
|
1469
|
-
const b2b = new Sha512(Sha512.SIZE_256);
|
|
1470
|
-
b2b.update(block);
|
|
1471
|
-
return b2b.digest();
|
|
1472
|
-
}
|
|
1473
|
-
/**
|
|
1474
|
-
* Perform Sum 224 on the block.
|
|
1475
|
-
* @param block The block to operate on.
|
|
1476
|
-
* @returns The sum 224 of the block.
|
|
1477
|
-
*/
|
|
1478
|
-
static sum224(block) {
|
|
1479
|
-
const b2b = new Sha512(Sha512.SIZE_224);
|
|
1480
|
-
b2b.update(block);
|
|
1481
|
-
return b2b.digest();
|
|
1482
|
-
}
|
|
1483
|
-
/**
|
|
1484
|
-
* Update the hash with the block.
|
|
1485
|
-
* @param block The block to update the hash with.
|
|
1486
|
-
* @returns The instance for chaining.
|
|
1487
|
-
*/
|
|
1488
|
-
update(block) {
|
|
1489
|
-
Guards.uint8Array(Sha512._CLASS_NAME, "block", block);
|
|
1490
|
-
this._instance.update(block);
|
|
1491
|
-
return this;
|
|
1492
|
-
}
|
|
1493
|
-
/**
|
|
1494
|
-
* Get the digest for the hash.
|
|
1495
|
-
* @returns The instance for chaining.
|
|
1496
|
-
*/
|
|
1497
|
-
digest() {
|
|
1498
|
-
return this._instance.digest();
|
|
1499
|
-
}
|
|
1500
|
-
}
|
|
1501
|
-
|
|
1502
|
-
// Copyright 2024 IOTA Stiftung.
|
|
1503
|
-
// SPDX-License-Identifier: Apache-2.0.
|
|
1504
|
-
/**
|
|
1505
|
-
* Helper class for working with PEM (Privacy-Enhanced Mail) formatted data.
|
|
1506
|
-
*/
|
|
1507
|
-
class PemHelper {
|
|
1508
|
-
/**
|
|
1509
|
-
* Runtime name for the class.
|
|
1510
|
-
* @internal
|
|
1511
|
-
*/
|
|
1512
|
-
static _CLASS_NAME = "PemHelper";
|
|
1513
|
-
/**
|
|
1514
|
-
* Strip the PEM content of its headers, footers, and newlines.
|
|
1515
|
-
* @param pemContent The PEM content to strip.
|
|
1516
|
-
* @returns The stripped PEM content in bas64 format.
|
|
1517
|
-
*/
|
|
1518
|
-
static stripPemMarkers(pemContent) {
|
|
1519
|
-
Guards.string(PemHelper._CLASS_NAME, "pemContent", pemContent);
|
|
1520
|
-
return pemContent
|
|
1521
|
-
.replace(/-----BEGIN.*-----/, "")
|
|
1522
|
-
.replace(/-----END.*-----/, "")
|
|
1523
|
-
.replace(/\n/g, "")
|
|
1524
|
-
.trim();
|
|
1525
|
-
}
|
|
1526
|
-
/**
|
|
1527
|
-
* Format the PEM content to have a specific line length.
|
|
1528
|
-
* @param marker The marker for the PEM content, e.g. RSA PRIVATE KEY
|
|
1529
|
-
* @param base64Content The base64 content to format.
|
|
1530
|
-
* @param lineLength The length of each line in the PEM content, default is 64 characters.
|
|
1531
|
-
* @returns The formatted PEM content.
|
|
1532
|
-
*/
|
|
1533
|
-
static formatPem(marker, base64Content, lineLength = 64) {
|
|
1534
|
-
Guards.stringValue(PemHelper._CLASS_NAME, "marker", marker);
|
|
1535
|
-
Guards.stringBase64(PemHelper._CLASS_NAME, "base64Content", base64Content);
|
|
1536
|
-
const lines = [];
|
|
1537
|
-
for (let i = 0; i < base64Content.length; i += lineLength) {
|
|
1538
|
-
lines.push(base64Content.slice(i, i + lineLength));
|
|
1539
|
-
}
|
|
1540
|
-
return [`-----BEGIN ${marker}-----`, ...lines, `-----END ${marker}-----`].join("\n");
|
|
1541
|
-
}
|
|
1542
|
-
}
|
|
1543
|
-
|
|
1544
|
-
// Copyright 2024 IOTA Stiftung.
|
|
1545
|
-
// SPDX-License-Identifier: Apache-2.0.
|
|
1546
|
-
/**
|
|
1547
|
-
* Implementation of Bip39 for mnemonic generation.
|
|
1548
|
-
*/
|
|
1549
|
-
class Bip39 {
|
|
1550
|
-
/**
|
|
1551
|
-
* Runtime name for the class.
|
|
1552
|
-
* @internal
|
|
1553
|
-
*/
|
|
1554
|
-
static _CLASS_NAME = "Bip39";
|
|
1555
|
-
/**
|
|
1556
|
-
* Generate a random mnemonic.
|
|
1557
|
-
* @param strength The strength of the mnemonic to generate, defaults to 256.
|
|
1558
|
-
* @param words The wordlist to use, defaults to the English wordlist.
|
|
1559
|
-
* @returns The random mnemonic.
|
|
1560
|
-
* @throws Error if the length is not a multiple of 32.
|
|
1561
|
-
*/
|
|
1562
|
-
static randomMnemonic(strength = 256, words = wordlist) {
|
|
1563
|
-
Guards.number(Bip39._CLASS_NAME, "strength", strength);
|
|
1564
|
-
Guards.arrayValue(Bip39._CLASS_NAME, "words", words);
|
|
1565
|
-
if (strength % 32 !== 0) {
|
|
1566
|
-
throw new GuardError(Bip39._CLASS_NAME, "guard.length32Multiple", "strength", strength);
|
|
1567
|
-
}
|
|
1568
|
-
return bip39.generateMnemonic(words, strength);
|
|
1569
|
-
}
|
|
1570
|
-
/**
|
|
1571
|
-
* Generate a mnemonic from the entropy.
|
|
1572
|
-
* @param entropy The entropy to generate.
|
|
1573
|
-
* @param words The wordlist to use, defaults to the English wordlist.
|
|
1574
|
-
* @returns The mnemonic.
|
|
1575
|
-
* @throws Error if the length of the entropy is not a multiple of 4, or is less than 16 or greater than 32.
|
|
1576
|
-
*/
|
|
1577
|
-
static entropyToMnemonic(entropy, words = wordlist) {
|
|
1578
|
-
Guards.uint8Array(Bip39._CLASS_NAME, "entropy", entropy);
|
|
1579
|
-
Guards.arrayValue(Bip39._CLASS_NAME, "words", words);
|
|
1580
|
-
if (entropy.length % 4 !== 0 || entropy.length < 16 || entropy.length > 32) {
|
|
1581
|
-
throw new GuardError(Bip39._CLASS_NAME, "guard.lengthEntropy", "entropy", entropy.length);
|
|
1582
|
-
}
|
|
1583
|
-
return bip39.entropyToMnemonic(entropy, words);
|
|
1584
|
-
}
|
|
1585
|
-
/**
|
|
1586
|
-
* Convert a mnemonic to a seed.
|
|
1587
|
-
* @param mnemonic The mnemonic to convert.
|
|
1588
|
-
* @param password The password to apply to the seed generation.
|
|
1589
|
-
* @returns The seed.
|
|
1590
|
-
*/
|
|
1591
|
-
static mnemonicToSeed(mnemonic, password) {
|
|
1592
|
-
Guards.stringValue(Bip39._CLASS_NAME, "mnemonic", mnemonic);
|
|
1593
|
-
return bip39.mnemonicToSeedSync(mnemonic, password);
|
|
1594
|
-
}
|
|
1595
|
-
/**
|
|
1596
|
-
* Convert the mnemonic back to entropy.
|
|
1597
|
-
* @param mnemonic The mnemonic to convert.
|
|
1598
|
-
* @param words The wordlist to use, defaults to the English wordlist.
|
|
1599
|
-
* @returns The entropy.
|
|
1600
|
-
* @throws Error if the number of words is not a multiple of 3.
|
|
1601
|
-
*/
|
|
1602
|
-
static mnemonicToEntropy(mnemonic, words = wordlist) {
|
|
1603
|
-
Guards.stringValue(Bip39._CLASS_NAME, "mnemonic", mnemonic);
|
|
1604
|
-
Guards.arrayValue(Bip39._CLASS_NAME, "words", words);
|
|
1605
|
-
return bip39.mnemonicToEntropy(mnemonic, words);
|
|
1606
|
-
}
|
|
1607
|
-
/**
|
|
1608
|
-
* Validate the mnemonic.
|
|
1609
|
-
* @param mnemonic The mnemonic to validate.
|
|
1610
|
-
* @param wordCount The expected number of words in the mnemonic, defaults to 24.
|
|
1611
|
-
* @param words The wordlist to use, defaults to the English wordlist.
|
|
1612
|
-
* @returns True if the mnemonic is valid.
|
|
1613
|
-
*/
|
|
1614
|
-
static validateMnemonic(mnemonic, wordCount = 24, words = wordlist) {
|
|
1615
|
-
Guards.string(Bip39._CLASS_NAME, "mnemonic", mnemonic);
|
|
1616
|
-
Guards.integer(Bip39._CLASS_NAME, "wordCount", wordCount);
|
|
1617
|
-
const mnemonicSplit = mnemonic.split(/\s+/);
|
|
1618
|
-
if (mnemonicSplit.length !== wordCount) {
|
|
1619
|
-
return false;
|
|
1620
|
-
}
|
|
1621
|
-
return bip39.validateMnemonic(mnemonic, words);
|
|
1622
|
-
}
|
|
1623
|
-
}
|
|
1624
|
-
|
|
1625
|
-
// Copyright 2024 IOTA Stiftung.
|
|
1626
|
-
// SPDX-License-Identifier: Apache-2.0.
|
|
1627
|
-
/**
|
|
1628
|
-
* Perform HOTP.
|
|
1629
|
-
* Implementation of https://datatracker.ietf.org/doc/html/rfc4226 .
|
|
1630
|
-
*/
|
|
1631
|
-
class Hotp {
|
|
1632
|
-
/**
|
|
1633
|
-
* Runtime name for the class.
|
|
1634
|
-
* @internal
|
|
1635
|
-
*/
|
|
1636
|
-
static _CLASS_NAME = "Hotp";
|
|
1637
|
-
/**
|
|
1638
|
-
* Generate a counter based One Time Password.
|
|
1639
|
-
* @param key Key for the one time password.
|
|
1640
|
-
* @param counter This should be stored by the application,
|
|
1641
|
-
* must be user specific, and be incremented for each request.
|
|
1642
|
-
* @returns The one time password.
|
|
1643
|
-
*/
|
|
1644
|
-
static generate(key, counter) {
|
|
1645
|
-
Guards.uint8Array(Hotp._CLASS_NAME, "key", key);
|
|
1646
|
-
Guards.number(Hotp._CLASS_NAME, "counter", counter);
|
|
1647
|
-
return otp.hotp({ secret: key, digits: 6, algorithm: "sha1", interval: 30 }, counter);
|
|
1648
|
-
}
|
|
1649
|
-
}
|
|
1650
|
-
|
|
1651
|
-
// Copyright 2024 IOTA Stiftung.
|
|
1652
|
-
// SPDX-License-Identifier: Apache-2.0.
|
|
1653
|
-
/**
|
|
1654
|
-
* Perform TOTP.
|
|
1655
|
-
* Implementation of https://datatracker.ietf.org/doc/html/rfc4226 .
|
|
1656
|
-
*/
|
|
1657
|
-
class Totp {
|
|
1658
|
-
/**
|
|
1659
|
-
* Generate a time based One Time Password.
|
|
1660
|
-
* @param key Key for the one time password.
|
|
1661
|
-
* @param interval The time step of the counter.
|
|
1662
|
-
* @param timestamp The timestamp.
|
|
1663
|
-
* @returns The one time password.
|
|
1664
|
-
*/
|
|
1665
|
-
static generate(key, interval = 30, timestamp = Date.now()) {
|
|
1666
|
-
return otp.totp({ secret: key, digits: 6, algorithm: "sha1", interval }, timestamp);
|
|
1667
|
-
}
|
|
1668
|
-
/**
|
|
1669
|
-
* Check a One Time Password based on a timer.
|
|
1670
|
-
* @param token Passcode to validate.
|
|
1671
|
-
* @param key Key for the one time password. This should be unique and secret for
|
|
1672
|
-
* every user as it is the seed used to calculate the HMAC.
|
|
1673
|
-
* @param window The allowable margin for the counter.
|
|
1674
|
-
* @param interval The time step of the counter.
|
|
1675
|
-
* @param timestamp The timestamp now.
|
|
1676
|
-
* @returns Undefined if failure, delta on success
|
|
1677
|
-
*/
|
|
1678
|
-
static verify(token, key, window = 2, interval = 30, timestamp = Date.now()) {
|
|
1679
|
-
for (let i = -window; i < window; i++) {
|
|
1680
|
-
const intervalWindow = i * interval * 1000;
|
|
1681
|
-
if (timestamp + intervalWindow > 0) {
|
|
1682
|
-
const gen = this.generate(key, interval, timestamp + intervalWindow);
|
|
1683
|
-
if (gen === token) {
|
|
1684
|
-
// We have found a matching code
|
|
1685
|
-
return i;
|
|
1686
|
-
}
|
|
1687
|
-
}
|
|
1688
|
-
}
|
|
1689
|
-
// If we get to here then no codes have matched, return undefined
|
|
1690
|
-
return undefined;
|
|
1691
|
-
}
|
|
1692
|
-
/**
|
|
1693
|
-
* Generate a secret.
|
|
1694
|
-
* @param length The length of the secret to generate.
|
|
1695
|
-
* @returns The secret encoded as base32.
|
|
1696
|
-
*/
|
|
1697
|
-
static generateSecret(length) {
|
|
1698
|
-
const encodedBase32 = Base32.encode(RandomHelper.generate(length));
|
|
1699
|
-
// Strip the trailing = the authenticator apps don't need them
|
|
1700
|
-
return encodedBase32.replace(/=/g, "");
|
|
1701
|
-
}
|
|
1702
|
-
/**
|
|
1703
|
-
* Convert the secret back to bytes.
|
|
1704
|
-
* @param secretBase32 The secret encoded as base32.
|
|
1705
|
-
* @returns The bytes of the secret.
|
|
1706
|
-
*/
|
|
1707
|
-
static secretToBytes(secretBase32) {
|
|
1708
|
-
return Base32.decode(secretBase32);
|
|
1709
|
-
}
|
|
1710
|
-
/**
|
|
1711
|
-
* Generate a url for use with authenticator apps.
|
|
1712
|
-
* See https://github.com/google/google-authenticator/wiki/Key-Uri-Format .
|
|
1713
|
-
* @param issuer The issuer of the totp.
|
|
1714
|
-
* @param label The label that will show in auth apps.
|
|
1715
|
-
* @param secretBase32 The secret as base 32.
|
|
1716
|
-
* @returns The url.
|
|
1717
|
-
*/
|
|
1718
|
-
static generateAuthUrl(issuer, label, secretBase32) {
|
|
1719
|
-
const encodedIssuer = encodeURIComponent(issuer);
|
|
1720
|
-
return `otpauth://totp/${encodedIssuer}%3A${encodeURIComponent(label)}?secret=${secretBase32}&issuer=${encodedIssuer}&digits=6&algorithm=SHA1&interval=30`;
|
|
1721
|
-
}
|
|
1722
|
-
}
|
|
1723
|
-
|
|
1724
|
-
// Copyright 2024 IOTA Stiftung.
|
|
1725
|
-
// SPDX-License-Identifier: Apache-2.0.
|
|
1726
|
-
/**
|
|
1727
|
-
* Generate random passwords.
|
|
1728
|
-
*/
|
|
1729
|
-
class PasswordGenerator {
|
|
1730
|
-
/**
|
|
1731
|
-
* Generate a password of given length.
|
|
1732
|
-
* @param length The length of the password to generate.
|
|
1733
|
-
* @returns The random password.
|
|
1734
|
-
*/
|
|
1735
|
-
static generate(length) {
|
|
1736
|
-
const alphabet = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
|
|
1737
|
-
const alphabet2 = `${alphabet}0123456789!#$£%^&*+=@~?}`;
|
|
1738
|
-
const chars = [];
|
|
1739
|
-
while (chars.length < length) {
|
|
1740
|
-
const charSet = chars.length === 0 ? alphabet : alphabet2;
|
|
1741
|
-
let b = 0;
|
|
1742
|
-
do {
|
|
1743
|
-
b = RandomHelper.generate(1)[0];
|
|
1744
|
-
} while (b >= charSet.length);
|
|
1745
|
-
chars.push(charSet[b]);
|
|
1746
|
-
}
|
|
1747
|
-
return chars.join("");
|
|
1748
|
-
}
|
|
1749
|
-
}
|
|
1750
|
-
|
|
1751
|
-
// Copyright 2024 IOTA Stiftung.
|
|
1752
|
-
// SPDX-License-Identifier: Apache-2.0.
|
|
1753
|
-
/**
|
|
1754
|
-
* Test password strength.
|
|
1755
|
-
* Ref https://www.owasp.org/index.php/Authentication_Cheat_Sheet#Implement_Proper_Password_Strength_Controls .
|
|
1756
|
-
*/
|
|
1757
|
-
class PasswordValidator {
|
|
1758
|
-
/**
|
|
1759
|
-
* Test the strength of the password.
|
|
1760
|
-
* @param property The name of the property.
|
|
1761
|
-
* @param password The password to test.
|
|
1762
|
-
* @param failures The list of failures to add to.
|
|
1763
|
-
* @param options Options to configure the testing.
|
|
1764
|
-
* @param options.minLength The minimum length of the password, defaults to 8.
|
|
1765
|
-
* @param options.maxLength The minimum length of the password, defaults to 128.
|
|
1766
|
-
* @param options.minPhraseLength The minimum length of the password for it to be considered a pass phrase.
|
|
1767
|
-
*/
|
|
1768
|
-
static validate(property, password, failures, options) {
|
|
1769
|
-
const isString = Validation.stringValue(property, password, failures);
|
|
1770
|
-
if (isString) {
|
|
1771
|
-
const minLength = options?.minLength ?? 8;
|
|
1772
|
-
if (password.length < minLength) {
|
|
1773
|
-
failures.push({
|
|
1774
|
-
property,
|
|
1775
|
-
reason: "validation.minLengthRequired",
|
|
1776
|
-
properties: {
|
|
1777
|
-
minLength
|
|
1778
|
-
}
|
|
1779
|
-
});
|
|
1780
|
-
}
|
|
1781
|
-
const maxLength = options?.maxLength ?? 128;
|
|
1782
|
-
if (password.length > maxLength) {
|
|
1783
|
-
failures.push({
|
|
1784
|
-
property,
|
|
1785
|
-
reason: "validation.maxLengthRequired",
|
|
1786
|
-
properties: {
|
|
1787
|
-
maxLength
|
|
1788
|
-
}
|
|
1789
|
-
});
|
|
1790
|
-
}
|
|
1791
|
-
if (/(.)\1{2,}/.test(password)) {
|
|
1792
|
-
failures.push({
|
|
1793
|
-
property,
|
|
1794
|
-
reason: "validation.repeatedCharacters"
|
|
1795
|
-
});
|
|
1796
|
-
}
|
|
1797
|
-
// If this looks like a phrase then apply additional rules
|
|
1798
|
-
const minPhraseLength = options?.minPhraseLength ?? 20;
|
|
1799
|
-
if (password.length < minPhraseLength || !password.includes(" ")) {
|
|
1800
|
-
if (!/[a-z]/.test(password)) {
|
|
1801
|
-
failures.push({
|
|
1802
|
-
property,
|
|
1803
|
-
reason: "validation.atLeastOneLowerCase"
|
|
1804
|
-
});
|
|
1805
|
-
}
|
|
1806
|
-
if (!/[A-Z]/.test(password)) {
|
|
1807
|
-
failures.push({
|
|
1808
|
-
property,
|
|
1809
|
-
reason: "validation.atLeastOneUpperCase"
|
|
1810
|
-
});
|
|
1811
|
-
}
|
|
1812
|
-
if (!/\d/.test(password)) {
|
|
1813
|
-
failures.push({
|
|
1814
|
-
property,
|
|
1815
|
-
reason: "validation.atLeastOneNumber"
|
|
1816
|
-
});
|
|
1817
|
-
}
|
|
1818
|
-
if (!/[^\dA-Za-z]/.test(password)) {
|
|
1819
|
-
failures.push({
|
|
1820
|
-
property,
|
|
1821
|
-
reason: "validation.atLeastOneSpecialChar"
|
|
1822
|
-
});
|
|
1823
|
-
}
|
|
1824
|
-
}
|
|
1825
|
-
}
|
|
1826
|
-
}
|
|
1827
|
-
}
|
|
1828
|
-
|
|
1829
|
-
export { Bech32, Bip32Path, Bip39, Bip44, Blake2b, Blake3, ChaCha20Poly1305, Ed25519, HmacSha1, HmacSha256, HmacSha512, Hotp, KeyType, PasswordGenerator, PasswordValidator, Pbkdf2, PemHelper, Secp256k1, Sha1, Sha256, Sha3, Sha512, Slip0010, Totp, X25519, Zip215 };
|