@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
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
// Copyright 2024 IOTA Stiftung.
|
|
2
|
+
// SPDX-License-Identifier: Apache-2.0.
|
|
3
|
+
import { bech32 } from "@scure/base";
|
|
4
|
+
import { BaseError, GeneralError, Guards, Is } from "@twin.org/core";
|
|
5
|
+
/**
|
|
6
|
+
* Bech32 encoding and decoding.
|
|
7
|
+
*/
|
|
8
|
+
export class Bech32 {
|
|
9
|
+
/**
|
|
10
|
+
* Runtime name for the class.
|
|
11
|
+
*/
|
|
12
|
+
static CLASS_NAME = "Bech32";
|
|
13
|
+
/**
|
|
14
|
+
* Encode the buffer.
|
|
15
|
+
* @param humanReadablePart The header.
|
|
16
|
+
* @param data The data to encode.
|
|
17
|
+
* @returns The encoded data.
|
|
18
|
+
*/
|
|
19
|
+
static encode(humanReadablePart, data) {
|
|
20
|
+
Guards.stringValue(Bech32.CLASS_NAME, "humanReadablePart", humanReadablePart);
|
|
21
|
+
Guards.uint8Array(Bech32.CLASS_NAME, "data", data);
|
|
22
|
+
return bech32.encode(humanReadablePart, bech32.toWords(data));
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Decode a bech32 string.
|
|
26
|
+
* @param bech The text to decode.
|
|
27
|
+
* @returns The decoded data or undefined if it could not be decoded.
|
|
28
|
+
* @throws An error if the decoding fails.
|
|
29
|
+
*/
|
|
30
|
+
static decode(bech) {
|
|
31
|
+
Guards.stringValue(Bech32.CLASS_NAME, "bech", bech);
|
|
32
|
+
try {
|
|
33
|
+
const result = bech32.decodeToBytes(bech);
|
|
34
|
+
return {
|
|
35
|
+
humanReadablePart: result.prefix,
|
|
36
|
+
data: result.bytes
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
catch (err) {
|
|
40
|
+
if (BaseError.isErrorMessage(err, /checksum/)) {
|
|
41
|
+
throw new GeneralError(Bech32.CLASS_NAME, "invalidChecksum", { bech32 });
|
|
42
|
+
}
|
|
43
|
+
else if (BaseError.isErrorMessage(err, /between prefix and data only/i)) {
|
|
44
|
+
throw new GeneralError(Bech32.CLASS_NAME, "separatorMisused", { bech32 });
|
|
45
|
+
}
|
|
46
|
+
else if (BaseError.isErrorMessage(err, /lowercase or uppercase/i)) {
|
|
47
|
+
throw new GeneralError(Bech32.CLASS_NAME, "lowerUpper", { bech32 });
|
|
48
|
+
}
|
|
49
|
+
else if (BaseError.isErrorMessage(err, /must be at least/i) ||
|
|
50
|
+
BaseError.isErrorMessage(err, /wrong string length/i)) {
|
|
51
|
+
throw new GeneralError(Bech32.CLASS_NAME, "dataTooShort", { bech32 });
|
|
52
|
+
}
|
|
53
|
+
throw new GeneralError(Bech32.CLASS_NAME, "decodeFailed", { bech32 }, err);
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Is the input a bech 32 address.
|
|
58
|
+
* @param bech The value to test.
|
|
59
|
+
* @returns True if this is potentially a match.
|
|
60
|
+
*/
|
|
61
|
+
static isBech32(bech) {
|
|
62
|
+
try {
|
|
63
|
+
if (Is.stringValue(bech)) {
|
|
64
|
+
const result = bech32.decodeToBytes(bech);
|
|
65
|
+
return (Is.stringValue(result.prefix) && Is.uint8Array(result.bytes) && result.bytes.length > 0);
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
catch { }
|
|
69
|
+
return false;
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
//# sourceMappingURL=bech32.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"bech32.js","sourceRoot":"","sources":["../../../src/address/bech32.ts"],"names":[],"mappings":"AAAA,gCAAgC;AAChC,uCAAuC;AACvC,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AACrC,OAAO,EAAE,SAAS,EAAE,YAAY,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,gBAAgB,CAAC;AAGrE;;GAEG;AACH,MAAM,OAAO,MAAM;IAClB;;OAEG;IACI,MAAM,CAAU,UAAU,YAA4B;IAE7D;;;;;OAKG;IACI,MAAM,CAAC,MAAM,CAAC,iBAAyB,EAAE,IAAgB;QAC/D,MAAM,CAAC,WAAW,CAAC,MAAM,CAAC,UAAU,EAAE,mBAAmB,EAAE,iBAAiB,CAAC,CAAC;QAC9E,MAAM,CAAC,UAAU,CAAC,MAAM,CAAC,UAAU,EAAE,MAAM,EAAE,IAAI,CAAC,CAAC;QACnD,OAAO,MAAM,CAAC,MAAM,CAAC,iBAAiB,EAAE,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC;IAC/D,CAAC;IAED;;;;;OAKG;IACI,MAAM,CAAC,MAAM,CAAC,IAAY;QAIhC,MAAM,CAAC,WAAW,CAAC,MAAM,CAAC,UAAU,EAAE,MAAM,EAAE,IAAI,CAAC,CAAC;QAEpD,IAAI,CAAC;YACJ,MAAM,MAAM,GAAG,MAAM,CAAC,aAAa,CAAC,IAAI,CAAC,CAAC;YAC1C,OAAO;gBACN,iBAAiB,EAAE,MAAM,CAAC,MAAM;gBAChC,IAAI,EAAE,MAAM,CAAC,KAAK;aAClB,CAAC;QACH,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACd,IAAI,SAAS,CAAC,cAAc,CAAC,GAAG,EAAE,UAAU,CAAC,EAAE,CAAC;gBAC/C,MAAM,IAAI,YAAY,CAAC,MAAM,CAAC,UAAU,EAAE,iBAAiB,EAAE,EAAE,MAAM,EAAE,CAAC,CAAC;YAC1E,CAAC;iBAAM,IAAI,SAAS,CAAC,cAAc,CAAC,GAAG,EAAE,+BAA+B,CAAC,EAAE,CAAC;gBAC3E,MAAM,IAAI,YAAY,CAAC,MAAM,CAAC,UAAU,EAAE,kBAAkB,EAAE,EAAE,MAAM,EAAE,CAAC,CAAC;YAC3E,CAAC;iBAAM,IAAI,SAAS,CAAC,cAAc,CAAC,GAAG,EAAE,yBAAyB,CAAC,EAAE,CAAC;gBACrE,MAAM,IAAI,YAAY,CAAC,MAAM,CAAC,UAAU,EAAE,YAAY,EAAE,EAAE,MAAM,EAAE,CAAC,CAAC;YACrE,CAAC;iBAAM,IACN,SAAS,CAAC,cAAc,CAAC,GAAG,EAAE,mBAAmB,CAAC;gBAClD,SAAS,CAAC,cAAc,CAAC,GAAG,EAAE,sBAAsB,CAAC,EACpD,CAAC;gBACF,MAAM,IAAI,YAAY,CAAC,MAAM,CAAC,UAAU,EAAE,cAAc,EAAE,EAAE,MAAM,EAAE,CAAC,CAAC;YACvE,CAAC;YAED,MAAM,IAAI,YAAY,CAAC,MAAM,CAAC,UAAU,EAAE,cAAc,EAAE,EAAE,MAAM,EAAE,EAAE,GAAG,CAAC,CAAC;QAC5E,CAAC;IACF,CAAC;IAED;;;;OAIG;IACI,MAAM,CAAC,QAAQ,CAAC,IAAa;QACnC,IAAI,CAAC;YACJ,IAAI,EAAE,CAAC,WAAW,CAAC,IAAI,CAAC,EAAE,CAAC;gBAC1B,MAAM,MAAM,GAAG,MAAM,CAAC,aAAa,CAAC,IAAI,CAAC,CAAC;gBAC1C,OAAO,CACN,EAAE,CAAC,WAAW,CAAC,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC,UAAU,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,MAAM,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,CACvF,CAAC;YACH,CAAC;QACF,CAAC;QAAC,MAAM,CAAC,CAAA,CAAC;QACV,OAAO,KAAK,CAAC;IACd,CAAC","sourcesContent":["// Copyright 2024 IOTA Stiftung.\n// SPDX-License-Identifier: Apache-2.0.\nimport { bech32 } from \"@scure/base\";\nimport { BaseError, GeneralError, Guards, Is } from \"@twin.org/core\";\nimport { nameof } from \"@twin.org/nameof\";\n\n/**\n * Bech32 encoding and decoding.\n */\nexport class Bech32 {\n\t/**\n\t * Runtime name for the class.\n\t */\n\tpublic static readonly CLASS_NAME: string = nameof<Bech32>();\n\n\t/**\n\t * Encode the buffer.\n\t * @param humanReadablePart The header.\n\t * @param data The data to encode.\n\t * @returns The encoded data.\n\t */\n\tpublic static encode(humanReadablePart: string, data: Uint8Array): string {\n\t\tGuards.stringValue(Bech32.CLASS_NAME, \"humanReadablePart\", humanReadablePart);\n\t\tGuards.uint8Array(Bech32.CLASS_NAME, \"data\", data);\n\t\treturn bech32.encode(humanReadablePart, bech32.toWords(data));\n\t}\n\n\t/**\n\t * Decode a bech32 string.\n\t * @param bech The text to decode.\n\t * @returns The decoded data or undefined if it could not be decoded.\n\t * @throws An error if the decoding fails.\n\t */\n\tpublic static decode(bech: string): {\n\t\thumanReadablePart: string;\n\t\tdata: Uint8Array;\n\t} {\n\t\tGuards.stringValue(Bech32.CLASS_NAME, \"bech\", bech);\n\n\t\ttry {\n\t\t\tconst result = bech32.decodeToBytes(bech);\n\t\t\treturn {\n\t\t\t\thumanReadablePart: result.prefix,\n\t\t\t\tdata: result.bytes\n\t\t\t};\n\t\t} catch (err) {\n\t\t\tif (BaseError.isErrorMessage(err, /checksum/)) {\n\t\t\t\tthrow new GeneralError(Bech32.CLASS_NAME, \"invalidChecksum\", { bech32 });\n\t\t\t} else if (BaseError.isErrorMessage(err, /between prefix and data only/i)) {\n\t\t\t\tthrow new GeneralError(Bech32.CLASS_NAME, \"separatorMisused\", { bech32 });\n\t\t\t} else if (BaseError.isErrorMessage(err, /lowercase or uppercase/i)) {\n\t\t\t\tthrow new GeneralError(Bech32.CLASS_NAME, \"lowerUpper\", { bech32 });\n\t\t\t} else if (\n\t\t\t\tBaseError.isErrorMessage(err, /must be at least/i) ||\n\t\t\t\tBaseError.isErrorMessage(err, /wrong string length/i)\n\t\t\t) {\n\t\t\t\tthrow new GeneralError(Bech32.CLASS_NAME, \"dataTooShort\", { bech32 });\n\t\t\t}\n\n\t\t\tthrow new GeneralError(Bech32.CLASS_NAME, \"decodeFailed\", { bech32 }, err);\n\t\t}\n\t}\n\n\t/**\n\t * Is the input a bech 32 address.\n\t * @param bech The value to test.\n\t * @returns True if this is potentially a match.\n\t */\n\tpublic static isBech32(bech: unknown): bech is string {\n\t\ttry {\n\t\t\tif (Is.stringValue(bech)) {\n\t\t\t\tconst result = bech32.decodeToBytes(bech);\n\t\t\t\treturn (\n\t\t\t\t\tIs.stringValue(result.prefix) && Is.uint8Array(result.bytes) && result.bytes.length > 0\n\t\t\t\t);\n\t\t\t}\n\t\t} catch {}\n\t\treturn false;\n\t}\n}\n"]}
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
// Copyright 2024 IOTA Stiftung.
|
|
2
|
+
// SPDX-License-Identifier: Apache-2.0.
|
|
3
|
+
import { Converter, GeneralError } from "@twin.org/core";
|
|
4
|
+
import { Bech32 } from "../address/bech32.js";
|
|
5
|
+
import { Ed25519 } from "../curves/ed25519.js";
|
|
6
|
+
import { Secp256k1 } from "../curves/secp256k1.js";
|
|
7
|
+
import { Blake2b } from "../hashes/blake2b.js";
|
|
8
|
+
import { Bip32Path } from "../keys/bip32Path.js";
|
|
9
|
+
import { Slip0010 } from "../keys/slip0010.js";
|
|
10
|
+
import { KeyType } from "../models/keyType.js";
|
|
11
|
+
/**
|
|
12
|
+
* Implementation of Bip44 for address generation.
|
|
13
|
+
*/
|
|
14
|
+
export class Bip44 {
|
|
15
|
+
/**
|
|
16
|
+
* Runtime name for the class.
|
|
17
|
+
*/
|
|
18
|
+
static CLASS_NAME = "Bip44";
|
|
19
|
+
/**
|
|
20
|
+
* Generate a bip44 key pair from the seed and parts.
|
|
21
|
+
* @param seed The account seed.
|
|
22
|
+
* @param keyType The key type.
|
|
23
|
+
* @param coinType The coin type.
|
|
24
|
+
* @param accountIndex The account index.
|
|
25
|
+
* @param isInternal Is this an internal address.
|
|
26
|
+
* @param addressIndex The address index.
|
|
27
|
+
* @returns The key pair.
|
|
28
|
+
* @throws Error if the address type is not supported.
|
|
29
|
+
*/
|
|
30
|
+
static keyPair(seed, keyType, coinType, accountIndex, isInternal, addressIndex) {
|
|
31
|
+
const bip44Path = Bip44.path(coinType, accountIndex, isInternal, addressIndex);
|
|
32
|
+
const keys = Slip0010.derivePath(seed, bip44Path);
|
|
33
|
+
if (keyType === KeyType.Ed25519) {
|
|
34
|
+
const publicKey = Ed25519.publicKeyFromPrivateKey(keys.privateKey);
|
|
35
|
+
return {
|
|
36
|
+
privateKey: keys.privateKey,
|
|
37
|
+
publicKey
|
|
38
|
+
};
|
|
39
|
+
}
|
|
40
|
+
else if (keyType === KeyType.Secp256k1) {
|
|
41
|
+
const publicKey = Secp256k1.publicKeyFromPrivateKey(keys.privateKey);
|
|
42
|
+
return {
|
|
43
|
+
privateKey: keys.privateKey,
|
|
44
|
+
publicKey
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
throw new GeneralError(Bip44.CLASS_NAME, "unsupportedKeyType", { keyType });
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Generate a bip44 path based on all its parts.
|
|
51
|
+
* @param coinType The coin type.
|
|
52
|
+
* @param accountIndex The account index.
|
|
53
|
+
* @param isInternal Is this an internal address.
|
|
54
|
+
* @param addressIndex The address index.
|
|
55
|
+
* @returns The generated path.
|
|
56
|
+
*/
|
|
57
|
+
static path(coinType, accountIndex, isInternal, addressIndex) {
|
|
58
|
+
const bip32Path = new Bip32Path(Bip44.basePath(coinType));
|
|
59
|
+
bip32Path.pushHardened(accountIndex);
|
|
60
|
+
bip32Path.pushHardened(isInternal ? 1 : 0);
|
|
61
|
+
bip32Path.pushHardened(addressIndex);
|
|
62
|
+
return bip32Path;
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* Create a bip44 base path for the provided coin type.
|
|
66
|
+
* @param coinType The coin type.
|
|
67
|
+
* @returns The bip44 address base path.
|
|
68
|
+
*/
|
|
69
|
+
static basePath(coinType) {
|
|
70
|
+
return `m/44'/${coinType}'`;
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* Generate an address from the seed and parts.
|
|
74
|
+
* @param seed The account seed.
|
|
75
|
+
* @param keyType The key type.
|
|
76
|
+
* @param coinType The coin type.
|
|
77
|
+
* @param accountIndex The account index.
|
|
78
|
+
* @param isInternal Is this an internal address.
|
|
79
|
+
* @param addressIndex The address index.
|
|
80
|
+
* @returns The generated path and the associated keypair.
|
|
81
|
+
*/
|
|
82
|
+
static address(seed, keyType, coinType, accountIndex, isInternal, addressIndex) {
|
|
83
|
+
const keyPair = Bip44.keyPair(seed, keyType, coinType, accountIndex, isInternal, addressIndex);
|
|
84
|
+
const addressData = Blake2b.sum256(keyPair.publicKey);
|
|
85
|
+
return {
|
|
86
|
+
address: Converter.bytesToHex(addressData, true),
|
|
87
|
+
...keyPair
|
|
88
|
+
};
|
|
89
|
+
}
|
|
90
|
+
/**
|
|
91
|
+
* Generate a bech32 address from the seed and parts.
|
|
92
|
+
* @param seed The account seed.
|
|
93
|
+
* @param keyType The key type.
|
|
94
|
+
* @param hrp The human readable part of the address.
|
|
95
|
+
* @param coinType The coin type.
|
|
96
|
+
* @param accountIndex The account index.
|
|
97
|
+
* @param isInternal Is this an internal address.
|
|
98
|
+
* @param addressIndex The address index.
|
|
99
|
+
* @returns The generated path and the associated keypair.
|
|
100
|
+
*/
|
|
101
|
+
static addressBech32(seed, keyType, hrp, coinType, accountIndex, isInternal, addressIndex) {
|
|
102
|
+
const keyPair = Bip44.keyPair(seed, keyType, coinType, accountIndex, isInternal, addressIndex);
|
|
103
|
+
const addressData = Blake2b.sum256(keyPair.publicKey);
|
|
104
|
+
const bech32Data = new Uint8Array(1 + addressData.length);
|
|
105
|
+
bech32Data[0] = keyType;
|
|
106
|
+
bech32Data.set(addressData, 1);
|
|
107
|
+
return {
|
|
108
|
+
address: Bech32.encode(hrp, bech32Data),
|
|
109
|
+
...keyPair
|
|
110
|
+
};
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
//# sourceMappingURL=bip44.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"bip44.js","sourceRoot":"","sources":["../../../src/address/bip44.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2024 IOTA Stiftung.\n// SPDX-License-Identifier: Apache-2.0.\nimport { Converter, GeneralError } from \"@twin.org/core\";\nimport { nameof } from \"@twin.org/nameof\";\nimport { Bech32 } from \"../address/bech32.js\";\nimport { Ed25519 } from \"../curves/ed25519.js\";\nimport { Secp256k1 } from \"../curves/secp256k1.js\";\nimport { Blake2b } from \"../hashes/blake2b.js\";\nimport { Bip32Path } from \"../keys/bip32Path.js\";\nimport { Slip0010 } from \"../keys/slip0010.js\";\nimport { KeyType } from \"../models/keyType.js\";\n\n/**\n * Implementation of Bip44 for address generation.\n */\nexport class Bip44 {\n\t/**\n\t * Runtime name for the class.\n\t */\n\tpublic static readonly CLASS_NAME: string = nameof<Bip44>();\n\n\t/**\n\t * Generate a bip44 key pair from the seed and parts.\n\t * @param seed The account seed.\n\t * @param keyType The key type.\n\t * @param coinType The coin type.\n\t * @param accountIndex The account index.\n\t * @param isInternal Is this an internal address.\n\t * @param addressIndex The address index.\n\t * @returns The key pair.\n\t * @throws Error if the address type is not supported.\n\t */\n\tpublic static keyPair(\n\t\tseed: Uint8Array,\n\t\tkeyType: KeyType,\n\t\tcoinType: number,\n\t\taccountIndex: number,\n\t\tisInternal: boolean,\n\t\taddressIndex: number\n\t): {\n\t\tprivateKey: Uint8Array;\n\t\tpublicKey: Uint8Array;\n\t} {\n\t\tconst bip44Path = Bip44.path(coinType, accountIndex, isInternal, addressIndex);\n\t\tconst keys = Slip0010.derivePath(seed, bip44Path);\n\n\t\tif (keyType === KeyType.Ed25519) {\n\t\t\tconst publicKey = Ed25519.publicKeyFromPrivateKey(keys.privateKey);\n\t\t\treturn {\n\t\t\t\tprivateKey: keys.privateKey,\n\t\t\t\tpublicKey\n\t\t\t};\n\t\t} else if (keyType === KeyType.Secp256k1) {\n\t\t\tconst publicKey = Secp256k1.publicKeyFromPrivateKey(keys.privateKey);\n\t\t\treturn {\n\t\t\t\tprivateKey: keys.privateKey,\n\t\t\t\tpublicKey\n\t\t\t};\n\t\t}\n\n\t\tthrow new GeneralError(Bip44.CLASS_NAME, \"unsupportedKeyType\", { keyType });\n\t}\n\n\t/**\n\t * Generate a bip44 path based on all its parts.\n\t * @param coinType The coin type.\n\t * @param accountIndex The account index.\n\t * @param isInternal Is this an internal address.\n\t * @param addressIndex The address index.\n\t * @returns The generated path.\n\t */\n\tpublic static path(\n\t\tcoinType: number,\n\t\taccountIndex: number,\n\t\tisInternal: boolean,\n\t\taddressIndex: number\n\t): Bip32Path {\n\t\tconst bip32Path = new Bip32Path(Bip44.basePath(coinType));\n\n\t\tbip32Path.pushHardened(accountIndex);\n\t\tbip32Path.pushHardened(isInternal ? 1 : 0);\n\t\tbip32Path.pushHardened(addressIndex);\n\n\t\treturn bip32Path;\n\t}\n\n\t/**\n\t * Create a bip44 base path for the provided coin type.\n\t * @param coinType The coin type.\n\t * @returns The bip44 address base path.\n\t */\n\tpublic static basePath(coinType: number): string {\n\t\treturn `m/44'/${coinType}'`;\n\t}\n\n\t/**\n\t * Generate an address from the seed and parts.\n\t * @param seed The account seed.\n\t * @param keyType The key type.\n\t * @param coinType The coin type.\n\t * @param accountIndex The account index.\n\t * @param isInternal Is this an internal address.\n\t * @param addressIndex The address index.\n\t * @returns The generated path and the associated keypair.\n\t */\n\tpublic static address(\n\t\tseed: Uint8Array,\n\t\tkeyType: KeyType,\n\t\tcoinType: number,\n\t\taccountIndex: number,\n\t\tisInternal: boolean,\n\t\taddressIndex: number\n\t): {\n\t\taddress: string;\n\t\tprivateKey: Uint8Array;\n\t\tpublicKey: Uint8Array;\n\t} {\n\t\tconst keyPair = Bip44.keyPair(seed, keyType, coinType, accountIndex, isInternal, addressIndex);\n\n\t\tconst addressData = Blake2b.sum256(keyPair.publicKey);\n\n\t\treturn {\n\t\t\taddress: Converter.bytesToHex(addressData, true),\n\t\t\t...keyPair\n\t\t};\n\t}\n\n\t/**\n\t * Generate a bech32 address from the seed and parts.\n\t * @param seed The account seed.\n\t * @param keyType The key type.\n\t * @param hrp The human readable part of the address.\n\t * @param coinType The coin type.\n\t * @param accountIndex The account index.\n\t * @param isInternal Is this an internal address.\n\t * @param addressIndex The address index.\n\t * @returns The generated path and the associated keypair.\n\t */\n\tpublic static addressBech32(\n\t\tseed: Uint8Array,\n\t\tkeyType: KeyType,\n\t\thrp: string,\n\t\tcoinType: number,\n\t\taccountIndex: number,\n\t\tisInternal: boolean,\n\t\taddressIndex: number\n\t): {\n\t\taddress: string;\n\t\tprivateKey: Uint8Array;\n\t\tpublicKey: Uint8Array;\n\t} {\n\t\tconst keyPair = Bip44.keyPair(seed, keyType, coinType, accountIndex, isInternal, addressIndex);\n\n\t\tconst addressData = Blake2b.sum256(keyPair.publicKey);\n\t\tconst bech32Data = new Uint8Array(1 + addressData.length);\n\t\tbech32Data[0] = keyType;\n\t\tbech32Data.set(addressData, 1);\n\n\t\treturn {\n\t\t\taddress: Bech32.encode(hrp, bech32Data),\n\t\t\t...keyPair\n\t\t};\n\t}\n}\n"]}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
// Copyright 2024 IOTA Stiftung.
|
|
2
|
+
// SPDX-License-Identifier: Apache-2.0.
|
|
3
|
+
import { chacha20poly1305 } from "@noble/ciphers/chacha.js";
|
|
4
|
+
import { Guards } from "@twin.org/core";
|
|
5
|
+
/**
|
|
6
|
+
* Implementation of the ChaCha20Poly1305 cipher.
|
|
7
|
+
*/
|
|
8
|
+
export class ChaCha20Poly1305 {
|
|
9
|
+
/**
|
|
10
|
+
* Runtime name for the class.
|
|
11
|
+
*/
|
|
12
|
+
static CLASS_NAME = "ChaCha20Poly1305";
|
|
13
|
+
/**
|
|
14
|
+
* The cipher instance.
|
|
15
|
+
* @internal
|
|
16
|
+
*/
|
|
17
|
+
_instance;
|
|
18
|
+
/**
|
|
19
|
+
* Create a new instance of ChaCha20Poly1305.
|
|
20
|
+
* @param key The key.
|
|
21
|
+
* @param nonce The nonce.
|
|
22
|
+
* @param aad The additional authenticated data.
|
|
23
|
+
*/
|
|
24
|
+
constructor(key, nonce, aad) {
|
|
25
|
+
Guards.uint8Array(ChaCha20Poly1305.CLASS_NAME, "key", key);
|
|
26
|
+
Guards.uint8Array(ChaCha20Poly1305.CLASS_NAME, "nonce", nonce);
|
|
27
|
+
this._instance = chacha20poly1305(key, nonce, aad);
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Encrypt the block.
|
|
31
|
+
* @param block The block to encrypt.
|
|
32
|
+
* @returns The block encrypted.
|
|
33
|
+
*/
|
|
34
|
+
encrypt(block) {
|
|
35
|
+
Guards.uint8Array(ChaCha20Poly1305.CLASS_NAME, "block", block);
|
|
36
|
+
return this._instance.encrypt(block);
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Decrypt the block.
|
|
40
|
+
* @param block The block to decrypt.
|
|
41
|
+
* @returns The block decrypted.
|
|
42
|
+
*/
|
|
43
|
+
decrypt(block) {
|
|
44
|
+
Guards.uint8Array(ChaCha20Poly1305.CLASS_NAME, "block", block);
|
|
45
|
+
return this._instance.decrypt(block);
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
//# sourceMappingURL=chaCha20Poly1305.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"chaCha20Poly1305.js","sourceRoot":"","sources":["../../../src/ciphers/chaCha20Poly1305.ts"],"names":[],"mappings":"AAAA,gCAAgC;AAChC,uCAAuC;AACvC,OAAO,EAAE,gBAAgB,EAAE,MAAM,0BAA0B,CAAC;AAE5D,OAAO,EAAE,MAAM,EAAE,MAAM,gBAAgB,CAAC;AAGxC;;GAEG;AACH,MAAM,OAAO,gBAAgB;IAC5B;;OAEG;IACI,MAAM,CAAU,UAAU,sBAAsC;IAEvE;;;OAGG;IACc,SAAS,CAAmB;IAE7C;;;;;OAKG;IACH,YAAY,GAAe,EAAE,KAAiB,EAAE,GAAgB;QAC/D,MAAM,CAAC,UAAU,CAAC,gBAAgB,CAAC,UAAU,SAAe,GAAG,CAAC,CAAC;QACjE,MAAM,CAAC,UAAU,CAAC,gBAAgB,CAAC,UAAU,WAAiB,KAAK,CAAC,CAAC;QACrE,IAAI,CAAC,SAAS,GAAG,gBAAgB,CAAC,GAAG,EAAE,KAAK,EAAE,GAAG,CAAC,CAAC;IACpD,CAAC;IAED;;;;OAIG;IACI,OAAO,CAAC,KAAiB;QAC/B,MAAM,CAAC,UAAU,CAAC,gBAAgB,CAAC,UAAU,WAAiB,KAAK,CAAC,CAAC;QACrE,OAAO,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;IACtC,CAAC;IAED;;;;OAIG;IACI,OAAO,CAAC,KAAiB;QAC/B,MAAM,CAAC,UAAU,CAAC,gBAAgB,CAAC,UAAU,WAAiB,KAAK,CAAC,CAAC;QACrE,OAAO,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;IACtC,CAAC","sourcesContent":["// Copyright 2024 IOTA Stiftung.\n// SPDX-License-Identifier: Apache-2.0.\nimport { chacha20poly1305 } from \"@noble/ciphers/chacha.js\";\nimport type { CipherWithOutput } from \"@noble/ciphers/utils.js\";\nimport { Guards } from \"@twin.org/core\";\nimport { nameof } from \"@twin.org/nameof\";\n\n/**\n * Implementation of the ChaCha20Poly1305 cipher.\n */\nexport class ChaCha20Poly1305 {\n\t/**\n\t * Runtime name for the class.\n\t */\n\tpublic static readonly CLASS_NAME: string = nameof<ChaCha20Poly1305>();\n\n\t/**\n\t * The cipher instance.\n\t * @internal\n\t */\n\tprivate readonly _instance: CipherWithOutput;\n\n\t/**\n\t * Create a new instance of ChaCha20Poly1305.\n\t * @param key The key.\n\t * @param nonce The nonce.\n\t * @param aad The additional authenticated data.\n\t */\n\tconstructor(key: Uint8Array, nonce: Uint8Array, aad?: Uint8Array) {\n\t\tGuards.uint8Array(ChaCha20Poly1305.CLASS_NAME, nameof(key), key);\n\t\tGuards.uint8Array(ChaCha20Poly1305.CLASS_NAME, nameof(nonce), nonce);\n\t\tthis._instance = chacha20poly1305(key, nonce, aad);\n\t}\n\n\t/**\n\t * Encrypt the block.\n\t * @param block The block to encrypt.\n\t * @returns The block encrypted.\n\t */\n\tpublic encrypt(block: Uint8Array): Uint8Array {\n\t\tGuards.uint8Array(ChaCha20Poly1305.CLASS_NAME, nameof(block), block);\n\t\treturn this._instance.encrypt(block);\n\t}\n\n\t/**\n\t * Decrypt the block.\n\t * @param block The block to decrypt.\n\t * @returns The block decrypted.\n\t */\n\tpublic decrypt(block: Uint8Array): Uint8Array {\n\t\tGuards.uint8Array(ChaCha20Poly1305.CLASS_NAME, nameof(block), block);\n\t\treturn this._instance.decrypt(block);\n\t}\n}\n"]}
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
// Copyright 2024 IOTA Stiftung.
|
|
2
|
+
// SPDX-License-Identifier: Apache-2.0.
|
|
3
|
+
import { ed25519 } from "@noble/curves/ed25519.js";
|
|
4
|
+
import { GeneralError, Guards, Uint8ArrayHelper } from "@twin.org/core";
|
|
5
|
+
/**
|
|
6
|
+
* Implementation of Ed25519.
|
|
7
|
+
*/
|
|
8
|
+
export class Ed25519 {
|
|
9
|
+
/**
|
|
10
|
+
* Private Key Size is the size, in bytes, of private keys as used in this package.
|
|
11
|
+
*/
|
|
12
|
+
static PRIVATE_KEY_SIZE = 32;
|
|
13
|
+
/**
|
|
14
|
+
* Public Key Size is the size, in bytes, of public keys as used in this package.
|
|
15
|
+
*/
|
|
16
|
+
static PUBLIC_KEY_SIZE = 32;
|
|
17
|
+
/**
|
|
18
|
+
* Runtime name for the class.
|
|
19
|
+
*/
|
|
20
|
+
static CLASS_NAME = "Ed25519";
|
|
21
|
+
/**
|
|
22
|
+
* Public returns the PublicKey corresponding to private.
|
|
23
|
+
* @param privateKey The private key to get the corresponding public key.
|
|
24
|
+
* @returns The public key.
|
|
25
|
+
* @throws Error if the private key is not the correct length.
|
|
26
|
+
*/
|
|
27
|
+
static publicKeyFromPrivateKey(privateKey) {
|
|
28
|
+
Guards.uint8Array(Ed25519.CLASS_NAME, "privateKey", privateKey);
|
|
29
|
+
if (privateKey.length !== Ed25519.PRIVATE_KEY_SIZE) {
|
|
30
|
+
throw new GeneralError(Ed25519.CLASS_NAME, "privateKeyLength", {
|
|
31
|
+
requiredSize: Ed25519.PRIVATE_KEY_SIZE,
|
|
32
|
+
actualSize: privateKey.length
|
|
33
|
+
});
|
|
34
|
+
}
|
|
35
|
+
return ed25519.getPublicKey(privateKey);
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Sign the block with privateKey and returns a signature.
|
|
39
|
+
* @param privateKey The private key.
|
|
40
|
+
* @param block The block to sign.
|
|
41
|
+
* @returns The signature.
|
|
42
|
+
* @throws Error if the private key is not the correct length.
|
|
43
|
+
*/
|
|
44
|
+
static sign(privateKey, block) {
|
|
45
|
+
Guards.uint8Array(Ed25519.CLASS_NAME, "privateKey", privateKey);
|
|
46
|
+
Guards.uint8Array(Ed25519.CLASS_NAME, "block", block);
|
|
47
|
+
if (privateKey.length !== Ed25519.PRIVATE_KEY_SIZE) {
|
|
48
|
+
throw new GeneralError(Ed25519.CLASS_NAME, "privateKeyLength", {
|
|
49
|
+
requiredSize: Ed25519.PRIVATE_KEY_SIZE,
|
|
50
|
+
actualSize: privateKey ? privateKey.length : 0
|
|
51
|
+
});
|
|
52
|
+
}
|
|
53
|
+
return ed25519.sign(block, privateKey);
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Verify reports whether sig is a valid signature of block by publicKey.
|
|
57
|
+
* @param publicKey The public key to verify the signature.
|
|
58
|
+
* @param block The block for the signature.
|
|
59
|
+
* @param signature The signature.
|
|
60
|
+
* @returns True if the signature matches.
|
|
61
|
+
* @throws Error if the public key is not the correct length.
|
|
62
|
+
*/
|
|
63
|
+
static verify(publicKey, block, signature) {
|
|
64
|
+
Guards.uint8Array(Ed25519.CLASS_NAME, "publicKey", publicKey);
|
|
65
|
+
Guards.uint8Array(Ed25519.CLASS_NAME, "block", block);
|
|
66
|
+
Guards.uint8Array(Ed25519.CLASS_NAME, "signature", signature);
|
|
67
|
+
if (publicKey.length !== Ed25519.PUBLIC_KEY_SIZE) {
|
|
68
|
+
throw new GeneralError(Ed25519.CLASS_NAME, "publicKeyLength", {
|
|
69
|
+
requiredSize: Ed25519.PUBLIC_KEY_SIZE,
|
|
70
|
+
actualSize: publicKey ? publicKey.length : 0
|
|
71
|
+
});
|
|
72
|
+
}
|
|
73
|
+
try {
|
|
74
|
+
return ed25519.verify(signature, block, publicKey);
|
|
75
|
+
}
|
|
76
|
+
catch {
|
|
77
|
+
return false;
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
/**
|
|
81
|
+
* Convert a private key in PKCS8 format.
|
|
82
|
+
* @param privateKey The private key to convert.
|
|
83
|
+
* @returns The private key in PKCS8 format.
|
|
84
|
+
*/
|
|
85
|
+
static async privateKeyToPkcs8(privateKey) {
|
|
86
|
+
Guards.uint8Array(Ed25519.CLASS_NAME, "privateKey", privateKey);
|
|
87
|
+
if (privateKey.length !== Ed25519.PRIVATE_KEY_SIZE) {
|
|
88
|
+
throw new GeneralError(Ed25519.CLASS_NAME, "privateKeyLength", {
|
|
89
|
+
requiredSize: Ed25519.PRIVATE_KEY_SIZE,
|
|
90
|
+
actualSize: privateKey.length
|
|
91
|
+
});
|
|
92
|
+
}
|
|
93
|
+
// crypto.subtle.importKey does not support Ed25519 keys in raw format.
|
|
94
|
+
// We need to convert the key to PKCS8 format before importing.
|
|
95
|
+
// The PKCS8 format is the raw key prefixed with the ASN.1 sequence for an Ed25519 private key.
|
|
96
|
+
// The ASN.1 sequence is 48 46 02 01 00 30 05 06 03 2b 65 70 04 20 04 20 (0x302e020100300506032b657004220420)
|
|
97
|
+
const pkcs8Prefix = new Uint8Array([48, 46, 2, 1, 0, 48, 5, 6, 3, 43, 101, 112, 4, 34, 4, 32]);
|
|
98
|
+
const fullKey = Uint8ArrayHelper.concat([pkcs8Prefix, privateKey]);
|
|
99
|
+
return crypto.subtle.importKey("pkcs8", new Uint8Array(fullKey), "Ed25519", true, ["sign"]);
|
|
100
|
+
}
|
|
101
|
+
/**
|
|
102
|
+
* Convert a crypto key to raw private key.
|
|
103
|
+
* @param cryptoKey The crypto key to convert.
|
|
104
|
+
* @returns The raw private key.
|
|
105
|
+
*/
|
|
106
|
+
static async pkcs8ToPrivateKey(cryptoKey) {
|
|
107
|
+
Guards.defined(Ed25519.CLASS_NAME, "cryptoKey", cryptoKey);
|
|
108
|
+
// crypto.subtle.exportKey does not support Ed25519 keys in raw format.
|
|
109
|
+
// so we export as PKCS8 and remove the ASN.1 sequence prefix.
|
|
110
|
+
const pkcs8Bytes = await crypto.subtle.exportKey("pkcs8", cryptoKey);
|
|
111
|
+
return new Uint8Array(pkcs8Bytes.slice(16));
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
//# sourceMappingURL=ed25519.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ed25519.js","sourceRoot":"","sources":["../../../src/curves/ed25519.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2024 IOTA Stiftung.\n// SPDX-License-Identifier: Apache-2.0.\nimport { ed25519 } from \"@noble/curves/ed25519.js\";\nimport { GeneralError, Guards, Uint8ArrayHelper } from \"@twin.org/core\";\nimport { nameof } from \"@twin.org/nameof\";\n\n/**\n * Implementation of Ed25519.\n */\nexport class Ed25519 {\n\t/**\n\t * Private Key Size is the size, in bytes, of private keys as used in this package.\n\t */\n\tpublic static PRIVATE_KEY_SIZE: number = 32;\n\n\t/**\n\t * Public Key Size is the size, in bytes, of public keys as used in this package.\n\t */\n\tpublic static PUBLIC_KEY_SIZE: number = 32;\n\n\t/**\n\t * Runtime name for the class.\n\t */\n\tpublic static readonly CLASS_NAME: string = nameof<Ed25519>();\n\n\t/**\n\t * Public returns the PublicKey corresponding to private.\n\t * @param privateKey The private key to get the corresponding public key.\n\t * @returns The public key.\n\t * @throws Error if the private key is not the correct length.\n\t */\n\tpublic static publicKeyFromPrivateKey(privateKey: Uint8Array): Uint8Array {\n\t\tGuards.uint8Array(Ed25519.CLASS_NAME, nameof(privateKey), privateKey);\n\n\t\tif (privateKey.length !== Ed25519.PRIVATE_KEY_SIZE) {\n\t\t\tthrow new GeneralError(Ed25519.CLASS_NAME, \"privateKeyLength\", {\n\t\t\t\trequiredSize: Ed25519.PRIVATE_KEY_SIZE,\n\t\t\t\tactualSize: privateKey.length\n\t\t\t});\n\t\t}\n\n\t\treturn ed25519.getPublicKey(privateKey);\n\t}\n\n\t/**\n\t * Sign the block with privateKey and returns a signature.\n\t * @param privateKey The private key.\n\t * @param block The block to sign.\n\t * @returns The signature.\n\t * @throws Error if the private key is not the correct length.\n\t */\n\tpublic static sign(privateKey: Uint8Array, block: Uint8Array): Uint8Array {\n\t\tGuards.uint8Array(Ed25519.CLASS_NAME, nameof(privateKey), privateKey);\n\t\tGuards.uint8Array(Ed25519.CLASS_NAME, nameof(block), block);\n\n\t\tif (privateKey.length !== Ed25519.PRIVATE_KEY_SIZE) {\n\t\t\tthrow new GeneralError(Ed25519.CLASS_NAME, \"privateKeyLength\", {\n\t\t\t\trequiredSize: Ed25519.PRIVATE_KEY_SIZE,\n\t\t\t\tactualSize: privateKey ? privateKey.length : 0\n\t\t\t});\n\t\t}\n\n\t\treturn ed25519.sign(block, privateKey);\n\t}\n\n\t/**\n\t * Verify reports whether sig is a valid signature of block by publicKey.\n\t * @param publicKey The public key to verify the signature.\n\t * @param block The block for the signature.\n\t * @param signature The signature.\n\t * @returns True if the signature matches.\n\t * @throws Error if the public key is not the correct length.\n\t */\n\tpublic static verify(publicKey: Uint8Array, block: Uint8Array, signature: Uint8Array): boolean {\n\t\tGuards.uint8Array(Ed25519.CLASS_NAME, nameof(publicKey), publicKey);\n\t\tGuards.uint8Array(Ed25519.CLASS_NAME, nameof(block), block);\n\t\tGuards.uint8Array(Ed25519.CLASS_NAME, nameof(signature), signature);\n\n\t\tif (publicKey.length !== Ed25519.PUBLIC_KEY_SIZE) {\n\t\t\tthrow new GeneralError(Ed25519.CLASS_NAME, \"publicKeyLength\", {\n\t\t\t\trequiredSize: Ed25519.PUBLIC_KEY_SIZE,\n\t\t\t\tactualSize: publicKey ? publicKey.length : 0\n\t\t\t});\n\t\t}\n\n\t\ttry {\n\t\t\treturn ed25519.verify(signature, block, publicKey);\n\t\t} catch {\n\t\t\treturn false;\n\t\t}\n\t}\n\n\t/**\n\t * Convert a private key in PKCS8 format.\n\t * @param privateKey The private key to convert.\n\t * @returns The private key in PKCS8 format.\n\t */\n\tpublic static async privateKeyToPkcs8(privateKey: Uint8Array): Promise<CryptoKey> {\n\t\tGuards.uint8Array(Ed25519.CLASS_NAME, nameof(privateKey), privateKey);\n\n\t\tif (privateKey.length !== Ed25519.PRIVATE_KEY_SIZE) {\n\t\t\tthrow new GeneralError(Ed25519.CLASS_NAME, \"privateKeyLength\", {\n\t\t\t\trequiredSize: Ed25519.PRIVATE_KEY_SIZE,\n\t\t\t\tactualSize: privateKey.length\n\t\t\t});\n\t\t}\n\n\t\t// crypto.subtle.importKey does not support Ed25519 keys in raw format.\n\t\t// We need to convert the key to PKCS8 format before importing.\n\t\t// The PKCS8 format is the raw key prefixed with the ASN.1 sequence for an Ed25519 private key.\n\t\t// The ASN.1 sequence is 48 46 02 01 00 30 05 06 03 2b 65 70 04 20 04 20 (0x302e020100300506032b657004220420)\n\t\tconst pkcs8Prefix = new Uint8Array([48, 46, 2, 1, 0, 48, 5, 6, 3, 43, 101, 112, 4, 34, 4, 32]);\n\t\tconst fullKey = Uint8ArrayHelper.concat([pkcs8Prefix, privateKey]);\n\t\treturn crypto.subtle.importKey(\"pkcs8\", new Uint8Array(fullKey), \"Ed25519\", true, [\"sign\"]);\n\t}\n\n\t/**\n\t * Convert a crypto key to raw private key.\n\t * @param cryptoKey The crypto key to convert.\n\t * @returns The raw private key.\n\t */\n\tpublic static async pkcs8ToPrivateKey(cryptoKey: CryptoKey): Promise<Uint8Array> {\n\t\tGuards.defined(Ed25519.CLASS_NAME, nameof(cryptoKey), cryptoKey);\n\n\t\t// crypto.subtle.exportKey does not support Ed25519 keys in raw format.\n\t\t// so we export as PKCS8 and remove the ASN.1 sequence prefix.\n\t\tconst pkcs8Bytes = await crypto.subtle.exportKey(\"pkcs8\", cryptoKey);\n\n\t\treturn new Uint8Array(pkcs8Bytes.slice(16));\n\t}\n}\n"]}
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
// Copyright 2024 IOTA Stiftung.
|
|
2
|
+
// SPDX-License-Identifier: Apache-2.0.
|
|
3
|
+
import { secp256k1 } from "@noble/curves/secp256k1.js";
|
|
4
|
+
import { GeneralError, Guards } from "@twin.org/core";
|
|
5
|
+
/**
|
|
6
|
+
* Implementation of secp256k1.
|
|
7
|
+
*/
|
|
8
|
+
export class Secp256k1 {
|
|
9
|
+
/**
|
|
10
|
+
* Private Key Size is the size, in bytes, of private keys as used in this package.
|
|
11
|
+
*/
|
|
12
|
+
static PRIVATE_KEY_SIZE = 32;
|
|
13
|
+
/**
|
|
14
|
+
* Public Key Size is the size, in bytes, of public keys as used in this package.
|
|
15
|
+
*/
|
|
16
|
+
static PUBLIC_KEY_SIZE = 33;
|
|
17
|
+
/**
|
|
18
|
+
* Runtime name for the class.
|
|
19
|
+
*/
|
|
20
|
+
static CLASS_NAME = "Secp256k1";
|
|
21
|
+
/**
|
|
22
|
+
* Public returns the PublicKey corresponding to private.
|
|
23
|
+
* @param privateKey The private key to get the corresponding public key.
|
|
24
|
+
* @returns The public key.
|
|
25
|
+
* @throws Error if the private key is not the correct length.
|
|
26
|
+
*/
|
|
27
|
+
static publicKeyFromPrivateKey(privateKey) {
|
|
28
|
+
Guards.uint8Array(Secp256k1.CLASS_NAME, "privateKey", privateKey);
|
|
29
|
+
if (privateKey.length !== Secp256k1.PRIVATE_KEY_SIZE) {
|
|
30
|
+
throw new GeneralError(Secp256k1.CLASS_NAME, "privateKeyLength", {
|
|
31
|
+
requiredSize: Secp256k1.PRIVATE_KEY_SIZE,
|
|
32
|
+
actualSize: privateKey.length
|
|
33
|
+
});
|
|
34
|
+
}
|
|
35
|
+
return secp256k1.getPublicKey(privateKey);
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Sign the block with privateKey and returns a signature.
|
|
39
|
+
* @param privateKey The private key.
|
|
40
|
+
* @param block The block to sign.
|
|
41
|
+
* @returns The signature.
|
|
42
|
+
* @throws Error if the private key is not the correct length.
|
|
43
|
+
*/
|
|
44
|
+
static sign(privateKey, block) {
|
|
45
|
+
Guards.uint8Array(Secp256k1.CLASS_NAME, "privateKey", privateKey);
|
|
46
|
+
Guards.uint8Array(Secp256k1.CLASS_NAME, "block", block);
|
|
47
|
+
if (privateKey.length !== Secp256k1.PRIVATE_KEY_SIZE) {
|
|
48
|
+
throw new GeneralError(Secp256k1.CLASS_NAME, "privateKeyLength", {
|
|
49
|
+
requiredSize: Secp256k1.PRIVATE_KEY_SIZE,
|
|
50
|
+
actualSize: privateKey.length
|
|
51
|
+
});
|
|
52
|
+
}
|
|
53
|
+
const res = secp256k1.sign(block, privateKey, { prehash: false });
|
|
54
|
+
return res;
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Verify reports whether sig is a valid signature of block by publicKey.
|
|
58
|
+
* @param publicKey The public key to verify the signature.
|
|
59
|
+
* @param block The block for the signature.
|
|
60
|
+
* @param signature The signature.
|
|
61
|
+
* @returns True if the signature matches.
|
|
62
|
+
* @throws Error if the public key is not the correct length.
|
|
63
|
+
*/
|
|
64
|
+
static verify(publicKey, block, signature) {
|
|
65
|
+
Guards.uint8Array(Secp256k1.CLASS_NAME, "publicKey", publicKey);
|
|
66
|
+
Guards.uint8Array(Secp256k1.CLASS_NAME, "block", block);
|
|
67
|
+
Guards.uint8Array(Secp256k1.CLASS_NAME, "signature", signature);
|
|
68
|
+
if (publicKey.length !== Secp256k1.PUBLIC_KEY_SIZE) {
|
|
69
|
+
throw new GeneralError(Secp256k1.CLASS_NAME, "publicKeyLength", {
|
|
70
|
+
requiredSize: Secp256k1.PUBLIC_KEY_SIZE,
|
|
71
|
+
actualSize: publicKey ? publicKey.length : 0
|
|
72
|
+
});
|
|
73
|
+
}
|
|
74
|
+
try {
|
|
75
|
+
return secp256k1.verify(signature, block, publicKey, { prehash: false });
|
|
76
|
+
}
|
|
77
|
+
catch {
|
|
78
|
+
return false;
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
//# sourceMappingURL=secp256k1.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"secp256k1.js","sourceRoot":"","sources":["../../../src/curves/secp256k1.ts"],"names":[],"mappings":"AAAA,gCAAgC;AAChC,uCAAuC;AACvC,OAAO,EAAE,SAAS,EAAE,MAAM,4BAA4B,CAAC;AACvD,OAAO,EAAE,YAAY,EAAE,MAAM,EAAE,MAAM,gBAAgB,CAAC;AAGtD;;GAEG;AACH,MAAM,OAAO,SAAS;IACrB;;OAEG;IACI,MAAM,CAAC,gBAAgB,GAAW,EAAE,CAAC;IAE5C;;OAEG;IACI,MAAM,CAAC,eAAe,GAAW,EAAE,CAAC;IAE3C;;OAEG;IACI,MAAM,CAAU,UAAU,eAA+B;IAEhE;;;;;OAKG;IACI,MAAM,CAAC,uBAAuB,CAAC,UAAsB;QAC3D,MAAM,CAAC,UAAU,CAAC,SAAS,CAAC,UAAU,gBAAsB,UAAU,CAAC,CAAC;QAExE,IAAI,UAAU,CAAC,MAAM,KAAK,SAAS,CAAC,gBAAgB,EAAE,CAAC;YACtD,MAAM,IAAI,YAAY,CAAC,SAAS,CAAC,UAAU,EAAE,kBAAkB,EAAE;gBAChE,YAAY,EAAE,SAAS,CAAC,gBAAgB;gBACxC,UAAU,EAAE,UAAU,CAAC,MAAM;aAC7B,CAAC,CAAC;QACJ,CAAC;QAED,OAAO,SAAS,CAAC,YAAY,CAAC,UAAU,CAAC,CAAC;IAC3C,CAAC;IAED;;;;;;OAMG;IACI,MAAM,CAAC,IAAI,CAAC,UAAsB,EAAE,KAAiB;QAC3D,MAAM,CAAC,UAAU,CAAC,SAAS,CAAC,UAAU,gBAAsB,UAAU,CAAC,CAAC;QACxE,MAAM,CAAC,UAAU,CAAC,SAAS,CAAC,UAAU,WAAiB,KAAK,CAAC,CAAC;QAE9D,IAAI,UAAU,CAAC,MAAM,KAAK,SAAS,CAAC,gBAAgB,EAAE,CAAC;YACtD,MAAM,IAAI,YAAY,CAAC,SAAS,CAAC,UAAU,EAAE,kBAAkB,EAAE;gBAChE,YAAY,EAAE,SAAS,CAAC,gBAAgB;gBACxC,UAAU,EAAE,UAAU,CAAC,MAAM;aAC7B,CAAC,CAAC;QACJ,CAAC;QAED,MAAM,GAAG,GAAG,SAAS,CAAC,IAAI,CAAC,KAAK,EAAE,UAAU,EAAE,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC,CAAC;QAClE,OAAO,GAAG,CAAC;IACZ,CAAC;IAED;;;;;;;OAOG;IACI,MAAM,CAAC,MAAM,CAAC,SAAqB,EAAE,KAAiB,EAAE,SAAqB;QACnF,MAAM,CAAC,UAAU,CAAC,SAAS,CAAC,UAAU,eAAqB,SAAS,CAAC,CAAC;QACtE,MAAM,CAAC,UAAU,CAAC,SAAS,CAAC,UAAU,WAAiB,KAAK,CAAC,CAAC;QAC9D,MAAM,CAAC,UAAU,CAAC,SAAS,CAAC,UAAU,eAAqB,SAAS,CAAC,CAAC;QAEtE,IAAI,SAAS,CAAC,MAAM,KAAK,SAAS,CAAC,eAAe,EAAE,CAAC;YACpD,MAAM,IAAI,YAAY,CAAC,SAAS,CAAC,UAAU,EAAE,iBAAiB,EAAE;gBAC/D,YAAY,EAAE,SAAS,CAAC,eAAe;gBACvC,UAAU,EAAE,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;aAC5C,CAAC,CAAC;QACJ,CAAC;QAED,IAAI,CAAC;YACJ,OAAO,SAAS,CAAC,MAAM,CAAC,SAAS,EAAE,KAAK,EAAE,SAAS,EAAE,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC,CAAC;QAC1E,CAAC;QAAC,MAAM,CAAC;YACR,OAAO,KAAK,CAAC;QACd,CAAC;IACF,CAAC","sourcesContent":["// Copyright 2024 IOTA Stiftung.\n// SPDX-License-Identifier: Apache-2.0.\nimport { secp256k1 } from \"@noble/curves/secp256k1.js\";\nimport { GeneralError, Guards } from \"@twin.org/core\";\nimport { nameof } from \"@twin.org/nameof\";\n\n/**\n * Implementation of secp256k1.\n */\nexport class Secp256k1 {\n\t/**\n\t * Private Key Size is the size, in bytes, of private keys as used in this package.\n\t */\n\tpublic static PRIVATE_KEY_SIZE: number = 32;\n\n\t/**\n\t * Public Key Size is the size, in bytes, of public keys as used in this package.\n\t */\n\tpublic static PUBLIC_KEY_SIZE: number = 33;\n\n\t/**\n\t * Runtime name for the class.\n\t */\n\tpublic static readonly CLASS_NAME: string = nameof<Secp256k1>();\n\n\t/**\n\t * Public returns the PublicKey corresponding to private.\n\t * @param privateKey The private key to get the corresponding public key.\n\t * @returns The public key.\n\t * @throws Error if the private key is not the correct length.\n\t */\n\tpublic static publicKeyFromPrivateKey(privateKey: Uint8Array): Uint8Array {\n\t\tGuards.uint8Array(Secp256k1.CLASS_NAME, nameof(privateKey), privateKey);\n\n\t\tif (privateKey.length !== Secp256k1.PRIVATE_KEY_SIZE) {\n\t\t\tthrow new GeneralError(Secp256k1.CLASS_NAME, \"privateKeyLength\", {\n\t\t\t\trequiredSize: Secp256k1.PRIVATE_KEY_SIZE,\n\t\t\t\tactualSize: privateKey.length\n\t\t\t});\n\t\t}\n\n\t\treturn secp256k1.getPublicKey(privateKey);\n\t}\n\n\t/**\n\t * Sign the block with privateKey and returns a signature.\n\t * @param privateKey The private key.\n\t * @param block The block to sign.\n\t * @returns The signature.\n\t * @throws Error if the private key is not the correct length.\n\t */\n\tpublic static sign(privateKey: Uint8Array, block: Uint8Array): Uint8Array {\n\t\tGuards.uint8Array(Secp256k1.CLASS_NAME, nameof(privateKey), privateKey);\n\t\tGuards.uint8Array(Secp256k1.CLASS_NAME, nameof(block), block);\n\n\t\tif (privateKey.length !== Secp256k1.PRIVATE_KEY_SIZE) {\n\t\t\tthrow new GeneralError(Secp256k1.CLASS_NAME, \"privateKeyLength\", {\n\t\t\t\trequiredSize: Secp256k1.PRIVATE_KEY_SIZE,\n\t\t\t\tactualSize: privateKey.length\n\t\t\t});\n\t\t}\n\n\t\tconst res = secp256k1.sign(block, privateKey, { prehash: false });\n\t\treturn res;\n\t}\n\n\t/**\n\t * Verify reports whether sig is a valid signature of block by publicKey.\n\t * @param publicKey The public key to verify the signature.\n\t * @param block The block for the signature.\n\t * @param signature The signature.\n\t * @returns True if the signature matches.\n\t * @throws Error if the public key is not the correct length.\n\t */\n\tpublic static verify(publicKey: Uint8Array, block: Uint8Array, signature: Uint8Array): boolean {\n\t\tGuards.uint8Array(Secp256k1.CLASS_NAME, nameof(publicKey), publicKey);\n\t\tGuards.uint8Array(Secp256k1.CLASS_NAME, nameof(block), block);\n\t\tGuards.uint8Array(Secp256k1.CLASS_NAME, nameof(signature), signature);\n\n\t\tif (publicKey.length !== Secp256k1.PUBLIC_KEY_SIZE) {\n\t\t\tthrow new GeneralError(Secp256k1.CLASS_NAME, \"publicKeyLength\", {\n\t\t\t\trequiredSize: Secp256k1.PUBLIC_KEY_SIZE,\n\t\t\t\tactualSize: publicKey ? publicKey.length : 0\n\t\t\t});\n\t\t}\n\n\t\ttry {\n\t\t\treturn secp256k1.verify(signature, block, publicKey, { prehash: false });\n\t\t} catch {\n\t\t\treturn false;\n\t\t}\n\t}\n}\n"]}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
// Copyright 2024 IOTA Stiftung.
|
|
2
|
+
// SPDX-License-Identifier: Apache-2.0.
|
|
3
|
+
import { ed25519 } from "@noble/curves/ed25519.js";
|
|
4
|
+
import { Guards } from "@twin.org/core";
|
|
5
|
+
import { Ed25519 } from "./ed25519.js";
|
|
6
|
+
/**
|
|
7
|
+
* Implementation of X25519.
|
|
8
|
+
*/
|
|
9
|
+
export class X25519 {
|
|
10
|
+
/**
|
|
11
|
+
* Runtime name for the class.
|
|
12
|
+
*/
|
|
13
|
+
static CLASS_NAME = "X25519";
|
|
14
|
+
/**
|
|
15
|
+
* Convert Ed25519 private key to X25519 private key.
|
|
16
|
+
* @param ed25519PrivateKey The ed25519 private key to convert.
|
|
17
|
+
* @returns The x25519 private key.
|
|
18
|
+
*/
|
|
19
|
+
static convertPrivateKeyToX25519(ed25519PrivateKey) {
|
|
20
|
+
Guards.uint8Array(X25519.CLASS_NAME, "ed25519PrivateKey", ed25519PrivateKey);
|
|
21
|
+
return ed25519.utils.toMontgomerySecret(ed25519PrivateKey.slice(0, Ed25519.PRIVATE_KEY_SIZE));
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Convert Ed25519 public key to X25519 public key.
|
|
25
|
+
* @param ed25519PublicKey The ed25519 public key to convert.
|
|
26
|
+
* @returns The x25519 public key.
|
|
27
|
+
* @throws GeneralError On invalid public key.
|
|
28
|
+
*/
|
|
29
|
+
static convertPublicKeyToX25519(ed25519PublicKey) {
|
|
30
|
+
Guards.uint8Array(X25519.CLASS_NAME, "ed25519PublicKey", ed25519PublicKey);
|
|
31
|
+
return ed25519.utils.toMontgomery(ed25519PublicKey);
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
//# sourceMappingURL=x25519.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"x25519.js","sourceRoot":"","sources":["../../../src/curves/x25519.ts"],"names":[],"mappings":"AAAA,gCAAgC;AAChC,uCAAuC;AACvC,OAAO,EAAE,OAAO,EAAE,MAAM,0BAA0B,CAAC;AACnD,OAAO,EAAE,MAAM,EAAE,MAAM,gBAAgB,CAAC;AAExC,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AAEvC;;GAEG;AACH,MAAM,OAAO,MAAM;IAClB;;OAEG;IACI,MAAM,CAAU,UAAU,YAA4B;IAE7D;;;;OAIG;IACI,MAAM,CAAC,yBAAyB,CAAC,iBAA6B;QACpE,MAAM,CAAC,UAAU,CAAC,MAAM,CAAC,UAAU,uBAA6B,iBAAiB,CAAC,CAAC;QACnF,OAAO,OAAO,CAAC,KAAK,CAAC,kBAAkB,CAAC,iBAAiB,CAAC,KAAK,CAAC,CAAC,EAAE,OAAO,CAAC,gBAAgB,CAAC,CAAC,CAAC;IAC/F,CAAC;IAED;;;;;OAKG;IACI,MAAM,CAAC,wBAAwB,CAAC,gBAA4B;QAClE,MAAM,CAAC,UAAU,CAAC,MAAM,CAAC,UAAU,sBAA4B,gBAAgB,CAAC,CAAC;QACjF,OAAO,OAAO,CAAC,KAAK,CAAC,YAAY,CAAC,gBAAgB,CAAC,CAAC;IACrD,CAAC","sourcesContent":["// Copyright 2024 IOTA Stiftung.\n// SPDX-License-Identifier: Apache-2.0.\nimport { ed25519 } from \"@noble/curves/ed25519.js\";\nimport { Guards } from \"@twin.org/core\";\nimport { nameof } from \"@twin.org/nameof\";\nimport { Ed25519 } from \"./ed25519.js\";\n\n/**\n * Implementation of X25519.\n */\nexport class X25519 {\n\t/**\n\t * Runtime name for the class.\n\t */\n\tpublic static readonly CLASS_NAME: string = nameof<X25519>();\n\n\t/**\n\t * Convert Ed25519 private key to X25519 private key.\n\t * @param ed25519PrivateKey The ed25519 private key to convert.\n\t * @returns The x25519 private key.\n\t */\n\tpublic static convertPrivateKeyToX25519(ed25519PrivateKey: Uint8Array): Uint8Array {\n\t\tGuards.uint8Array(X25519.CLASS_NAME, nameof(ed25519PrivateKey), ed25519PrivateKey);\n\t\treturn ed25519.utils.toMontgomerySecret(ed25519PrivateKey.slice(0, Ed25519.PRIVATE_KEY_SIZE));\n\t}\n\n\t/**\n\t * Convert Ed25519 public key to X25519 public key.\n\t * @param ed25519PublicKey The ed25519 public key to convert.\n\t * @returns The x25519 public key.\n\t * @throws GeneralError On invalid public key.\n\t */\n\tpublic static convertPublicKeyToX25519(ed25519PublicKey: Uint8Array): Uint8Array {\n\t\tGuards.uint8Array(X25519.CLASS_NAME, nameof(ed25519PublicKey), ed25519PublicKey);\n\t\treturn ed25519.utils.toMontgomery(ed25519PublicKey);\n\t}\n}\n"]}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
// Copyright 2024 IOTA Stiftung.
|
|
2
|
+
// SPDX-License-Identifier: Apache-2.0.
|
|
3
|
+
import { ed25519 } from "@noble/curves/ed25519.js";
|
|
4
|
+
import { Guards } from "@twin.org/core";
|
|
5
|
+
import { Ed25519 } from "./ed25519.js";
|
|
6
|
+
/**
|
|
7
|
+
* Implementation of Zip215.
|
|
8
|
+
*/
|
|
9
|
+
export class Zip215 {
|
|
10
|
+
/**
|
|
11
|
+
* Runtime name for the class.
|
|
12
|
+
*/
|
|
13
|
+
static CLASS_NAME = "Zip215";
|
|
14
|
+
/**
|
|
15
|
+
* Verify reports whether sig is a valid signature of block by
|
|
16
|
+
* publicKey, using precisely-specified validation criteria (ZIP 215) suitable
|
|
17
|
+
* for use in consensus-critical contexts.
|
|
18
|
+
* @param publicKey The public key for the block.
|
|
19
|
+
* @param block The block content to validate.
|
|
20
|
+
* @param sig The signature to verify.
|
|
21
|
+
* @returns True if the signature is valid.
|
|
22
|
+
*/
|
|
23
|
+
static verify(publicKey, block, sig) {
|
|
24
|
+
Guards.uint8Array(Zip215.CLASS_NAME, "publicKey", publicKey);
|
|
25
|
+
Guards.uint8Array(Zip215.CLASS_NAME, "block", block);
|
|
26
|
+
Guards.uint8Array(Zip215.CLASS_NAME, "sig", sig);
|
|
27
|
+
if (publicKey.length !== Ed25519.PUBLIC_KEY_SIZE) {
|
|
28
|
+
return false;
|
|
29
|
+
}
|
|
30
|
+
return ed25519.verify(sig, block, publicKey, { zip215: true });
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
//# sourceMappingURL=zip215.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"zip215.js","sourceRoot":"","sources":["../../../src/curves/zip215.ts"],"names":[],"mappings":"AAAA,gCAAgC;AAChC,uCAAuC;AACvC,OAAO,EAAE,OAAO,EAAE,MAAM,0BAA0B,CAAC;AACnD,OAAO,EAAE,MAAM,EAAE,MAAM,gBAAgB,CAAC;AAExC,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AAEvC;;GAEG;AACH,MAAM,OAAO,MAAM;IAClB;;OAEG;IACI,MAAM,CAAU,UAAU,YAA4B;IAE7D;;;;;;;;OAQG;IACI,MAAM,CAAC,MAAM,CAAC,SAAqB,EAAE,KAAiB,EAAE,GAAe;QAC7E,MAAM,CAAC,UAAU,CAAC,MAAM,CAAC,UAAU,eAAqB,SAAS,CAAC,CAAC;QACnE,MAAM,CAAC,UAAU,CAAC,MAAM,CAAC,UAAU,WAAiB,KAAK,CAAC,CAAC;QAC3D,MAAM,CAAC,UAAU,CAAC,MAAM,CAAC,UAAU,SAAe,GAAG,CAAC,CAAC;QACvD,IAAI,SAAS,CAAC,MAAM,KAAK,OAAO,CAAC,eAAe,EAAE,CAAC;YAClD,OAAO,KAAK,CAAC;QACd,CAAC;QACD,OAAO,OAAO,CAAC,MAAM,CAAC,GAAG,EAAE,KAAK,EAAE,SAAS,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC;IAChE,CAAC","sourcesContent":["// Copyright 2024 IOTA Stiftung.\n// SPDX-License-Identifier: Apache-2.0.\nimport { ed25519 } from \"@noble/curves/ed25519.js\";\nimport { Guards } from \"@twin.org/core\";\nimport { nameof } from \"@twin.org/nameof\";\nimport { Ed25519 } from \"./ed25519.js\";\n\n/**\n * Implementation of Zip215.\n */\nexport class Zip215 {\n\t/**\n\t * Runtime name for the class.\n\t */\n\tpublic static readonly CLASS_NAME: string = nameof<Zip215>();\n\n\t/**\n\t * Verify reports whether sig is a valid signature of block by\n\t * publicKey, using precisely-specified validation criteria (ZIP 215) suitable\n\t * for use in consensus-critical contexts.\n\t * @param publicKey The public key for the block.\n\t * @param block The block content to validate.\n\t * @param sig The signature to verify.\n\t * @returns True if the signature is valid.\n\t */\n\tpublic static verify(publicKey: Uint8Array, block: Uint8Array, sig: Uint8Array): boolean {\n\t\tGuards.uint8Array(Zip215.CLASS_NAME, nameof(publicKey), publicKey);\n\t\tGuards.uint8Array(Zip215.CLASS_NAME, nameof(block), block);\n\t\tGuards.uint8Array(Zip215.CLASS_NAME, nameof(sig), sig);\n\t\tif (publicKey.length !== Ed25519.PUBLIC_KEY_SIZE) {\n\t\t\treturn false;\n\t\t}\n\t\treturn ed25519.verify(sig, block, publicKey, { zip215: true });\n\t}\n}\n"]}
|