@twin.org/crypto 0.0.2-next.9 → 0.0.3-next.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/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 +267 -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
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
// Copyright 2024 IOTA Stiftung.
|
|
2
|
+
// SPDX-License-Identifier: Apache-2.0.
|
|
3
|
+
import { HDKey as HDKeySecp256k1 } from "@scure/bip32";
|
|
4
|
+
import { Converter, GeneralError } from "@twin.org/core";
|
|
5
|
+
import { HDKey as HDKeyEd25519 } from "micro-key-producer/slip10.js";
|
|
6
|
+
import { Ed25519 } from "../curves/ed25519.js";
|
|
7
|
+
import { Secp256k1 } from "../curves/secp256k1.js";
|
|
8
|
+
import { KeyType } from "../models/keyType.js";
|
|
9
|
+
/**
|
|
10
|
+
* Class to help with slip0010 key derivation
|
|
11
|
+
* https://github.com/satoshilabs/slips/blob/master/slip-0010.md.
|
|
12
|
+
*/
|
|
13
|
+
export class Slip0010 {
|
|
14
|
+
/**
|
|
15
|
+
* Runtime name for the class.
|
|
16
|
+
*/
|
|
17
|
+
static CLASS_NAME = "Slip0010";
|
|
18
|
+
/**
|
|
19
|
+
* Get the master key from the seed.
|
|
20
|
+
* @param seed The seed to generate the master key from.
|
|
21
|
+
* @param keyType The key type.
|
|
22
|
+
* @returns The key and chain code.
|
|
23
|
+
* @throws If the seed is invalid.
|
|
24
|
+
*/
|
|
25
|
+
static getMasterKeyFromSeed(seed, keyType = KeyType.Ed25519) {
|
|
26
|
+
try {
|
|
27
|
+
const masterKey = keyType === KeyType.Ed25519
|
|
28
|
+
? HDKeyEd25519.fromMasterSeed(seed)
|
|
29
|
+
: HDKeySecp256k1.fromMasterSeed(seed);
|
|
30
|
+
return {
|
|
31
|
+
privateKey: masterKey.privateKey ?? new Uint8Array(),
|
|
32
|
+
chainCode: masterKey.chainCode ?? new Uint8Array()
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
catch (error) {
|
|
36
|
+
throw new GeneralError(Slip0010.CLASS_NAME, "invalidSeed", { seed: Converter.bytesToUtf8(seed) }, error);
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Derive a key from the path.
|
|
41
|
+
* @param seed The seed.
|
|
42
|
+
* @param path The path.
|
|
43
|
+
* @param keyType The key type.
|
|
44
|
+
* @returns The key and chain code.
|
|
45
|
+
*/
|
|
46
|
+
static derivePath(seed, path, keyType = KeyType.Ed25519) {
|
|
47
|
+
const keyOpts = Slip0010.getMasterKeyFromSeed(seed, keyType);
|
|
48
|
+
if (keyType === KeyType.Ed25519) {
|
|
49
|
+
const hdKey = new HDKeyEd25519(keyOpts);
|
|
50
|
+
const derivedKey = hdKey.derive(path.toString());
|
|
51
|
+
return {
|
|
52
|
+
privateKey: derivedKey.privateKey,
|
|
53
|
+
chainCode: derivedKey.chainCode
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
const hdKey = new HDKeySecp256k1(keyOpts);
|
|
57
|
+
const derivedKey = hdKey.derive(path.toString());
|
|
58
|
+
return {
|
|
59
|
+
privateKey: derivedKey.privateKey ?? new Uint8Array(),
|
|
60
|
+
chainCode: derivedKey.chainCode ?? new Uint8Array()
|
|
61
|
+
};
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* Get the public key from the private key.
|
|
65
|
+
* @param privateKey The private key.
|
|
66
|
+
* @param keyType The key type.
|
|
67
|
+
* @param withZeroByte Include a zero bute prefix.
|
|
68
|
+
* @returns The public key.
|
|
69
|
+
*/
|
|
70
|
+
static getPublicKey(privateKey, keyType = KeyType.Ed25519, withZeroByte = true) {
|
|
71
|
+
const signPk = keyType === KeyType.Ed25519
|
|
72
|
+
? Ed25519.publicKeyFromPrivateKey(privateKey)
|
|
73
|
+
: Secp256k1.publicKeyFromPrivateKey(privateKey);
|
|
74
|
+
if (withZeroByte) {
|
|
75
|
+
const arr = new Uint8Array(1 + signPk.length);
|
|
76
|
+
arr[0] = 0;
|
|
77
|
+
arr.set(signPk, 1);
|
|
78
|
+
return arr;
|
|
79
|
+
}
|
|
80
|
+
return signPk;
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
//# sourceMappingURL=slip0010.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"slip0010.js","sourceRoot":"","sources":["../../../src/keys/slip0010.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2024 IOTA Stiftung.\n// SPDX-License-Identifier: Apache-2.0.\nimport { HDKey as HDKeySecp256k1 } from \"@scure/bip32\";\nimport { Converter, GeneralError } from \"@twin.org/core\";\nimport { nameof } from \"@twin.org/nameof\";\nimport { HDKey as HDKeyEd25519 } from \"micro-key-producer/slip10.js\";\nimport type { Bip32Path } from \"./bip32Path.js\";\nimport { Ed25519 } from \"../curves/ed25519.js\";\nimport { Secp256k1 } from \"../curves/secp256k1.js\";\nimport { KeyType } from \"../models/keyType.js\";\n\n/**\n * Class to help with slip0010 key derivation\n * https://github.com/satoshilabs/slips/blob/master/slip-0010.md.\n */\nexport class Slip0010 {\n\t/**\n\t * Runtime name for the class.\n\t */\n\tpublic static readonly CLASS_NAME: string = nameof<Slip0010>();\n\n\t/**\n\t * Get the master key from the seed.\n\t * @param seed The seed to generate the master key from.\n\t * @param keyType The key type.\n\t * @returns The key and chain code.\n\t * @throws If the seed is invalid.\n\t */\n\tpublic static getMasterKeyFromSeed(\n\t\tseed: Uint8Array,\n\t\tkeyType: KeyType = KeyType.Ed25519\n\t): {\n\t\tprivateKey: Uint8Array;\n\t\tchainCode: Uint8Array;\n\t} {\n\t\ttry {\n\t\t\tconst masterKey =\n\t\t\t\tkeyType === KeyType.Ed25519\n\t\t\t\t\t? HDKeyEd25519.fromMasterSeed(seed)\n\t\t\t\t\t: HDKeySecp256k1.fromMasterSeed(seed);\n\n\t\t\treturn {\n\t\t\t\tprivateKey: masterKey.privateKey ?? new Uint8Array(),\n\t\t\t\tchainCode: masterKey.chainCode ?? new Uint8Array()\n\t\t\t};\n\t\t} catch (error) {\n\t\t\tthrow new GeneralError(\n\t\t\t\tSlip0010.CLASS_NAME,\n\t\t\t\t\"invalidSeed\",\n\t\t\t\t{ seed: Converter.bytesToUtf8(seed) },\n\t\t\t\terror\n\t\t\t);\n\t\t}\n\t}\n\n\t/**\n\t * Derive a key from the path.\n\t * @param seed The seed.\n\t * @param path The path.\n\t * @param keyType The key type.\n\t * @returns The key and chain code.\n\t */\n\tpublic static derivePath(\n\t\tseed: Uint8Array,\n\t\tpath: Bip32Path,\n\t\tkeyType: KeyType = KeyType.Ed25519\n\t): {\n\t\tprivateKey: Uint8Array;\n\t\tchainCode: Uint8Array;\n\t} {\n\t\tconst keyOpts = Slip0010.getMasterKeyFromSeed(seed, keyType);\n\n\t\tif (keyType === KeyType.Ed25519) {\n\t\t\tconst hdKey = new HDKeyEd25519(keyOpts);\n\t\t\tconst derivedKey = hdKey.derive(path.toString());\n\t\t\treturn {\n\t\t\t\tprivateKey: derivedKey.privateKey,\n\t\t\t\tchainCode: derivedKey.chainCode\n\t\t\t};\n\t\t}\n\t\tconst hdKey = new HDKeySecp256k1(keyOpts);\n\t\tconst derivedKey = hdKey.derive(path.toString());\n\t\treturn {\n\t\t\tprivateKey: derivedKey.privateKey ?? new Uint8Array(),\n\t\t\tchainCode: derivedKey.chainCode ?? new Uint8Array()\n\t\t};\n\t}\n\n\t/**\n\t * Get the public key from the private key.\n\t * @param privateKey The private key.\n\t * @param keyType The key type.\n\t * @param withZeroByte Include a zero bute prefix.\n\t * @returns The public key.\n\t */\n\tpublic static getPublicKey(\n\t\tprivateKey: Uint8Array,\n\t\tkeyType: KeyType = KeyType.Ed25519,\n\t\twithZeroByte: boolean = true\n\t): Uint8Array {\n\t\tconst signPk =\n\t\t\tkeyType === KeyType.Ed25519\n\t\t\t\t? Ed25519.publicKeyFromPrivateKey(privateKey)\n\t\t\t\t: Secp256k1.publicKeyFromPrivateKey(privateKey);\n\t\tif (withZeroByte) {\n\t\t\tconst arr = new Uint8Array(1 + signPk.length);\n\t\t\tarr[0] = 0;\n\t\t\tarr.set(signPk, 1);\n\t\t\treturn arr;\n\t\t}\n\t\treturn signPk;\n\t}\n}\n"]}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
// Copyright 2024 IOTA Stiftung.
|
|
2
|
+
// SPDX-License-Identifier: Apache-2.0.
|
|
3
|
+
/**
|
|
4
|
+
* The names of the key types.
|
|
5
|
+
*/
|
|
6
|
+
// eslint-disable-next-line @typescript-eslint/naming-convention
|
|
7
|
+
export const KeyType = {
|
|
8
|
+
/**
|
|
9
|
+
* Ed25519.
|
|
10
|
+
*/
|
|
11
|
+
Ed25519: 0,
|
|
12
|
+
/**
|
|
13
|
+
* Secp256k1.
|
|
14
|
+
*/
|
|
15
|
+
Secp256k1: 1
|
|
16
|
+
};
|
|
17
|
+
//# sourceMappingURL=keyType.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"keyType.js","sourceRoot":"","sources":["../../../src/models/keyType.ts"],"names":[],"mappings":"AAAA,gCAAgC;AAChC,uCAAuC;AAEvC;;GAEG;AACH,gEAAgE;AAChE,MAAM,CAAC,MAAM,OAAO,GAAG;IACtB;;OAEG;IACH,OAAO,EAAE,CAAC;IAEV;;OAEG;IACH,SAAS,EAAE,CAAC;CACH,CAAC","sourcesContent":["// Copyright 2024 IOTA Stiftung.\n// SPDX-License-Identifier: Apache-2.0.\n\n/**\n * The names of the key types.\n */\n// eslint-disable-next-line @typescript-eslint/naming-convention\nexport const KeyType = {\n\t/**\n\t * Ed25519.\n\t */\n\tEd25519: 0,\n\n\t/**\n\t * Secp256k1.\n\t */\n\tSecp256k1: 1\n} as const;\n\n/**\n * Key types.\n */\nexport type KeyType = (typeof KeyType)[keyof typeof KeyType];\n"]}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
// Copyright 2024 IOTA Stiftung.
|
|
2
|
+
// SPDX-License-Identifier: Apache-2.0.
|
|
3
|
+
import { Guards } from "@twin.org/core";
|
|
4
|
+
import * as otp from "micro-key-producer/otp.js";
|
|
5
|
+
/**
|
|
6
|
+
* Perform HOTP.
|
|
7
|
+
* Implementation of https://datatracker.ietf.org/doc/html/rfc4226 .
|
|
8
|
+
*/
|
|
9
|
+
export class Hotp {
|
|
10
|
+
/**
|
|
11
|
+
* Runtime name for the class.
|
|
12
|
+
*/
|
|
13
|
+
static CLASS_NAME = "Hotp";
|
|
14
|
+
/**
|
|
15
|
+
* Generate a counter based One Time Password.
|
|
16
|
+
* @param key Key for the one time password.
|
|
17
|
+
* @param counter This should be stored by the application,
|
|
18
|
+
* must be user specific, and be incremented for each request.
|
|
19
|
+
* @returns The one time password.
|
|
20
|
+
*/
|
|
21
|
+
static generate(key, counter) {
|
|
22
|
+
Guards.uint8Array(Hotp.CLASS_NAME, "key", key);
|
|
23
|
+
Guards.number(Hotp.CLASS_NAME, "counter", counter);
|
|
24
|
+
return otp.hotp({ secret: key, digits: 6, algorithm: "sha1", interval: 30 }, counter);
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
//# sourceMappingURL=hotp.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hotp.js","sourceRoot":"","sources":["../../../src/otp/hotp.ts"],"names":[],"mappings":"AAAA,gCAAgC;AAChC,uCAAuC;AACvC,OAAO,EAAE,MAAM,EAAE,MAAM,gBAAgB,CAAC;AAExC,OAAO,KAAK,GAAG,MAAM,2BAA2B,CAAC;AAEjD;;;GAGG;AACH,MAAM,OAAO,IAAI;IAChB;;OAEG;IACI,MAAM,CAAU,UAAU,UAA0B;IAE3D;;;;;;OAMG;IACI,MAAM,CAAC,QAAQ,CAAC,GAAe,EAAE,OAAe;QACtD,MAAM,CAAC,UAAU,CAAC,IAAI,CAAC,UAAU,SAAe,GAAG,CAAC,CAAC;QACrD,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,UAAU,aAAmB,OAAO,CAAC,CAAC;QAEzD,OAAO,GAAG,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,CAAC,EAAE,SAAS,EAAE,MAAM,EAAE,QAAQ,EAAE,EAAE,EAAE,EAAE,OAAO,CAAC,CAAC;IACvF,CAAC","sourcesContent":["// Copyright 2024 IOTA Stiftung.\n// SPDX-License-Identifier: Apache-2.0.\nimport { Guards } from \"@twin.org/core\";\nimport { nameof } from \"@twin.org/nameof\";\nimport * as otp from \"micro-key-producer/otp.js\";\n\n/**\n * Perform HOTP.\n * Implementation of https://datatracker.ietf.org/doc/html/rfc4226 .\n */\nexport class Hotp {\n\t/**\n\t * Runtime name for the class.\n\t */\n\tpublic static readonly CLASS_NAME: string = nameof<Hotp>();\n\n\t/**\n\t * Generate a counter based One Time Password.\n\t * @param key Key for the one time password.\n\t * @param counter This should be stored by the application,\n\t * must be user specific, and be incremented for each request.\n\t * @returns The one time password.\n\t */\n\tpublic static generate(key: Uint8Array, counter: number): string {\n\t\tGuards.uint8Array(Hotp.CLASS_NAME, nameof(key), key);\n\t\tGuards.number(Hotp.CLASS_NAME, nameof(counter), counter);\n\n\t\treturn otp.hotp({ secret: key, digits: 6, algorithm: \"sha1\", interval: 30 }, counter);\n\t}\n}\n"]}
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
// Copyright 2024 IOTA Stiftung.
|
|
2
|
+
// SPDX-License-Identifier: Apache-2.0.
|
|
3
|
+
import { Base32, RandomHelper } from "@twin.org/core";
|
|
4
|
+
import * as otp from "micro-key-producer/otp.js";
|
|
5
|
+
/**
|
|
6
|
+
* Perform TOTP.
|
|
7
|
+
* Implementation of https://datatracker.ietf.org/doc/html/rfc4226 .
|
|
8
|
+
*/
|
|
9
|
+
export class Totp {
|
|
10
|
+
/**
|
|
11
|
+
* Generate a time based One Time Password.
|
|
12
|
+
* @param key Key for the one time password.
|
|
13
|
+
* @param interval The time step of the counter.
|
|
14
|
+
* @param timestamp The timestamp.
|
|
15
|
+
* @returns The one time password.
|
|
16
|
+
*/
|
|
17
|
+
static generate(key, interval = 30, timestamp = Date.now()) {
|
|
18
|
+
return otp.totp({ secret: key, digits: 6, algorithm: "sha1", interval }, timestamp);
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Check a One Time Password based on a timer.
|
|
22
|
+
* @param token Passcode to validate.
|
|
23
|
+
* @param key Key for the one time password. This should be unique and secret for
|
|
24
|
+
* every user as it is the seed used to calculate the HMAC.
|
|
25
|
+
* @param window The allowable margin for the counter.
|
|
26
|
+
* @param interval The time step of the counter.
|
|
27
|
+
* @param timestamp The timestamp now.
|
|
28
|
+
* @returns Undefined if failure, delta on success
|
|
29
|
+
*/
|
|
30
|
+
static verify(token, key, window = 2, interval = 30, timestamp = Date.now()) {
|
|
31
|
+
for (let i = -window; i < window; i++) {
|
|
32
|
+
const intervalWindow = i * interval * 1000;
|
|
33
|
+
if (timestamp + intervalWindow > 0) {
|
|
34
|
+
const gen = Totp.generate(key, interval, timestamp + intervalWindow);
|
|
35
|
+
if (gen === token) {
|
|
36
|
+
// We have found a matching code
|
|
37
|
+
return i;
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
// If we get to here then no codes have matched, return undefined
|
|
42
|
+
return undefined;
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Generate a secret.
|
|
46
|
+
* @param length The length of the secret to generate.
|
|
47
|
+
* @returns The secret encoded as base32.
|
|
48
|
+
*/
|
|
49
|
+
static generateSecret(length) {
|
|
50
|
+
const encodedBase32 = Base32.encode(RandomHelper.generate(length));
|
|
51
|
+
// Strip the trailing = the authenticator apps don't need them
|
|
52
|
+
return encodedBase32.replace(/=/g, "");
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Convert the secret back to bytes.
|
|
56
|
+
* @param secretBase32 The secret encoded as base32.
|
|
57
|
+
* @returns The bytes of the secret.
|
|
58
|
+
*/
|
|
59
|
+
static secretToBytes(secretBase32) {
|
|
60
|
+
return Base32.decode(secretBase32);
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* Generate a url for use with authenticator apps.
|
|
64
|
+
* See https://github.com/google/google-authenticator/wiki/Key-Uri-Format .
|
|
65
|
+
* @param issuer The issuer of the totp.
|
|
66
|
+
* @param label The label that will show in auth apps.
|
|
67
|
+
* @param secretBase32 The secret as base 32.
|
|
68
|
+
* @returns The url.
|
|
69
|
+
*/
|
|
70
|
+
static generateAuthUrl(issuer, label, secretBase32) {
|
|
71
|
+
const encodedIssuer = encodeURIComponent(issuer);
|
|
72
|
+
return `otpauth://totp/${encodedIssuer}%3A${encodeURIComponent(label)}?secret=${secretBase32}&issuer=${encodedIssuer}&digits=6&algorithm=SHA1&interval=30`;
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
//# sourceMappingURL=totp.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"totp.js","sourceRoot":"","sources":["../../../src/otp/totp.ts"],"names":[],"mappings":"AAAA,gCAAgC;AAChC,uCAAuC;AACvC,OAAO,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AACtD,OAAO,KAAK,GAAG,MAAM,2BAA2B,CAAC;AAEjD;;;GAGG;AACH,MAAM,OAAO,IAAI;IAChB;;;;;;OAMG;IACI,MAAM,CAAC,QAAQ,CACrB,GAAe,EACf,WAAmB,EAAE,EACrB,YAAoB,IAAI,CAAC,GAAG,EAAE;QAE9B,OAAO,GAAG,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,CAAC,EAAE,SAAS,EAAE,MAAM,EAAE,QAAQ,EAAE,EAAE,SAAS,CAAC,CAAC;IACrF,CAAC;IAED;;;;;;;;;OASG;IACI,MAAM,CAAC,MAAM,CACnB,KAAa,EACb,GAAe,EACf,SAAiB,CAAC,EAClB,WAAmB,EAAE,EACrB,YAAoB,IAAI,CAAC,GAAG,EAAE;QAE9B,KAAK,IAAI,CAAC,GAAG,CAAC,MAAM,EAAE,CAAC,GAAG,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;YACvC,MAAM,cAAc,GAAG,CAAC,GAAG,QAAQ,GAAG,IAAI,CAAC;YAC3C,IAAI,SAAS,GAAG,cAAc,GAAG,CAAC,EAAE,CAAC;gBACpC,MAAM,GAAG,GAAG,IAAI,CAAC,QAAQ,CAAC,GAAG,EAAE,QAAQ,EAAE,SAAS,GAAG,cAAc,CAAC,CAAC;gBACrE,IAAI,GAAG,KAAK,KAAK,EAAE,CAAC;oBACnB,gCAAgC;oBAChC,OAAO,CAAC,CAAC;gBACV,CAAC;YACF,CAAC;QACF,CAAC;QAED,iEAAiE;QACjE,OAAO,SAAS,CAAC;IAClB,CAAC;IAED;;;;OAIG;IACI,MAAM,CAAC,cAAc,CAAC,MAAc;QAC1C,MAAM,aAAa,GAAG,MAAM,CAAC,MAAM,CAAC,YAAY,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC;QAEnE,8DAA8D;QAC9D,OAAO,aAAa,CAAC,OAAO,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC;IACxC,CAAC;IAED;;;;OAIG;IACI,MAAM,CAAC,aAAa,CAAC,YAAoB;QAC/C,OAAO,MAAM,CAAC,MAAM,CAAC,YAAY,CAAC,CAAC;IACpC,CAAC;IAED;;;;;;;OAOG;IACI,MAAM,CAAC,eAAe,CAAC,MAAc,EAAE,KAAa,EAAE,YAAoB;QAChF,MAAM,aAAa,GAAG,kBAAkB,CAAC,MAAM,CAAC,CAAC;QACjD,OAAO,kBAAkB,aAAa,MAAM,kBAAkB,CAC7D,KAAK,CACL,WAAW,YAAY,WAAW,aAAa,sCAAsC,CAAC;IACxF,CAAC;CACD","sourcesContent":["// Copyright 2024 IOTA Stiftung.\n// SPDX-License-Identifier: Apache-2.0.\nimport { Base32, RandomHelper } from \"@twin.org/core\";\nimport * as otp from \"micro-key-producer/otp.js\";\n\n/**\n * Perform TOTP.\n * Implementation of https://datatracker.ietf.org/doc/html/rfc4226 .\n */\nexport class Totp {\n\t/**\n\t * Generate a time based One Time Password.\n\t * @param key Key for the one time password.\n\t * @param interval The time step of the counter.\n\t * @param timestamp The timestamp.\n\t * @returns The one time password.\n\t */\n\tpublic static generate(\n\t\tkey: Uint8Array,\n\t\tinterval: number = 30,\n\t\ttimestamp: number = Date.now()\n\t): string {\n\t\treturn otp.totp({ secret: key, digits: 6, algorithm: \"sha1\", interval }, timestamp);\n\t}\n\n\t/**\n\t * Check a One Time Password based on a timer.\n\t * @param token Passcode to validate.\n\t * @param key Key for the one time password. This should be unique and secret for\n\t * every user as it is the seed used to calculate the HMAC.\n\t * @param window The allowable margin for the counter.\n\t * @param interval The time step of the counter.\n\t * @param timestamp The timestamp now.\n\t * @returns Undefined if failure, delta on success\n\t */\n\tpublic static verify(\n\t\ttoken: string,\n\t\tkey: Uint8Array,\n\t\twindow: number = 2,\n\t\tinterval: number = 30,\n\t\ttimestamp: number = Date.now()\n\t): number | undefined {\n\t\tfor (let i = -window; i < window; i++) {\n\t\t\tconst intervalWindow = i * interval * 1000;\n\t\t\tif (timestamp + intervalWindow > 0) {\n\t\t\t\tconst gen = Totp.generate(key, interval, timestamp + intervalWindow);\n\t\t\t\tif (gen === token) {\n\t\t\t\t\t// We have found a matching code\n\t\t\t\t\treturn i;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// If we get to here then no codes have matched, return undefined\n\t\treturn undefined;\n\t}\n\n\t/**\n\t * Generate a secret.\n\t * @param length The length of the secret to generate.\n\t * @returns The secret encoded as base32.\n\t */\n\tpublic static generateSecret(length: number): string {\n\t\tconst encodedBase32 = Base32.encode(RandomHelper.generate(length));\n\n\t\t// Strip the trailing = the authenticator apps don't need them\n\t\treturn encodedBase32.replace(/=/g, \"\");\n\t}\n\n\t/**\n\t * Convert the secret back to bytes.\n\t * @param secretBase32 The secret encoded as base32.\n\t * @returns The bytes of the secret.\n\t */\n\tpublic static secretToBytes(secretBase32: string): Uint8Array {\n\t\treturn Base32.decode(secretBase32);\n\t}\n\n\t/**\n\t * Generate a url for use with authenticator apps.\n\t * See https://github.com/google/google-authenticator/wiki/Key-Uri-Format .\n\t * @param issuer The issuer of the totp.\n\t * @param label The label that will show in auth apps.\n\t * @param secretBase32 The secret as base 32.\n\t * @returns The url.\n\t */\n\tpublic static generateAuthUrl(issuer: string, label: string, secretBase32: string): string {\n\t\tconst encodedIssuer = encodeURIComponent(issuer);\n\t\treturn `otpauth://totp/${encodedIssuer}%3A${encodeURIComponent(\n\t\t\tlabel\n\t\t)}?secret=${secretBase32}&issuer=${encodedIssuer}&digits=6&algorithm=SHA1&interval=30`;\n\t}\n}\n"]}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
// Copyright 2024 IOTA Stiftung.
|
|
2
|
+
// SPDX-License-Identifier: Apache-2.0.
|
|
3
|
+
import { RandomHelper } from "@twin.org/core";
|
|
4
|
+
/**
|
|
5
|
+
* Generate random passwords.
|
|
6
|
+
*/
|
|
7
|
+
export class PasswordGenerator {
|
|
8
|
+
/**
|
|
9
|
+
* Generate a password of given length.
|
|
10
|
+
* @param length The length of the password to generate.
|
|
11
|
+
* @returns The random password.
|
|
12
|
+
*/
|
|
13
|
+
static generate(length) {
|
|
14
|
+
const alphabet = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
|
|
15
|
+
const alphabet2 = `${alphabet}0123456789!#$£%^&*+=@~?}`;
|
|
16
|
+
const chars = [];
|
|
17
|
+
while (chars.length < length) {
|
|
18
|
+
const charSet = chars.length === 0 ? alphabet : alphabet2;
|
|
19
|
+
let b = 0;
|
|
20
|
+
do {
|
|
21
|
+
b = RandomHelper.generate(1)[0];
|
|
22
|
+
} while (b >= charSet.length);
|
|
23
|
+
chars.push(charSet[b]);
|
|
24
|
+
}
|
|
25
|
+
return chars.join("");
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
//# sourceMappingURL=passwordGenerator.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"passwordGenerator.js","sourceRoot":"","sources":["../../../src/passwords/passwordGenerator.ts"],"names":[],"mappings":"AAAA,gCAAgC;AAChC,uCAAuC;AACvC,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAE9C;;GAEG;AACH,MAAM,OAAO,iBAAiB;IAC7B;;;;OAIG;IACI,MAAM,CAAC,QAAQ,CAAC,MAAc;QACpC,MAAM,QAAQ,GAAG,sDAAsD,CAAC;QACxE,MAAM,SAAS,GAAG,GAAG,QAAQ,0BAA0B,CAAC;QAExD,MAAM,KAAK,GAAa,EAAE,CAAC;QAE3B,OAAO,KAAK,CAAC,MAAM,GAAG,MAAM,EAAE,CAAC;YAC9B,MAAM,OAAO,GAAG,KAAK,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,SAAS,CAAC;YAC1D,IAAI,CAAC,GAAG,CAAC,CAAC;YACV,GAAG,CAAC;gBACH,CAAC,GAAG,YAAY,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;YACjC,CAAC,QAAQ,CAAC,IAAI,OAAO,CAAC,MAAM,EAAE;YAC9B,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC;QACxB,CAAC;QAED,OAAO,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IACvB,CAAC;CACD","sourcesContent":["// Copyright 2024 IOTA Stiftung.\n// SPDX-License-Identifier: Apache-2.0.\nimport { RandomHelper } from \"@twin.org/core\";\n\n/**\n * Generate random passwords.\n */\nexport class PasswordGenerator {\n\t/**\n\t * Generate a password of given length.\n\t * @param length The length of the password to generate.\n\t * @returns The random password.\n\t */\n\tpublic static generate(length: number): string {\n\t\tconst alphabet = \"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ\";\n\t\tconst alphabet2 = `${alphabet}0123456789!#$£%^&*+=@~?}`;\n\n\t\tconst chars: string[] = [];\n\n\t\twhile (chars.length < length) {\n\t\t\tconst charSet = chars.length === 0 ? alphabet : alphabet2;\n\t\t\tlet b = 0;\n\t\t\tdo {\n\t\t\t\tb = RandomHelper.generate(1)[0];\n\t\t\t} while (b >= charSet.length);\n\t\t\tchars.push(charSet[b]);\n\t\t}\n\n\t\treturn chars.join(\"\");\n\t}\n}\n"]}
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
// Copyright 2024 IOTA Stiftung.
|
|
2
|
+
// SPDX-License-Identifier: Apache-2.0.
|
|
3
|
+
import { Validation } from "@twin.org/core";
|
|
4
|
+
/**
|
|
5
|
+
* Test password strength.
|
|
6
|
+
* Ref https://www.owasp.org/index.php/Authentication_Cheat_Sheet#Implement_Proper_Password_Strength_Controls .
|
|
7
|
+
*/
|
|
8
|
+
export class PasswordValidator {
|
|
9
|
+
/**
|
|
10
|
+
* Test the strength of the password.
|
|
11
|
+
* @param property The name of the property.
|
|
12
|
+
* @param password The password to test.
|
|
13
|
+
* @param failures The list of failures to add to.
|
|
14
|
+
* @param options Options to configure the testing.
|
|
15
|
+
* @param options.minLength The minimum length of the password, defaults to 8.
|
|
16
|
+
* @param options.maxLength The minimum length of the password, defaults to 128.
|
|
17
|
+
* @param options.minPhraseLength The minimum length of the password for it to be considered a pass phrase.
|
|
18
|
+
*/
|
|
19
|
+
static validate(property, password, failures, options) {
|
|
20
|
+
const isString = Validation.stringValue(property, password, failures);
|
|
21
|
+
if (isString) {
|
|
22
|
+
const minLength = options?.minLength ?? 8;
|
|
23
|
+
if (password.length < minLength) {
|
|
24
|
+
failures.push({
|
|
25
|
+
property,
|
|
26
|
+
reason: "validation.minLengthRequired",
|
|
27
|
+
properties: {
|
|
28
|
+
minLength,
|
|
29
|
+
actualLength: password.length
|
|
30
|
+
}
|
|
31
|
+
});
|
|
32
|
+
}
|
|
33
|
+
const maxLength = options?.maxLength ?? 128;
|
|
34
|
+
if (password.length > maxLength) {
|
|
35
|
+
failures.push({
|
|
36
|
+
property,
|
|
37
|
+
reason: "validation.maxLengthRequired",
|
|
38
|
+
properties: {
|
|
39
|
+
maxLength,
|
|
40
|
+
actualLength: password.length
|
|
41
|
+
}
|
|
42
|
+
});
|
|
43
|
+
}
|
|
44
|
+
if (/(.)\1{2,}/.test(password)) {
|
|
45
|
+
failures.push({
|
|
46
|
+
property,
|
|
47
|
+
reason: "validation.repeatedCharacters"
|
|
48
|
+
});
|
|
49
|
+
}
|
|
50
|
+
// If this looks like a phrase then apply additional rules
|
|
51
|
+
const minPhraseLength = options?.minPhraseLength ?? 20;
|
|
52
|
+
if (password.length < minPhraseLength || !password.includes(" ")) {
|
|
53
|
+
if (!/[a-z]/.test(password)) {
|
|
54
|
+
failures.push({
|
|
55
|
+
property,
|
|
56
|
+
reason: "validation.atLeastOneLowerCase"
|
|
57
|
+
});
|
|
58
|
+
}
|
|
59
|
+
if (!/[A-Z]/.test(password)) {
|
|
60
|
+
failures.push({
|
|
61
|
+
property,
|
|
62
|
+
reason: "validation.atLeastOneUpperCase"
|
|
63
|
+
});
|
|
64
|
+
}
|
|
65
|
+
if (!/\d/.test(password)) {
|
|
66
|
+
failures.push({
|
|
67
|
+
property,
|
|
68
|
+
reason: "validation.atLeastOneNumber"
|
|
69
|
+
});
|
|
70
|
+
}
|
|
71
|
+
if (!/[^\dA-Za-z]/.test(password)) {
|
|
72
|
+
failures.push({
|
|
73
|
+
property,
|
|
74
|
+
reason: "validation.atLeastOneSpecialChar"
|
|
75
|
+
});
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
//# sourceMappingURL=passwordValidator.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"passwordValidator.js","sourceRoot":"","sources":["../../../src/passwords/passwordValidator.ts"],"names":[],"mappings":"AAAA,gCAAgC;AAChC,uCAAuC;AACvC,OAAO,EAA2B,UAAU,EAAE,MAAM,gBAAgB,CAAC;AAErE;;;GAGG;AACH,MAAM,OAAO,iBAAiB;IAC7B;;;;;;;;;OASG;IACI,MAAM,CAAC,QAAQ,CACrB,QAAgB,EAChB,QAAgB,EAChB,QAA8B,EAC9B,OAIC;QAED,MAAM,QAAQ,GAAG,UAAU,CAAC,WAAW,CAAC,QAAQ,EAAE,QAAQ,EAAE,QAAQ,CAAC,CAAC;QAEtE,IAAI,QAAQ,EAAE,CAAC;YACd,MAAM,SAAS,GAAG,OAAO,EAAE,SAAS,IAAI,CAAC,CAAC;YAC1C,IAAI,QAAQ,CAAC,MAAM,GAAG,SAAS,EAAE,CAAC;gBACjC,QAAQ,CAAC,IAAI,CAAC;oBACb,QAAQ;oBACR,MAAM,EAAE,8BAA8B;oBACtC,UAAU,EAAE;wBACX,SAAS;wBACT,YAAY,EAAE,QAAQ,CAAC,MAAM;qBAC7B;iBACD,CAAC,CAAC;YACJ,CAAC;YAED,MAAM,SAAS,GAAG,OAAO,EAAE,SAAS,IAAI,GAAG,CAAC;YAC5C,IAAI,QAAQ,CAAC,MAAM,GAAG,SAAS,EAAE,CAAC;gBACjC,QAAQ,CAAC,IAAI,CAAC;oBACb,QAAQ;oBACR,MAAM,EAAE,8BAA8B;oBACtC,UAAU,EAAE;wBACX,SAAS;wBACT,YAAY,EAAE,QAAQ,CAAC,MAAM;qBAC7B;iBACD,CAAC,CAAC;YACJ,CAAC;YAED,IAAI,WAAW,CAAC,IAAI,CAAC,QAAQ,CAAC,EAAE,CAAC;gBAChC,QAAQ,CAAC,IAAI,CAAC;oBACb,QAAQ;oBACR,MAAM,EAAE,+BAA+B;iBACvC,CAAC,CAAC;YACJ,CAAC;YAED,0DAA0D;YAC1D,MAAM,eAAe,GAAG,OAAO,EAAE,eAAe,IAAI,EAAE,CAAC;YAEvD,IAAI,QAAQ,CAAC,MAAM,GAAG,eAAe,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC;gBAClE,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,QAAQ,CAAC,EAAE,CAAC;oBAC7B,QAAQ,CAAC,IAAI,CAAC;wBACb,QAAQ;wBACR,MAAM,EAAE,gCAAgC;qBACxC,CAAC,CAAC;gBACJ,CAAC;gBAED,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,QAAQ,CAAC,EAAE,CAAC;oBAC7B,QAAQ,CAAC,IAAI,CAAC;wBACb,QAAQ;wBACR,MAAM,EAAE,gCAAgC;qBACxC,CAAC,CAAC;gBACJ,CAAC;gBAED,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,EAAE,CAAC;oBAC1B,QAAQ,CAAC,IAAI,CAAC;wBACb,QAAQ;wBACR,MAAM,EAAE,6BAA6B;qBACrC,CAAC,CAAC;gBACJ,CAAC;gBAED,IAAI,CAAC,aAAa,CAAC,IAAI,CAAC,QAAQ,CAAC,EAAE,CAAC;oBACnC,QAAQ,CAAC,IAAI,CAAC;wBACb,QAAQ;wBACR,MAAM,EAAE,kCAAkC;qBAC1C,CAAC,CAAC;gBACJ,CAAC;YACF,CAAC;QACF,CAAC;IACF,CAAC;CACD","sourcesContent":["// Copyright 2024 IOTA Stiftung.\n// SPDX-License-Identifier: Apache-2.0.\nimport { type IValidationFailure, Validation } from \"@twin.org/core\";\n\n/**\n * Test password strength.\n * Ref https://www.owasp.org/index.php/Authentication_Cheat_Sheet#Implement_Proper_Password_Strength_Controls .\n */\nexport class PasswordValidator {\n\t/**\n\t * Test the strength of the password.\n\t * @param property The name of the property.\n\t * @param password The password to test.\n\t * @param failures The list of failures to add to.\n\t * @param options Options to configure the testing.\n\t * @param options.minLength The minimum length of the password, defaults to 8.\n\t * @param options.maxLength The minimum length of the password, defaults to 128.\n\t * @param options.minPhraseLength The minimum length of the password for it to be considered a pass phrase.\n\t */\n\tpublic static validate(\n\t\tproperty: string,\n\t\tpassword: string,\n\t\tfailures: IValidationFailure[],\n\t\toptions?: {\n\t\t\tminLength?: number;\n\t\t\tmaxLength?: number;\n\t\t\tminPhraseLength?: number;\n\t\t}\n\t): void {\n\t\tconst isString = Validation.stringValue(property, password, failures);\n\n\t\tif (isString) {\n\t\t\tconst minLength = options?.minLength ?? 8;\n\t\t\tif (password.length < minLength) {\n\t\t\t\tfailures.push({\n\t\t\t\t\tproperty,\n\t\t\t\t\treason: \"validation.minLengthRequired\",\n\t\t\t\t\tproperties: {\n\t\t\t\t\t\tminLength,\n\t\t\t\t\t\tactualLength: password.length\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t}\n\n\t\t\tconst maxLength = options?.maxLength ?? 128;\n\t\t\tif (password.length > maxLength) {\n\t\t\t\tfailures.push({\n\t\t\t\t\tproperty,\n\t\t\t\t\treason: \"validation.maxLengthRequired\",\n\t\t\t\t\tproperties: {\n\t\t\t\t\t\tmaxLength,\n\t\t\t\t\t\tactualLength: password.length\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t}\n\n\t\t\tif (/(.)\\1{2,}/.test(password)) {\n\t\t\t\tfailures.push({\n\t\t\t\t\tproperty,\n\t\t\t\t\treason: \"validation.repeatedCharacters\"\n\t\t\t\t});\n\t\t\t}\n\n\t\t\t// If this looks like a phrase then apply additional rules\n\t\t\tconst minPhraseLength = options?.minPhraseLength ?? 20;\n\n\t\t\tif (password.length < minPhraseLength || !password.includes(\" \")) {\n\t\t\t\tif (!/[a-z]/.test(password)) {\n\t\t\t\t\tfailures.push({\n\t\t\t\t\t\tproperty,\n\t\t\t\t\t\treason: \"validation.atLeastOneLowerCase\"\n\t\t\t\t\t});\n\t\t\t\t}\n\n\t\t\t\tif (!/[A-Z]/.test(password)) {\n\t\t\t\t\tfailures.push({\n\t\t\t\t\t\tproperty,\n\t\t\t\t\t\treason: \"validation.atLeastOneUpperCase\"\n\t\t\t\t\t});\n\t\t\t\t}\n\n\t\t\t\tif (!/\\d/.test(password)) {\n\t\t\t\t\tfailures.push({\n\t\t\t\t\t\tproperty,\n\t\t\t\t\t\treason: \"validation.atLeastOneNumber\"\n\t\t\t\t\t});\n\t\t\t\t}\n\n\t\t\t\tif (!/[^\\dA-Za-z]/.test(password)) {\n\t\t\t\t\tfailures.push({\n\t\t\t\t\t\tproperty,\n\t\t\t\t\t\treason: \"validation.atLeastOneSpecialChar\"\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n"]}
|
|
@@ -1,9 +1,13 @@
|
|
|
1
|
-
import { Bip32Path } from "../keys/bip32Path";
|
|
2
|
-
import { KeyType } from "../models/keyType";
|
|
1
|
+
import { Bip32Path } from "../keys/bip32Path.js";
|
|
2
|
+
import { KeyType } from "../models/keyType.js";
|
|
3
3
|
/**
|
|
4
4
|
* Implementation of Bip44 for address generation.
|
|
5
5
|
*/
|
|
6
6
|
export declare class Bip44 {
|
|
7
|
+
/**
|
|
8
|
+
* Runtime name for the class.
|
|
9
|
+
*/
|
|
10
|
+
static readonly CLASS_NAME: string;
|
|
7
11
|
/**
|
|
8
12
|
* Generate a bip44 key pair from the seed and parts.
|
|
9
13
|
* @param seed The account seed.
|
|
@@ -10,6 +10,10 @@ export declare class Ed25519 {
|
|
|
10
10
|
* Public Key Size is the size, in bytes, of public keys as used in this package.
|
|
11
11
|
*/
|
|
12
12
|
static PUBLIC_KEY_SIZE: number;
|
|
13
|
+
/**
|
|
14
|
+
* Runtime name for the class.
|
|
15
|
+
*/
|
|
16
|
+
static readonly CLASS_NAME: string;
|
|
13
17
|
/**
|
|
14
18
|
* Public returns the PublicKey corresponding to private.
|
|
15
19
|
* @param privateKey The private key to get the corresponding public key.
|
|
@@ -10,6 +10,10 @@ export declare class Secp256k1 {
|
|
|
10
10
|
* Public Key Size is the size, in bytes, of public keys as used in this package.
|
|
11
11
|
*/
|
|
12
12
|
static PUBLIC_KEY_SIZE: number;
|
|
13
|
+
/**
|
|
14
|
+
* Runtime name for the class.
|
|
15
|
+
*/
|
|
16
|
+
static readonly CLASS_NAME: string;
|
|
13
17
|
/**
|
|
14
18
|
* Public returns the PublicKey corresponding to private.
|
|
15
19
|
* @param privateKey The private key to get the corresponding public key.
|
|
@@ -2,6 +2,10 @@
|
|
|
2
2
|
* Implementation of X25519.
|
|
3
3
|
*/
|
|
4
4
|
export declare class X25519 {
|
|
5
|
+
/**
|
|
6
|
+
* Runtime name for the class.
|
|
7
|
+
*/
|
|
8
|
+
static readonly CLASS_NAME: string;
|
|
5
9
|
/**
|
|
6
10
|
* Convert Ed25519 private key to X25519 private key.
|
|
7
11
|
* @param ed25519PrivateKey The ed25519 private key to convert.
|
|
@@ -2,6 +2,10 @@
|
|
|
2
2
|
* Implementation of Zip215.
|
|
3
3
|
*/
|
|
4
4
|
export declare class Zip215 {
|
|
5
|
+
/**
|
|
6
|
+
* Runtime name for the class.
|
|
7
|
+
*/
|
|
8
|
+
static readonly CLASS_NAME: string;
|
|
5
9
|
/**
|
|
6
10
|
* Verify reports whether sig is a valid signature of block by
|
|
7
11
|
* publicKey, using precisely-specified validation criteria (ZIP 215) suitable
|
|
@@ -14,6 +14,10 @@ export declare class Blake2b {
|
|
|
14
14
|
* Blake2b 512.
|
|
15
15
|
*/
|
|
16
16
|
static SIZE_512: number;
|
|
17
|
+
/**
|
|
18
|
+
* Runtime name for the class.
|
|
19
|
+
*/
|
|
20
|
+
static readonly CLASS_NAME: string;
|
|
17
21
|
/**
|
|
18
22
|
* Create a new instance of Blake2b.
|
|
19
23
|
* @param outputLength The output length.
|
|
@@ -10,6 +10,10 @@ export declare class HmacSha256 {
|
|
|
10
10
|
* Sha256 224.
|
|
11
11
|
*/
|
|
12
12
|
static readonly SIZE_224: number;
|
|
13
|
+
/**
|
|
14
|
+
* Runtime name for the class.
|
|
15
|
+
*/
|
|
16
|
+
static readonly CLASS_NAME: string;
|
|
13
17
|
/**
|
|
14
18
|
* Create a new instance of HmacSha256.
|
|
15
19
|
* @param key The key for the hmac.
|
|
@@ -18,6 +18,10 @@ export declare class HmacSha512 {
|
|
|
18
18
|
* Sha512 512.
|
|
19
19
|
*/
|
|
20
20
|
static SIZE_512: number;
|
|
21
|
+
/**
|
|
22
|
+
* Runtime name for the class.
|
|
23
|
+
*/
|
|
24
|
+
static readonly CLASS_NAME: string;
|
|
21
25
|
/**
|
|
22
26
|
* Create a new instance of HmacSha512.
|
|
23
27
|
* @param key The key for the hmac.
|
|
@@ -2,6 +2,10 @@
|
|
|
2
2
|
* Implementation of the password based key derivation function 2.
|
|
3
3
|
*/
|
|
4
4
|
export declare class Pbkdf2 {
|
|
5
|
+
/**
|
|
6
|
+
* Runtime name for the class.
|
|
7
|
+
*/
|
|
8
|
+
static readonly CLASS_NAME: string;
|
|
5
9
|
/**
|
|
6
10
|
* Derive a key from the parameters using Sha256.
|
|
7
11
|
* @param password The password to derive the key from.
|
|
@@ -10,6 +10,10 @@ export declare class Sha256 {
|
|
|
10
10
|
* Sha256 224.
|
|
11
11
|
*/
|
|
12
12
|
static readonly SIZE_224: number;
|
|
13
|
+
/**
|
|
14
|
+
* Runtime name for the class.
|
|
15
|
+
*/
|
|
16
|
+
static readonly CLASS_NAME: string;
|
|
13
17
|
/**
|
|
14
18
|
* Create a new instance of Sha256.
|
|
15
19
|
* @param bits The number of bits.
|
|
@@ -2,6 +2,10 @@
|
|
|
2
2
|
* Helper class for working with PEM (Privacy-Enhanced Mail) formatted data.
|
|
3
3
|
*/
|
|
4
4
|
export declare class PemHelper {
|
|
5
|
+
/**
|
|
6
|
+
* Runtime name for the class.
|
|
7
|
+
*/
|
|
8
|
+
static readonly CLASS_NAME: string;
|
|
5
9
|
/**
|
|
6
10
|
* Strip the PEM content of its headers, footers, and newlines.
|
|
7
11
|
* @param pemContent The PEM content to strip.
|
package/dist/types/index.d.ts
CHANGED
|
@@ -1,26 +1,26 @@
|
|
|
1
|
-
export * from "./address/bech32";
|
|
2
|
-
export * from "./address/bip44";
|
|
3
|
-
export * from "./ciphers/chaCha20Poly1305";
|
|
4
|
-
export * from "./curves/ed25519";
|
|
5
|
-
export * from "./curves/secp256k1";
|
|
6
|
-
export * from "./curves/x25519";
|
|
7
|
-
export * from "./curves/zip215";
|
|
8
|
-
export * from "./hashes/blake2b";
|
|
9
|
-
export * from "./hashes/blake3";
|
|
10
|
-
export * from "./hashes/hmacSha1";
|
|
11
|
-
export * from "./hashes/hmacSha256";
|
|
12
|
-
export * from "./hashes/hmacSha512";
|
|
13
|
-
export * from "./hashes/pbkdf2";
|
|
14
|
-
export * from "./hashes/sha1";
|
|
15
|
-
export * from "./hashes/sha256";
|
|
16
|
-
export * from "./hashes/sha3";
|
|
17
|
-
export * from "./hashes/sha512";
|
|
18
|
-
export * from "./helpers/pemHelper";
|
|
19
|
-
export * from "./keys/bip32Path";
|
|
20
|
-
export * from "./keys/bip39";
|
|
21
|
-
export * from "./keys/slip0010";
|
|
22
|
-
export * from "./models/keyType";
|
|
23
|
-
export * from "./otp/hotp";
|
|
24
|
-
export * from "./otp/totp";
|
|
25
|
-
export * from "./passwords/passwordGenerator";
|
|
26
|
-
export * from "./passwords/passwordValidator";
|
|
1
|
+
export * from "./address/bech32.js";
|
|
2
|
+
export * from "./address/bip44.js";
|
|
3
|
+
export * from "./ciphers/chaCha20Poly1305.js";
|
|
4
|
+
export * from "./curves/ed25519.js";
|
|
5
|
+
export * from "./curves/secp256k1.js";
|
|
6
|
+
export * from "./curves/x25519.js";
|
|
7
|
+
export * from "./curves/zip215.js";
|
|
8
|
+
export * from "./hashes/blake2b.js";
|
|
9
|
+
export * from "./hashes/blake3.js";
|
|
10
|
+
export * from "./hashes/hmacSha1.js";
|
|
11
|
+
export * from "./hashes/hmacSha256.js";
|
|
12
|
+
export * from "./hashes/hmacSha512.js";
|
|
13
|
+
export * from "./hashes/pbkdf2.js";
|
|
14
|
+
export * from "./hashes/sha1.js";
|
|
15
|
+
export * from "./hashes/sha256.js";
|
|
16
|
+
export * from "./hashes/sha3.js";
|
|
17
|
+
export * from "./hashes/sha512.js";
|
|
18
|
+
export * from "./helpers/pemHelper.js";
|
|
19
|
+
export * from "./keys/bip32Path.js";
|
|
20
|
+
export * from "./keys/bip39.js";
|
|
21
|
+
export * from "./keys/slip0010.js";
|
|
22
|
+
export * from "./models/keyType.js";
|
|
23
|
+
export * from "./otp/hotp.js";
|
|
24
|
+
export * from "./otp/totp.js";
|
|
25
|
+
export * from "./passwords/passwordGenerator.js";
|
|
26
|
+
export * from "./passwords/passwordValidator.js";
|