From e97d58ed1d02feaefd90108cf683f83adba02e19 Mon Sep 17 00:00:00 2001 From: Angel Castillo Date: Fri, 20 Jan 2023 04:02:45 +0000 Subject: [PATCH 1/4] feat: added Ed25519 EdDSA signature scheme to crypto package based on libsodium --- packages/crypto/AUDIT.md | 9 + packages/crypto/README.md | 3 + packages/crypto/package.json | 2 +- .../crypto/src/Bip32/Bip32KeyDerivation.ts | 175 +++++++++ .../crypto/src/Ed25519e/Ed25519KeyHash.ts | 57 +++ .../crypto/src/Ed25519e/Ed25519PrivateKey.ts | 183 +++++++++ .../crypto/src/Ed25519e/Ed25519PublicKey.ts | 83 ++++ .../crypto/src/Ed25519e/Ed25519Signature.ts | 57 +++ packages/crypto/src/Ed25519e/index.ts | 4 + .../test/ed25519e/Ed25519KeyHash.test.ts | 23 ++ .../test/ed25519e/Ed25519PrivateKey.test.ts | 116 ++++++ .../test/ed25519e/Ed25519PublicKey.test.ts | 64 ++++ .../test/ed25519e/Ed25519Signature.test.ts | 25 ++ .../test/ed25519e/Ed25519TestVectors.ts | 359 ++++++++++++++++++ packages/e2e/package.json | 2 + .../test/web-extension/webpack.config.base.js | 1 + yarn-project.nix | 16 + yarn.lock | 214 ++++++++++- 18 files changed, 1382 insertions(+), 11 deletions(-) create mode 100644 packages/crypto/AUDIT.md create mode 100644 packages/crypto/src/Bip32/Bip32KeyDerivation.ts create mode 100644 packages/crypto/src/Ed25519e/Ed25519KeyHash.ts create mode 100644 packages/crypto/src/Ed25519e/Ed25519PrivateKey.ts create mode 100644 packages/crypto/src/Ed25519e/Ed25519PublicKey.ts create mode 100644 packages/crypto/src/Ed25519e/Ed25519Signature.ts create mode 100644 packages/crypto/src/Ed25519e/index.ts create mode 100644 packages/crypto/test/ed25519e/Ed25519KeyHash.test.ts create mode 100644 packages/crypto/test/ed25519e/Ed25519PrivateKey.test.ts create mode 100644 packages/crypto/test/ed25519e/Ed25519PublicKey.test.ts create mode 100644 packages/crypto/test/ed25519e/Ed25519Signature.test.ts create mode 100644 packages/crypto/test/ed25519e/Ed25519TestVectors.ts diff --git a/packages/crypto/AUDIT.md b/packages/crypto/AUDIT.md new file mode 100644 index 00000000000..abf5f9c5d7f --- /dev/null +++ b/packages/crypto/AUDIT.md @@ -0,0 +1,9 @@ +# Security audit + +The security audit of the libsodium crypto provider is still ongoing, list of current open topics: + +Form PR: https://github.com/input-output-hk/cardano-js-sdk/pull/574 + +- https://github.com/input-output-hk/cardano-js-sdk/pull/574#discussion_r1086409503 +- https://github.com/input-output-hk/cardano-js-sdk/pull/574#discussion_r1085173470 +- https://github.com/input-output-hk/cardano-js-sdk/pull/574#discussion_r1085128396 diff --git a/packages/crypto/README.md b/packages/crypto/README.md index d4e6473b43c..420f4fa85c0 100644 --- a/packages/crypto/README.md +++ b/packages/crypto/README.md @@ -2,3 +2,6 @@ This package provides a set of high level primitives to perform hashing, signature generation/verification, import private keys from BIP39 mnemonics, and derive BIP32-Ed25519 extended signing keys. + +> **Warning** +> The libsodium crypto provider has not yet been audited. Use at this stage is at own risk diff --git a/packages/crypto/package.json b/packages/crypto/package.json index fb35e486485..970db8ddcf3 100644 --- a/packages/crypto/package.json +++ b/packages/crypto/package.json @@ -1,7 +1,7 @@ { "name": "@cardano-sdk/crypto", "version": "0.1.12", - "description": "Cryptographic types and functions for Cardano", + "description": "Cryptographic types and functions for Cardano. Warning: The libsodium crypto provider has not yet been audited. Use at this stage is at own risk", "engines": { "node": ">=16.20.1" }, diff --git a/packages/crypto/src/Bip32/Bip32KeyDerivation.ts b/packages/crypto/src/Bip32/Bip32KeyDerivation.ts new file mode 100644 index 00000000000..5d07adcf86b --- /dev/null +++ b/packages/crypto/src/Bip32/Bip32KeyDerivation.ts @@ -0,0 +1,175 @@ +import { BN } from 'bn.js'; +import { InvalidArgumentError } from '../errors'; +import { crypto_auth_hmacsha512, crypto_scalarmult_ed25519_base_noclamp } from 'libsodium-wrappers-sumo'; +import { eddsa } from 'elliptic'; + +const ed25519 = new eddsa('ed25519'); + +/** + * Check if the index is hardened. + * + * @param index The index to verify. + * @returns true if hardened; otherwise; false. + */ +const isHardenedDerivation = (index: number) => index >= 0x80_00_00_00; + +/** + * Derives the private key with a hardened index. + * + * @param index The derivation index. + * @param scalar Ed25519 curve scalar. + * @param iv Ed25519 binary blob used as IV for signing. + * @param chainCode The chain code. + */ +const deriveHardened = ( + index: number, + scalar: Buffer, + iv: Buffer, + chainCode: Buffer +): { zMac: Uint8Array; ccMac: Uint8Array } => { + const data = Buffer.allocUnsafe(1 + 64 + 4); + data.writeUInt32LE(index, 1 + 64); + scalar.copy(data, 1); + iv.copy(data, 1 + 32); + + data[0] = 0x00; + const zMac = crypto_auth_hmacsha512(data, chainCode); + data[0] = 0x01; + const ccMac = crypto_auth_hmacsha512(data, chainCode); + + return { ccMac, zMac }; +}; + +/** + * Derives the private key with a 'soft' index. + * + * @param index The derivation index. + * @param scalar Ed25519 curve scalar. + * @param chainCode The chain code. + */ +const deriveSoft = (index: number, scalar: Buffer, chainCode: Buffer): { zMac: Uint8Array; ccMac: Uint8Array } => { + const data = Buffer.allocUnsafe(1 + 32 + 4); + data.writeUInt32LE(index, 1 + 32); + + const vk = Buffer.from(crypto_scalarmult_ed25519_base_noclamp(scalar)); + + vk.copy(data, 1); + + data[0] = 0x02; + const zMac = crypto_auth_hmacsha512(data, chainCode); + data[0] = 0x03; + const ccMac = crypto_auth_hmacsha512(data, chainCode); + + return { ccMac, zMac }; +}; + +/** + * Adds the left hand side to 28 bytes of the right hand side and multiplies the result by 8. + * + * @param lhs Left hand side Little-Endian big number. + * @param rhs Right hand side Little-Endian big number. + */ +const truc28Mul8 = (lhs: Uint8Array, rhs: Uint8Array): Buffer => + new BN(lhs, 16, 'le').add(new BN(rhs.slice(0, 28), 16, 'le').mul(new BN(8))).toArrayLike(Buffer, 'le', 32); + +/** + * Computes `(8 * sk[:28])*G` where `sk` is a little-endian encoded int and `G` is the curve's base point. + * + * @param sk The secret key. + */ +const pointOfTrunc28Mul8 = (sk: Uint8Array) => { + const left = new BN(sk.slice(0, 28), 16, 'le').mul(new BN(8)); + return ed25519.curve.g.mul(left); +}; + +/** + * Adds the left hand side to the right hand side. + * + * @param lhs Left hand side Little-Endian big number. + * @param rhs Right hand side Little-Endian big number. + */ +const add = (lhs: Uint8Array, rhs: Uint8Array): Buffer => { + let r = new BN(lhs, 16, 'le').add(new BN(rhs, 16, 'le')).toArrayLike(Buffer, 'le').subarray(0, 32); + + if (r.length !== 32) { + r = Buffer.from(r.toString('hex').padEnd(32, '0'), 'hex'); + } + + return r; +}; + +/** + * Derive the given private key with the given index. + * + * # Security considerations + * + * hard derivation index cannot be soft derived with the public key. + * + * # Hard derivation vs Soft derivation + * + * If you pass an index below 0x80000000 then it is a soft derivation. + * The advantage of soft derivation is that it is possible to derive the + * public key too. I.e. derivation the private key with a soft derivation + * index and then retrieving the associated public key is equivalent to + * deriving the public key associated to the parent private key. + * + * Hard derivation index does not allow public key derivation. + * + * This is why deriving the private key should not fail while deriving + * the public key may fail (if the derivation index is invalid). + * + * @param key The parent key to be derived. + * @param index The derivation index. + * @returns The child BIP32 key. + */ +export const derivePrivate = (key: Buffer, index: number): Buffer => { + const kl = key.subarray(0, 32); + const kr = key.subarray(32, 64); + const cc = key.subarray(64, 96); + + const { ccMac, zMac } = isHardenedDerivation(index) ? deriveHardened(index, kl, kr, cc) : deriveSoft(index, kl, cc); + + const chainCode = ccMac.slice(32, 64); + const zl = zMac.slice(0, 32); + const zr = zMac.slice(32, 64); + + const left = truc28Mul8(kl, zl); + const right = add(kr, zr); + + return Buffer.concat([left, right, chainCode]); +}; + +/** + * Derive the given public key with the given index. + * + * Public key derivation is only possible with non-hardened indices. + * + * @param key The parent key to be derived. + * @param index The derivation index. + * @returns The child BIP32 key. + */ +export const derivePublic = (key: Buffer, index: number): Buffer => { + const pk = key.subarray(0, 32); + const cc = key.subarray(32, 64); + + const data = Buffer.allocUnsafe(1 + 32 + 4); + data.writeUInt32LE(index, 1 + 32); + + if (isHardenedDerivation(index)) + throw new InvalidArgumentError('index', 'Public key can not be derived from a hardened index.'); + + pk.copy(data, 1); + data[0] = 0x02; + const z = crypto_auth_hmacsha512(data, cc); + data[0] = 0x03; + const c = crypto_auth_hmacsha512(data, cc); + + const chainCode = c.slice(32, 64); + const zl = z.slice(0, 32); + + const p = pointOfTrunc28Mul8(zl); + const pp = ed25519.decodePoint(pk.toString('hex')); + const point = pp.add(p); + + return Buffer.concat([Buffer.from(ed25519.encodePoint(point)), chainCode]); +}; diff --git a/packages/crypto/src/Ed25519e/Ed25519KeyHash.ts b/packages/crypto/src/Ed25519e/Ed25519KeyHash.ts new file mode 100644 index 00000000000..ee0b3dd247a --- /dev/null +++ b/packages/crypto/src/Ed25519e/Ed25519KeyHash.ts @@ -0,0 +1,57 @@ +import { Ed25519KeyHashHex } from '../hexTypes'; +import { InvalidArgumentError } from '@cardano-sdk/util'; + +export const ED25519_PUBLIC_KEY_HASH_LENGTH = 28; + +/** + * The computed cryptographic hash of an Ed25519 Key with the Blake2b hashing algorithm. + */ +export class Ed25519KeyHash { + readonly #hash: Uint8Array; + + /** + * Initializes a new instance of the Ed25519KeyHash class. + * + * @param hash The ED25519 public key hash. + */ + private constructor(hash: Uint8Array) { + this.#hash = hash; + } + + /** + * Initializes a new Ed25519KeyHash provided as a byte array. + * + * @param hash The Ed25519 key hash. + */ + static fromBytes(hash: Uint8Array) { + if (hash.length !== ED25519_PUBLIC_KEY_HASH_LENGTH) + throw new InvalidArgumentError( + 'hash', + `Hash should be ${ED25519_PUBLIC_KEY_HASH_LENGTH} bytes; however ${hash.length} bytes were provided.` + ); + return new Ed25519KeyHash(hash); + } + + /** + * Initializes a new instance of the Ed25519KeyHash class from its hash provided as a hex string. + * + * @param hash The hash as a hex string. + */ + static fromHex(hash: Ed25519KeyHashHex) { + return Ed25519KeyHash.fromBytes(Buffer.from(hash, 'hex')); + } + + /** + * Gets the Ed25519KeyHash as a byte array. + */ + bytes(): Uint8Array { + return this.#hash; + } + + /** + * Gets the Ed25519KeyHash as a hex string. + */ + hex(): Ed25519KeyHashHex { + return Ed25519KeyHashHex(Buffer.from(this.#hash).toString('hex')); + } +} diff --git a/packages/crypto/src/Ed25519e/Ed25519PrivateKey.ts b/packages/crypto/src/Ed25519e/Ed25519PrivateKey.ts new file mode 100644 index 00000000000..69e2f5a0dea --- /dev/null +++ b/packages/crypto/src/Ed25519e/Ed25519PrivateKey.ts @@ -0,0 +1,183 @@ +/* eslint-disable no-bitwise */ +import { Ed25519PrivateExtendedKeyHex, Ed25519PrivateNormalKeyHex } from '../hexTypes'; +import { Ed25519PublicKey } from './Ed25519PublicKey'; +import { Ed25519Signature } from './Ed25519Signature'; +import { HexBlob, InvalidArgumentError } from '@cardano-sdk/util'; +import { + crypto_core_ed25519_scalar_add, + crypto_core_ed25519_scalar_mul, + crypto_core_ed25519_scalar_reduce, + crypto_hash_sha512, + crypto_scalarmult_ed25519_base_noclamp, + crypto_sign_detached, + crypto_sign_seed_keypair, + ready +} from 'libsodium-wrappers-sumo'; + +const SCALAR_INDEX = 0; +const SCALAR_SIZE = 32; +const IV_INDEX = 32; +const IV_SIZE = 32; + +export const NORMAL_ED25519_PRIVATE_KEY_LENGTH = 32; +export const EXTENDED_ED25519_PRIVATE_KEY_LENGTH = 64; + +/** + * Extract the scalar part (first 32 bytes) from the extended key. + * + * @param extendedKey The extended key. + * @returns the scalar part of the extended key. + */ +const extendedScalar = (extendedKey: Uint8Array) => extendedKey.slice(SCALAR_INDEX, SCALAR_SIZE); + +/** + * Extract the random part (last 32 bytes) from the extended key to be used as IV for signing. + * + * @param extendedKey The extended key. + * @returns the random part of the extended key. + */ +const extendedIv = (extendedKey: Uint8Array) => extendedKey.slice(IV_INDEX, IV_INDEX + IV_SIZE); + +/** + * Creates a detached Ed25519 digital signatures using libSodium elliptic curve primitives. + * + * @param extendedKey The extended secret. + * @param message The message to be signed. + */ +const signExtendedDetached = (extendedKey: Uint8Array, message: Uint8Array) => { + const scalar = extendedScalar(extendedKey); + const publicKey = crypto_scalarmult_ed25519_base_noclamp(scalar); + const nonce = crypto_core_ed25519_scalar_reduce( + crypto_hash_sha512(Buffer.concat([extendedIv(extendedKey), message])) + ); + + const r = crypto_scalarmult_ed25519_base_noclamp(nonce); + + let hram = crypto_hash_sha512(Buffer.concat([r, publicKey, message])); + hram = crypto_core_ed25519_scalar_reduce(hram); + + return Buffer.concat([r, crypto_core_ed25519_scalar_add(crypto_core_ed25519_scalar_mul(hram, scalar), nonce)]); +}; + +/** + * Ed25519 private key type. + */ +export enum Ed25519PrivateKeyType { + Normal = 'Normal', + Extended = 'Extended' +} + +/** + * Ed25519 raw private key. This key can be used for cryptographically signing messages. + */ +export class Ed25519PrivateKey { + readonly #keyMaterial: Uint8Array; + readonly __type: Ed25519PrivateKeyType; + + /** + * Initializes a new instance of the Ed25519PrivateKey class. + * + * @param keyMaterial The key Ed25519 private key material. + * @param type The ley type (Normal or Extended). + */ + private constructor(keyMaterial: Uint8Array, type: Ed25519PrivateKeyType) { + this.#keyMaterial = keyMaterial; + this.__type = type; + } + + /** + * Computes the raw public key from this raw private key. + * + * @returns the public key. + */ + async toPublic(): Promise { + await ready; + + return Ed25519PublicKey.fromBytes( + this.__type === Ed25519PrivateKeyType.Extended + ? crypto_scalarmult_ed25519_base_noclamp(extendedScalar(this.#keyMaterial)) + : crypto_sign_seed_keypair(this.#keyMaterial).publicKey + ); + } + + /** + * Generates an Ed25519 signature. + * + * @param message The message to be signed. + * @returns The Ed25519 digital signature. + */ + async sign(message: HexBlob): Promise { + await ready; + return Ed25519Signature.fromBytes( + this.__type === Ed25519PrivateKeyType.Extended + ? signExtendedDetached(this.#keyMaterial, Buffer.from(message, 'hex')) + : crypto_sign_detached( + Buffer.from(message, 'hex'), + Buffer.concat([this.#keyMaterial, (await this.toPublic()).bytes()]) + ) + ); + } + + /** + * Initializes a new Normal Ed25519PrivateKey from its key material provided as a byte array. + * + * @param keyMaterial The key material. + */ + static fromNormalBytes(keyMaterial: Uint8Array): Ed25519PrivateKey { + if (keyMaterial.length !== NORMAL_ED25519_PRIVATE_KEY_LENGTH) + throw new InvalidArgumentError( + 'keyMaterial', + `Key should be ${NORMAL_ED25519_PRIVATE_KEY_LENGTH} bytes; however ${keyMaterial.length} bytes were provided.` + ); + + return new Ed25519PrivateKey(keyMaterial, Ed25519PrivateKeyType.Normal); + } + + /** + * Initializes a new Extended Ed25519PrivateKey from its key material provided as a byte array. + * + * @param keyMaterial The key material. + */ + static fromExtendedBytes(keyMaterial: Uint8Array): Ed25519PrivateKey { + if (keyMaterial.length !== EXTENDED_ED25519_PRIVATE_KEY_LENGTH) + throw new InvalidArgumentError( + 'keyMaterial', + `Key should be ${EXTENDED_ED25519_PRIVATE_KEY_LENGTH} bytes; however ${keyMaterial.length} bytes were provided.` + ); + return new Ed25519PrivateKey(keyMaterial, Ed25519PrivateKeyType.Extended); + } + + /** + * Initializes a new Normal Ed25519PrivateKey from its key material provided as a hex string. + * + * @param keyMaterial The key material as a hex string. + */ + static fromNormalHex(keyMaterial: Ed25519PrivateNormalKeyHex): Ed25519PrivateKey { + return Ed25519PrivateKey.fromNormalBytes(Buffer.from(keyMaterial, 'hex')); + } + + /** + * Initializes a new Extended Ed25519PrivateKey from its key material provided as a hex string. + * + * @param keyMaterial The key material as a hex string. + */ + static fromExtendedHex(keyMaterial: Ed25519PrivateExtendedKeyHex): Ed25519PrivateKey { + return Ed25519PrivateKey.fromExtendedBytes(Buffer.from(keyMaterial, 'hex')); + } + + /** + * Gets the Ed25519PrivateKey key material as a byte array. + */ + bytes(): Uint8Array { + return this.#keyMaterial; + } + + /** + * Gets the Ed25519PrivateKey key material as a hex string. + */ + hex(): Ed25519PrivateNormalKeyHex | Ed25519PrivateExtendedKeyHex { + return this.__type === Ed25519PrivateKeyType.Extended + ? Ed25519PrivateExtendedKeyHex(Buffer.from(this.#keyMaterial).toString('hex')) + : Ed25519PrivateNormalKeyHex(Buffer.from(this.#keyMaterial).toString('hex')); + } +} diff --git a/packages/crypto/src/Ed25519e/Ed25519PublicKey.ts b/packages/crypto/src/Ed25519e/Ed25519PublicKey.ts new file mode 100644 index 00000000000..e5d17d7ac03 --- /dev/null +++ b/packages/crypto/src/Ed25519e/Ed25519PublicKey.ts @@ -0,0 +1,83 @@ +import { ED25519_PUBLIC_KEY_HASH_LENGTH, Ed25519KeyHash } from './Ed25519KeyHash'; +import { Ed25519PublicKeyHex } from '../hexTypes'; +import { Ed25519Signature } from './Ed25519Signature'; +import { HexBlob, InvalidArgumentError } from '@cardano-sdk/util'; +import { crypto_generichash, crypto_sign_verify_detached, ready } from 'libsodium-wrappers-sumo'; + +export const ED25519_PUBLIC_KEY_LENGTH = 32; + +/** + * Ed25519 raw public key. This key can be used for cryptographically verifying messages + * previously signed with the matching Ed25519 raw private key. + */ +export class Ed25519PublicKey { + readonly #keyMaterial: Uint8Array; + + /** + * Initializes a new instance of the Ed25519PublicKey class. + * + * @param keyMaterial The key Ed25519 Public key material. + */ + constructor(keyMaterial: Uint8Array) { + this.#keyMaterial = keyMaterial; + } + + /** + * Verifies that the passed-in signature was generated with a private key that matches + * the given public key. + * + * @param signature The signature bytes to be verified. + * @param message The original message the signature was computed from. + * @returns true if the signature is valid; otherwise; false. + */ + async verify(signature: Ed25519Signature, message: HexBlob): Promise { + await ready; + return crypto_sign_verify_detached(signature.bytes(), Buffer.from(message, 'hex'), this.#keyMaterial); + } + + /** + * Initializes a new Ed25519PublicKey from its key material provided as a byte array. + * + * @param keyMaterial The key material. + */ + static fromBytes(keyMaterial: Uint8Array) { + if (keyMaterial.length !== ED25519_PUBLIC_KEY_LENGTH) + throw new InvalidArgumentError( + 'keyMaterial', + `Key should be ${ED25519_PUBLIC_KEY_LENGTH} bytes; however ${keyMaterial.length} bytes were provided.` + ); + return new Ed25519PublicKey(keyMaterial); + } + + /** + * Initializes a new Ed25519PublicKey from its key material provided as a hex string. + * + * @param keyMaterial The key material as a hex string. + */ + static fromHex(keyMaterial: Ed25519PublicKeyHex) { + return Ed25519PublicKey.fromBytes(Buffer.from(keyMaterial, 'hex')); + } + + /** + * Gets the blake2 hash of the key material. + */ + async hash(): Promise { + await ready; + const hash = crypto_generichash(ED25519_PUBLIC_KEY_HASH_LENGTH, this.#keyMaterial); + return Ed25519KeyHash.fromBytes(hash); + } + + /** + * Gets the Ed25519PublicKey key material as a byte array. + */ + bytes(): Uint8Array { + return this.#keyMaterial; + } + + /** + * Gets the Ed25519PublicKey key material as a hex string. + */ + hex(): Ed25519PublicKeyHex { + return Ed25519PublicKeyHex(Buffer.from(this.#keyMaterial).toString('hex')); + } +} diff --git a/packages/crypto/src/Ed25519e/Ed25519Signature.ts b/packages/crypto/src/Ed25519e/Ed25519Signature.ts new file mode 100644 index 00000000000..1e4ba58a291 --- /dev/null +++ b/packages/crypto/src/Ed25519e/Ed25519Signature.ts @@ -0,0 +1,57 @@ +import { Ed25519SignatureHex } from '../hexTypes'; +import { InvalidArgumentError } from '@cardano-sdk/util'; + +export const ED25519_SIGNATURE_LENGTH = 64; + +/** + * Ed25519 cryptographic digital signature. + */ +export class Ed25519Signature { + readonly #signature: Uint8Array; + + /** + * Initializes a new instance of the Ed25519Signature class. + * + * @param signature The bip32 private key. + */ + constructor(signature: Uint8Array) { + this.#signature = signature; + } + + /** + * Initializes a new Ed25519Signature provided as a byte array. + * + * @param signature The Ed25519 signature. + */ + static fromBytes(signature: Uint8Array) { + if (signature.length !== ED25519_SIGNATURE_LENGTH) + throw new InvalidArgumentError( + 'signature', + `signature should be ${ED25519_SIGNATURE_LENGTH} bytes; however ${signature.length} bytes were provided.` + ); + return new Ed25519Signature(signature); + } + + /** + * Initializes a new instance of the Ed25519Signature class from its signature provided as a hex string. + * + * @param signature The signature as a hex string. + */ + static fromHex(signature: Ed25519SignatureHex) { + return Ed25519Signature.fromBytes(Buffer.from(signature, 'hex')); + } + + /** + * Gets the Ed25519Signature as a byte array. + */ + bytes(): Uint8Array { + return this.#signature; + } + + /** + * Gets the Ed25519Signature as a hex string. + */ + hex(): Ed25519SignatureHex { + return Ed25519SignatureHex(Buffer.from(this.#signature).toString('hex')); + } +} diff --git a/packages/crypto/src/Ed25519e/index.ts b/packages/crypto/src/Ed25519e/index.ts new file mode 100644 index 00000000000..b86865c06d4 --- /dev/null +++ b/packages/crypto/src/Ed25519e/index.ts @@ -0,0 +1,4 @@ +export * from './Ed25519PrivateKey'; +export * from './Ed25519PublicKey'; +export * from './Ed25519Signature'; +export * from './Ed25519KeyHash'; diff --git a/packages/crypto/test/ed25519e/Ed25519KeyHash.test.ts b/packages/crypto/test/ed25519e/Ed25519KeyHash.test.ts new file mode 100644 index 00000000000..622842fb7c7 --- /dev/null +++ b/packages/crypto/test/ed25519e/Ed25519KeyHash.test.ts @@ -0,0 +1,23 @@ +import * as Crypto from '../../src'; +import { Ed25519KeyHashHex } from '../../src'; +import { InvalidStringError } from '@cardano-sdk/util'; + +describe('Ed25519KeyHash', () => { + const kEY_HASH = 'b275b08c999097247f7c17e77007c7010cd19f20cc086ad99d398538'; + + it('can create an instance from a valid key hash hex representation', () => { + const signature = Crypto.Ed25519KeyHash.fromHex(Ed25519KeyHashHex(kEY_HASH)); + expect(signature.hex()).toBe(kEY_HASH); + }); + + test('can create an instance from a valid key hash raw binary representation', () => { + const sigBytes = Buffer.from(kEY_HASH, 'hex'); + const signature = Crypto.Ed25519KeyHash.fromBytes(sigBytes); + expect(signature.bytes()).toBe(sigBytes); + }); + + test('throws if a key hash of invalid size is given.', () => { + expect(() => Crypto.Ed25519KeyHash.fromHex(Ed25519KeyHashHex('1f'))).toThrow(InvalidStringError); + expect(() => Crypto.Ed25519KeyHash.fromHex(Ed25519KeyHashHex(`${kEY_HASH}1f2f3f`))).toThrow(InvalidStringError); + }); +}); diff --git a/packages/crypto/test/ed25519e/Ed25519PrivateKey.test.ts b/packages/crypto/test/ed25519e/Ed25519PrivateKey.test.ts new file mode 100644 index 00000000000..8d1c942fb49 --- /dev/null +++ b/packages/crypto/test/ed25519e/Ed25519PrivateKey.test.ts @@ -0,0 +1,116 @@ +import * as Crypto from '../../src'; +import { HexBlob, InvalidStringError } from '@cardano-sdk/util'; +import { + bip32TestVectorMessageOneLength, + extendedVectors, + testVectorMessageZeroLength, + vectors +} from './Ed25519TestVectors'; + +describe('Ed25519PrivateKey', () => { + it('can create an instance from a valid normal Ed25519 private key hex representation', () => { + const privateKey = Crypto.Ed25519PrivateKey.fromNormalHex( + Crypto.Ed25519PrivateNormalKeyHex(testVectorMessageZeroLength.secretKey) + ); + + expect(privateKey.hex()).toBe(testVectorMessageZeroLength.secretKey); + }); + + it('can create an instance from a valid extended Ed25519 private key hex representation', () => { + const privateKey = Crypto.Ed25519PrivateKey.fromExtendedHex( + Crypto.Ed25519PrivateExtendedKeyHex(bip32TestVectorMessageOneLength.ed25519eVector.secretKey) + ); + + expect(privateKey.hex()).toBe(bip32TestVectorMessageOneLength.ed25519eVector.secretKey); + }); + + it('can create an instance from a valid normal Ed25519 private key raw binary representation', () => { + const bytes = Buffer.from(testVectorMessageZeroLength.secretKey, 'hex'); + const privateKey = Crypto.Ed25519PrivateKey.fromNormalBytes(bytes); + + expect(privateKey.bytes()).toBe(bytes); + }); + + it('can create an instance from a valid extended Ed25519 private key raw binary representation', () => { + const bytes = Buffer.from(bip32TestVectorMessageOneLength.ed25519eVector.secretKey, 'hex'); + const privateKey = Crypto.Ed25519PrivateKey.fromExtendedBytes(bytes); + + expect(privateKey.bytes()).toBe(bytes); + }); + + it('throws if a Ed25519 private key of invalid size is given.', () => { + expect(() => Crypto.Ed25519PrivateKey.fromNormalHex(Crypto.Ed25519PrivateNormalKeyHex('1f'))).toThrow( + InvalidStringError + ); + expect(() => Crypto.Ed25519PrivateKey.fromExtendedHex(Crypto.Ed25519PrivateExtendedKeyHex('1f'))).toThrow( + InvalidStringError + ); + expect(() => + Crypto.Ed25519PrivateKey.fromNormalHex( + Crypto.Ed25519PrivateNormalKeyHex(`${testVectorMessageZeroLength.secretKey}1f2f3f`) + ) + ).toThrow(InvalidStringError); + expect(() => + Crypto.Ed25519PrivateKey.fromExtendedHex( + Crypto.Ed25519PrivateExtendedKeyHex(`${testVectorMessageZeroLength.secretKey}1f2f3f`) + ) + ).toThrow(InvalidStringError); + }); + + it('can compute the public key from a non extended Ed25519 private key.', async () => { + expect.assertions(vectors.length); + + for (const vector of vectors) { + const privateKey = Crypto.Ed25519PrivateKey.fromNormalHex(Crypto.Ed25519PrivateNormalKeyHex(vector.secretKey)); + const publicKey = await privateKey.toPublic(); + + expect(publicKey.hex()).toBe(vector.publicKey); + } + }); + + it('can compute the public key from an extended Ed25519 private key.', async () => { + expect.assertions(extendedVectors.length); + + for (const vector of extendedVectors) { + const privateKey = Crypto.Ed25519PrivateKey.fromExtendedHex( + Crypto.Ed25519PrivateExtendedKeyHex(vector.ed25519eVector.secretKey) + ); + const publicKey = await privateKey.toPublic(); + + expect(publicKey.hex()).toBe(vector.ed25519eVector.publicKey); + } + }); + + it('can compute the correct signature of a message with a non extended Ed25519 private key.', async () => { + expect.assertions(vectors.length * 2); + + for (const vector of vectors) { + const privateKey = Crypto.Ed25519PrivateKey.fromNormalHex(Crypto.Ed25519PrivateNormalKeyHex(vector.secretKey)); + const publicKey = Crypto.Ed25519PublicKey.fromHex(Crypto.Ed25519PublicKeyHex(vector.publicKey)); + const message = HexBlob(vector.message); + const signature = await privateKey.sign(HexBlob(vector.message)); + + const isSignatureValid = await publicKey.verify(signature, message); + expect(signature.hex()).toBe(vector.signature); + expect(isSignatureValid).toBeTruthy(); + } + }); + + it('can compute the correct signature of a message with an extended Ed25519 private key.', async () => { + expect.assertions(extendedVectors.length * 2); + + for (const extendedVector of extendedVectors) { + const vector = extendedVector.ed25519eVector; + const privateKey = Crypto.Ed25519PrivateKey.fromExtendedHex( + Crypto.Ed25519PrivateExtendedKeyHex(vector.secretKey) + ); + const publicKey = Crypto.Ed25519PublicKey.fromHex(Crypto.Ed25519PublicKeyHex(vector.publicKey)); + const message = HexBlob(vector.message); + const signature = await privateKey.sign(HexBlob(vector.message)); + + const isSignatureValid = await publicKey.verify(signature, message); + expect(signature.hex()).toBe(vector.signature); + expect(isSignatureValid).toBeTruthy(); + } + }); +}); diff --git a/packages/crypto/test/ed25519e/Ed25519PublicKey.test.ts b/packages/crypto/test/ed25519e/Ed25519PublicKey.test.ts new file mode 100644 index 00000000000..852d6361ca9 --- /dev/null +++ b/packages/crypto/test/ed25519e/Ed25519PublicKey.test.ts @@ -0,0 +1,64 @@ +import * as Crypto from '../../src'; +import { HexBlob, InvalidStringError } from '@cardano-sdk/util'; +import { InvalidSignature, testVectorMessageZeroLength, vectors } from './Ed25519TestVectors'; + +describe('Ed25519PublicKey', () => { + it('can create an instance from a valid Ed25519 public key hex representation', () => { + const publicKey = Crypto.Ed25519PublicKey.fromHex( + Crypto.Ed25519PublicKeyHex(testVectorMessageZeroLength.publicKey) + ); + + expect(publicKey.hex()).toBe(testVectorMessageZeroLength.publicKey); + }); + + it('can create an instance from a valid Ed25519 public key raw binary representation', () => { + const sigBytes = Buffer.from(testVectorMessageZeroLength.publicKey, 'hex'); + const publicKey = Crypto.Ed25519PublicKey.fromBytes(sigBytes); + + expect(publicKey.bytes()).toBe(sigBytes); + }); + + it('throws if a Ed25519 public key of invalid size is given.', () => { + expect(() => Crypto.Ed25519PublicKey.fromHex(Crypto.Ed25519PublicKeyHex('1f'))).toThrow(InvalidStringError); + expect(() => + Crypto.Ed25519PublicKey.fromHex(Crypto.Ed25519PublicKeyHex(`${testVectorMessageZeroLength.publicKey}1f2f3f`)) + ).toThrow(InvalidStringError); + }); + + it('can compute the right Blake2b hash of an Ed25519 public key', async () => { + expect.assertions(vectors.length); + + for (const vector of vectors) { + const publicKey = Crypto.Ed25519PublicKey.fromHex(Crypto.Ed25519PublicKeyHex(vector.publicKey)); + const hash = (await publicKey.hash()).hex(); + + expect(hash).toBe(vector.publicKeyHash); + } + }); + + it('can verify a Ed25519 digital signature given the right public key and original message', async () => { + expect.assertions(vectors.length); + + for (const vector of vectors) { + const publicKey = Crypto.Ed25519PublicKey.fromHex(Crypto.Ed25519PublicKeyHex(vector.publicKey)); + const signature = Crypto.Ed25519Signature.fromHex(Crypto.Ed25519SignatureHex(vector.signature)); + const message = HexBlob(vector.message); + + const isValid = await publicKey.verify(signature, message); + + expect(isValid).toBeTruthy(); + } + }); + + it('can not verify a Ed25519 digital invalid signature given a public key and a message', async () => { + const publicKey = Crypto.Ed25519PublicKey.fromHex( + Crypto.Ed25519PublicKeyHex(testVectorMessageZeroLength.publicKey) + ); + const signature = Crypto.Ed25519Signature.fromHex(Crypto.Ed25519SignatureHex(InvalidSignature)); + const message = HexBlob(testVectorMessageZeroLength.message); + + const isValid = await publicKey.verify(signature, message); + + expect(isValid).toBeFalsy(); + }); +}); diff --git a/packages/crypto/test/ed25519e/Ed25519Signature.test.ts b/packages/crypto/test/ed25519e/Ed25519Signature.test.ts new file mode 100644 index 00000000000..21a6590fd4c --- /dev/null +++ b/packages/crypto/test/ed25519e/Ed25519Signature.test.ts @@ -0,0 +1,25 @@ +import * as Crypto from '../../src'; +import { InvalidStringError } from '@cardano-sdk/util'; +import { testVectorMessageZeroLength } from './Ed25519TestVectors'; + +describe('Ed25519Signature', () => { + it('can create an instance from a valid Ed25519 signature hex representation', () => { + const signature = Crypto.Ed25519Signature.fromHex( + Crypto.Ed25519SignatureHex(testVectorMessageZeroLength.signature) + ); + expect(signature.hex()).toBe(testVectorMessageZeroLength.signature); + }); + + test('can create an instance from a valid Ed25519 signature raw binary representation', () => { + const sigBytes = Buffer.from(testVectorMessageZeroLength.signature, 'hex'); + const signature = Crypto.Ed25519Signature.fromBytes(sigBytes); + expect(signature.bytes()).toBe(sigBytes); + }); + + test('throws if a signature of invalid size is given.', () => { + expect(() => Crypto.Ed25519Signature.fromHex(Crypto.Ed25519SignatureHex('1f'))).toThrow(InvalidStringError); + expect(() => + Crypto.Ed25519Signature.fromHex(Crypto.Ed25519SignatureHex(`${testVectorMessageZeroLength.signature}1f2f3f`)) + ).toThrow(InvalidStringError); + }); +}); diff --git a/packages/crypto/test/ed25519e/Ed25519TestVectors.ts b/packages/crypto/test/ed25519e/Ed25519TestVectors.ts new file mode 100644 index 00000000000..244b57e717d --- /dev/null +++ b/packages/crypto/test/ed25519e/Ed25519TestVectors.ts @@ -0,0 +1,359 @@ +/** + * Edwards 25519 test vector. + */ +export interface Ed25519TestVector { + /** + * The secret key in hexadecimal representation. + */ + secretKey: string; + /** + * The public key in hexadecimal representation. + */ + publicKey: string; + + /** + * The Blake2b hash of the public key. + */ + publicKeyHash: string; + + /** + * The message to be signed in hexadecimal representation. + */ + message: string; + /** + * The signature in hexadecimal representation. + */ + signature: string; +} + +/** + * BIP-32 Ed25519 test vector. + */ +export interface Bip32Ed25519TestVector { + /** + * The BIP39 entropy generated from a set of mnemonic words. + */ + bip39Entropy: string; + + /** + * Root BIP32 root private key. + */ + rootKey: string; + + /** + * Root BIP32 root public key. + */ + publicKey: string; + + /** + * The BIP32 derived chlid private key. + */ + childPrivateKey: string; + + /** + * The BIP32 derived child public key. + */ + childPublicKey: string; + + /** + * The 2-factor authentication password. + */ + password: string; + + /** + * The BIP32 index chain that derived the extended keys. + */ + derivationPath: number[]; + + /** + * The Edwards 25519 extended vector. + */ + ed25519eVector: Ed25519TestVector; +} + +export const InvalidSignature = + '00000000c360ac729086e2cc806e828a' + + '84877f1000000074d873e06522490155' + + '5fb8821590a33b00000000701cf9b46b' + + 'd25bf5f0595bbe246551410000000000'; + +// These test vectors for non extended keys were taken from https://www.rfc-editor.org/rfc/rfc8032#page-23 and added the +// public key Blake2b key hashes. +export const testVectorMessageZeroLength: Ed25519TestVector = { + message: '', + publicKey: 'd75a980182b10ab7d54bfed3c964073a0ee172f3daa62325af021a68f707511a', + publicKeyHash: '35dedd2982a03cf39e7dce03c839994ffdec2ec6b04f1cf2d40e61a3', + secretKey: '9d61b19deffd5a60ba844af492ec2cc44449c5697b326919703bac031cae7f60', + signature: + 'e5564300c360ac729086e2cc806e828a' + + '84877f1eb8e5d974d873e06522490155' + + '5fb8821590a33bacc61e39701cf9b46b' + + 'd25bf5f0595bbe24655141438e7a100b' +}; + +export const testVectorMessageOneLength: Ed25519TestVector = { + message: '72', + publicKey: '3d4017c3e843895a92b70aa74d1b7ebc9c982ccf2ec4968cc0cd55f12af4660c', + publicKeyHash: '977efb35ab621d39dbeb7274ec7795a34708ff4d25a01a1df04c1f27', + secretKey: '4ccd089b28ff96da9db6c346ec114e0f5b8a319f35aba624da8cf6ed4fb8a6fb', + signature: + '92a009a9f0d4cab8720e820b5f642540' + + 'a2b27b5416503f8fb3762223ebdb69da' + + '085ac1e43e15996e458f3613d0f11d8c' + + '387b2eaeb4302aeeb00d291612bb0c00' +}; + +export const testVectorMessageTwoLength: Ed25519TestVector = { + message: 'af82', + publicKey: 'fc51cd8e6218a1a38da47ed00230f0580816ed13ba3303ac5deb911548908025', + publicKeyHash: '7f8a76c0ebaa4ad20dfdcd51a5de070ab771f4bf377f2c41e6b71c0a', + secretKey: 'c5aa8df43f9f837bedb7442f31dcb7b166d38535076f094b85ce3a2e0b4458f7', + signature: + '6291d657deec24024827e69c3abe01a3' + + '0ce548a284743a445e3680d7db5ac3ac' + + '18ff9b538d16f290ae67f760984dc659' + + '4a7c15e9716ed28dc027beceea1ec40a' +}; + +export const testVectorMessage1023Length: Ed25519TestVector = { + message: + '08b8b2b733424243760fe426a4b54908' + + '632110a66c2f6591eabd3345e3e4eb98' + + 'fa6e264bf09efe12ee50f8f54e9f77b1' + + 'e355f6c50544e23fb1433ddf73be84d8' + + '79de7c0046dc4996d9e773f4bc9efe57' + + '38829adb26c81b37c93a1b270b20329d' + + '658675fc6ea534e0810a4432826bf58c' + + '941efb65d57a338bbd2e26640f89ffbc' + + '1a858efcb8550ee3a5e1998bd177e93a' + + '7363c344fe6b199ee5d02e82d522c4fe' + + 'ba15452f80288a821a579116ec6dad2b' + + '3b310da903401aa62100ab5d1a36553e' + + '06203b33890cc9b832f79ef80560ccb9' + + 'a39ce767967ed628c6ad573cb116dbef' + + 'efd75499da96bd68a8a97b928a8bbc10' + + '3b6621fcde2beca1231d206be6cd9ec7' + + 'aff6f6c94fcd7204ed3455c68c83f4a4' + + '1da4af2b74ef5c53f1d8ac70bdcb7ed1' + + '85ce81bd84359d44254d95629e9855a9' + + '4a7c1958d1f8ada5d0532ed8a5aa3fb2' + + 'd17ba70eb6248e594e1a2297acbbb39d' + + '502f1a8c6eb6f1ce22b3de1a1f40cc24' + + '554119a831a9aad6079cad88425de6bd' + + 'e1a9187ebb6092cf67bf2b13fd65f270' + + '88d78b7e883c8759d2c4f5c65adb7553' + + '878ad575f9fad878e80a0c9ba63bcbcc' + + '2732e69485bbc9c90bfbd62481d9089b' + + 'eccf80cfe2df16a2cf65bd92dd597b07' + + '07e0917af48bbb75fed413d238f5555a' + + '7a569d80c3414a8d0859dc65a46128ba' + + 'b27af87a71314f318c782b23ebfe808b' + + '82b0ce26401d2e22f04d83d1255dc51a' + + 'ddd3b75a2b1ae0784504df543af8969b' + + 'e3ea7082ff7fc9888c144da2af58429e' + + 'c96031dbcad3dad9af0dcbaaaf268cb8' + + 'fcffead94f3c7ca495e056a9b47acdb7' + + '51fb73e666c6c655ade8297297d07ad1' + + 'ba5e43f1bca32301651339e22904cc8c' + + '42f58c30c04aafdb038dda0847dd988d' + + 'cda6f3bfd15c4b4c4525004aa06eeff8' + + 'ca61783aacec57fb3d1f92b0fe2fd1a8' + + '5f6724517b65e614ad6808d6f6ee34df' + + 'f7310fdc82aebfd904b01e1dc54b2927' + + '094b2db68d6f903b68401adebf5a7e08' + + 'd78ff4ef5d63653a65040cf9bfd4aca7' + + '984a74d37145986780fc0b16ac451649' + + 'de6188a7dbdf191f64b5fc5e2ab47b57' + + 'f7f7276cd419c17a3ca8e1b939ae49e4' + + '88acba6b965610b5480109c8b17b80e1' + + 'b7b750dfc7598d5d5011fd2dcc5600a3' + + '2ef5b52a1ecc820e308aa342721aac09' + + '43bf6686b64b2579376504ccc493d97e' + + '6aed3fb0f9cd71a43dd497f01f17c0e2' + + 'cb3797aa2a2f256656168e6c496afc5f' + + 'b93246f6b1116398a346f1a641f3b041' + + 'e989f7914f90cc2c7fff357876e506b5' + + '0d334ba77c225bc307ba537152f3f161' + + '0e4eafe595f6d9d90d11faa933a15ef1' + + '369546868a7f3a45a96768d40fd9d034' + + '12c091c6315cf4fde7cb68606937380d' + + 'b2eaaa707b4c4185c32eddcdd306705e' + + '4dc1ffc872eeee475a64dfac86aba41c' + + '0618983f8741c5ef68d3a101e8a3b8ca' + + 'c60c905c15fc910840b94c00a0b9d0', + publicKey: '278117fc144c72340f67d0f2316e8386ceffbf2b2428c9c51fef7c597f1d426e', + publicKeyHash: '3fa478a09cf841058b3e63abe2cfc50aac0ea46d84eaa50a6ae5accc', + secretKey: 'f5e5767cf153319517630f226876b86c8160cc583bc013744c6bf255f5cc0ee5', + signature: + '0aab4c900501b3e24d7cdf4663326a3a' + + '87df5e4843b2cbdb67cbf6e460fec350' + + 'aa5371b1508f9f4528ecea23c436d94b' + + '5e8fcd4f681e30a6ac00a9704a188a03' +}; + +export const testVectorMessageShaOfAbc: Ed25519TestVector = { + message: + 'ddaf35a193617abacc417349ae204131' + + '12e6fa4e89a97ea20a9eeee64b55d39a' + + '2192992a274fc1a836ba3c23a3feebbd' + + '454d4423643ce80e2a9ac94fa54ca49f', + publicKey: 'ec172b93ad5e563bf4932c70e1245034c35467ef2efd4d64ebf819683467e2bf', + publicKeyHash: '04914a5d895b6ecb480359279b0ab415a06363dbe2c8c4b9dcaa2f29', + secretKey: '833fe62409237b9d62ec77587520911e9a759cec1d19755b7da901b96dca3d42', + signature: + 'dc2a4459e7369633a52b1bf277839a00' + + '201009a3efbf3ecb69bea2186c26b589' + + '09351fc9ac90b3ecfdfbc7c66431e030' + + '3dca179c138ac17ad9bef1177331a704' +}; + +export const vectors = [ + testVectorMessageZeroLength, + testVectorMessageOneLength, + testVectorMessageTwoLength, + testVectorMessage1023Length, + testVectorMessageShaOfAbc +]; + +// This test vectors for extended keys were created using https://github.com/dcSpark/cardano-multiplatform-lib + +/** + * Hardens the given index. + * + * @param num The index to be hardened. + */ +const harden = (num: number): number => 0x80_00_00_00 + num; + +export const bip32TestVectorMessageShaOfAbc: Bip32Ed25519TestVector = { + bip39Entropy: 'f07e8b397c93a16c06f83c8f0c1a1866477c6090926445fc0cb1201228ace6e9', + childPrivateKey: + '3809937b61bd4f180a1e9bd15237e7bc20e36b9037dd95ef60d84f6004758250' + + 'a22e1bfc0d81e9adb7760bcba7f5214416b3e9f27c8d58794a3a7fead2d5b695' + + '8d515cb54181fb2f5fc3af329e80949c082fb52f7b07e359bd7835a6762148bf', + childPublicKey: + 'b857a8cd1dbbfed1824359d9d9e58bc8ffb9f66812b404f4c6ffc315629835bf' + + '9db12d11a3559131a47f51f854a6234725ab8767d3fcc4c9908be55508f3c712', + derivationPath: [harden(1852), harden(1815), harden(0)], + ed25519eVector: { + message: + 'ddaf35a193617abacc417349ae204131' + + '12e6fa4e89a97ea20a9eeee64b55d39a' + + '2192992a274fc1a836ba3c23a3feebbd' + + '454d4423643ce80e2a9ac94fa54ca49f', + publicKey: '311f8914b8934efbe7cbb8cc4745853de12e8ea402df6f9f69b18d2792c6bed8', + publicKeyHash: 'ebf46bc374bda5b937d4d964fc0b73e940a9ea7d8cfdf39162a6f207', + secretKey: + 'a0ab55b174ba8cd95e2362d035f377b4' + + 'dc779a0fae65767e3b8dd790fa748250' + + 'f3ef2cc372c207d7902607ffef01872a' + + '4c785cd27e7342de7f4332f2d5fdc3a8', + signature: + '843aa4353184193bdf01aab7f636ac53' + + 'f86746dd97a2a2e01fe7923c37bfec40' + + 'b68a73881a26ba57dc974abc1123d086' + + '6b542a5447e03677134a8f4e1db2bc0c' + }, + password: '', + publicKey: + '311f8914b8934efbe7cbb8cc4745853d' + + 'e12e8ea402df6f9f69b18d2792c6bed8' + + 'd0c110e1d6a061d3558eb6a3138a3982' + + '253c6616e1bf4d8bd31e92de8328affe', + rootKey: + 'a0ab55b174ba8cd95e2362d035f377b4' + + 'dc779a0fae65767e3b8dd790fa748250' + + 'f3ef2cc372c207d7902607ffef01872a' + + '4c785cd27e7342de7f4332f2d5fdc3a8' + + 'd0c110e1d6a061d3558eb6a3138a3982' + + '253c6616e1bf4d8bd31e92de8328affe' +}; + +export const bip32TestVectorMessageOneLength: Bip32Ed25519TestVector = { + bip39Entropy: 'caec96d09fc2020ab230199e0188cd6a554e2da2cba32de9ff6c0908c7f04d65', + childPrivateKey: + 'd0d3ddf972ca055ca7fe5703ebb03201128c2c5a93a0d9350bd7a65f2e1d045f' + + 'fc5fc40c42a98fab3a4afa2d31eef5e1e85d982ca3dccafb364aa2ef369c3e09' + + 'ee2372d821e7b4d95f2cb0cd7fa53d5620c952864ed931f7bc9d390e17fb39f4', + childPublicKey: + 'b857a8cd1dbbfed1824359d9d9e58bc8ffb9f66812b404f4c6ffc315629835bf' + + '9db12d11a3559131a47f51f854a6234725ab8767d3fcc4c9908be55508f3c712', + derivationPath: [harden(1852), harden(1815), harden(1)], + ed25519eVector: { + message: '72', + publicKey: 'ba4f80dea2632a17c99ae9d8b934abf02643db5426b889fef14709c85e294aa1', + publicKeyHash: '2a6383e079acd8e32b7e56a53f5749d5c8da260170d8306a0a716024', + secretKey: + '60292301b8dd20a74b58a0bd4ecdeb24' + + '4a95e757c7a2d25962ada75e271d045f' + + 'f827c85a5530bfe76975b4189c5fd6d3' + + '2d4fe43c81373f386fde2fa0e6d0255a', + signature: + 'c1d21c78e17c62a7536bb791dbac908a' + + 'd8f3c6c6a9f0634d3fcad1286d31ebdc' + + '5aacdb7ccb7c4d02c192266f0088d570' + + 'e566a3e2203a75803aea72595332ca05' + }, + password: 'some_password_@#$%^&', + publicKey: + 'ba4f80dea2632a17c99ae9d8b934abf0' + + '2643db5426b889fef14709c85e294aa1' + + '2ac1f1560a893ea7937c5bfbfdeab459' + + 'b1a396f1174b9c5a673a640d01880c35', + rootKey: + '60292301b8dd20a74b58a0bd4ecdeb24' + + '4a95e757c7a2d25962ada75e271d045f' + + 'f827c85a5530bfe76975b4189c5fd6d3' + + '2d4fe43c81373f386fde2fa0e6d0255a' + + '2ac1f1560a893ea7937c5bfbfdeab459' + + 'b1a396f1174b9c5a673a640d01880c35' +}; + +export const bip32TestVectorMessageShaOfAbcUnhardened: Bip32Ed25519TestVector = { + bip39Entropy: 'be9ffd296c0ccabadf51c6fbb904995b182d6ac84181c08d8b016ab1eefd78ce', + childPrivateKey: + '08f9d7de597d31fade994b8a1e9d3e3afe53ac8393297e8f4d96225d72586951' + + '7ae54c631588abb408fcab0676a4da6b60c82b3a3d7045a26a576c7901e5e957' + + '9db12d11a3559131a47f51f854a6234725ab8767d3fcc4c9908be55508f3c712', + childPublicKey: + 'b857a8cd1dbbfed1824359d9d9e58bc8ffb9f66812b404f4c6ffc315629835bf' + + '9db12d11a3559131a47f51f854a6234725ab8767d3fcc4c9908be55508f3c712', + derivationPath: [1852, 1815, 0], // Non hardened. + ed25519eVector: { + message: + 'ddaf35a193617abacc417349ae204131' + + '12e6fa4e89a97ea20a9eeee64b55d39a' + + '2192992a274fc1a836ba3c23a3feebbd' + + '454d4423643ce80e2a9ac94fa54ca49f', + publicKey: '6fd8d9c696b01525cc45f15583fc9447c66e1c71fd1a11c8885368404cd0a4ab', + publicKeyHash: 'b79e58495d0aabbe068cde6cef2c6659eca348950ff9966510c90cee', + secretKey: + 'd8287e922756977dc0b79659e6eebcae' + + '3a1fb29a22ce1449c94f125462586951' + + '390af99a0350130451e9bf4f4691f37c' + + '352dc7025d52d9132f61a82f61d3803d', + signature: + 'f363d78e0a315ae1fc0ceb6b8efdd163' + + '1a3a2ce16f6cf43f596ff92c4a7b2926' + + '39c6e352cc24efcf80ccea39cbdb7ec9' + + 'a02f4a5b332afc2de7f7a2e65e67780e' + }, + password: '', + publicKey: + '6fd8d9c696b01525cc45f15583fc9447' + + 'c66e1c71fd1a11c8885368404cd0a4ab' + + '00b5f1652f5cbe257e567c883dc2b16e' + + '0a9568b19c5b81ea8bd197fc95e8bdcf', + rootKey: + 'd8287e922756977dc0b79659e6eebcae' + + '3a1fb29a22ce1449c94f125462586951' + + '390af99a0350130451e9bf4f4691f37c' + + '352dc7025d52d9132f61a82f61d3803d' + + '00b5f1652f5cbe257e567c883dc2b16e' + + '0a9568b19c5b81ea8bd197fc95e8bdcf' +}; + +export const extendedVectors = [ + bip32TestVectorMessageShaOfAbc, + bip32TestVectorMessageOneLength, + bip32TestVectorMessageShaOfAbcUnhardened +]; diff --git a/packages/e2e/package.json b/packages/e2e/package.json index e442fb8a1d1..45daeca8b31 100644 --- a/packages/e2e/package.json +++ b/packages/e2e/package.json @@ -151,6 +151,8 @@ "copy-webpack-plugin": "^10.2.4", "dockerode": "^3.3.1", "dockerode-utils": "^0.0.7", + "crypto-browserify": "^3.12.0", + "delay": "^5.0.0", "eslint": "^7.32.0", "events": "^3.3.0", "expect-webdriverio": "^3.2.1", diff --git a/packages/e2e/test/web-extension/webpack.config.base.js b/packages/e2e/test/web-extension/webpack.config.base.js index ddc2e9da757..b6e4cd449f6 100644 --- a/packages/e2e/test/web-extension/webpack.config.base.js +++ b/packages/e2e/test/web-extension/webpack.config.base.js @@ -79,6 +79,7 @@ module.exports = { os: false, path: false, perf_hooks: false, + crypto: require.resolve('crypto-browserify'), stream: require.resolve('readable-stream'), util: require.resolve('util/') } diff --git a/yarn-project.nix b/yarn-project.nix index 22e374cc4c4..51b7115983d 100644 --- a/yarn-project.nix +++ b/yarn-project.nix @@ -838,6 +838,7 @@ cacheEntries = { "artillery-plugin-publish-metrics@npm:2.5.1" = { filename = "artillery-plugin-publish-metrics-npm-2.5.1-18dae68bd3-a42fc82083.zip"; sha512 = "a42fc82083d045d51bd071d158694b8ca0eb49173b287eee4c282bb4e1cb9a0979c8886e421a28c84f1a9a91c58a56d9de5925ba9269a361c6709cda49a67dc5"; }; "artillery@npm:2.0.0-35-e92306e" = { filename = "artillery-npm-2.0.0-35-e92306e-d4de8fd4f9-cace3b326a.zip"; sha512 = "cace3b326a5f201018e07ba1424c7f53895580bc6bbe7cabe272e877e2d9d1b53645a02cfe22ef79fcca1e7f107ccca928d6269d2cdc785476340d9620a8e7ca"; }; "asap@npm:2.0.6" = { filename = "asap-npm-2.0.6-36714d439d-b296c92c4b.zip"; sha512 = "b296c92c4b969e973260e47523207cd5769abd27c245a68c26dc7a0fe8053c55bb04360237cb51cab1df52be939da77150ace99ad331fb7fb13b3423ed73ff3d"; }; +"asn1.js@npm:5.4.1" = { filename = "asn1.js-npm-5.4.1-37c7edbcb0-3786a101ac.zip"; sha512 = "3786a101ac6f304bd4e9a7df79549a7561950a13d4bcaec0c7790d44c80d147c1a94ba3d4e663673406064642a40b23fcd6c82a9952468e386c1a1376d747f9a"; }; "asn1@npm:0.2.6" = { filename = "asn1-npm-0.2.6-bdd07356c4-39f2ae343b.zip"; sha512 = "39f2ae343b03c15ad4f238ba561e626602a3de8d94ae536c46a4a93e69578826305366dc09fbb9b56aec39b4982a463682f259c38e59f6fa380cd72cd61e493d"; }; "assert-node-version@npm:1.0.3" = { filename = "assert-node-version-npm-1.0.3-c1f8590b8e-3fb6b2ff67.zip"; sha512 = "3fb6b2ff674d67cfad89c3702040929b93e8a5f65dc896c5952df364757b930c72339b3e6a6f22ed53ed39911181fc56dac7552c601103537d09e301c2513483"; }; "assert-plus@npm:1.0.0" = { filename = "assert-plus-npm-1.0.0-cac95ef098-19b4340cb8.zip"; sha512 = "19b4340cb8f0e6a981c07225eacac0e9d52c2644c080198765d63398f0075f83bbc0c8e95474d54224e297555ad0d631c1dcd058adb1ddc2437b41a6b424ac64"; }; @@ -918,6 +919,11 @@ cacheEntries = { "browser-or-node@npm:1.3.0" = { filename = "browser-or-node-npm-1.3.0-747274248d-14a7e3f7bd.zip"; sha512 = "14a7e3f7bd2dfeac0d1e8fed378a22c7e3c943c30e84ce09ba0636c82f79f78d321536fd2846dd505b6d7ee6fb0fdb8d7f084afe40f2378eee5533cb8e7cd456"; }; "browser-process-hrtime@npm:1.0.0" = { filename = "browser-process-hrtime-npm-1.0.0-db700805c2-e30f868cdb.zip"; sha512 = "e30f868cdb770b1201afb714ad1575dd86366b6e861900884665fb627109b3cc757c40067d3bfee1ff2a29c835257ea30725a8018a9afd02ac1c24b408b1e45f"; }; "browser-stdout@npm:1.3.1" = { filename = "browser-stdout-npm-1.3.1-6b2376bf3f-b717b19b25.zip"; sha512 = "b717b19b25952dd6af483e368f9bcd6b14b87740c3d226c2977a65e84666ffd67000bddea7d911f111a9b6ddc822b234de42d52ab6507bce4119a4cc003ef7b3"; }; +"browserify-aes@npm:1.2.0" = { filename = "browserify-aes-npm-1.2.0-2ad4aeefbe-4a17c3eb55.zip"; sha512 = "4a17c3eb55a2aa61c934c286f34921933086bf6d67f02d4adb09fcc6f2fc93977b47d9d884c25619144fccd47b3b3a399e1ad8b3ff5a346be47270114bcf7104"; }; +"browserify-cipher@npm:1.0.1" = { filename = "browserify-cipher-npm-1.0.1-e00d75c093-2d8500acf1.zip"; sha512 = "2d8500acf1ee535e6bebe808f7a20e4c3a9e2ed1a6885fff1facbfd201ac013ef030422bec65ca9ece8ffe82b03ca580421463f9c45af6c8415fd629f4118c13"; }; +"browserify-des@npm:1.0.2" = { filename = "browserify-des-npm-1.0.2-5d04e0cde2-b15a3e358a.zip"; sha512 = "b15a3e358a1d78a3b62ddc06c845d02afde6fc826dab23f1b9c016e643e7b1fda41de628d2110b712f6a44fb10cbc1800bc6872a03ddd363fb50768e010395b7"; }; +"browserify-rsa@npm:4.1.0" = { filename = "browserify-rsa-npm-4.1.0-2a224a51bc-155f0c1358.zip"; sha512 = "155f0c135873efc85620571a33d884aa8810e40176125ad424ec9d85016ff105a07f6231650914a760cca66f29af0494087947b7be34880dd4599a0cd3c38e54"; }; +"browserify-sign@npm:4.2.1" = { filename = "browserify-sign-npm-4.2.1-9a8530ca87-0221f190e3.zip"; sha512 = "0221f190e3f5b2d40183fa51621be7e838d9caa329fe1ba773406b7637855f37b30f5d83e52ff8f244ed12ffe6278dd9983638609ed88c841ce547e603855707"; }; "browserslist@npm:4.21.4" = { filename = "browserslist-npm-4.21.4-7d64a96afc-4af3793704.zip"; sha512 = "4af3793704dbb4615bcd29059ab472344dc7961c8680aa6c4bb84f05340e14038d06a5aead58724eae69455b8fade8b8c69f1638016e87e5578969d74c078b79"; }; "bs-logger@npm:0.2.6" = { filename = "bs-logger-npm-0.2.6-7670f88b66-d34bdaf68c.zip"; sha512 = "d34bdaf68c64bd099ab97c3ea608c9ae7d3f5faa1178b3f3f345acd94e852e608b2d4f9103fb2e503f5e69780e98293df41691b84be909b41cf5045374d54606"; }; "bs58@npm:4.0.1" = { filename = "bs58-npm-4.0.1-8d2a7822b1-b3c5365bb9.zip"; sha512 = "b3c5365bb9e0c561e1a82f1a2d809a1a692059fae016be233a6127ad2f50a6b986467c3a50669ce4c18929dcccb297c5909314dd347a25a68c21b68eb3e95ac2"; }; @@ -930,6 +936,7 @@ cacheEntries = { "buffer-from@npm:1.1.2" = { filename = "buffer-from-npm-1.1.2-03d2f20d7e-0448524a56.zip"; sha512 = "0448524a562b37d4d7ed9efd91685a5b77a50672c556ea254ac9a6d30e3403a517d8981f10e565db24e8339413b43c97ca2951f10e399c6125a0d8911f5679bb"; }; "buffer-more-ints@npm:1.0.0" = { filename = "buffer-more-ints-npm-1.0.0-36b3be4e82-f6e88dade0.zip"; sha512 = "f6e88dade08a6d36f32d5f3ece141583a4f61d6c36970b16f4699bd00cfe95d4015525c2a741cf46eb918acfd61cac95683fb995189fd65c13b14949c90bfe75"; }; "buffer-writer@npm:2.0.0" = { filename = "buffer-writer-npm-2.0.0-5cd2ef55bc-11736b48bb.zip"; sha512 = "11736b48bb75106c52ca8ec9f025e7c1b3b25ce31875f469d7210eabd5c576c329e34f6b805d4a8d605ff3f0db1e16342328802c4c963e9c826b0e43a4e631c2"; }; +"buffer-xor@npm:1.0.3" = { filename = "buffer-xor-npm-1.0.3-56bb81b0dd-10c520df29.zip"; sha512 = "10c520df29d62fa6e785e2800e586a20fc4f6dfad84bcdbd12e1e8a83856de1cb75c7ebd7abe6d036bbfab738a6cf18a3ae9c8e5a2e2eb3167ca7399ce65373a"; }; "buffer@npm:4.9.2" = { filename = "buffer-npm-4.9.2-9e40b5e87a-8801bc1ba0.zip"; sha512 = "8801bc1ba08539f3be70eee307a8b9db3d40f6afbfd3cf623ab7ef41dffff1d0a31de0addbe1e66e0ca5f7193eeb667bfb1ecad3647f8f1b0750de07c13295c3"; }; "buffer@npm:5.6.0" = { filename = "buffer-npm-5.6.0-e1494693bf-d659494c50.zip"; sha512 = "d659494c5032dd39d03d2912e64179cc44c6340e7e9d1f68d3840e7ab4559989fbce92b4950174593c38d05268224235ba404f0878775cab2a616b6dcad9c23e"; }; "buffer@npm:5.7.1" = { filename = "buffer-npm-5.7.1-513ef8259e-e2cf8429e1.zip"; sha512 = "e2cf8429e1c4c7b8cbd30834ac09bd61da46ce35f5c22a78e6c2f04497d6d25541b16881e30a019c6fd3154150650ccee27a308eff3e26229d788bbdeb08ab84"; }; @@ -1076,6 +1083,7 @@ cacheEntries = { "cpu-features@npm:0.0.4" = { filename = "cpu-features-npm-0.0.4-b474ef5da3-a20d58e41e.zip"; sha512 = "a20d58e41e63182b34753dfe23bd1d967944ec13d84b70849b5d334fb4a558b7e71e7f955ed86c8e75dd65b5c5b882f1c494174d342cb6d8a062d77f79d39596"; }; "crc-32@npm:1.2.2" = { filename = "crc-32-npm-1.2.2-28bdc12bcc-ad2d0ad0cb.zip"; sha512 = "ad2d0ad0cbd465b75dcaeeff0600f8195b686816ab5f3ba4c6e052a07f728c3e70df2e3ca9fd3d4484dc4ba70586e161ca5a2334ec8bf5a41bf022a6103ff243"; }; "crc32-stream@npm:4.0.2" = { filename = "crc32-stream-npm-4.0.2-32a2ec50b7-1099559283.zip"; sha512 = "1099559283b86e8a55390228b57ff4d57a74cac6aa8086aa4730f84317c9f93e914aeece115352f2d706a9df7ed75327ffacd86cfe23f040aef821231b528e76"; }; +"create-ecdh@npm:4.0.4" = { filename = "create-ecdh-npm-4.0.4-1048ce2035-0dd7fca971.zip"; sha512 = "0dd7fca9711d09e152375b79acf1e3f306d1a25ba87b8ff14c2fd8e68b83aafe0a7dd6c4e540c9ffbdd227a5fa1ad9b81eca1f233c38bb47770597ba247e614b"; }; "create-hash@npm:1.2.0" = { filename = "create-hash-npm-1.2.0-afd048e1ce-02a6ae3bb9.zip"; sha512 = "02a6ae3bb9cd4afee3fabd846c1d8426a0e6b495560a977ba46120c473cb283be6aa1cace76b5f927cf4e499c6146fb798253e48e83d522feba807d6b722eaa9"; }; "create-hmac@npm:1.1.7" = { filename = "create-hmac-npm-1.1.7-b4ef32668a-ba12bb2257.zip"; sha512 = "ba12bb2257b585a0396108c72830e85f882ab659c3320c83584b1037f8ab72415095167ced80dc4ce8e446a8ecc4b2acf36d87befe0707d73b26cf9dc77440ed"; }; "create-require@npm:1.1.1" = { filename = "create-require-npm-1.1.1-839884ca2e-a9a1503d43.zip"; sha512 = "a9a1503d4390d8b59ad86f4607de7870b39cad43d929813599a23714831e81c520bddf61bcdd1f8e30f05fd3a2b71ae8538e946eb2786dc65c2bbc520f692eff"; }; @@ -1085,6 +1093,7 @@ cacheEntries = { "cross-spawn@npm:4.0.2" = { filename = "cross-spawn-npm-4.0.2-3c23494e5b-8ce57b3e11.zip"; sha512 = "8ce57b3e11c5c798542a21ddfdc1edef33ab6fe001958b31f3340a6ff684e3334a8baad2751efa78b6200aad442cf12b939396d758b0dd5c42c9b782c28fe06e"; }; "cross-spawn@npm:6.0.5" = { filename = "cross-spawn-npm-6.0.5-2deab6c280-f893bb0d96.zip"; sha512 = "f893bb0d96cd3d5751d04e67145bdddf25f99449531a72e82dcbbd42796bbc8268c1076c6b3ea51d4d455839902804b94bc45dfb37ecbb32ea8e54a6741c3ab9"; }; "cross-spawn@npm:7.0.3" = { filename = "cross-spawn-npm-7.0.3-e4ff3e65b3-671cc7c728.zip"; sha512 = "671cc7c7288c3a8406f3c69a3ae2fc85555c04169e9d611def9a675635472614f1c0ed0ef80955d5b6d4e724f6ced67f0ad1bb006c2ea643488fcfef994d7f52"; }; +"crypto-browserify@npm:3.12.0" = { filename = "crypto-browserify-npm-3.12.0-bed454fef0-c1609af826.zip"; sha512 = "c1609af82605474262f3eaa07daa0b2140026bd264ab316d4bf1170272570dbe02f0c49e29407fe0d3634f96c507c27a19a6765fb856fed854a625f9d15618e2"; }; "css-select@npm:5.1.0" = { filename = "css-select-npm-5.1.0-9365a79de5-2772c049b1.zip"; sha512 = "2772c049b188d3b8a8159907192e926e11824aea525b8282981f72ba3f349cf9ecd523fdf7734875ee2cb772246c22117fc062da105b6d59afe8dcd5c99c9bda"; }; "css-shorthand-properties@npm:1.1.1" = { filename = "css-shorthand-properties-npm-1.1.1-38b8b5d6a7-014b48e9fd.zip"; sha512 = "014b48e9fda528da7155cdf41e4ad9a0079ace4890e853d1d3ce4e41c2bb38c19e627d0be93dafe8b202c3a9fe83a6120b684e1405ee79b69ea8e248bd8833e9"; }; "css-value@npm:0.0.1" = { filename = "css-value-npm-0.0.1-e6e2039cae-976a5832d1.zip"; sha512 = "976a5832d1e5e5dc041903395a2842a382c7a0b150026f0f81671046f8125d4b86c7a9eed014a047c7a2111bc56d807d0e8d2e08b6e028798054593a9afc6b4d"; }; @@ -1138,6 +1147,7 @@ cacheEntries = { "dependency-tree@npm:6.5.0" = { filename = "dependency-tree-npm-6.5.0-af8d490c4e-17a5e08b78.zip"; sha512 = "17a5e08b785aa9d32c0e67401c0c97f42467d9af6e3236d614b206830f9b0be6a556205ada2daa9bf0501801ba53cc494a249b18777f01e4aeb3837d9475978d"; }; "dependency-tree@npm:8.1.2" = { filename = "dependency-tree-npm-8.1.2-dd336d8e28-e26dffd033.zip"; sha512 = "e26dffd0332b80ac6303fa4073dcd8f3df05c1584e26fe8fd15f59572f0427e8618757e9797d8963578648f80eb9d4f4496f25bbbb5984329b4c55e49e51d7be"; }; "deprecation@npm:2.3.1" = { filename = "deprecation-npm-2.3.1-e19c92d6e7-f56a05e182.zip"; sha512 = "f56a05e182c2c195071385455956b0c4106fe14e36245b00c689ceef8e8ab639235176a96977ba7c74afb173317fac2e0ec6ec7a1c6d1e6eaa401c586c714132"; }; +"des.js@npm:1.0.1" = { filename = "des.js-npm-1.0.1-9f155eddb6-1ec2eedd7e.zip"; sha512 = "1ec2eedd7ed6bd61dd5e0519fd4c96124e93bb22de8a9d211b02d63e5dd152824853d919bb2090f965cc0e3eb9c515950a9836b332020d810f9c71feb0fd7df4"; }; "destr@npm:1.2.2" = { filename = "destr-npm-1.2.2-7e9fbb823a-3906b49513.zip"; sha512 = "3906b49513a64d8442dacb8b798c59d66257ded4ccd2ef1d99b58644d4aa6b30ca61f9a9823d3dcbc78b4db812596e53e85e499f39a498b3b165a045b5228b2b"; }; "destroy@npm:1.2.0" = { filename = "destroy-npm-1.2.0-6a511802e2-0acb300b74.zip"; sha512 = "0acb300b7478a08b92d810ab229d5afe0d2f4399272045ab22affa0d99dbaf12637659411530a6fcd597a9bdac718fc94373a61a95b4651bbc7b83684a565e38"; }; "detect-indent@npm:7.0.1" = { filename = "detect-indent-npm-7.0.1-f2bf421cb1-cbf3f0b1c3.zip"; sha512 = "cbf3f0b1c3c881934ca94428e1179b26ab2a587e0d719031d37a67fb506d49d067de54ff057cb1e772e75975fed5155c01cd4518306fee60988b1486e3fc7768"; }; @@ -1167,6 +1177,7 @@ cacheEntries = { "diff@npm:4.0.2" = { filename = "diff-npm-4.0.2-73133c7102-f2c09b0ce4.zip"; sha512 = "f2c09b0ce4e6b301c221addd83bf3f454c0bc00caa3dd837cf6c127d6edf7223aa2bbe3b688feea110b7f262adbfc845b757c44c8a9f8c0c5b15d8fa9ce9d20d"; }; "diff@npm:5.0.0" = { filename = "diff-npm-5.0.0-ad6900db18-f19fe29284.zip"; sha512 = "f19fe29284b633afdb2725c2a8bb7d25761ea54d321d8e67987ac851c5294be4afeab532bd84531e02583a3fe7f4014aa314a3eda84f5590e7a9e6b371ef3b46"; }; "diff@npm:5.1.0" = { filename = "diff-npm-5.1.0-d24d222280-c7bf0df7c9.zip"; sha512 = "c7bf0df7c9bfbe1cf8a678fd1b2137c4fb11be117a67bc18a0e03ae75105e8533dbfb1cda6b46beb3586ef5aed22143ef9d70713977d5fb1f9114e21455fba90"; }; +"diffie-hellman@npm:5.0.3" = { filename = "diffie-hellman-npm-5.0.3-cbef8f3171-0e620f3221.zip"; sha512 = "0e620f322170c41076e70181dd1c24e23b08b47dbb92a22a644f3b89b6d3834b0f8ee19e37916164e5eb1ee26d2aa836d6129f92723995267250a0b541811065"; }; "dir-glob@npm:3.0.1" = { filename = "dir-glob-npm-3.0.1-1aea628b1b-fa05e18324.zip"; sha512 = "fa05e18324510d7283f55862f3161c6759a3f2f8dbce491a2fc14c8324c498286c54282c1f0e933cb930da8419b30679389499b919122952a4f8592362ef4615"; }; "docker-modem@npm:3.0.6" = { filename = "docker-modem-npm-3.0.6-b6a8554417-f80abc8ddf.zip"; sha512 = "f80abc8ddf4d6026ba460bf66c8e039ef8e41a6705086a0770ce1b7cabd91bcd4681c32a6531b79dab23ceea680a3aae363bee29e8089b55a8eb775abfb6b67d"; }; "dockerode-utils@npm:0.0.7" = { filename = "dockerode-utils-npm-0.0.7-ffa1a4624f-9133d55428.zip"; sha512 = "9133d554280491ff1e48403e64aa69d6d0311480420c0e867bf05fdc9c88725109ab03b5b43324391ac1fc8d6e131c74b7b18874c73fb86136726d4152a54d79"; }; @@ -1276,6 +1287,7 @@ cacheEntries = { "eventemitter3@npm:4.0.7" = { filename = "eventemitter3-npm-4.0.7-7afcdd74ae-1875311c42.zip"; sha512 = "1875311c42fcfe9c707b2712c32664a245629b42bb0a5a84439762dd0fd637fc54d078155ea83c2af9e0323c9ac13687e03cfba79b03af9f40c89b4960099374"; }; "events@npm:1.1.1" = { filename = "events-npm-1.1.1-ca9e5d580e-40431eb005.zip"; sha512 = "40431eb005cc4c57861b93d44c2981a49e7feb99df84cf551baed299ceea4444edf7744733f6a6667e942af687359b1f4a87ec1ec4f21d5127dac48a782039b9"; }; "events@npm:3.3.0" = { filename = "events-npm-3.3.0-c280bc7e48-f6f487ad21.zip"; sha512 = "f6f487ad2198aa41d878fa31452f1a3c00958f46e9019286ff4787c84aac329332ab45c9cdc8c445928fc6d7ded294b9e005a7fce9426488518017831b272780"; }; +"evp_bytestokey@npm:1.0.3" = { filename = "evp_bytestokey-npm-1.0.3-4a2644aaea-ad4e1577f1.zip"; sha512 = "ad4e1577f1a6b721c7800dcc7c733fe01f6c310732bb5bf2240245c2a5b45a38518b91d8be2c610611623160b9d1c0e91f1ce96d639f8b53e8894625cf20fa45"; }; "execa@npm:1.0.0" = { filename = "execa-npm-1.0.0-7028e37029-ddf1342c1c.zip"; sha512 = "ddf1342c1c7d02dd93b41364cd847640f6163350d9439071abf70bf4ceb1b9b2b2e37f54babb1d8dc1df8e0d8def32d0e81e74a2e62c3e1d70c303eb4c306bc4"; }; "execa@npm:4.1.0" = { filename = "execa-npm-4.1.0-cc675b4189-e30d298934.zip"; sha512 = "e30d298934d9c52f90f3847704fd8224e849a081ab2b517bbc02f5f7732c24e56a21f14cb96a08256deffeb2d12b2b7cb7e2b014a12fb36f8d3357e06417ed55"; }; "execa@npm:5.1.1" = { filename = "execa-npm-5.1.1-191347acf5-fba9022c8c.zip"; sha512 = "fba9022c8c8c15ed862847e94c252b3d946036d7547af310e344a527e59021fd8b6bb0723883ea87044dc4f0201f949046993124a42ccb0855cae5bf8c786343"; }; @@ -1790,6 +1802,7 @@ cacheEntries = { "merge2@npm:1.4.1" = { filename = "merge2-npm-1.4.1-a2507bd06c-7268db63ed.zip"; sha512 = "7268db63ed5169466540b6fb947aec313200bcf6d40c5ab722c22e242f651994619bcd85601602972d3c85bd2cc45a358a4c61937e9f11a061919a1da569b0c2"; }; "methods@npm:1.1.2" = { filename = "methods-npm-1.1.2-92f6fdb39b-0917ff4041.zip"; sha512 = "0917ff4041fa8e2f2fda5425a955fe16ca411591fbd123c0d722fcf02b73971ed6f764d85f0a6f547ce49ee0221ce2c19a5fa692157931cecb422984f1dcd13a"; }; "micromatch@npm:4.0.5" = { filename = "micromatch-npm-4.0.5-cfab5d7669-02a17b671c.zip"; sha512 = "02a17b671c06e8fefeeb6ef996119c1e597c942e632a21ef589154f23898c9c6a9858526246abb14f8bca6e77734aa9dcf65476fca47cedfb80d9577d52843fc"; }; +"miller-rabin@npm:4.0.1" = { filename = "miller-rabin-npm-4.0.1-3426ac0bf7-00cd1ab838.zip"; sha512 = "00cd1ab838ac49b03f236cc32a14d29d7d28637a53096bf5c6246a032a37749c9bd9ce7360cbf55b41b89b7d649824949ff12bc8eee29ac77c6b38eada619ece"; }; "mime-db@npm:1.52.0" = { filename = "mime-db-npm-1.52.0-b5371d6fd2-0d99a03585.zip"; sha512 = "0d99a03585f8b39d68182803b12ac601d9c01abfa28ec56204fa330bc9f3d1c5e14beb049bafadb3dbdf646dfb94b87e24d4ec7b31b7279ef906a8ea9b6a513f"; }; "mime-types@npm:2.1.35" = { filename = "mime-types-npm-2.1.35-dd9ea9f3e2-89a5b7f1de.zip"; sha512 = "89a5b7f1def9f3af5dad6496c5ed50191ae4331cc5389d7c521c8ad28d5fdad2d06fd81baf38fed813dc4e46bb55c8145bb0ff406330818c9cf712fb2e9b3836"; }; "mime@npm:1.6.0" = { filename = "mime-npm-1.6.0-60ae95038a-fef25e3926.zip"; sha512 = "fef25e39263e6d207580bdc629f8872a3f9772c923c7f8c7e793175cee22777bbe8bba95e5d509a40aaa292d8974514ce634ae35769faa45f22d17edda5e8557"; }; @@ -1971,6 +1984,7 @@ cacheEntries = { "pad-component@npm:0.0.1" = { filename = "pad-component-npm-0.0.1-96c929da6f-2d92ad68b6.zip"; sha512 = "2d92ad68b6c86ce2afcc75c9536401ef8b25a03f9b1330fbe5a9a9862a5cbb0e4088848d427919f4cb7526c333b7eada7cb590328e69775257e20363023bb424"; }; "pako@npm:1.0.11" = { filename = "pako-npm-1.0.11-b8f1b69d3e-1be2bfa1f8.zip"; sha512 = "1be2bfa1f807608c7538afa15d6f25baa523c30ec870a3228a89579e474a4d992f4293859524e46d5d87fd30fa17c5edf34dbef0671251d9749820b488660b16"; }; "parent-module@npm:1.0.1" = { filename = "parent-module-npm-1.0.1-1fae11b095-6ba8b25514.zip"; sha512 = "6ba8b255145cae9470cf5551eb74be2d22281587af787a2626683a6c20fbb464978784661478dd2a3f1dad74d1e802d403e1b03c1a31fab310259eec8ac560ff"; }; +"parse-asn1@npm:5.1.6" = { filename = "parse-asn1-npm-5.1.6-6cc3a6eeae-9243311d1f.zip"; sha512 = "9243311d1f88089bc9f2158972aa38d1abd5452f7b7cabf84954ed766048fe574d434d82c6f5a39b988683e96fb84cd933071dda38927e03469dc8c8d14463c7"; }; "parse-conflict-json@npm:3.0.0" = { filename = "parse-conflict-json-npm-3.0.0-72604a137c-06112b03d6.zip"; sha512 = "06112b03d6506538ef4b59525627fa7c3f941b32279f049868038e34c36fb9f653da22d5418cfba43db52986464dc5229f1ce5f340444def8409556c9360bbd8"; }; "parse-json@npm:2.2.0" = { filename = "parse-json-npm-2.2.0-f7c91e74a7-dda78a63e5.zip"; sha512 = "dda78a63e57a47b713a038630868538f718a7ca0cd172a36887b0392ccf544ed0374902eb28f8bf3409e8b71d62b79d17062f8543afccf2745f9b0b2d2bb80ca"; }; "parse-json@npm:4.0.0" = { filename = "parse-json-npm-4.0.0-a6f7771010-0fe227d410.zip"; sha512 = "0fe227d410a61090c247e34fa210552b834613c006c2c64d9a05cfe9e89cf8b4246d1246b1a99524b53b313e9ac024438d0680f67e33eaed7e6f38db64cfe7b5"; }; @@ -2085,6 +2099,7 @@ cacheEntries = { "prr@npm:1.0.1" = { filename = "prr-npm-1.0.1-608d442761-3bca2db047.zip"; sha512 = "3bca2db0479fd38f8c4c9439139b0c42dcaadcc2fbb7bb8e0e6afaa1383457f1d19aea9e5f961d5b080f1cfc05bfa1fe9e45c97a1d3fd6d421950a73d3108381"; }; "pseudomap@npm:1.0.2" = { filename = "pseudomap-npm-1.0.2-0d0e40fee0-856c0aae0f.zip"; sha512 = "856c0aae0ff2ad60881168334448e898ad7a0e45fe7386d114b150084254c01e200c957cf378378025df4e052c7890c5bd933939b0e0d2ecfcc1dc2f0b2991f5"; }; "psl@npm:1.9.0" = { filename = "psl-npm-1.9.0-a546edad1a-20c4277f64.zip"; sha512 = "20c4277f640c93d393130673f392618e9a8044c6c7bf61c53917a0fddb4952790f5f362c6c730a9c32b124813e173733f9895add8d26f566ed0ea0654b2e711d"; }; +"public-encrypt@npm:4.0.3" = { filename = "public-encrypt-npm-4.0.3-b25e19fada-215d446e43.zip"; sha512 = "215d446e43cef021a20b67c1df455e5eea134af0b1f9b8a35f9e850abf32991b0c307327bc5b9bc07162c288d5cdb3d4a783ea6c6640979ed7b5017e3e0c9935"; }; "pump@npm:3.0.0" = { filename = "pump-npm-3.0.0-0080bf6a7a-e42e9229fb.zip"; sha512 = "e42e9229fba14732593a718b04cb5e1cfef8254544870997e0ecd9732b189a48e1256e4e5478148ecb47c8511dca2b09eae56b4d0aad8009e6fac8072923cfc9"; }; "punycode@npm:1.3.2" = { filename = "punycode-npm-1.3.2-3727a84cea-b8807fd594.zip"; sha512 = "b8807fd594b1db33335692d1f03e8beeddde6fda7fbb4a2e32925d88d20a3aa4cd8dcc0c109ccaccbd2ba761c208dfaaada83007087ea8bfb0129c9ef1b99ed6"; }; "punycode@npm:2.1.1" = { filename = "punycode-npm-2.1.1-26eb3e15cf-823bf443c6.zip"; sha512 = "823bf443c6dd14f669984dea25757b37993f67e8d94698996064035edd43bed8a5a17a9f12e439c2b35df1078c6bec05a6c86e336209eb1061e8025c481168e8"; }; @@ -2104,6 +2119,7 @@ cacheEntries = { "quick-lru@npm:5.1.1" = { filename = "quick-lru-npm-5.1.1-e38e0edce3-a516faa255.zip"; sha512 = "a516faa25574be7947969883e6068dbe4aa19e8ef8e8e0fd96cddd6d36485e9106d85c0041a27153286b0770b381328f4072aa40d3b18a19f5f7d2b78b94b5ed"; }; "quote-unquote@npm:1.0.0" = { filename = "quote-unquote-npm-1.0.0-5aa1091ab3-955a2ead53.zip"; sha512 = "955a2ead534f5b6a3f8d4dc5a4b95ac6468213d3fb11f8c1592a0a56345c45a3d14d5ca04d3de2bc9891493fcac38c03dfa91c48a6159aef50124e9c5afcea49"; }; "randombytes@npm:2.1.0" = { filename = "randombytes-npm-2.1.0-e3da76bccf-d779499376.zip"; sha512 = "d779499376bd4cbb435ef3ab9a957006c8682f343f14089ed5f27764e4645114196e75b7f6abf1cbd84fd247c0cb0651698444df8c9bf30e62120fbbc52269d6"; }; +"randomfill@npm:1.0.4" = { filename = "randomfill-npm-1.0.4-a08651a679-33734bb578.zip"; sha512 = "33734bb578a868d29ee1b8555e21a36711db084065d94e019a6d03caa67debef8d6a1bfd06a2b597e32901ddc761ab483a85393f0d9a75838f1912461d4dbfc7"; }; "range-parser@npm:1.2.1" = { filename = "range-parser-npm-1.2.1-1a470fa390-0a268d4fea.zip"; sha512 = "0a268d4fea508661cf5743dfe3d5f47ce214fd6b7dec1de0da4d669dd4ef3d2144468ebe4179049eff253d9d27e719c88dae55be64f954e80135a0cada804ec9"; }; "rapiq@npm:0.8.0" = { filename = "rapiq-npm-0.8.0-9680259de7-86c4d483c3.zip"; sha512 = "86c4d483c3cb7f598867464a647b879f689f77e7cf803ce08c6a6b6f1c335aa103c04a47ba3ef8f4f96081cbe89e5ab3f44bfdc07e5ea5950f72efe5f818f2a3"; }; "raw-body@npm:2.5.1" = { filename = "raw-body-npm-2.5.1-9dd1d9fff9-5362adff15.zip"; sha512 = "5362adff1575d691bb3f75998803a0ffed8c64eabeaa06e54b4ada25a0cd1b2ae7f4f5ec46565d1bec337e08b5ac90c76eaa0758de6f72a633f025d754dec29e"; }; diff --git a/yarn.lock b/yarn.lock index e84816efd57..91ce6c465a8 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3245,7 +3245,8 @@ __metadata: cli-spinners: ^2.9.0 convict: ^6.2.4 copy-webpack-plugin: ^10.2.4 - delay: 5.0.0 + crypto-browserify: ^3.12.0 + delay: ^5.0.0 dockerode: ^3.3.1 dockerode-utils: ^0.0.7 dotenv: ^16.0.1 @@ -8525,6 +8526,18 @@ __metadata: languageName: node linkType: hard +"asn1.js@npm:^5.2.0": + version: 5.4.1 + resolution: "asn1.js@npm:5.4.1" + dependencies: + bn.js: ^4.0.0 + inherits: ^2.0.1 + minimalistic-assert: ^1.0.0 + safer-buffer: ^2.1.0 + checksum: 3786a101ac6f304bd4e9a7df79549a7561950a13d4bcaec0c7790d44c80d147c1a94ba3d4e663673406064642a40b23fcd6c82a9952468e386c1a1376d747f9a + languageName: node + linkType: hard + "asn1@npm:^0.2.4, asn1@npm:~0.2.3": version: 0.2.6 resolution: "asn1@npm:0.2.6" @@ -9170,14 +9183,14 @@ __metadata: languageName: node linkType: hard -"bn.js@npm:^4.11.8, bn.js@npm:^4.11.9": +"bn.js@npm:^4.0.0, bn.js@npm:^4.1.0, bn.js@npm:^4.11.8, bn.js@npm:^4.11.9": version: 4.12.0 resolution: "bn.js@npm:4.12.0" checksum: 39afb4f15f4ea537b55eaf1446c896af28ac948fdcf47171961475724d1bb65118cca49fa6e3d67706e4790955ec0e74de584e45c8f1ef89f46c812bee5b5a12 languageName: node linkType: hard -"bn.js@npm:^5.1.1, bn.js@npm:^5.2.1": +"bn.js@npm:^5.0.0, bn.js@npm:^5.1.1, bn.js@npm:^5.2.1": version: 5.2.1 resolution: "bn.js@npm:5.2.1" checksum: 3dd8c8d38055fedfa95c1d5fc3c99f8dd547b36287b37768db0abab3c239711f88ff58d18d155dd8ad902b0b0cee973747b7ae20ea12a09473272b0201c9edd3 @@ -9253,7 +9266,7 @@ __metadata: languageName: node linkType: hard -"brorand@npm:^1.0.5, brorand@npm:^1.1.0": +"brorand@npm:^1.0.1, brorand@npm:^1.0.5, brorand@npm:^1.1.0": version: 1.1.0 resolution: "brorand@npm:1.1.0" checksum: 8a05c9f3c4b46572dec6ef71012b1946db6cae8c7bb60ccd4b7dd5a84655db49fe043ecc6272e7ef1f69dc53d6730b9e2a3a03a8310509a3d797a618cbee52be @@ -9281,6 +9294,70 @@ __metadata: languageName: node linkType: hard +"browserify-aes@npm:^1.0.0, browserify-aes@npm:^1.0.4": + version: 1.2.0 + resolution: "browserify-aes@npm:1.2.0" + dependencies: + buffer-xor: ^1.0.3 + cipher-base: ^1.0.0 + create-hash: ^1.1.0 + evp_bytestokey: ^1.0.3 + inherits: ^2.0.1 + safe-buffer: ^5.0.1 + checksum: 4a17c3eb55a2aa61c934c286f34921933086bf6d67f02d4adb09fcc6f2fc93977b47d9d884c25619144fccd47b3b3a399e1ad8b3ff5a346be47270114bcf7104 + languageName: node + linkType: hard + +"browserify-cipher@npm:^1.0.0": + version: 1.0.1 + resolution: "browserify-cipher@npm:1.0.1" + dependencies: + browserify-aes: ^1.0.4 + browserify-des: ^1.0.0 + evp_bytestokey: ^1.0.0 + checksum: 2d8500acf1ee535e6bebe808f7a20e4c3a9e2ed1a6885fff1facbfd201ac013ef030422bec65ca9ece8ffe82b03ca580421463f9c45af6c8415fd629f4118c13 + languageName: node + linkType: hard + +"browserify-des@npm:^1.0.0": + version: 1.0.2 + resolution: "browserify-des@npm:1.0.2" + dependencies: + cipher-base: ^1.0.1 + des.js: ^1.0.0 + inherits: ^2.0.1 + safe-buffer: ^5.1.2 + checksum: b15a3e358a1d78a3b62ddc06c845d02afde6fc826dab23f1b9c016e643e7b1fda41de628d2110b712f6a44fb10cbc1800bc6872a03ddd363fb50768e010395b7 + languageName: node + linkType: hard + +"browserify-rsa@npm:^4.0.0, browserify-rsa@npm:^4.0.1": + version: 4.1.0 + resolution: "browserify-rsa@npm:4.1.0" + dependencies: + bn.js: ^5.0.0 + randombytes: ^2.0.1 + checksum: 155f0c135873efc85620571a33d884aa8810e40176125ad424ec9d85016ff105a07f6231650914a760cca66f29af0494087947b7be34880dd4599a0cd3c38e54 + languageName: node + linkType: hard + +"browserify-sign@npm:^4.0.0": + version: 4.2.1 + resolution: "browserify-sign@npm:4.2.1" + dependencies: + bn.js: ^5.1.1 + browserify-rsa: ^4.0.1 + create-hash: ^1.2.0 + create-hmac: ^1.1.7 + elliptic: ^6.5.3 + inherits: ^2.0.4 + parse-asn1: ^5.1.5 + readable-stream: ^3.6.0 + safe-buffer: ^5.2.0 + checksum: 0221f190e3f5b2d40183fa51621be7e838d9caa329fe1ba773406b7637855f37b30f5d83e52ff8f244ed12ffe6278dd9983638609ed88c841ce547e603855707 + languageName: node + linkType: hard + "browserslist@npm:^4.14.5, browserslist@npm:^4.21.3, browserslist@npm:^4.21.4": version: 4.21.4 resolution: "browserslist@npm:4.21.4" @@ -9387,6 +9464,13 @@ __metadata: languageName: node linkType: hard +"buffer-xor@npm:^1.0.3": + version: 1.0.3 + resolution: "buffer-xor@npm:1.0.3" + checksum: 10c520df29d62fa6e785e2800e586a20fc4f6dfad84bcdbd12e1e8a83856de1cb75c7ebd7abe6d036bbfab738a6cf18a3ae9c8e5a2e2eb3167ca7399ce65373a + languageName: node + linkType: hard + "buffer@npm:4.9.2": version: 4.9.2 resolution: "buffer@npm:4.9.2" @@ -9990,7 +10074,7 @@ __metadata: languageName: node linkType: hard -"cipher-base@npm:^1.0.1, cipher-base@npm:^1.0.3": +"cipher-base@npm:^1.0.0, cipher-base@npm:^1.0.1, cipher-base@npm:^1.0.3": version: 1.0.4 resolution: "cipher-base@npm:1.0.4" dependencies: @@ -10828,6 +10912,16 @@ __metadata: languageName: node linkType: hard +"create-ecdh@npm:^4.0.0": + version: 4.0.4 + resolution: "create-ecdh@npm:4.0.4" + dependencies: + bn.js: ^4.1.0 + elliptic: ^6.5.3 + checksum: 0dd7fca9711d09e152375b79acf1e3f306d1a25ba87b8ff14c2fd8e68b83aafe0a7dd6c4e540c9ffbdd227a5fa1ad9b81eca1f233c38bb47770597ba247e614b + languageName: node + linkType: hard + "create-hash@npm:^1.1.0, create-hash@npm:^1.1.2, create-hash@npm:^1.2.0": version: 1.2.0 resolution: "create-hash@npm:1.2.0" @@ -10841,7 +10935,7 @@ __metadata: languageName: node linkType: hard -"create-hmac@npm:^1.1.4, create-hmac@npm:^1.1.7": +"create-hmac@npm:^1.1.0, create-hmac@npm:^1.1.4, create-hmac@npm:^1.1.7": version: 1.1.7 resolution: "create-hmac@npm:1.1.7" dependencies: @@ -10923,6 +11017,25 @@ __metadata: languageName: node linkType: hard +"crypto-browserify@npm:^3.12.0": + version: 3.12.0 + resolution: "crypto-browserify@npm:3.12.0" + dependencies: + browserify-cipher: ^1.0.0 + browserify-sign: ^4.0.0 + create-ecdh: ^4.0.0 + create-hash: ^1.1.0 + create-hmac: ^1.1.0 + diffie-hellman: ^5.0.0 + inherits: ^2.0.1 + pbkdf2: ^3.0.3 + public-encrypt: ^4.0.0 + randombytes: ^2.0.0 + randomfill: ^1.0.3 + checksum: c1609af82605474262f3eaa07daa0b2140026bd264ab316d4bf1170272570dbe02f0c49e29407fe0d3634f96c507c27a19a6765fb856fed854a625f9d15618e2 + languageName: node + linkType: hard + "css-select@npm:^5.1.0": version: 5.1.0 resolution: "css-select@npm:5.1.0" @@ -11319,7 +11432,7 @@ __metadata: languageName: node linkType: hard -"delay@npm:5.0.0, delay@npm:^5.0.0": +"delay@npm:^5.0.0": version: 5.0.0 resolution: "delay@npm:5.0.0" checksum: 62f151151ecfde0d9afbb8a6be37a6d103c4cb24f35a20ef3fe56f920b0d0d0bb02bc9c0a3084d0179ef669ca332b91155f2ee4d9854622cd2cdba5fc95285f9 @@ -11390,6 +11503,16 @@ __metadata: languageName: node linkType: hard +"des.js@npm:^1.0.0": + version: 1.0.1 + resolution: "des.js@npm:1.0.1" + dependencies: + inherits: ^2.0.1 + minimalistic-assert: ^1.0.0 + checksum: 1ec2eedd7ed6bd61dd5e0519fd4c96124e93bb22de8a9d211b02d63e5dd152824853d919bb2090f965cc0e3eb9c515950a9836b332020d810f9c71feb0fd7df4 + languageName: node + linkType: hard + "destr@npm:^1.2.2": version: 1.2.2 resolution: "destr@npm:1.2.2" @@ -11663,6 +11786,17 @@ __metadata: languageName: node linkType: hard +"diffie-hellman@npm:^5.0.0": + version: 5.0.3 + resolution: "diffie-hellman@npm:5.0.3" + dependencies: + bn.js: ^4.1.0 + miller-rabin: ^4.0.0 + randombytes: ^2.0.0 + checksum: 0e620f322170c41076e70181dd1c24e23b08b47dbb92a22a644f3b89b6d3834b0f8ee19e37916164e5eb1ee26d2aa836d6129f92723995267250a0b541811065 + languageName: node + linkType: hard + "dir-glob@npm:^3.0.1": version: 3.0.1 resolution: "dir-glob@npm:3.0.1" @@ -11946,7 +12080,7 @@ __metadata: languageName: node linkType: hard -"elliptic@npm:^6.4.0, elliptic@npm:^6.5.4": +"elliptic@npm:^6.4.0, elliptic@npm:^6.5.3, elliptic@npm:^6.5.4": version: 6.5.4 resolution: "elliptic@npm:6.5.4" dependencies: @@ -12793,6 +12927,17 @@ __metadata: languageName: node linkType: hard +"evp_bytestokey@npm:^1.0.0, evp_bytestokey@npm:^1.0.3": + version: 1.0.3 + resolution: "evp_bytestokey@npm:1.0.3" + dependencies: + md5.js: ^1.3.4 + node-gyp: latest + safe-buffer: ^5.1.1 + checksum: ad4e1577f1a6b721c7800dcc7c733fe01f6c310732bb5bf2240245c2a5b45a38518b91d8be2c610611623160b9d1c0e91f1ce96d639f8b53e8894625cf20fa45 + languageName: node + linkType: hard + "execa@npm:^1.0.0": version: 1.0.0 resolution: "execa@npm:1.0.0" @@ -17891,6 +18036,18 @@ __metadata: languageName: node linkType: hard +"miller-rabin@npm:^4.0.0": + version: 4.0.1 + resolution: "miller-rabin@npm:4.0.1" + dependencies: + bn.js: ^4.0.0 + brorand: ^1.0.1 + bin: + miller-rabin: bin/miller-rabin + checksum: 00cd1ab838ac49b03f236cc32a14d29d7d28637a53096bf5c6246a032a37749c9bd9ce7360cbf55b41b89b7d649824949ff12bc8eee29ac77c6b38eada619ece + languageName: node + linkType: hard + "mime-db@npm:1.52.0": version: 1.52.0 resolution: "mime-db@npm:1.52.0" @@ -19739,6 +19896,19 @@ __metadata: languageName: node linkType: hard +"parse-asn1@npm:^5.0.0, parse-asn1@npm:^5.1.5": + version: 5.1.6 + resolution: "parse-asn1@npm:5.1.6" + dependencies: + asn1.js: ^5.2.0 + browserify-aes: ^1.0.0 + evp_bytestokey: ^1.0.0 + pbkdf2: ^3.0.3 + safe-buffer: ^5.1.1 + checksum: 9243311d1f88089bc9f2158972aa38d1abd5452f7b7cabf84954ed766048fe574d434d82c6f5a39b988683e96fb84cd933071dda38927e03469dc8c8d14463c7 + languageName: node + linkType: hard + "parse-conflict-json@npm:^3.0.0": version: 3.0.0 resolution: "parse-conflict-json@npm:3.0.0" @@ -20001,7 +20171,7 @@ __metadata: languageName: node linkType: hard -"pbkdf2@npm:^3.0.9, pbkdf2@npm:^3.1.2": +"pbkdf2@npm:^3.0.3, pbkdf2@npm:^3.0.9, pbkdf2@npm:^3.1.2": version: 3.1.2 resolution: "pbkdf2@npm:3.1.2" dependencies: @@ -20882,6 +21052,20 @@ __metadata: languageName: node linkType: hard +"public-encrypt@npm:^4.0.0": + version: 4.0.3 + resolution: "public-encrypt@npm:4.0.3" + dependencies: + bn.js: ^4.1.0 + browserify-rsa: ^4.0.0 + create-hash: ^1.1.0 + parse-asn1: ^5.0.0 + randombytes: ^2.0.1 + safe-buffer: ^5.1.2 + checksum: 215d446e43cef021a20b67c1df455e5eea134af0b1f9b8a35f9e850abf32991b0c307327bc5b9bc07162c288d5cdb3d4a783ea6c6640979ed7b5017e3e0c9935 + languageName: node + linkType: hard + "pump@npm:^3.0.0": version: 3.0.0 resolution: "pump@npm:3.0.0" @@ -21032,7 +21216,7 @@ __metadata: languageName: node linkType: hard -"randombytes@npm:2.1.0, randombytes@npm:^2.0.1, randombytes@npm:^2.1.0": +"randombytes@npm:2.1.0, randombytes@npm:^2.0.0, randombytes@npm:^2.0.1, randombytes@npm:^2.0.5, randombytes@npm:^2.1.0": version: 2.1.0 resolution: "randombytes@npm:2.1.0" dependencies: @@ -21041,6 +21225,16 @@ __metadata: languageName: node linkType: hard +"randomfill@npm:^1.0.3": + version: 1.0.4 + resolution: "randomfill@npm:1.0.4" + dependencies: + randombytes: ^2.0.5 + safe-buffer: ^5.1.0 + checksum: 33734bb578a868d29ee1b8555e21a36711db084065d94e019a6d03caa67debef8d6a1bfd06a2b597e32901ddc761ab483a85393f0d9a75838f1912461d4dbfc7 + languageName: node + linkType: hard + "range-parser@npm:~1.2.1": version: 1.2.1 resolution: "range-parser@npm:1.2.1" From 149e73119aceb2acabfff9a0922edc0df7bb054b Mon Sep 17 00:00:00 2001 From: Angel Castillo Date: Fri, 20 Jan 2023 04:03:43 +0000 Subject: [PATCH 2/4] feat(crypto): added BIP-32 key management and derivation to crypto package --- .../crypto/src/Bip32/Bip32KeyDerivation.ts | 21 +- packages/crypto/src/Bip32/Bip32PrivateKey.ts | 183 ++++++++++++++++++ packages/crypto/src/Bip32/Bip32PublicKey.ts | 85 ++++++++ packages/crypto/src/Bip32/index.ts | 2 + packages/crypto/src/index.ts | 3 + .../crypto/test/bip32/Bip32PrivateKey.test.ts | 72 +++++++ .../crypto/test/bip32/Bip32PublicKey.test.ts | 50 +++++ 7 files changed, 406 insertions(+), 10 deletions(-) create mode 100644 packages/crypto/src/Bip32/Bip32PrivateKey.ts create mode 100644 packages/crypto/src/Bip32/Bip32PublicKey.ts create mode 100644 packages/crypto/src/Bip32/index.ts create mode 100644 packages/crypto/test/bip32/Bip32PrivateKey.test.ts create mode 100644 packages/crypto/test/bip32/Bip32PublicKey.test.ts diff --git a/packages/crypto/src/Bip32/Bip32KeyDerivation.ts b/packages/crypto/src/Bip32/Bip32KeyDerivation.ts index 5d07adcf86b..8b7fed9d199 100644 --- a/packages/crypto/src/Bip32/Bip32KeyDerivation.ts +++ b/packages/crypto/src/Bip32/Bip32KeyDerivation.ts @@ -1,9 +1,10 @@ import { BN } from 'bn.js'; -import { InvalidArgumentError } from '../errors'; -import { crypto_auth_hmacsha512, crypto_scalarmult_ed25519_base_noclamp } from 'libsodium-wrappers-sumo'; -import { eddsa } from 'elliptic'; - -const ed25519 = new eddsa('ed25519'); +import { InvalidArgumentError } from '@cardano-sdk/util'; +import { + crypto_auth_hmacsha512, + crypto_core_ed25519_add, + crypto_scalarmult_ed25519_base_noclamp +} from 'libsodium-wrappers-sumo'; /** * Check if the index is hardened. @@ -78,8 +79,9 @@ const truc28Mul8 = (lhs: Uint8Array, rhs: Uint8Array): Buffer => * @param sk The secret key. */ const pointOfTrunc28Mul8 = (sk: Uint8Array) => { - const left = new BN(sk.slice(0, 28), 16, 'le').mul(new BN(8)); - return ed25519.curve.g.mul(left); + const left = new BN(sk.slice(0, 28), 16, 'le').mul(new BN(8)).toArrayLike(Buffer, 'le', 32); + + return crypto_scalarmult_ed25519_base_noclamp(left); }; /** @@ -165,11 +167,10 @@ export const derivePublic = (key: Buffer, index: number): Buffer => { const c = crypto_auth_hmacsha512(data, cc); const chainCode = c.slice(32, 64); + const zl = z.slice(0, 32); const p = pointOfTrunc28Mul8(zl); - const pp = ed25519.decodePoint(pk.toString('hex')); - const point = pp.add(p); - return Buffer.concat([Buffer.from(ed25519.encodePoint(point)), chainCode]); + return Buffer.concat([crypto_core_ed25519_add(p, pk), chainCode]); }; diff --git a/packages/crypto/src/Bip32/Bip32PrivateKey.ts b/packages/crypto/src/Bip32/Bip32PrivateKey.ts new file mode 100644 index 00000000000..825f75481ba --- /dev/null +++ b/packages/crypto/src/Bip32/Bip32PrivateKey.ts @@ -0,0 +1,183 @@ +/* eslint-disable no-bitwise */ +import * as Bip32KeyDerivation from './Bip32KeyDerivation'; +import { Bip32PrivateKeyHex } from '../hexTypes'; +import { Bip32PublicKey } from './Bip32PublicKey'; +import { EXTENDED_ED25519_PRIVATE_KEY_LENGTH, Ed25519PrivateKey, NORMAL_ED25519_PRIVATE_KEY_LENGTH } from '../Ed25519e'; +import { InvalidArgumentError } from '@cardano-sdk/util'; +import { crypto_scalarmult_ed25519_base_noclamp, ready } from 'libsodium-wrappers-sumo'; +import { pbkdf2 } from 'pbkdf2'; + +const SCALAR_INDEX = 0; +const SCALAR_SIZE = 32; +const PBKDF2_ITERATIONS = 4096; +const PBKDF2_KEY_SIZE = 96; +const PBKDF2_DIGEST_ALGORITHM = 'sha512'; +const CHAIN_CODE_INDEX = 64; +const CHAIN_CODE_SIZE = 32; + +/** + * clamp the scalar by: + * + * 1. clearing the 3 lower bits. + * 2. clearing the three highest bits. + * 3. setting the second-highest bit. + * + * @param scalar The clamped scalar. + */ +const clampScalar = (scalar: Buffer): Buffer => { + scalar[0] &= 0b1111_1000; + scalar[31] &= 0b0001_1111; + scalar[31] |= 0b0100_0000; + return scalar; +}; + +/** + * Extract the scalar part (first 32 bytes) from the extended key. + * + * @param extendedKey The extended key. + * @returns the scalar part of the extended key. + */ +const extendedScalar = (extendedKey: Uint8Array) => extendedKey.slice(SCALAR_INDEX, SCALAR_SIZE); + +export const BIP32_ED25519_PRIVATE_KEY_LENGTH = 96; + +/** + * Bip32PrivateKey private key. This type of key have the ability to derive additional keys from them + * following the BIP-32 derivation scheme variant called BIP32-Ed25519. + * + * @see + * BIP32-Ed25519: Hierarchical Deterministic Keys over a Non-linear Keyspace + * + */ +export class Bip32PrivateKey { + readonly #key: Uint8Array; + + /** + * Initializes a new instance of the Bip32PrivateKey class. + * + * @param key The BIP-32 private key. + */ + constructor(key: Uint8Array) { + this.#key = key; + } + + /** + * Turns an initial entropy into a secure cryptographic master key. + * + * To generate a BIP32PrivateKey from a BIP39 recovery phrase it must be first converted to entropy following + * the BIP39 protocol. + * + * The resulting extended Ed25519 secret key composed of: + * - 32 bytes: Ed25519 curve scalar from which few bits have been tweaked according to ED25519-BIP32 + * - 32 bytes: Ed25519 binary blob used as IV for signing + * + * @param entropy Random stream of bytes generated from a BIP39 seed phrase. + * @param password The second factor authentication password for the mnemonic phrase. + * @returns The secret extended key. + */ + static fromBip39Entropy(entropy: Buffer, password: string): Promise { + return new Promise((resolve, reject) => { + pbkdf2(password, entropy, PBKDF2_ITERATIONS, PBKDF2_KEY_SIZE, PBKDF2_DIGEST_ALGORITHM, (err, xprv) => { + if (err) { + reject(err); + } + + xprv = clampScalar(xprv); + resolve(Bip32PrivateKey.fromBytes(xprv)); + }); + }); + } + + /** + * Initializes a new Bip32PrivateKey provided as a byte array. + * + * @param key The BIP-32 private key. + */ + static fromBytes(key: Uint8Array) { + if (key.length !== BIP32_ED25519_PRIVATE_KEY_LENGTH) + throw new InvalidArgumentError( + 'key', + `Key should be ${NORMAL_ED25519_PRIVATE_KEY_LENGTH} bytes; however ${key.length} bytes were provided.` + ); + return new Bip32PrivateKey(key); + } + + /** + * Initializes a new instance of the Bip32PrivateKey class from its key material provided as a hex string. + * + * @param key The key as a hex string. + */ + static fromHex(key: Bip32PrivateKeyHex) { + return Bip32PrivateKey.fromBytes(Buffer.from(key, 'hex')); + } + + /** + * Given a set of indices, this function computes the corresponding child extended key. + * + * # Security considerations + * + * hard derivation index cannot be soft derived with the public key. + * + * # Hard derivation vs Soft derivation + * + * If you pass an index below 0x80000000 then it is a soft derivation. + * The advantage of soft derivation is that it is possible to derive the + * public key too. I.e. derivation the private key with a soft derivation + * index and then retrieving the associated public key is equivalent to + * deriving the public key associated to the parent private key. + * + * Hard derivation index does not allow public key derivation. + * + * This is why deriving the private key should not fail while deriving + * the public key may fail (if the derivation index is invalid). + * + * @param derivationIndices The derivation indices. + * @returns The child BIP-32 key. + */ + async derive(derivationIndices: number[]): Promise { + await ready; + let key = Buffer.from(this.#key); + + for (const index of derivationIndices) { + key = Bip32KeyDerivation.derivePrivate(key, index); + } + + return Bip32PrivateKey.fromBytes(key); + } + + /** + * Gets the Ed25519 raw private key. This key can be used for cryptographically signing messages. + */ + toRawKey(): Ed25519PrivateKey { + return Ed25519PrivateKey.fromExtendedBytes(this.#key.slice(0, EXTENDED_ED25519_PRIVATE_KEY_LENGTH)); + } + + /** + * Computes the BIP-32 public key from this BIP-32 private key. + * + * @returns the public key. + */ + async toPublic(): Promise { + await ready; + const scalar = extendedScalar(this.#key.slice(0, EXTENDED_ED25519_PRIVATE_KEY_LENGTH)); + const publicKey = crypto_scalarmult_ed25519_base_noclamp(scalar); + + return Bip32PublicKey.fromBytes( + Buffer.concat([publicKey, this.#key.slice(CHAIN_CODE_INDEX, CHAIN_CODE_INDEX + CHAIN_CODE_SIZE)]) + ); + } + + /** + * Gets the BIP-32 private key as a byte array. + */ + bytes(): Uint8Array { + return this.#key; + } + + /** + * Gets the BIP-32 private key as a hex string. + */ + hex(): Bip32PrivateKeyHex { + return Bip32PrivateKeyHex(Buffer.from(this.#key).toString('hex')); + } +} diff --git a/packages/crypto/src/Bip32/Bip32PublicKey.ts b/packages/crypto/src/Bip32/Bip32PublicKey.ts new file mode 100644 index 00000000000..e915c59feba --- /dev/null +++ b/packages/crypto/src/Bip32/Bip32PublicKey.ts @@ -0,0 +1,85 @@ +import * as Bip32KeyDerivation from './Bip32KeyDerivation'; +import { Bip32PublicKeyHex } from '../hexTypes'; +import { ED25519_PUBLIC_KEY_LENGTH, Ed25519PublicKey } from '../Ed25519e'; +import { InvalidArgumentError } from '@cardano-sdk/util'; +import { ready } from 'libsodium-wrappers-sumo'; + +export const BIP32_ED25519_PUBLIC_KEY_LENGTH = 64; + +/** + * BIP32 public key. + */ +export class Bip32PublicKey { + readonly #key: Uint8Array; + + /** + * Initializes a new instance of the Bip32PublicKey class. + * + * @param key The BIP32 public key. + */ + private constructor(key: Uint8Array) { + this.#key = key; + } + + /** + * Initializes a new Bip32PublicKey provided as a byte array. + * + * @param key The BIP32 public key. + */ + static fromBytes(key: Uint8Array): Bip32PublicKey { + if (key.length !== BIP32_ED25519_PUBLIC_KEY_LENGTH) + throw new InvalidArgumentError( + 'key', + `Key should be ${BIP32_ED25519_PUBLIC_KEY_LENGTH} bytes; however ${key.length} bytes were provided.` + ); + return new Bip32PublicKey(key); + } + + /** + * Initializes a new instance of the Bip32PublicKey class from its key material provided as a hex string. + * + * @param key The key as a hex string. + */ + static fromHex(key: Bip32PublicKeyHex): Bip32PublicKey { + return Bip32PublicKey.fromBytes(Buffer.from(key, 'hex')); + } + + /** + * Gets the Ed25519 raw public key. This key can be used for cryptographically verifying messages + * previously signed with the matching Ed25519 raw private key. + */ + toRawKey(): Ed25519PublicKey { + return Ed25519PublicKey.fromBytes(this.#key.slice(0, ED25519_PUBLIC_KEY_LENGTH)); + } + + /** + * Given a set of indices, this function computes the corresponding child extended key. + * + * @param derivationIndices The list of derivation indices. + * @returns The child extended private key. + */ + async derive(derivationIndices: number[]): Promise { + await ready; + let key = Buffer.from(this.#key); + + for (const index of derivationIndices) { + key = Bip32KeyDerivation.derivePublic(key, index); + } + + return Bip32PublicKey.fromBytes(key); + } + + /** + * Gets the Bip32PublicKey as a byte array. + */ + bytes(): Uint8Array { + return this.#key; + } + + /** + * Gets the Bip32PublicKey as a hex string. + */ + hex(): Bip32PublicKeyHex { + return Bip32PublicKeyHex(Buffer.from(this.#key).toString('hex')); + } +} diff --git a/packages/crypto/src/Bip32/index.ts b/packages/crypto/src/Bip32/index.ts new file mode 100644 index 00000000000..a1c97ff1822 --- /dev/null +++ b/packages/crypto/src/Bip32/index.ts @@ -0,0 +1,2 @@ +export * from './Bip32PrivateKey'; +export * from './Bip32PublicKey'; diff --git a/packages/crypto/src/index.ts b/packages/crypto/src/index.ts index 404ea286f23..db819acc77d 100644 --- a/packages/crypto/src/index.ts +++ b/packages/crypto/src/index.ts @@ -1,6 +1,9 @@ import blake2b from 'blake2b'; export { blake2b }; + +export * from './Bip32'; export * from './Bip32Ed25519'; +export * from './Ed25519e'; export * from './strategies'; export * from './hexTypes'; export * from './types'; diff --git a/packages/crypto/test/bip32/Bip32PrivateKey.test.ts b/packages/crypto/test/bip32/Bip32PrivateKey.test.ts new file mode 100644 index 00000000000..3bc362dfbfa --- /dev/null +++ b/packages/crypto/test/bip32/Bip32PrivateKey.test.ts @@ -0,0 +1,72 @@ +import * as Crypto from '../../src'; +import { InvalidStringError } from '@cardano-sdk/util'; +import { bip32TestVectorMessageOneLength, extendedVectors } from '../ed25519e/Ed25519TestVectors'; + +describe('Bip32PrivateKey', () => { + it('can create an instance from a valid normal BIP-32 private key hex representation', async () => { + const privateKey = Crypto.Bip32PrivateKey.fromHex( + Crypto.Bip32PrivateKeyHex(bip32TestVectorMessageOneLength.rootKey) + ); + expect(privateKey.hex()).toBe(bip32TestVectorMessageOneLength.rootKey); + }); + + it('can create an instance from a valid normal BIP-32 private key raw binary representation', () => { + const bytes = Buffer.from(bip32TestVectorMessageOneLength.rootKey, 'hex'); + const privateKey = Crypto.Bip32PrivateKey.fromBytes(bytes); + + expect(privateKey.bytes()).toBe(bytes); + }); + + it('throws if a BIP-32 private key of invalid size is given.', () => { + expect(() => Crypto.Bip32PrivateKey.fromHex(Crypto.Bip32PrivateKeyHex('1f'))).toThrow(InvalidStringError); + expect(() => + Crypto.Bip32PrivateKey.fromHex(Crypto.Bip32PrivateKeyHex(`${bip32TestVectorMessageOneLength.rootKey}1f2f3f`)) + ).toThrow(InvalidStringError); + }); + + it('can create the correct BIP-32 key given the right bip39 entropy and password.', async () => { + expect.assertions(extendedVectors.length); + + for (const vector of extendedVectors) { + const bip32Key = await Crypto.Bip32PrivateKey.fromBip39Entropy( + Buffer.from(vector.bip39Entropy, 'hex'), + vector.password + ); + + expect(bip32Key.hex()).toBe(vector.rootKey); + } + }); + + it('can derive the correct child BIP-32 private key given a derivation path.', async () => { + expect.assertions(extendedVectors.length); + + for (const vector of extendedVectors) { + const rootKey = await Crypto.Bip32PrivateKey.fromHex(Crypto.Bip32PrivateKeyHex(vector.rootKey)); + const childKey = await rootKey.derive(vector.derivationPath); + + expect(childKey.hex()).toBe(vector.childPrivateKey); + } + }); + + it('can compute the matching BIP-32 public key.', async () => { + expect.assertions(extendedVectors.length); + + for (const vector of extendedVectors) { + const rootKey = await Crypto.Bip32PrivateKey.fromHex(Crypto.Bip32PrivateKeyHex(vector.rootKey)); + const publicKey = await rootKey.toPublic(); + + expect(publicKey.hex()).toBe(vector.publicKey); + } + }); + + it('can compute the correct ED25519e raw private key.', async () => { + expect.assertions(extendedVectors.length); + + for (const vector of extendedVectors) { + const rootKey = await Crypto.Bip32PrivateKey.fromHex(Crypto.Bip32PrivateKeyHex(vector.rootKey)); + const rawKey = await rootKey.toRawKey(); + + expect(rawKey.hex()).toBe(vector.ed25519eVector.secretKey); + } + }); +}); diff --git a/packages/crypto/test/bip32/Bip32PublicKey.test.ts b/packages/crypto/test/bip32/Bip32PublicKey.test.ts new file mode 100644 index 00000000000..f30ab30cab5 --- /dev/null +++ b/packages/crypto/test/bip32/Bip32PublicKey.test.ts @@ -0,0 +1,50 @@ +import * as Crypto from '../../src'; +import { InvalidStringError } from '@cardano-sdk/util'; +import { + bip32TestVectorMessageOneLength, + bip32TestVectorMessageShaOfAbcUnhardened, + extendedVectors +} from '../ed25519e/Ed25519TestVectors'; + +describe('Bip32PublicKey', () => { + it('can create an instance from a valid normal BIP-32 public key hex representation', async () => { + const publicKey = Crypto.Bip32PublicKey.fromHex( + Crypto.Bip32PublicKeyHex(bip32TestVectorMessageOneLength.publicKey) + ); + expect(publicKey.hex()).toBe(bip32TestVectorMessageOneLength.publicKey); + }); + + it('can create an instance from a valid normal BIP-32 public key raw binary representation', () => { + const bytes = Buffer.from(bip32TestVectorMessageOneLength.publicKey, 'hex'); + const publicKey = Crypto.Bip32PublicKey.fromBytes(bytes); + + expect(publicKey.bytes()).toBe(bytes); + }); + + it('throws if a BIP-32 public key of invalid size is given.', () => { + expect(() => Crypto.Bip32PublicKey.fromHex(Crypto.Bip32PublicKeyHex('1f'))).toThrow(InvalidStringError); + expect(() => + Crypto.Bip32PublicKey.fromHex(Crypto.Bip32PublicKeyHex(`${bip32TestVectorMessageOneLength.publicKey}1f2f3f`)) + ).toThrow(InvalidStringError); + }); + + it('can derive the correct child BIP-32 public key given a derivation path.', async () => { + const rootKey = await Crypto.Bip32PublicKey.fromHex( + Crypto.Bip32PublicKeyHex(bip32TestVectorMessageShaOfAbcUnhardened.publicKey) + ); + const childKey = await rootKey.derive(bip32TestVectorMessageShaOfAbcUnhardened.derivationPath); + + expect(childKey.hex()).toBe(bip32TestVectorMessageShaOfAbcUnhardened.childPublicKey); + }); + + it('can compute the correct ED25519e raw public key.', async () => { + expect.assertions(extendedVectors.length); + + for (const vector of extendedVectors) { + const rootKey = await Crypto.Bip32PublicKey.fromHex(Crypto.Bip32PublicKeyHex(vector.publicKey)); + const rawKey = await rootKey.toRawKey(); + + expect(rawKey.hex()).toBe(vector.ed25519eVector.publicKey); + } + }); +}); From 47011d4f4a21f91b1c566f7a6eef0b8157bfa87e Mon Sep 17 00:00:00 2001 From: Angel Castillo Date: Tue, 7 Feb 2023 01:49:51 +0000 Subject: [PATCH 3/4] feat(crypto): added libSodium based Bip32Ed25519 implementation --- .../src/strategies/SodiumBip32Ed25519.ts | 88 +++++++++++++++++++ packages/crypto/src/strategies/index.ts | 1 + .../test/strategies/Bip32Ed25519.test.ts | 1 + 3 files changed, 90 insertions(+) create mode 100644 packages/crypto/src/strategies/SodiumBip32Ed25519.ts diff --git a/packages/crypto/src/strategies/SodiumBip32Ed25519.ts b/packages/crypto/src/strategies/SodiumBip32Ed25519.ts new file mode 100644 index 00000000000..87221148fea --- /dev/null +++ b/packages/crypto/src/strategies/SodiumBip32Ed25519.ts @@ -0,0 +1,88 @@ +import { BIP32Path } from '../types'; +import { Bip32Ed25519 } from '../Bip32Ed25519'; +import { Bip32PrivateKey, Bip32PublicKey } from '../Bip32'; +import { + Bip32PrivateKeyHex, + Bip32PublicKeyHex, + Ed25519KeyHashHex, + Ed25519PrivateExtendedKeyHex, + Ed25519PrivateNormalKeyHex, + Ed25519PublicKeyHex, + Ed25519SignatureHex +} from '../hexTypes'; +import { Ed25519PrivateKey, Ed25519PublicKey, Ed25519Signature } from '../Ed25519e'; +import { HexBlob } from '@cardano-sdk/util'; + +const EXTENDED_KEY_HEX_LENGTH = 128; + +export class SodiumBip32Ed25519 implements Bip32Ed25519 { + public async fromBip39Entropy(entropy: Buffer, passphrase: string): Promise { + return (await Bip32PrivateKey.fromBip39Entropy(entropy, passphrase)).hex(); + } + + public async getPublicKey( + privateKey: Ed25519PrivateExtendedKeyHex | Ed25519PrivateNormalKeyHex + ): Promise { + const key = + privateKey.length === EXTENDED_KEY_HEX_LENGTH + ? Ed25519PrivateKey.fromExtendedHex(privateKey) + : Ed25519PrivateKey.fromNormalHex(privateKey); + + return (await key.toPublic()).hex(); + } + + public async getPubKeyHash(publicKey: Ed25519PublicKeyHex): Promise { + const pubKey = await Ed25519PublicKey.fromHex(publicKey); + + return (await pubKey.hash()).hex(); + } + + public async getRawPrivateKey(bip32PrivateKey: Bip32PrivateKeyHex): Promise { + return (await Bip32PrivateKey.fromHex(bip32PrivateKey)).toRawKey().hex(); + } + + public async getRawPublicKey(bip32PublicKey: Bip32PublicKeyHex): Promise { + const pubKey = await Bip32PublicKey.fromHex(bip32PublicKey); + return (await pubKey.toRawKey()).hex(); + } + + public async getBip32PublicKey(privateKey: Bip32PrivateKeyHex): Promise { + const privKey = await Bip32PrivateKey.fromHex(privateKey); + return (await privKey.toPublic()).hex(); + } + + public async derivePrivateKey( + parentKey: Bip32PrivateKeyHex, + derivationIndices: BIP32Path + ): Promise { + const privKey = await Bip32PrivateKey.fromHex(parentKey); + return (await privKey.derive(derivationIndices)).hex(); + } + + public async derivePublicKey(parentKey: Bip32PublicKeyHex, derivationIndices: BIP32Path): Promise { + const pubKey = await Bip32PublicKey.fromHex(parentKey); + return (await pubKey.derive(derivationIndices)).hex(); + } + + public async sign( + privateKey: Ed25519PrivateExtendedKeyHex | Ed25519PrivateNormalKeyHex, + message: HexBlob + ): Promise { + const key = + privateKey.length === EXTENDED_KEY_HEX_LENGTH + ? Ed25519PrivateKey.fromExtendedHex(privateKey) + : Ed25519PrivateKey.fromNormalHex(privateKey); + + return (await key.sign(message)).hex(); + } + + public async verify( + signature: Ed25519SignatureHex, + message: HexBlob, + publicKey: Ed25519PublicKeyHex + ): Promise { + const key = await Ed25519PublicKey.fromHex(publicKey); + + return await key.verify(Ed25519Signature.fromHex(signature), message); + } +} diff --git a/packages/crypto/src/strategies/index.ts b/packages/crypto/src/strategies/index.ts index 0f890163c53..cac087235db 100644 --- a/packages/crypto/src/strategies/index.ts +++ b/packages/crypto/src/strategies/index.ts @@ -1 +1,2 @@ export * from './CmlBip32Ed25519'; +export * from './SodiumBip32Ed25519'; diff --git a/packages/crypto/test/strategies/Bip32Ed25519.test.ts b/packages/crypto/test/strategies/Bip32Ed25519.test.ts index ce6b0a6a2ed..e3e503b79ae 100644 --- a/packages/crypto/test/strategies/Bip32Ed25519.test.ts +++ b/packages/crypto/test/strategies/Bip32Ed25519.test.ts @@ -169,3 +169,4 @@ const testBip32Ed25519 = (name: string, bip32Ed25519: Crypto.Bip32Ed25519) => { }; testBip32Ed25519('CmlBip32Ed25519', new Crypto.CmlBip32Ed25519(CML)); +testBip32Ed25519('SodiumBip32Ed25519', new Crypto.SodiumBip32Ed25519()); From e11a9a8325d1968ea2556024a5fd0e2d807405bf Mon Sep 17 00:00:00 2001 From: Angel Castillo Date: Tue, 7 Feb 2023 02:00:40 +0000 Subject: [PATCH 4/4] test: replaced bip32Ed25519 default strategy (CML for Sodium) --- .github/workflows/continuous-integration-e2e.yaml | 2 +- packages/e2e/.env.example | 10 +++++----- packages/e2e/package.json | 4 ++-- packages/e2e/src/factories.ts | 1 + packages/e2e/src/scripts/mnemonic.ts | 5 ++--- packages/governance/test/cip36.test.ts | 4 ++-- packages/key-management/test/InMemoryKeyAgent.test.ts | 4 ++-- packages/key-management/test/KeyAgentBase.test.ts | 4 ++-- .../test/mocks/mockKeyAgentDependencies.ts | 5 ++--- .../test/util/createAsyncKeyAgent.test.ts | 4 ++-- packages/wallet/test/PersonalWallet/load.test.ts | 3 +-- packages/wallet/test/PersonalWallet/rollback.test.ts | 3 +-- packages/wallet/test/PersonalWallet/shutdown.test.ts | 3 +-- .../hardware/ledger/LedgerKeyAgent.integration.test.ts | 7 ++++--- .../hardware/trezor/TrezorKeyAgent.integration.test.ts | 6 +++--- .../wallet/test/hardware/trezor/TrezorKeyAgent.test.ts | 4 ++-- packages/wallet/test/integration/util.ts | 3 +-- .../test/services/KeyAgent/restoreKeyAgent.test.ts | 5 +++-- packages/wallet/test/setupWallet.test.ts | 3 +-- 19 files changed, 38 insertions(+), 42 deletions(-) diff --git a/.github/workflows/continuous-integration-e2e.yaml b/.github/workflows/continuous-integration-e2e.yaml index 78e2de3c87a..384e7906a36 100644 --- a/.github/workflows/continuous-integration-e2e.yaml +++ b/.github/workflows/continuous-integration-e2e.yaml @@ -5,7 +5,7 @@ env: TL_LEVEL: ${{ github.event.pull_request.head.repo.fork && 'info' || vars.TL_LEVEL }} # ----------------------------------------------------------------------------------------- KEY_MANAGEMENT_PROVIDER: 'inMemory' - KEY_MANAGEMENT_PARAMS: '{"bip32Ed25519": "CML", "accountIndex": 0, "chainId":{"networkId": 0, "networkMagic": 888}, "passphrase":"some_passphrase","mnemonic":"vacant violin soft weird deliver render brief always monitor general maid smart jelly core drastic erode echo there clump dizzy card filter option defense"}' + KEY_MANAGEMENT_PARAMS: '{"bip32Ed25519": "Sodium", "accountIndex": 0, "chainId":{"networkId": 0, "networkMagic": 888}, "passphrase":"some_passphrase","mnemonic":"vacant violin soft weird deliver render brief always monitor general maid smart jelly core drastic erode echo there clump dizzy card filter option defense"}' ASSET_PROVIDER: 'http' ASSET_PROVIDER_PARAMS: '{"baseUrl":"http://localhost:4000/"}' CHAIN_HISTORY_PROVIDER: 'http' diff --git a/packages/e2e/.env.example b/packages/e2e/.env.example index 89cb0b79119..b7258269ad2 100644 --- a/packages/e2e/.env.example +++ b/packages/e2e/.env.example @@ -3,11 +3,11 @@ LOGGER_MIN_SEVERITY=info # Key management setup - required by getWallet KEY_MANAGEMENT_PROVIDER=inMemory -KEY_MANAGEMENT_PARAMS='{"bip32Ed25519": "CML", "accountIndex": 0, "chainId":{"networkId": 0, "networkMagic": 888}, "passphrase":"some_passphrase","mnemonic":"vacant violin soft weird deliver render brief always monitor general maid smart jelly core drastic erode echo there clump dizzy card filter option defense"}' -#KEY_MANAGEMENT_PARAMS='{"bip32Ed25519": "CML", "accountIndex": 0, "chainId":{"networkId": 0, "networkMagic": 888}, "passphrase":"some_passphrase","mnemonic":"slab gorilla reflect display cage aim silver add own arrange crew start female bitter menu inner combine exit swallow bamboo midnight wealth culture picnic"}' -#KEY_MANAGEMENT_PARAMS='{"bip32Ed25519": "CML", "accountIndex": 0, "chainId":{"networkId": 0, "networkMagic": 888}, "passphrase":"some_passphrase","mnemonic":"decorate survey empower stairs pledge humble social leisure baby wrap grief exact monster rug dash kiss perfect select science light frame play swallow day"}' -#KEY_MANAGEMENT_PARAMS='{"bip32Ed25519": "CML", "accountIndex": 0, "chainId":{"networkId": 0, "networkMagic": 888}, "passphrase":"some_passphrase","mnemonic":"phrase raw learn suspect inmate powder combine apology regular hero gain chronic fruit ritual short screen goddess odor keen creek brand today kit machine"}' -#KEY_MANAGEMENT_PARAMS='{"bip32Ed25519": "CML", "accountIndex": 0, "chainId":{"networkId": 0, "networkMagic": 888}, "passphrase":"some_passphrase","mnemonic":"salon zoo engage submit smile frost later decide wing sight chaos renew lizard rely canal coral scene hobby scare step bus leaf tobacco slice"}' +KEY_MANAGEMENT_PARAMS='{"bip32Ed25519": "Sodium", "accountIndex": 0, "chainId":{"networkId": 0, "networkMagic": 888}, "passphrase":"some_passphrase","mnemonic":"vacant violin soft weird deliver render brief always monitor general maid smart jelly core drastic erode echo there clump dizzy card filter option defense"}' +#KEY_MANAGEMENT_PARAMS='{"bip32Ed25519": "Sodium", "accountIndex": 0, "chainId":{"networkId": 0, "networkMagic": 888}, "passphrase":"some_passphrase","mnemonic":"slab gorilla reflect display cage aim silver add own arrange crew start female bitter menu inner combine exit swallow bamboo midnight wealth culture picnic"}' +#KEY_MANAGEMENT_PARAMS='{"bip32Ed25519": "Sodium", "accountIndex": 0, "chainId":{"networkId": 0, "networkMagic": 888}, "passphrase":"some_passphrase","mnemonic":"decorate survey empower stairs pledge humble social leisure baby wrap grief exact monster rug dash kiss perfect select science light frame play swallow day"}' +#KEY_MANAGEMENT_PARAMS='{"bip32Ed25519": "Sodium", "accountIndex": 0, "chainId":{"networkId": 0, "networkMagic": 888}, "passphrase":"some_passphrase","mnemonic":"phrase raw learn suspect inmate powder combine apology regular hero gain chronic fruit ritual short screen goddess odor keen creek brand today kit machine"}' +#KEY_MANAGEMENT_PARAMS='{"bip32Ed25519": "Sodium", "accountIndex": 0, "chainId":{"networkId": 0, "networkMagic": 888}, "passphrase":"some_passphrase","mnemonic":"salon zoo engage submit smile frost later decide wing sight chaos renew lizard rely canal coral scene hobby scare step bus leaf tobacco slice"}' # Providers setup - required by getWallet ASSET_PROVIDER=http diff --git a/packages/e2e/package.json b/packages/e2e/package.json index 45daeca8b31..6ce365f20c9 100644 --- a/packages/e2e/package.json +++ b/packages/e2e/package.json @@ -149,10 +149,10 @@ "blake2b-no-wasm": "2.1.4", "buffer": "^6.0.3", "copy-webpack-plugin": "^10.2.4", - "dockerode": "^3.3.1", - "dockerode-utils": "^0.0.7", "crypto-browserify": "^3.12.0", "delay": "^5.0.0", + "dockerode": "^3.3.1", + "dockerode-utils": "^0.0.7", "eslint": "^7.32.0", "events": "^3.3.0", "expect-webdriverio": "^3.2.1", diff --git a/packages/e2e/src/factories.ts b/packages/e2e/src/factories.ts index bb0b95b3e90..48d69fd966a 100644 --- a/packages/e2e/src/factories.ts +++ b/packages/e2e/src/factories.ts @@ -87,6 +87,7 @@ addressDiscoveryFactory.register( // bip32Ed25519 bip32Ed25519Factory.register('CML', async () => new Crypto.CmlBip32Ed25519(CML)); +bip32Ed25519Factory.register('Sodium', async () => new Crypto.SodiumBip32Ed25519()); // Asset providers diff --git a/packages/e2e/src/scripts/mnemonic.ts b/packages/e2e/src/scripts/mnemonic.ts index a34804bb3e4..ac5ad85d57a 100644 --- a/packages/e2e/src/scripts/mnemonic.ts +++ b/packages/e2e/src/scripts/mnemonic.ts @@ -2,8 +2,7 @@ /* eslint-disable @typescript-eslint/no-floating-promises */ import * as Crypto from '@cardano-sdk/crypto'; import { AddressType, InMemoryKeyAgent, util } from '@cardano-sdk/key-management'; -import { CML } from '@cardano-sdk/core'; -import { localNetworkChainId } from '../util/localNetworkChainId'; +import { localNetworkChainId } from '../util'; /** * Generates a new set of Mnemonic words and prints them to the console. @@ -20,7 +19,7 @@ import { localNetworkChainId } from '../util/localNetworkChainId'; mnemonicWords: mnemonicArray }, { - bip32Ed25519: new Crypto.CmlBip32Ed25519(CML), + bip32Ed25519: new Crypto.SodiumBip32Ed25519(), inputResolver: { resolveInput: async () => null }, logger: console } diff --git a/packages/governance/test/cip36.test.ts b/packages/governance/test/cip36.test.ts index 64cc762843d..87e1effaabd 100644 --- a/packages/governance/test/cip36.test.ts +++ b/packages/governance/test/cip36.test.ts @@ -1,5 +1,5 @@ import * as Crypto from '@cardano-sdk/crypto'; -import { CML, Cardano, coreToCml } from '@cardano-sdk/core'; +import { Cardano, coreToCml } from '@cardano-sdk/core'; import { cip36 } from '../src'; import { usingAutoFree } from '@cardano-sdk/util'; @@ -57,7 +57,7 @@ describe('cip36', () => { ); const signedCip36Metadata = await cip36.metadataBuilder.signVotingRegistration(votingRegistrationMetadata, { signBlob: async (blob) => { - const bip32Ed25519 = new Crypto.CmlBip32Ed25519(CML); + const bip32Ed25519 = new Crypto.SodiumBip32Ed25519(); const privateStakeKey = Crypto.Ed25519PrivateNormalKeyHex( '852fa5d17df3efdfdcd6dac53ec9fe5593f3c0bd7cadb3c2af76c7e15dfa8a5c' ); diff --git a/packages/key-management/test/InMemoryKeyAgent.test.ts b/packages/key-management/test/InMemoryKeyAgent.test.ts index 9eaab2d0063..f7e628d5ae7 100644 --- a/packages/key-management/test/InMemoryKeyAgent.test.ts +++ b/packages/key-management/test/InMemoryKeyAgent.test.ts @@ -1,6 +1,6 @@ import * as Crypto from '@cardano-sdk/crypto'; import { AddressType, InMemoryKeyAgent, KeyRole, SerializableInMemoryKeyAgentData, util } from '../src'; -import { CML, Cardano } from '@cardano-sdk/core'; +import { Cardano } from '@cardano-sdk/core'; import { HexBlob } from '@cardano-sdk/util'; import { dummyLogger } from 'ts-log'; @@ -12,7 +12,7 @@ describe('InMemoryKeyAgent', () => { let getPassphrase: jest.Mock; let inputResolver: jest.Mocked; let mnemonicWords: string[]; - const bip32Ed25519 = new Crypto.CmlBip32Ed25519(CML); + const bip32Ed25519 = new Crypto.SodiumBip32Ed25519(); beforeEach(async () => { mnemonicWords = util.generateMnemonicWords(); diff --git a/packages/key-management/test/KeyAgentBase.test.ts b/packages/key-management/test/KeyAgentBase.test.ts index f42fff29edd..279ca3304fb 100644 --- a/packages/key-management/test/KeyAgentBase.test.ts +++ b/packages/key-management/test/KeyAgentBase.test.ts @@ -8,11 +8,11 @@ import { KeyRole, SerializableInMemoryKeyAgentData } from '../src'; -import { CML, Cardano } from '@cardano-sdk/core'; +import { Cardano } from '@cardano-sdk/core'; import { dummyLogger } from 'ts-log'; const ACCOUNT_INDEX = 1; -const bip32Ed25519 = new Crypto.CmlBip32Ed25519(CML); +const bip32Ed25519 = new Crypto.SodiumBip32Ed25519(); class MockKeyAgent extends KeyAgentBase { constructor(data: SerializableInMemoryKeyAgentData) { diff --git a/packages/key-management/test/mocks/mockKeyAgentDependencies.ts b/packages/key-management/test/mocks/mockKeyAgentDependencies.ts index 88a2f693eeb..81b9ee603d0 100644 --- a/packages/key-management/test/mocks/mockKeyAgentDependencies.ts +++ b/packages/key-management/test/mocks/mockKeyAgentDependencies.ts @@ -1,10 +1,9 @@ -import { CML } from '@cardano-sdk/core'; -import { CmlBip32Ed25519 } from '@cardano-sdk/crypto'; import { KeyAgentDependencies } from '../../src/'; +import { SodiumBip32Ed25519 } from '@cardano-sdk/crypto'; import { dummyLogger } from 'ts-log'; export const mockKeyAgentDependencies = (): jest.Mocked => ({ - bip32Ed25519: new CmlBip32Ed25519(CML), + bip32Ed25519: new SodiumBip32Ed25519(), inputResolver: { resolveInput: jest.fn().mockResolvedValue(null) }, diff --git a/packages/key-management/test/util/createAsyncKeyAgent.test.ts b/packages/key-management/test/util/createAsyncKeyAgent.test.ts index 7f5402c77d1..f4062411f44 100644 --- a/packages/key-management/test/util/createAsyncKeyAgent.test.ts +++ b/packages/key-management/test/util/createAsyncKeyAgent.test.ts @@ -1,6 +1,6 @@ import * as Crypto from '@cardano-sdk/crypto'; import { AsyncKeyAgent, InMemoryKeyAgent, KeyAgent, util } from '../../src'; -import { CML, Cardano } from '@cardano-sdk/core'; +import { Cardano } from '@cardano-sdk/core'; import { HexBlob } from '@cardano-sdk/util'; import { dummyLogger } from 'ts-log'; import { firstValueFrom } from 'rxjs'; @@ -21,7 +21,7 @@ describe('createAsyncKeyAgent maps KeyAgent to AsyncKeyAgent', () => { getPassphrase, mnemonicWords }, - { bip32Ed25519: new Crypto.CmlBip32Ed25519(CML), inputResolver, logger: dummyLogger } + { bip32Ed25519: new Crypto.SodiumBip32Ed25519(), inputResolver, logger: dummyLogger } ); asyncKeyAgent = util.createAsyncKeyAgent(keyAgent); }); diff --git a/packages/wallet/test/PersonalWallet/load.test.ts b/packages/wallet/test/PersonalWallet/load.test.ts index 59b7bca3a91..91e7c131c96 100644 --- a/packages/wallet/test/PersonalWallet/load.test.ts +++ b/packages/wallet/test/PersonalWallet/load.test.ts @@ -21,7 +21,6 @@ import { somePartialStakePools } from '@cardano-sdk/util-dev'; import { - CML, Cardano, ChainHistoryProvider, HandleProvider, @@ -56,7 +55,7 @@ const name = 'Test Wallet'; const address = mocks.utxo[0][0].address!; const rewardAccount = mocks.rewardAccount; -const bip32Ed25519 = new Crypto.CmlBip32Ed25519(CML); +const bip32Ed25519 = new Crypto.SodiumBip32Ed25519(); interface Providers { rewardsProvider: RewardsProvider; utxoProvider: UtxoProvider; diff --git a/packages/wallet/test/PersonalWallet/rollback.test.ts b/packages/wallet/test/PersonalWallet/rollback.test.ts index 11b287ec079..2241c6b6438 100644 --- a/packages/wallet/test/PersonalWallet/rollback.test.ts +++ b/packages/wallet/test/PersonalWallet/rollback.test.ts @@ -1,7 +1,6 @@ import * as Crypto from '@cardano-sdk/crypto'; import { AddressType, GroupedAddress } from '@cardano-sdk/key-management'; import { - CML, Cardano, ChainHistoryProvider, NetworkInfoProvider, @@ -32,7 +31,7 @@ interface Providers { const createWallet = async (stores: WalletStores, providers: Providers, pollingConfig?: PollingConfig) => { const { wallet } = await setupWallet({ - bip32Ed25519: new Crypto.CmlBip32Ed25519(CML), + bip32Ed25519: new Crypto.SodiumBip32Ed25519(), createKeyAgent: async (dependencies) => { const groupedAddress: GroupedAddress = { accountIndex: 0, diff --git a/packages/wallet/test/PersonalWallet/shutdown.test.ts b/packages/wallet/test/PersonalWallet/shutdown.test.ts index 828bb0dd691..b77a0a58934 100644 --- a/packages/wallet/test/PersonalWallet/shutdown.test.ts +++ b/packages/wallet/test/PersonalWallet/shutdown.test.ts @@ -9,7 +9,6 @@ import { somePartialStakePools } from '@cardano-sdk/util-dev'; import { - CML, Cardano, ChainHistoryProvider, NetworkInfoProvider, @@ -50,7 +49,7 @@ const createWallet = async ( pollingConfig?: PollingConfig ) => { const { wallet } = await setupWallet({ - bip32Ed25519: new Crypto.CmlBip32Ed25519(CML), + bip32Ed25519: new Crypto.SodiumBip32Ed25519(), createKeyAgent: async (dependencies) => { const groupedAddress: GroupedAddress = { accountIndex: 0, diff --git a/packages/wallet/test/hardware/ledger/LedgerKeyAgent.integration.test.ts b/packages/wallet/test/hardware/ledger/LedgerKeyAgent.integration.test.ts index 7af659750d1..6b431dcd79f 100644 --- a/packages/wallet/test/hardware/ledger/LedgerKeyAgent.integration.test.ts +++ b/packages/wallet/test/hardware/ledger/LedgerKeyAgent.integration.test.ts @@ -1,5 +1,6 @@ import * as Crypto from '@cardano-sdk/crypto'; -import { CML, Cardano } from '@cardano-sdk/core'; + +import { Cardano } from '@cardano-sdk/core'; import { CommunicationType, KeyAgent, util } from '@cardano-sdk/key-management'; import { LedgerKeyAgent } from '@cardano-sdk/hardware-ledger'; import { ObservableWallet, PersonalWallet, restoreKeyAgent, setupWallet } from '../../../src'; @@ -46,7 +47,7 @@ const getAddress = async (wallet: ObservableWallet) => (await firstValueFrom(wal describe('LedgerKeyAgent+PersonalWallet', () => { test('creating and restoring LedgerKeyAgent wallet', async () => { const { wallet: freshWallet, keyAgent: freshKeyAgent } = await setupWallet({ - bip32Ed25519: new Crypto.CmlBip32Ed25519(CML), + bip32Ed25519: new Crypto.SodiumBip32Ed25519(), createKeyAgent: (dependencies) => LedgerKeyAgent.createWithDevice( { @@ -59,7 +60,7 @@ describe('LedgerKeyAgent+PersonalWallet', () => { logger }); const { wallet: restoredWallet } = await setupWallet({ - bip32Ed25519: new Crypto.CmlBip32Ed25519(CML), + bip32Ed25519: new Crypto.SodiumBip32Ed25519(), createKeyAgent: (dependencies) => restoreKeyAgent(freshKeyAgent.serializableData, dependencies), createWallet, logger diff --git a/packages/wallet/test/hardware/trezor/TrezorKeyAgent.integration.test.ts b/packages/wallet/test/hardware/trezor/TrezorKeyAgent.integration.test.ts index c706e993cea..842db2bbaaa 100644 --- a/packages/wallet/test/hardware/trezor/TrezorKeyAgent.integration.test.ts +++ b/packages/wallet/test/hardware/trezor/TrezorKeyAgent.integration.test.ts @@ -1,5 +1,5 @@ import * as Crypto from '@cardano-sdk/crypto'; -import { CML, Cardano } from '@cardano-sdk/core'; +import { Cardano } from '@cardano-sdk/core'; import { CommunicationType, KeyAgent, TrezorKeyAgent, util } from '@cardano-sdk/key-management'; import { ObservableWallet, PersonalWallet, restoreKeyAgent, setupWallet } from '../../../src'; import { createStubStakePoolProvider, mockProviders } from '@cardano-sdk/util-dev'; @@ -45,7 +45,7 @@ const getAddress = async (wallet: ObservableWallet) => (await firstValueFrom(wal describe('TrezorKeyAgent+PersonalWallet', () => { test('creating and restoring TrezorKeyAgent wallet', async () => { const { wallet: freshWallet, keyAgent: freshKeyAgent } = await setupWallet({ - bip32Ed25519: new Crypto.CmlBip32Ed25519(CML), + bip32Ed25519: new Crypto.SodiumBip32Ed25519(), createKeyAgent: (dependencies) => TrezorKeyAgent.createWithDevice( { @@ -64,7 +64,7 @@ describe('TrezorKeyAgent+PersonalWallet', () => { logger }); const { wallet: restoredWallet } = await setupWallet({ - bip32Ed25519: new Crypto.CmlBip32Ed25519(CML), + bip32Ed25519: new Crypto.SodiumBip32Ed25519(), createKeyAgent: (dependencies) => restoreKeyAgent(freshKeyAgent.serializableData, dependencies), createWallet, logger diff --git a/packages/wallet/test/hardware/trezor/TrezorKeyAgent.test.ts b/packages/wallet/test/hardware/trezor/TrezorKeyAgent.test.ts index dcf00c385d1..d127af58f1d 100644 --- a/packages/wallet/test/hardware/trezor/TrezorKeyAgent.test.ts +++ b/packages/wallet/test/hardware/trezor/TrezorKeyAgent.test.ts @@ -8,7 +8,7 @@ import { util } from '@cardano-sdk/key-management'; import { AssetId, createStubStakePoolProvider, mockProviders as mocks } from '@cardano-sdk/util-dev'; -import { CML, Cardano } from '@cardano-sdk/core'; +import { Cardano } from '@cardano-sdk/core'; import { PersonalWallet, setupWallet } from '../../../src'; import { dummyLogger as logger } from 'ts-log'; import { mockKeyAgentDependencies, stakeKeyDerivationPath } from '../../../../key-management/test/mocks'; @@ -28,7 +28,7 @@ describe('TrezorKeyAgent', () => { beforeAll(async () => { txSubmitProvider = mocks.mockTxSubmitProvider(); ({ keyAgent, wallet } = await setupWallet({ - bip32Ed25519: new Crypto.CmlBip32Ed25519(CML), + bip32Ed25519: new Crypto.SodiumBip32Ed25519(), createKeyAgent: async (dependencies) => { const trezorKeyAgent = await TrezorKeyAgent.createWithDevice( diff --git a/packages/wallet/test/integration/util.ts b/packages/wallet/test/integration/util.ts index 29a4c51a695..5f0c8f01342 100644 --- a/packages/wallet/test/integration/util.ts +++ b/packages/wallet/test/integration/util.ts @@ -1,5 +1,4 @@ import * as Crypto from '@cardano-sdk/crypto'; -import { CML } from '@cardano-sdk/core'; import { PersonalWallet, setupWallet } from '../../src'; import { WalletStores } from '../../src/persistence'; import { createStubStakePoolProvider, mockProviders } from '@cardano-sdk/util-dev'; @@ -32,7 +31,7 @@ export type Providers = { export const createWallet = async (stores?: WalletStores, providers: Providers = {}) => await setupWallet({ - bip32Ed25519: new Crypto.CmlBip32Ed25519(CML), + bip32Ed25519: new Crypto.SodiumBip32Ed25519(), createKeyAgent: (dependencies) => testAsyncKeyAgent(undefined, dependencies), createWallet: async (keyAgent) => new PersonalWallet( diff --git a/packages/wallet/test/services/KeyAgent/restoreKeyAgent.test.ts b/packages/wallet/test/services/KeyAgent/restoreKeyAgent.test.ts index eeb4f5bd7a6..638e889a0db 100644 --- a/packages/wallet/test/services/KeyAgent/restoreKeyAgent.test.ts +++ b/packages/wallet/test/services/KeyAgent/restoreKeyAgent.test.ts @@ -11,13 +11,14 @@ import { errors, util } from '@cardano-sdk/key-management'; -import { CML, Cardano } from '@cardano-sdk/core'; +import { Cardano } from '@cardano-sdk/core'; + import { dummyLogger } from 'ts-log'; import { restoreKeyAgent } from '../../../src'; describe('KeyManagement/restoreKeyAgent', () => { const dependencies: KeyAgentDependencies = { - bip32Ed25519: new Crypto.CmlBip32Ed25519(CML), + bip32Ed25519: new Crypto.SodiumBip32Ed25519(), inputResolver: { resolveInput: jest.fn() }, logger: dummyLogger }; diff --git a/packages/wallet/test/setupWallet.test.ts b/packages/wallet/test/setupWallet.test.ts index 010295e75dd..f07b518e9f1 100644 --- a/packages/wallet/test/setupWallet.test.ts +++ b/packages/wallet/test/setupWallet.test.ts @@ -1,5 +1,4 @@ import * as Crypto from '@cardano-sdk/crypto'; -import { CML } from '@cardano-sdk/core'; import { logger } from '@cardano-sdk/util-dev'; import { setupWallet } from '../src'; @@ -7,7 +6,7 @@ jest.mock('../src/services/WalletUtil'); const { createLazyWalletUtil } = jest.requireMock('../src/services/WalletUtil'); describe('setupWallet', () => { - const bip32Ed25519 = new Crypto.CmlBip32Ed25519(CML); + const bip32Ed25519 = new Crypto.SodiumBip32Ed25519(); it('initializes WalletUtil with the wallet that is then used as InputResolver for KeyAgent', async () => { const initialize = jest.fn();