diff --git a/docs/setup-electron.md b/docs/setup-electron.md index 9e10a6e6ae..1e43b7c724 100644 --- a/docs/setup-electron.md +++ b/docs/setup-electron.md @@ -10,6 +10,8 @@ To start using Electron, the prerequisites of NodeJS are required. Please follow To add the aries framework and indy to your project execute the following: +## Installing dependencies + ```sh yarn add @aries-framework/core @aries-framework/node indy-sdk @@ -17,6 +19,9 @@ yarn add @aries-framework/core @aries-framework/node indy-sdk yarn add --dev @types/indy-sdk ``` +Right now, as a patch that will later be changed, some platforms will have an "error" when installing the dependencies. This is because the BBS signatures library that we use is built for Linux x86 and MacOS x86 (and not Windows and MacOS arm). This means that it will show that it could not download the binary. +This is not an error, as the library that fails is `node-bbs-signaturs` and is an optional dependency for perfomance improvements. It will fallback to a, slower, wasm build. + Because Electron is like a browser-environment, some additional work has to be done to get it working. The indy-sdk is used to make calls to `libindy`. Since `libindy` is not build for browser environments, a binding for the indy-sdk has to be created from the browser to the NodeJS environment in the `public/preload.js` file. ```ts diff --git a/docs/setup-nodejs.md b/docs/setup-nodejs.md index f8714ffe9f..44b3d13186 100644 --- a/docs/setup-nodejs.md +++ b/docs/setup-nodejs.md @@ -12,10 +12,15 @@ To start using Aries Framework JavaScript in NodeJS some platform specific depen - [Windows](../docs/libindy/windows.md) 3. Add `@aries-framework/core` and `@aries-framework/node` to your project. +## Installing dependencies + ```bash yarn add @aries-framework/core @aries-framework/node ``` +Right now, as a patch that will later be changed, some platforms will have an "error" when installing the dependencies. This is because the BBS signatures library that we use is built for Linux x86 and MacOS x86 (and not Windows and MacOS arm). This means that it will show that it could not download the binary. +This is not an error, as the library that fails is `node-bbs-signaturs` and is an optional dependency for perfomance improvements. It will fallback to a, slower, wasm build. + ## Agent Setup Initializing the Agent also requires some NodeJS specific setup, mainly for the Indy SDK and File System. Below is a sample config, see the [README](../README.md#getting-started) for an overview of getting started guides. If you want to jump right in, check the [Getting Started: Agent](./getting-started/0-agent.md) guide. diff --git a/docs/setup-react-native.md b/docs/setup-react-native.md index 596cb70b7f..495f823808 100644 --- a/docs/setup-react-native.md +++ b/docs/setup-react-native.md @@ -7,10 +7,15 @@ To start using Aries Framework JavaScript in React Native some platform specific 1. Follow the [React Native Setup](https://reactnative.dev/docs/environment-setup) guide to set up your environment. 2. Add `@aries-framework/core`, `@aries-framework/react-native`, `react-native-fs`, and `react-native-get-random-values` to your project. +## Installing dependencies + ```bash yarn add @aries-framework/core @aries-framework/react-native react-native-fs react-native-get-random-values ``` +Right now, as a patch that will later be changed, some platforms will have an "error" when installing the dependencies. This is because the BBS signatures library that we use is built for Linux x86 and MacOS x86 (and not Windows and MacOS arm). This means that it will show that it could not download the binary. +This is not an error, as the library that fails is `node-bbs-signaturs` and is an optional dependency for perfomance improvements. It will fallback to a, slower, wasm build. + 3. Install [Libindy](https://github.com/hyperledger/indy-sdk) for iOS and Android: - [iOS](../docs/libindy/ios.md) @@ -81,3 +86,39 @@ try { console.log(error) } ``` + +## Using BBS Signatures + +When using AFJ inside the React Native environment, temporarily, a dependency for creating keys, sigining and verifying +with bbs keys must be swapped. Inside your package.json the following must be added: + +#### yarn + +```diff ++ "resolutions": { ++ "@mattrglobal/bbs-signatures": "@animo-id/react-native-bbs-signatures@0.1.0", ++ }, + "dependencies": { + ... ++ "@animo-id/react-native-bbs-signatures": "0.1.0", + } +``` + +#### npm + +```diff ++ "overrides": { ++ "@mattrglobal/bbs-signatures": "@animo-id/react-native-bbs-signatures@0.1.0", ++ }, + "dependencies": { + ... ++ "@animo-id/react-native-bbs-signatures": "0.1.0", + } +``` + +The resolution field says that any instance of `@mattrglobal/bbs-signatures` in any child dependency must be swapped +with `react-native-bbs-signatures`. + +The added dependency is required for autolinking and should be the same as the one used in the resolution. + +[React Native Bbs Signature](https://github.com/animo/react-native-bbs-signatures) has some quirks with setting it up correctly. If any errors occur while using this library, please refer to their README for the installation guide. diff --git a/packages/core/package.json b/packages/core/package.json index 7dc29699c6..80a6925341 100644 --- a/packages/core/package.json +++ b/packages/core/package.json @@ -23,6 +23,7 @@ "prepublishOnly": "yarn run build" }, "dependencies": { + "@mattrglobal/bbs-signatures": "^1.0.0", "@multiformats/base-x": "^4.0.1", "@stablelib/ed25519": "^1.0.2", "@stablelib/sha256": "^1.0.1", diff --git a/packages/core/src/crypto/BbsService.ts b/packages/core/src/crypto/BbsService.ts new file mode 100644 index 0000000000..c00e814249 --- /dev/null +++ b/packages/core/src/crypto/BbsService.ts @@ -0,0 +1,151 @@ +import type { CreateKeyOptions } from '../wallet' +import type { BlsKeyPair as _BlsKeyPair } from '@mattrglobal/bbs-signatures' + +import { + bls12381toBbs, + generateBls12381G2KeyPair, + generateBls12381G1KeyPair, + sign, + verify, +} from '@mattrglobal/bbs-signatures' + +import { TypedArrayEncoder } from '../utils/TypedArrayEncoder' +import { Buffer } from '../utils/buffer' +import { WalletError } from '../wallet/error' + +import { KeyType } from './KeyType' + +export interface BlsKeyPair { + publicKeyBase58: string + privateKeyBase58: string + keyType: Extract +} + +interface BbsCreateKeyOptions extends CreateKeyOptions { + keyType: Extract +} + +interface BbsSignOptions { + messages: Buffer | Buffer[] + publicKey: Buffer + privateKey: Buffer +} + +interface BbsVerifyOptions { + publicKey: Buffer + signature: Buffer + messages: Buffer | Buffer[] +} + +export class BbsService { + /** + * Create an instance of a Key class for the following key types: + * - Bls12381g1 + * - Bls12381g2 + * + * @param keyType KeyType The type of key to be created (see above for the accepted types) + * + * @returns A Key class with the public key and key type + * + * @throws {WalletError} When a key could not be created + * @throws {WalletError} When the method is called with an invalid keytype + */ + public static async createKey({ keyType, seed }: BbsCreateKeyOptions): Promise { + // Generate bytes from the seed as required by the bbs-signatures libraries + const seedBytes = seed ? TypedArrayEncoder.fromString(seed) : undefined + + // Temporary keypair holder + let blsKeyPair: Required<_BlsKeyPair> + + switch (keyType) { + case KeyType.Bls12381g1: + // Generate a bls12-381G1 keypair + blsKeyPair = await generateBls12381G1KeyPair(seedBytes) + break + case KeyType.Bls12381g2: + // Generate a bls12-381G2 keypair + blsKeyPair = await generateBls12381G2KeyPair(seedBytes) + break + default: + // additional check. Should never be hit as this function will only be called from a place where + // a key type check already happened. + throw new WalletError(`Cannot create key with the BbsService for key type: ${keyType}`) + } + + return { + keyType, + publicKeyBase58: TypedArrayEncoder.toBase58(blsKeyPair.publicKey), + privateKeyBase58: TypedArrayEncoder.toBase58(blsKeyPair.secretKey), + } + } + + /** + * Sign an arbitrary amount of messages, in byte form, with a keypair + * + * @param messages Buffer[] List of messages in Buffer form + * @param publicKey Buffer Publickey required for the signing process + * @param privateKey Buffer PrivateKey required for the signing process + * + * @returns A Buffer containing the signature of the messages + * + * @throws {WalletError} When there are no supplied messages + */ + public static async sign({ messages, publicKey, privateKey }: BbsSignOptions): Promise { + if (messages.length === 0) throw new WalletError('Unable to create a signature without any messages') + // Check if it is a single message or list and if it is a single message convert it to a list + const normalizedMessages = (TypedArrayEncoder.isTypedArray(messages) ? [messages as Buffer] : messages) as Buffer[] + + // Get the Uint8Array variant of all the messages + const messageBuffers = normalizedMessages.map((m) => Uint8Array.from(m)) + + const bbsKeyPair = await bls12381toBbs({ + keyPair: { publicKey: Uint8Array.from(publicKey), secretKey: Uint8Array.from(privateKey) }, + messageCount: normalizedMessages.length, + }) + + // Sign the messages via the keyPair + const signature = await sign({ + keyPair: bbsKeyPair, + messages: messageBuffers, + }) + + // Convert the Uint8Array signature to a Buffer type + return Buffer.from(signature) + } + + /** + * Verify an arbitrary amount of messages with their signature created with their key pair + * + * @param publicKey Buffer The public key used to sign the messages + * @param messages Buffer[] The messages that have to be verified if they are signed + * @param signature Buffer The signature that has to be verified if it was created with the messages and public key + * + * @returns A boolean whether the signature is create with the public key over the messages + * + * @throws {WalletError} When the message list is empty + * @throws {WalletError} When the verification process failed + */ + public static async verify({ signature, messages, publicKey }: BbsVerifyOptions): Promise { + if (messages.length === 0) throw new WalletError('Unable to create a signature without any messages') + // Check if it is a single message or list and if it is a single message convert it to a list + const normalizedMessages = (TypedArrayEncoder.isTypedArray(messages) ? [messages as Buffer] : messages) as Buffer[] + + // Get the Uint8Array variant of all the messages + const messageBuffers = normalizedMessages.map((m) => Uint8Array.from(m)) + + const bbsKeyPair = await bls12381toBbs({ + keyPair: { publicKey: Uint8Array.from(publicKey) }, + messageCount: normalizedMessages.length, + }) + + // Verify the signature against the messages with their public key + const { verified, error } = await verify({ signature, messages: messageBuffers, publicKey: bbsKeyPair.publicKey }) + + // If the messages could not be verified and an error occured + if (!verified && error) { + throw new WalletError(`Could not verify the signature against the messages: ${error}`) + } + + return verified + } +} diff --git a/packages/core/src/crypto/JwsService.ts b/packages/core/src/crypto/JwsService.ts index 1e7d7c99fa..09caa2cc67 100644 --- a/packages/core/src/crypto/JwsService.ts +++ b/packages/core/src/crypto/JwsService.ts @@ -9,6 +9,9 @@ import { JsonEncoder, TypedArrayEncoder } from '../utils' import { Wallet } from '../wallet' import { WalletError } from '../wallet/error' +import { Key } from './Key' +import { KeyType } from './KeyType' + // TODO: support more key types, more generic jws format const JWS_KEY_TYPE = 'OKP' const JWS_CURVE = 'Ed25519' @@ -25,9 +28,10 @@ export class JwsService { public async createJws({ payload, verkey, header }: CreateJwsOptions): Promise { const base64Payload = TypedArrayEncoder.toBase64URL(payload) const base64Protected = JsonEncoder.toBase64URL(this.buildProtected(verkey)) + const key = Key.fromPublicKeyBase58(verkey, KeyType.Ed25519) const signature = TypedArrayEncoder.toBase64URL( - await this.wallet.sign(TypedArrayEncoder.fromString(`${base64Protected}.${base64Payload}`), verkey) + await this.wallet.sign({ data: TypedArrayEncoder.fromString(`${base64Protected}.${base64Payload}`), key }) ) return { @@ -38,7 +42,7 @@ export class JwsService { } /** - * Verify a a JWS + * Verify a JWS */ public async verifyJws({ jws, payload }: VerifyJwsOptions): Promise { const base64Payload = TypedArrayEncoder.toBase64URL(payload) @@ -64,10 +68,11 @@ export class JwsService { const signature = TypedArrayEncoder.fromBase64(jws.signature) const verkey = TypedArrayEncoder.toBase58(TypedArrayEncoder.fromBase64(protectedJson?.jwk?.x)) + const key = Key.fromPublicKeyBase58(verkey, KeyType.Ed25519) signerVerkeys.push(verkey) try { - const isValid = await this.wallet.verify(verkey, data, signature) + const isValid = await this.wallet.verify({ key, data, signature }) if (!isValid) { return { diff --git a/packages/core/src/modules/dids/domain/Key.ts b/packages/core/src/crypto/Key.ts similarity index 89% rename from packages/core/src/modules/dids/domain/Key.ts rename to packages/core/src/crypto/Key.ts index f9c9595966..c5d03507f0 100644 --- a/packages/core/src/modules/dids/domain/Key.ts +++ b/packages/core/src/crypto/Key.ts @@ -1,8 +1,8 @@ -import type { KeyType } from '../../../crypto' +import type { KeyType } from './KeyType' -import { Buffer, TypedArrayEncoder, MultiBaseEncoder, VarintEncoder } from '../../../utils' +import { Buffer, MultiBaseEncoder, TypedArrayEncoder, VarintEncoder } from '../utils' -import { getKeyTypeByMultiCodecPrefix, getMultiCodecPrefixByKeytype } from './key-type/multiCodecKey' +import { getKeyTypeByMultiCodecPrefix, getMultiCodecPrefixByKeytype } from './multiCodecKey' export class Key { public readonly publicKey: Buffer diff --git a/packages/core/src/crypto/__tests__/JwsService.test.ts b/packages/core/src/crypto/__tests__/JwsService.test.ts index c1f4be7721..87ced7bd95 100644 --- a/packages/core/src/crypto/__tests__/JwsService.test.ts +++ b/packages/core/src/crypto/__tests__/JwsService.test.ts @@ -1,10 +1,11 @@ import type { Wallet } from '@aries-framework/core' import { getAgentConfig } from '../../../tests/helpers' -import { DidKey, Key } from '../../modules/dids' +import { DidKey } from '../../modules/dids' import { Buffer, JsonEncoder } from '../../utils' import { IndyWallet } from '../../wallet/IndyWallet' import { JwsService } from '../JwsService' +import { Key } from '../Key' import { KeyType } from '../KeyType' import * as didJwsz6Mkf from './__fixtures__/didJwsz6Mkf' diff --git a/packages/core/src/crypto/index.ts b/packages/core/src/crypto/index.ts index 208a940d03..4c598a5a2a 100644 --- a/packages/core/src/crypto/index.ts +++ b/packages/core/src/crypto/index.ts @@ -1 +1,2 @@ export { KeyType } from './KeyType' +export { Key } from './Key' diff --git a/packages/core/src/modules/dids/domain/key-type/multiCodecKey.ts b/packages/core/src/crypto/multiCodecKey.ts similarity index 95% rename from packages/core/src/modules/dids/domain/key-type/multiCodecKey.ts rename to packages/core/src/crypto/multiCodecKey.ts index 884145f1da..20d3f4b070 100644 --- a/packages/core/src/modules/dids/domain/key-type/multiCodecKey.ts +++ b/packages/core/src/crypto/multiCodecKey.ts @@ -1,4 +1,4 @@ -import { KeyType } from '../../../../crypto' +import { KeyType } from './KeyType' // based on https://github.com/multiformats/multicodec/blob/master/table.csv const multiCodecPrefixMap: Record = { diff --git a/packages/core/src/decorators/signature/SignatureDecoratorUtils.ts b/packages/core/src/decorators/signature/SignatureDecoratorUtils.ts index 4518f67b33..dedbde2610 100644 --- a/packages/core/src/decorators/signature/SignatureDecoratorUtils.ts +++ b/packages/core/src/decorators/signature/SignatureDecoratorUtils.ts @@ -1,5 +1,6 @@ import type { Wallet } from '../../wallet/Wallet' +import { Key, KeyType } from '../../crypto' import { AriesFrameworkError } from '../../error' import { JsonEncoder } from '../../utils/JsonEncoder' import { TypedArrayEncoder } from '../../utils/TypedArrayEncoder' @@ -21,12 +22,14 @@ export async function unpackAndVerifySignatureDecorator( wallet: Wallet ): Promise> { const signerVerkey = decorator.signer + const key = Key.fromPublicKeyBase58(signerVerkey, KeyType.Ed25519) // first 8 bytes are for 64 bit integer from unix epoch const signedData = TypedArrayEncoder.fromBase64(decorator.signatureData) const signature = TypedArrayEncoder.fromBase64(decorator.signature) - const isValid = await wallet.verify(signerVerkey, signedData, signature) + // const isValid = await wallet.verify(signerVerkey, signedData, signature) + const isValid = await wallet.verify({ signature, data: signedData, key }) if (!isValid) { throw new AriesFrameworkError('Signature is not valid') @@ -47,8 +50,9 @@ export async function unpackAndVerifySignatureDecorator( */ export async function signData(data: unknown, wallet: Wallet, signerKey: string): Promise { const dataBuffer = Buffer.concat([timestamp(), JsonEncoder.toBuffer(data)]) + const key = Key.fromPublicKeyBase58(signerKey, KeyType.Ed25519) - const signatureBuffer = await wallet.sign(dataBuffer, signerKey) + const signatureBuffer = await wallet.sign({ key, data: dataBuffer }) const signatureDecorator = new SignatureDecorator({ signatureType: 'https://didcomm.org/signature/1.0/ed25519Sha512_single', diff --git a/packages/core/src/modules/dids/__tests__/peer-did.test.ts b/packages/core/src/modules/dids/__tests__/peer-did.test.ts index 098b16d745..265e64a5b0 100644 --- a/packages/core/src/modules/dids/__tests__/peer-did.test.ts +++ b/packages/core/src/modules/dids/__tests__/peer-did.test.ts @@ -1,11 +1,11 @@ import type { IndyLedgerService } from '../../ledger' import { getAgentConfig } from '../../../../tests/helpers' -import { KeyType } from '../../../crypto' +import { Key, KeyType } from '../../../crypto' import { IndyStorageService } from '../../../storage/IndyStorageService' import { JsonTransformer } from '../../../utils' import { IndyWallet } from '../../../wallet/IndyWallet' -import { DidCommService, DidDocument, DidDocumentBuilder, Key } from '../domain' +import { DidCommService, DidDocument, DidDocumentBuilder } from '../domain' import { DidDocumentRole } from '../domain/DidDocumentRole' import { convertPublicKeyToX25519, getEd25519VerificationMethod } from '../domain/key-type/ed25519' import { getX25519VerificationMethod } from '../domain/key-type/x25519' diff --git a/packages/core/src/modules/dids/domain/index.ts b/packages/core/src/modules/dids/domain/index.ts index 5e2bbcd60f..bf0ff1c854 100644 --- a/packages/core/src/modules/dids/domain/index.ts +++ b/packages/core/src/modules/dids/domain/index.ts @@ -2,4 +2,3 @@ export * from './service' export * from './verificationMethod' export * from './DidDocument' export * from './DidDocumentBuilder' -export * from './Key' diff --git a/packages/core/src/modules/dids/domain/key-type/__tests__/bls12381g1.test.ts b/packages/core/src/modules/dids/domain/key-type/__tests__/bls12381g1.test.ts index 7c2068d092..518baf918f 100644 --- a/packages/core/src/modules/dids/domain/key-type/__tests__/bls12381g1.test.ts +++ b/packages/core/src/modules/dids/domain/key-type/__tests__/bls12381g1.test.ts @@ -1,7 +1,7 @@ import { KeyType } from '../../../../../crypto' -import { JsonTransformer, TypedArrayEncoder, Buffer } from '../../../../../utils' +import { Key } from '../../../../../crypto/Key' +import { Buffer, JsonTransformer, TypedArrayEncoder } from '../../../../../utils' import keyBls12381g1Fixture from '../../../__tests__/__fixtures__/didKeyBls12381g1.json' -import { Key } from '../../Key' import { VerificationMethod } from '../../verificationMethod' import { keyDidBls12381g1 } from '../bls12381g1' diff --git a/packages/core/src/modules/dids/domain/key-type/__tests__/bls12381g1g2.test.ts b/packages/core/src/modules/dids/domain/key-type/__tests__/bls12381g1g2.test.ts index 61704f7c81..43f1b1f01a 100644 --- a/packages/core/src/modules/dids/domain/key-type/__tests__/bls12381g1g2.test.ts +++ b/packages/core/src/modules/dids/domain/key-type/__tests__/bls12381g1g2.test.ts @@ -1,7 +1,7 @@ import { KeyType } from '../../../../../crypto' -import { JsonTransformer, TypedArrayEncoder, Buffer } from '../../../../../utils' +import { Key } from '../../../../../crypto/Key' +import { Buffer, JsonTransformer, TypedArrayEncoder } from '../../../../../utils' import keyBls12381g1g2Fixture from '../../../__tests__/__fixtures__/didKeyBls12381g1g2.json' -import { Key } from '../../Key' import { VerificationMethod } from '../../verificationMethod' import { keyDidBls12381g1g2 } from '../bls12381g1g2' diff --git a/packages/core/src/modules/dids/domain/key-type/__tests__/bls12381g2.test.ts b/packages/core/src/modules/dids/domain/key-type/__tests__/bls12381g2.test.ts index 2351a9a3b2..7ad46f1cab 100644 --- a/packages/core/src/modules/dids/domain/key-type/__tests__/bls12381g2.test.ts +++ b/packages/core/src/modules/dids/domain/key-type/__tests__/bls12381g2.test.ts @@ -1,7 +1,7 @@ import { KeyType } from '../../../../../crypto' -import { JsonTransformer, TypedArrayEncoder, Buffer } from '../../../../../utils' +import { Key } from '../../../../../crypto/Key' +import { Buffer, JsonTransformer, TypedArrayEncoder } from '../../../../../utils' import keyBls12381g2Fixture from '../../../__tests__/__fixtures__/didKeyBls12381g2.json' -import { Key } from '../../Key' import { VerificationMethod } from '../../verificationMethod' import { keyDidBls12381g2 } from '../bls12381g2' diff --git a/packages/core/src/modules/dids/domain/key-type/__tests__/ed25519.test.ts b/packages/core/src/modules/dids/domain/key-type/__tests__/ed25519.test.ts index d38f96da3b..67f2020c57 100644 --- a/packages/core/src/modules/dids/domain/key-type/__tests__/ed25519.test.ts +++ b/packages/core/src/modules/dids/domain/key-type/__tests__/ed25519.test.ts @@ -1,7 +1,7 @@ import { KeyType } from '../../../../../crypto' -import { JsonTransformer, TypedArrayEncoder, Buffer } from '../../../../../utils' +import { Key } from '../../../../../crypto/Key' +import { Buffer, JsonTransformer, TypedArrayEncoder } from '../../../../../utils' import didKeyEd25519Fixture from '../../../__tests__/__fixtures__//didKeyEd25519.json' -import { Key } from '../../../domain/Key' import { VerificationMethod } from '../../../domain/verificationMethod' import { keyDidEd25519 } from '../ed25519' diff --git a/packages/core/src/modules/dids/domain/key-type/__tests__/x25519.test.ts b/packages/core/src/modules/dids/domain/key-type/__tests__/x25519.test.ts index ee4080f83f..f4775b2cec 100644 --- a/packages/core/src/modules/dids/domain/key-type/__tests__/x25519.test.ts +++ b/packages/core/src/modules/dids/domain/key-type/__tests__/x25519.test.ts @@ -1,7 +1,7 @@ import { KeyType } from '../../../../../crypto' -import { JsonTransformer, TypedArrayEncoder, Buffer } from '../../../../../utils' +import { Key } from '../../../../../crypto/Key' +import { Buffer, JsonTransformer, TypedArrayEncoder } from '../../../../../utils' import didKeyX25519Fixture from '../../../__tests__/__fixtures__/didKeyX25519.json' -import { Key } from '../../Key' import { VerificationMethod } from '../../verificationMethod' import { keyDidX25519 } from '../x25519' diff --git a/packages/core/src/modules/dids/domain/key-type/bls12381g1.ts b/packages/core/src/modules/dids/domain/key-type/bls12381g1.ts index 18fe54bc0a..20dbe45424 100644 --- a/packages/core/src/modules/dids/domain/key-type/bls12381g1.ts +++ b/packages/core/src/modules/dids/domain/key-type/bls12381g1.ts @@ -2,7 +2,7 @@ import type { VerificationMethod } from '../verificationMethod' import type { KeyDidMapping } from './keyDidMapping' import { KeyType } from '../../../../crypto' -import { Key } from '../Key' +import { Key } from '../../../../crypto/Key' import { getSignatureKeyBase } from './getSignatureKeyBase' diff --git a/packages/core/src/modules/dids/domain/key-type/bls12381g1g2.ts b/packages/core/src/modules/dids/domain/key-type/bls12381g1g2.ts index 88f84783fc..ca9f584742 100644 --- a/packages/core/src/modules/dids/domain/key-type/bls12381g1g2.ts +++ b/packages/core/src/modules/dids/domain/key-type/bls12381g1g2.ts @@ -1,8 +1,8 @@ import type { KeyDidMapping } from './keyDidMapping' import { KeyType } from '../../../../crypto' +import { Key } from '../../../../crypto/Key' import { DidDocumentBuilder } from '../DidDocumentBuilder' -import { Key } from '../Key' import { getBls12381g1VerificationMethod } from './bls12381g1' import { getBls12381g2VerificationMethod } from './bls12381g2' diff --git a/packages/core/src/modules/dids/domain/key-type/bls12381g2.ts b/packages/core/src/modules/dids/domain/key-type/bls12381g2.ts index 1d215b61fd..cb5a5a4082 100644 --- a/packages/core/src/modules/dids/domain/key-type/bls12381g2.ts +++ b/packages/core/src/modules/dids/domain/key-type/bls12381g2.ts @@ -2,7 +2,7 @@ import type { VerificationMethod } from '../verificationMethod' import type { KeyDidMapping } from './keyDidMapping' import { KeyType } from '../../../../crypto' -import { Key } from '../Key' +import { Key } from '../../../../crypto/Key' import { getSignatureKeyBase } from './getSignatureKeyBase' diff --git a/packages/core/src/modules/dids/domain/key-type/ed25519.ts b/packages/core/src/modules/dids/domain/key-type/ed25519.ts index 11fd98bf7c..d9723dbd3c 100644 --- a/packages/core/src/modules/dids/domain/key-type/ed25519.ts +++ b/packages/core/src/modules/dids/domain/key-type/ed25519.ts @@ -4,7 +4,7 @@ import type { KeyDidMapping } from './keyDidMapping' import { convertPublicKeyToX25519 } from '@stablelib/ed25519' import { KeyType } from '../../../../crypto' -import { Key } from '../Key' +import { Key } from '../../../../crypto/Key' import { getSignatureKeyBase } from './getSignatureKeyBase' import { getX25519VerificationMethod } from './x25519' diff --git a/packages/core/src/modules/dids/domain/key-type/getSignatureKeyBase.ts b/packages/core/src/modules/dids/domain/key-type/getSignatureKeyBase.ts index 377c8111bd..4cb72e6273 100644 --- a/packages/core/src/modules/dids/domain/key-type/getSignatureKeyBase.ts +++ b/packages/core/src/modules/dids/domain/key-type/getSignatureKeyBase.ts @@ -1,4 +1,4 @@ -import type { Key } from '../Key' +import type { Key } from '../../../../crypto/Key' import type { VerificationMethod } from '../verificationMethod' import { DidDocumentBuilder } from '../DidDocumentBuilder' diff --git a/packages/core/src/modules/dids/domain/key-type/index.ts b/packages/core/src/modules/dids/domain/key-type/index.ts index ce5cbb0a5d..8e0d752102 100644 --- a/packages/core/src/modules/dids/domain/key-type/index.ts +++ b/packages/core/src/modules/dids/domain/key-type/index.ts @@ -1,2 +1 @@ -export { getKeyTypeByMultiCodecPrefix, getMultiCodecPrefixByKeytype } from './multiCodecKey' export { getKeyDidMappingByKeyType, getKeyDidMappingByVerificationMethod } from './keyDidMapping' diff --git a/packages/core/src/modules/dids/domain/key-type/keyDidMapping.ts b/packages/core/src/modules/dids/domain/key-type/keyDidMapping.ts index 760d8b40db..334c4f13b0 100644 --- a/packages/core/src/modules/dids/domain/key-type/keyDidMapping.ts +++ b/packages/core/src/modules/dids/domain/key-type/keyDidMapping.ts @@ -1,5 +1,5 @@ +import type { Key } from '../../../../crypto/Key' import type { DidDocument } from '../DidDocument' -import type { Key } from '../Key' import type { VerificationMethod } from '../verificationMethod' import { KeyType } from '../../../../crypto' diff --git a/packages/core/src/modules/dids/domain/key-type/x25519.ts b/packages/core/src/modules/dids/domain/key-type/x25519.ts index 943e2027ae..14f7e8c11d 100644 --- a/packages/core/src/modules/dids/domain/key-type/x25519.ts +++ b/packages/core/src/modules/dids/domain/key-type/x25519.ts @@ -2,8 +2,8 @@ import type { VerificationMethod } from '../verificationMethod' import type { KeyDidMapping } from './keyDidMapping' import { KeyType } from '../../../../crypto' +import { Key } from '../../../../crypto/Key' import { DidDocumentBuilder } from '../DidDocumentBuilder' -import { Key } from '../Key' const VERIFICATION_METHOD_TYPE_X25519_KEY_AGREEMENT_KEY_2019 = 'X25519KeyAgreementKey2019' diff --git a/packages/core/src/modules/dids/methods/key/DidKey.ts b/packages/core/src/modules/dids/methods/key/DidKey.ts index 7f6fbb3c51..3b2ba66017 100644 --- a/packages/core/src/modules/dids/methods/key/DidKey.ts +++ b/packages/core/src/modules/dids/methods/key/DidKey.ts @@ -1,4 +1,4 @@ -import { Key } from '../../domain/Key' +import { Key } from '../../../../crypto/Key' import { getKeyDidMappingByKeyType } from '../../domain/key-type' import { parseDid } from '../../domain/parse' diff --git a/packages/core/src/modules/dids/methods/key/__tests__/DidKey.test.ts b/packages/core/src/modules/dids/methods/key/__tests__/DidKey.test.ts index 661feea4e2..ce63ed8a83 100644 --- a/packages/core/src/modules/dids/methods/key/__tests__/DidKey.test.ts +++ b/packages/core/src/modules/dids/methods/key/__tests__/DidKey.test.ts @@ -1,10 +1,10 @@ import { KeyType } from '../../../../../crypto' +import { Key } from '../../../../../crypto/Key' import didKeyBls12381g1 from '../../../__tests__/__fixtures__/didKeyBls12381g1.json' import didKeyBls12381g1g2 from '../../../__tests__/__fixtures__/didKeyBls12381g1g2.json' import didKeyBls12381g2 from '../../../__tests__/__fixtures__/didKeyBls12381g2.json' import didKeyEd25519 from '../../../__tests__/__fixtures__/didKeyEd25519.json' import didKeyX25519 from '../../../__tests__/__fixtures__/didKeyX25519.json' -import { Key } from '../../../domain/Key' import { DidKey } from '../DidKey' describe('DidKey', () => { diff --git a/packages/core/src/modules/dids/methods/peer/__tests__/peerDidNumAlgo0.test.ts b/packages/core/src/modules/dids/methods/peer/__tests__/peerDidNumAlgo0.test.ts index 7433903849..efc938ae2d 100644 --- a/packages/core/src/modules/dids/methods/peer/__tests__/peerDidNumAlgo0.test.ts +++ b/packages/core/src/modules/dids/methods/peer/__tests__/peerDidNumAlgo0.test.ts @@ -1,9 +1,9 @@ +import { Key } from '../../../../../crypto' import didKeyBls12381g1 from '../../../__tests__/__fixtures__/didKeyBls12381g1.json' import didKeyBls12381g1g2 from '../../../__tests__/__fixtures__/didKeyBls12381g1g2.json' import didKeyBls12381g2 from '../../../__tests__/__fixtures__/didKeyBls12381g2.json' import didKeyEd25519 from '../../../__tests__/__fixtures__/didKeyEd25519.json' import didKeyX25519 from '../../../__tests__/__fixtures__/didKeyX25519.json' -import { Key } from '../../../domain' import { didToNumAlgo0DidDocument, keyToNumAlgo0DidDocument } from '../peerDidNumAlgo0' describe('peerDidNumAlgo0', () => { diff --git a/packages/core/src/modules/dids/methods/peer/peerDidNumAlgo0.ts b/packages/core/src/modules/dids/methods/peer/peerDidNumAlgo0.ts index 11a8dcbe14..60398cc5ea 100644 --- a/packages/core/src/modules/dids/methods/peer/peerDidNumAlgo0.ts +++ b/packages/core/src/modules/dids/methods/peer/peerDidNumAlgo0.ts @@ -1,4 +1,4 @@ -import { Key } from '../../domain/Key' +import { Key } from '../../../../crypto' import { getKeyDidMappingByKeyType } from '../../domain/key-type' import { parseDid } from '../../domain/parse' diff --git a/packages/core/src/modules/dids/methods/peer/peerDidNumAlgo2.ts b/packages/core/src/modules/dids/methods/peer/peerDidNumAlgo2.ts index c873a9b508..d31695c689 100644 --- a/packages/core/src/modules/dids/methods/peer/peerDidNumAlgo2.ts +++ b/packages/core/src/modules/dids/methods/peer/peerDidNumAlgo2.ts @@ -1,8 +1,9 @@ import type { JsonObject } from '../../../../types' import type { DidDocument, VerificationMethod } from '../../domain' +import { Key } from '../../../../crypto' import { JsonEncoder, JsonTransformer } from '../../../../utils' -import { DidDocumentService, Key } from '../../domain' +import { DidDocumentService } from '../../domain' import { DidDocumentBuilder } from '../../domain/DidDocumentBuilder' import { getKeyDidMappingByKeyType, getKeyDidMappingByVerificationMethod } from '../../domain/key-type' import { parseDid } from '../../domain/parse' diff --git a/packages/core/src/utils/TypedArrayEncoder.ts b/packages/core/src/utils/TypedArrayEncoder.ts index 69cee41d27..685eac485c 100644 --- a/packages/core/src/utils/TypedArrayEncoder.ts +++ b/packages/core/src/utils/TypedArrayEncoder.ts @@ -60,4 +60,18 @@ export class TypedArrayEncoder { public static toUtf8String(buffer: Buffer | Uint8Array) { return Buffer.from(buffer).toString() } + + /** + * Check whether an array is byte, or typed, array + * + * @param array unknown The array that has to be checked + * + * @returns A boolean if the array is a byte array + */ + public static isTypedArray(array: unknown): boolean { + // Checks whether the static property 'BYTES_PER_ELEMENT' exists on the provided array. + // This has to be done, since the TypedArrays, e.g. Uint8Array and Float32Array, do not + // extend a single base class + return 'BYTES_PER_ELEMENT' in (array as Record) + } } diff --git a/packages/core/src/utils/__tests__/TypedArrayEncoder.test.ts b/packages/core/src/utils/__tests__/TypedArrayEncoder.test.ts index 6d2d42d7bd..925bf97f82 100644 --- a/packages/core/src/utils/__tests__/TypedArrayEncoder.test.ts +++ b/packages/core/src/utils/__tests__/TypedArrayEncoder.test.ts @@ -26,6 +26,23 @@ describe('TypedArrayEncoder', () => { }) ) + describe('isTypedArray', () => { + test('is array of type typedArray', () => { + const mockArray = [0, 1, 2] + expect(TypedArrayEncoder.isTypedArray(mockArray)).toStrictEqual(false) + }) + + test('is Uint8Array of type typedArray', () => { + const mockArray = new Uint8Array([0, 1, 2]) + expect(TypedArrayEncoder.isTypedArray(mockArray)).toStrictEqual(true) + }) + + test('is Buffer of type typedArray', () => { + const mockArray = new Buffer([0, 1, 2]) + expect(TypedArrayEncoder.isTypedArray(mockArray)).toStrictEqual(true) + }) + }) + describe('toBase64', () => { test('encodes buffer to Base64 string', () => { expect(TypedArrayEncoder.toBase64(mockCredentialRequestBuffer)).toEqual( diff --git a/packages/core/src/wallet/IndyWallet.test.ts b/packages/core/src/wallet/IndyWallet.test.ts new file mode 100644 index 0000000000..a1147a6260 --- /dev/null +++ b/packages/core/src/wallet/IndyWallet.test.ts @@ -0,0 +1,142 @@ +import { BBS_SIGNATURE_LENGTH } from '@mattrglobal/bbs-signatures' +import { SIGNATURE_LENGTH as ED25519_SIGNATURE_LENGTH } from '@stablelib/ed25519' + +import { getBaseConfig } from '../../tests/helpers' +import { Agent } from '../agent/Agent' +import { KeyType } from '../crypto' +import { TypedArrayEncoder } from '../utils' + +import { IndyWallet } from './IndyWallet' +import { WalletError } from './error' + +describe('IndyWallet', () => { + let indyWallet: IndyWallet + let agent: Agent + const seed = 'sample-seed' + const message = TypedArrayEncoder.fromString('sample-message') + + beforeEach(async () => { + const { config, agentDependencies } = getBaseConfig('IndyWallettest') + agent = new Agent(config, agentDependencies) + indyWallet = agent.injectionContainer.resolve(IndyWallet) + await agent.initialize() + }) + + afterEach(async () => { + await agent.shutdown() + await agent.wallet.delete() + }) + + test('Get the public DID', () => { + expect(indyWallet.publicDid).toMatchObject({ + did: expect.any(String), + verkey: expect.any(String), + }) + }) + + test('Get the Master Secret', () => { + expect(indyWallet.masterSecretId).toEqual('Wallet: IndyWallettest') + }) + + test('Get the wallet handle', () => { + expect(indyWallet.handle).toEqual(expect.any(Number)) + }) + + test('Initializes a public did', async () => { + await indyWallet.initPublicDid({ seed: '00000000000000000000000Forward01' }) + + expect(indyWallet.publicDid).toEqual({ + did: 'DtWRdd6C5dN5vpcN6XRAvu', + verkey: '82RBSn3heLgXzZd74UsMC8Q8YRfEEhQoAM7LUqE6bevJ', + }) + }) + + test('Create DID', async () => { + const didInfo = await indyWallet.createDid({ seed: '00000000000000000000000Forward01' }) + expect(didInfo).toMatchObject({ + did: 'DtWRdd6C5dN5vpcN6XRAvu', + verkey: '82RBSn3heLgXzZd74UsMC8Q8YRfEEhQoAM7LUqE6bevJ', + }) + }) + + test('Generate Nonce', async () => { + await expect(indyWallet.generateNonce()).resolves.toEqual(expect.any(String)) + }) + + test('Create ed25519 keypair', async () => { + await expect( + indyWallet.createKey({ seed: '2103de41b4ae37e8e28586d84a342b67', keyType: KeyType.Ed25519 }) + ).resolves.toMatchObject({ + keyType: KeyType.Ed25519, + }) + }) + + test('Create blsg12381g1 keypair', async () => { + await expect(indyWallet.createKey({ seed, keyType: KeyType.Bls12381g1 })).resolves.toMatchObject({ + publicKeyBase58: '6RhvX1RK5rA9uXdTtV6WvHWNQqcCW86BQxz1aBPr6ebBcppCYMD3LLy7QLg4cGcWaq', + keyType: KeyType.Bls12381g1, + }) + }) + + test('Create bls12381g2 keypair', async () => { + await expect(indyWallet.createKey({ seed, keyType: KeyType.Bls12381g2 })).resolves.toMatchObject({ + publicKeyBase58: + 't54oLBmhhRcDLUyWTvfYRWw8VRXRy1p43pVm62hrpShrYPuHe9WNAgS33DPfeTK6xK7iPrtJDwCHZjYgbFYDVTJHxXex9xt2XEGF8D356jBT1HtqNeucv3YsPLfTWcLcpFA', + keyType: KeyType.Bls12381g2, + }) + }) + + test('Fail to create bls12381g1g2 keypair', async () => { + await expect(indyWallet.createKey({ seed, keyType: KeyType.Bls12381g1g2 })).rejects.toThrowError(WalletError) + }) + + test('Fail to create x25519 keypair', async () => { + await expect(indyWallet.createKey({ seed, keyType: KeyType.X25519 })).rejects.toThrowError(WalletError) + }) + + test('Create a signature with a ed25519 keypair', async () => { + const ed25519Key = await indyWallet.createKey({ keyType: KeyType.Ed25519 }) + const signature = await indyWallet.sign({ + data: message, + key: ed25519Key, + }) + expect(signature.length).toStrictEqual(ED25519_SIGNATURE_LENGTH) + }) + + test('Create a signature with a bls12381g2 keypair', async () => { + const bls12381g2Key = await indyWallet.createKey({ seed, keyType: KeyType.Bls12381g2 }) + const signature = await indyWallet.sign({ + data: message, + key: bls12381g2Key, + }) + expect(signature.length).toStrictEqual(BBS_SIGNATURE_LENGTH) + }) + + test('Fail to create a signature with a bls12381g1 keypair', async () => { + const bls12381g1Key = await indyWallet.createKey({ seed, keyType: KeyType.Bls12381g1 }) + await expect( + indyWallet.sign({ + data: message, + key: bls12381g1Key, + }) + ).rejects.toThrowError(WalletError) + }) + + test('Verify a signed message with a ed25519 publicKey', async () => { + const ed25519Key = await indyWallet.createKey({ keyType: KeyType.Ed25519 }) + const signature = await indyWallet.sign({ + data: message, + key: ed25519Key, + }) + await expect(indyWallet.verify({ key: ed25519Key, data: message, signature })).resolves.toStrictEqual(true) + }) + + test('Verify a signed message with a bls12381g2 publicKey', async () => { + const bls12381g2Key = await indyWallet.createKey({ seed, keyType: KeyType.Bls12381g2 }) + const signature = await indyWallet.sign({ + data: message, + key: bls12381g2Key, + }) + await expect(indyWallet.verify({ key: bls12381g2Key, data: message, signature })).resolves.toStrictEqual(true) + }) +}) diff --git a/packages/core/src/wallet/IndyWallet.ts b/packages/core/src/wallet/IndyWallet.ts index 3c683e1ef6..ecbbb200d9 100644 --- a/packages/core/src/wallet/IndyWallet.ts +++ b/packages/core/src/wallet/IndyWallet.ts @@ -1,3 +1,4 @@ +import type { BlsKeyPair } from '../crypto/BbsService' import type { Logger } from '../logger' import type { EncryptedMessage, @@ -8,14 +9,17 @@ import type { KeyDerivationMethod, } from '../types' import type { Buffer } from '../utils/buffer' -import type { Wallet, DidInfo, DidConfig } from './Wallet' +import type { Wallet, DidInfo, DidConfig, CreateKeyOptions, SignOptions, VerifyOptions } from './Wallet' import type { default as Indy, WalletStorageConfig } from 'indy-sdk' import { Lifecycle, scoped } from 'tsyringe' import { AgentConfig } from '../agent/AgentConfig' -import { AriesFrameworkError } from '../error' -import { JsonEncoder } from '../utils/JsonEncoder' +import { KeyType } from '../crypto' +import { BbsService } from '../crypto/BbsService' +import { Key } from '../crypto/Key' +import { AriesFrameworkError, IndySdkError, RecordDuplicateError, RecordNotFoundError } from '../error' +import { TypedArrayEncoder, JsonEncoder } from '../utils' import { isIndyError } from '../utils/indyError' import { WalletDuplicateError, WalletNotFoundError, WalletError } from './error' @@ -401,6 +405,110 @@ export class IndyWallet implements Wallet { } } + /** + * Create a key with an optional seed and keyType. + * The keypair is also automatically stored in the wallet afterwards + * + * Bls12381g1g2 and X25519 are not supported. + * + * @param seed string The seed for creating a key + * @param keyType KeyType the type of key that should be created + * + * @returns a Key instance with a publicKeyBase58 + * + * @throws {WalletError} When an unsupported keytype is requested + * @throws {WalletError} When the key could not be created + */ + public async createKey({ seed, keyType }: CreateKeyOptions): Promise { + try { + if (keyType === KeyType.Ed25519) { + // eslint-disable-next-line @typescript-eslint/ban-ts-comment + //@ts-ignore + const verkey = await this.indy.createKey(this.handle, { seed, crypto_type: 'ed25519' }) + return Key.fromPublicKeyBase58(verkey, keyType) + } + + if (keyType === KeyType.Bls12381g1 || keyType === KeyType.Bls12381g2) { + const blsKeyPair = await BbsService.createKey({ keyType, seed }) + await this.storeKeyPair(blsKeyPair) + return Key.fromPublicKeyBase58(blsKeyPair.publicKeyBase58, keyType) + } + } catch (error) { + throw new WalletError(`Error creating key with key type '${keyType}': ${error.message}`, { cause: error }) + } + + throw new WalletError(`Unsupported key type: '${keyType}' for wallet IndyWallet`) + } + + /** + * sign a Buffer with an instance of a Key class + * + * Bls12381g1g2, Bls12381g1 and X25519 are not supported. + * + * @param data Buffer The data that needs to be signed + * @param key Key The key that is used to sign the data + * + * @returns A signature for the data + */ + public async sign({ data, key }: SignOptions): Promise { + try { + if (key.keyType === KeyType.Ed25519) { + // Checks to see if it is an not an Array of messages, but just a single one + if (!TypedArrayEncoder.isTypedArray(data)) { + throw new WalletError(`${KeyType.Ed25519} does not support multiple singing of multiple messages`) + } + return await this.indy.cryptoSign(this.handle, key.publicKeyBase58, data as Buffer) + } + + if (key.keyType === KeyType.Bls12381g2) { + const blsKeyPair = await this.retrieveKeyPair(key.publicKeyBase58) + return BbsService.sign({ + messages: data, + publicKey: key.publicKey, + privateKey: TypedArrayEncoder.fromBase58(blsKeyPair.privateKeyBase58), + }) + } + } catch (error) { + throw new WalletError(`Error signing data with verkey ${key.publicKeyBase58}`, { cause: error }) + } + throw new WalletError(`Unsupported keyType: ${key.keyType}`) + } + + /** + * Verify the signature with the data and the used key + * + * Bls12381g1g2, Bls12381g1 and X25519 are not supported. + * + * @param data Buffer The data that has to be confirmed to be signed + * @param key Key The key that was used in the signing process + * @param signature Buffer The signature that was created by the signing process + * + * @returns A boolean whether the signature was created with the supplied data and key + * + * @throws {WalletError} When it could not do the verification + * @throws {WalletError} When an unsupported keytype is used + */ + public async verify({ data, key, signature }: VerifyOptions): Promise { + try { + if (key.keyType === KeyType.Ed25519) { + // Checks to see if it is an not an Array of messages, but just a single one + if (!TypedArrayEncoder.isTypedArray(data)) { + throw new WalletError(`${KeyType.Ed25519} does not support multiple singing of multiple messages`) + } + return await this.indy.cryptoVerify(key.publicKeyBase58, data as Buffer, signature) + } + + if (key.keyType === KeyType.Bls12381g2) { + return await BbsService.verify({ signature, publicKey: key.publicKey, messages: data }) + } + } catch (error) { + throw new WalletError(`Error verifying signature of data signed with verkey ${key.publicKeyBase58}`, { + cause: error, + }) + } + throw new WalletError(`Unsupported keyType: ${key.keyType}`) + } + public async pack( payload: Record, recipientKeys: string[], @@ -429,30 +537,47 @@ export class IndyWallet implements Wallet { } } - public async sign(data: Buffer, verkey: string): Promise { + public async generateNonce(): Promise { try { - return await this.indy.cryptoSign(this.handle, verkey, data) + return await this.indy.generateNonce() } catch (error) { - throw new WalletError(`Error signing data with verkey ${verkey}`, { cause: error }) + throw new WalletError('Error generating nonce', { cause: error }) } } - public async verify(signerVerkey: string, data: Buffer, signature: Buffer): Promise { + private async retrieveKeyPair(publicKeyBase58: string): Promise { try { - // check signature - const isValid = await this.indy.cryptoVerify(signerVerkey, data, signature) - - return isValid + const { value } = await this.indy.getWalletRecord(this.handle, 'KeyPairRecord', `keypair-${publicKeyBase58}`, {}) + if (value) { + return JsonEncoder.fromString(value) as BlsKeyPair + } else { + throw new WalletError(`No content found for record with public key: ${publicKeyBase58}`) + } } catch (error) { - throw new WalletError(`Error verifying signature of data signed with verkey ${signerVerkey}`, { cause: error }) + if (isIndyError(error, 'WalletItemNotFound')) { + throw new RecordNotFoundError(`KeyPairRecord not found for public key: ${publicKeyBase58}.`, { + recordType: 'KeyPairRecord', + cause: error, + }) + } + throw isIndyError(error) ? new IndySdkError(error) : error } } - public async generateNonce() { + private async storeKeyPair(blsKeyPair: BlsKeyPair): Promise { try { - return await this.indy.generateNonce() + await this.indy.addWalletRecord( + this.handle, + 'KeyPairRecord', + `keypair-${blsKeyPair.publicKeyBase58}`, + JSON.stringify(blsKeyPair), + {} + ) } catch (error) { - throw new WalletError('Error generating nonce', { cause: error }) + if (isIndyError(error, 'WalletItemAlreadyExists')) { + throw new RecordDuplicateError(`Record already exists`, { recordType: 'KeyPairRecord' }) + } + throw isIndyError(error) ? new IndySdkError(error) : error } } } diff --git a/packages/core/src/wallet/Wallet.test.ts b/packages/core/src/wallet/Wallet.test.ts deleted file mode 100644 index 6d6a85da7d..0000000000 --- a/packages/core/src/wallet/Wallet.test.ts +++ /dev/null @@ -1,24 +0,0 @@ -import { getAgentConfig } from '../../tests/helpers' - -import { IndyWallet } from './IndyWallet' - -describe('Wallet', () => { - const config = getAgentConfig('WalletTest') - const wallet = new IndyWallet(config) - - test('initialize public did', async () => { - // eslint-disable-next-line @typescript-eslint/no-non-null-assertion - await wallet.createAndOpen(config.walletConfig!) - - await wallet.initPublicDid({ seed: '00000000000000000000000Forward01' }) - - expect(wallet.publicDid).toEqual({ - did: 'DtWRdd6C5dN5vpcN6XRAvu', - verkey: '82RBSn3heLgXzZd74UsMC8Q8YRfEEhQoAM7LUqE6bevJ', - }) - }) - - afterEach(async () => { - await wallet.delete() - }) -}) diff --git a/packages/core/src/wallet/Wallet.ts b/packages/core/src/wallet/Wallet.ts index aa9debe092..93240b99cb 100644 --- a/packages/core/src/wallet/Wallet.ts +++ b/packages/core/src/wallet/Wallet.ts @@ -1,9 +1,10 @@ +import type { Key, KeyType } from '../crypto' import type { - EncryptedMessage, DecryptedMessageContext, + EncryptedMessage, WalletConfig, - WalletExportImportConfig, WalletConfigRekey, + WalletExportImportConfig, } from '../types' import type { Buffer } from '../utils/buffer' @@ -21,12 +22,14 @@ export interface Wallet { export(exportConfig: WalletExportImportConfig): Promise import(walletConfig: WalletConfig, importConfig: WalletExportImportConfig): Promise + createKey(options: CreateKeyOptions): Promise + sign(options: SignOptions): Promise + verify(options: VerifyOptions): Promise + initPublicDid(didConfig: DidConfig): Promise createDid(didConfig?: DidConfig): Promise pack(payload: Record, recipientKeys: string[], senderVerkey?: string): Promise unpack(encryptedMessage: EncryptedMessage): Promise - sign(data: Buffer, verkey: string): Promise - verify(signerVerkey: string, data: Buffer, signature: Buffer): Promise generateNonce(): Promise } @@ -35,6 +38,22 @@ export interface DidInfo { verkey: string } +export interface CreateKeyOptions { + keyType: KeyType + seed?: string +} + +export interface SignOptions { + data: Buffer | Buffer[] + key: Key +} + +export interface VerifyOptions { + data: Buffer | Buffer[] + key: Key + signature: Buffer +} + export interface DidConfig { seed?: string } diff --git a/packages/react-native/package.json b/packages/react-native/package.json index 9678d68e4a..6553a1b79f 100644 --- a/packages/react-native/package.json +++ b/packages/react-native/package.json @@ -29,6 +29,7 @@ "events": "^3.3.0" }, "devDependencies": { + "@animo-id/react-native-bbs-signatures": "^0.1.0", "@types/indy-sdk-react-native": "npm:@types/indy-sdk@^1.16.16", "@types/react-native": "^0.64.10", "indy-sdk-react-native": "^0.2.0", diff --git a/yarn.lock b/yarn.lock index f1ea05bf10..5d16276f4f 100644 --- a/yarn.lock +++ b/yarn.lock @@ -10,6 +10,11 @@ "@jridgewell/gen-mapping" "^0.1.0" "@jridgewell/trace-mapping" "^0.3.9" +"@animo-id/react-native-bbs-signatures@^0.1.0": + version "0.1.0" + resolved "https://registry.yarnpkg.com/@animo-id/react-native-bbs-signatures/-/react-native-bbs-signatures-0.1.0.tgz#f62bc16b867c9f690977982d66f0a03566b21ad2" + integrity sha512-7qvsiWhGfUev8ngE8YzF6ON9PtCID5LiYVYM4EC5eyj80gCdhx3R46CI7K1qbqIlGsoTYQ/Xx5Ubo5Ji9eaUEA== + "@azure/core-asynciterator-polyfill@^1.0.0": version "1.0.2" resolved "https://registry.yarnpkg.com/@azure/core-asynciterator-polyfill/-/core-asynciterator-polyfill-1.0.2.tgz#0dd3849fb8d97f062a39db0e5cadc9ffaf861fec" @@ -1710,6 +1715,23 @@ npmlog "^4.1.2" write-file-atomic "^3.0.3" +"@mattrglobal/bbs-signatures@^1.0.0": + version "1.0.0" + resolved "https://registry.yarnpkg.com/@mattrglobal/bbs-signatures/-/bbs-signatures-1.0.0.tgz#8ff272c6d201aadab7e08bd84dbfd6e0d48ba12d" + integrity sha512-FFzybdKqSCrS/e7pl5s6Tl/m/x8ZD5EMBbcTBQaqSOms/lebm91lFukYOIe2qc0a5o+gLhtRKye8OfKwD1Ex/g== + dependencies: + "@stablelib/random" "1.0.0" + optionalDependencies: + "@mattrglobal/node-bbs-signatures" "0.13.0" + +"@mattrglobal/node-bbs-signatures@0.13.0": + version "0.13.0" + resolved "https://registry.yarnpkg.com/@mattrglobal/node-bbs-signatures/-/node-bbs-signatures-0.13.0.tgz#3e431b915325d4b139706f8b26fd84b27c192a29" + integrity sha512-S2wOwDCQYxdjSEjVfcbP3bTq4ZMKeRw/wvBhWRff8CEwuH5u3Qiul+azwDGSesvve1DDceaEhXWiGkXeZTojfQ== + dependencies: + neon-cli "0.8.2" + node-pre-gyp "0.17.0" + "@multiformats/base-x@^4.0.1": version "4.0.1" resolved "https://registry.yarnpkg.com/@multiformats/base-x/-/base-x-4.0.1.tgz#95ff0fa58711789d53aefb2590a8b7a4e715d121" @@ -2082,7 +2104,7 @@ resolved "https://registry.yarnpkg.com/@sovpro/delimited-stream/-/delimited-stream-1.1.0.tgz#4334bba7ee241036e580fdd99c019377630d26b4" integrity sha512-kQpk267uxB19X3X2T1mvNMjyvIEonpNSHrMlK5ZaBU6aZxw7wPbpgKJOjHN3+/GPVpXgAV9soVT2oyHpLkLtyw== -"@stablelib/binary@^1.0.1": +"@stablelib/binary@^1.0.0", "@stablelib/binary@^1.0.1": version "1.0.1" resolved "https://registry.yarnpkg.com/@stablelib/binary/-/binary-1.0.1.tgz#c5900b94368baf00f811da5bdb1610963dfddf7f" integrity sha512-ClJWvmL6UBM/wjkvv/7m5VP3GMr9t0osr4yVgLZsLCOz4hGN9gIAFEqnJ0TsSMAN+n840nf2cHZnA5/KFqHC7Q== @@ -2108,6 +2130,14 @@ resolved "https://registry.yarnpkg.com/@stablelib/int/-/int-1.0.1.tgz#75928cc25d59d73d75ae361f02128588c15fd008" integrity sha512-byr69X/sDtDiIjIV6m4roLVWnNNlRGzsvxw+agj8CIEazqWGOQp2dTYgQhtyVXV9wpO6WyXRQUzLV/JRNumT2w== +"@stablelib/random@1.0.0": + version "1.0.0" + resolved "https://registry.yarnpkg.com/@stablelib/random/-/random-1.0.0.tgz#f441495075cdeaa45de16d7ddcc269c0b8edb16b" + integrity sha512-G9vwwKrNCGMI/uHL6XeWe2Nk4BuxkYyWZagGaDU9wrsuV+9hUwNI1lok2WVo8uJDa2zx7ahNwN7Ij983hOUFEw== + dependencies: + "@stablelib/binary" "^1.0.0" + "@stablelib/wipe" "^1.0.0" + "@stablelib/random@^1.0.1": version "1.0.1" resolved "https://registry.yarnpkg.com/@stablelib/random/-/random-1.0.1.tgz#4357a00cb1249d484a9a71e6054bc7b8324a7009" @@ -2134,7 +2164,7 @@ "@stablelib/hash" "^1.0.1" "@stablelib/wipe" "^1.0.1" -"@stablelib/wipe@^1.0.1": +"@stablelib/wipe@^1.0.0", "@stablelib/wipe@^1.0.1": version "1.0.1" resolved "https://registry.yarnpkg.com/@stablelib/wipe/-/wipe-1.0.1.tgz#d21401f1d59ade56a62e139462a97f104ed19a36" integrity sha512-WfqfX/eXGiAd3RJe4VU2snh/ZPwtSjLG4ynQ/vYzvghTh7dHFcI1wl+nrkWG6lGhukOxOsUHfv8dUXr58D0ayg== @@ -2824,6 +2854,16 @@ arr-union@^3.1.0: resolved "https://registry.yarnpkg.com/arr-union/-/arr-union-3.1.0.tgz#e39b09aea9def866a8f206e288af63919bae39c4" integrity sha1-45sJrqne+Gao8gbiiK9jkZuuOcQ= +array-back@^3.0.1, array-back@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/array-back/-/array-back-3.1.0.tgz#b8859d7a508871c9a7b2cf42f99428f65e96bfb0" + integrity sha512-TkuxA4UCOvxuDK6NZYXCalszEzj+TLszyASooky+i742l9TqsOdYCMJJupxRic61hwquNtppB3hgcuq9SVSH1Q== + +array-back@^4.0.1: + version "4.0.2" + resolved "https://registry.yarnpkg.com/array-back/-/array-back-4.0.2.tgz#8004e999a6274586beeb27342168652fdb89fa1e" + integrity sha512-NbdMezxqf94cnNfWLL7V/im0Ub+Anbb0IoZhvzie8+4HJ4nMQuzHuy49FkGYCJK2yAloZ3meiB6AVMClbrI1vg== + array-differ@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/array-differ/-/array-differ-3.0.0.tgz#3cbb3d0f316810eafcc47624734237d6aee4ae6b" @@ -3658,6 +3698,33 @@ command-exists@^1.2.8: resolved "https://registry.yarnpkg.com/command-exists/-/command-exists-1.2.9.tgz#c50725af3808c8ab0260fd60b01fbfa25b954f69" integrity sha512-LTQ/SGc+s0Xc0Fu5WaKnR0YiygZkm9eKFvyS+fRsU7/ZWFF8ykFM6Pc9aCVf1+xasOOZpO3BAVgVrKvsqKHV7w== +command-line-args@^5.1.1: + version "5.2.1" + resolved "https://registry.yarnpkg.com/command-line-args/-/command-line-args-5.2.1.tgz#c44c32e437a57d7c51157696893c5909e9cec42e" + integrity sha512-H4UfQhZyakIjC74I9d34fGYDwk3XpSr17QhEd0Q3I9Xq1CETHo4Hcuo87WyWHpAF1aSLjLRf5lD9ZGX2qStUvg== + dependencies: + array-back "^3.1.0" + find-replace "^3.0.0" + lodash.camelcase "^4.3.0" + typical "^4.0.0" + +command-line-commands@^3.0.1: + version "3.0.2" + resolved "https://registry.yarnpkg.com/command-line-commands/-/command-line-commands-3.0.2.tgz#53872a1181db837f21906b1228e260a4eeb42ee4" + integrity sha512-ac6PdCtdR6q7S3HN+JiVLIWGHY30PRYIEl2qPo+FuEuzwAUk0UYyimrngrg7FvF/mCr4Jgoqv5ZnHZgads50rw== + dependencies: + array-back "^4.0.1" + +command-line-usage@^6.1.0: + version "6.1.1" + resolved "https://registry.yarnpkg.com/command-line-usage/-/command-line-usage-6.1.1.tgz#c908e28686108917758a49f45efb4f02f76bc03f" + integrity sha512-F59pEuAR9o1SF/bD0dQBDluhpT4jJQNWUHEuVBqpDmCUo6gPjCi+m9fCWnWZVR/oG6cMTUms4h+3NPl74wGXvA== + dependencies: + array-back "^4.0.1" + chalk "^2.4.2" + table-layout "^1.0.1" + typical "^5.2.0" + commander@^2.15.0, commander@^2.19.0: version "2.20.3" resolved "https://registry.yarnpkg.com/commander/-/commander-2.20.3.tgz#fd485e84c03eb4881c20722ba48035e8531aeb33" @@ -4051,6 +4118,11 @@ dedent@^0.7.0: resolved "https://registry.yarnpkg.com/dedent/-/dedent-0.7.0.tgz#2495ddbaf6eb874abb0e1be9df22d2e5a544326c" integrity sha1-JJXduvbrh0q7Dhvp3yLS5aVEMmw= +deep-extend@^0.6.0, deep-extend@~0.6.0: + version "0.6.0" + resolved "https://registry.yarnpkg.com/deep-extend/-/deep-extend-0.6.0.tgz#c4fa7c95404a17a9c3e8ca7e1537312b736330ac" + integrity sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA== + deep-is@^0.1.3, deep-is@~0.1.3: version "0.1.4" resolved "https://registry.yarnpkg.com/deep-is/-/deep-is-0.1.4.tgz#a6f2dce612fadd2ef1f519b73551f17e85199831" @@ -4148,6 +4220,11 @@ detect-indent@^6.0.0: resolved "https://registry.yarnpkg.com/detect-indent/-/detect-indent-6.1.0.tgz#592485ebbbf6b3b1ab2be175c8393d04ca0d57e6" integrity sha512-reYkTUJAZb9gUuZ2RvVCNhVHdg62RHnJ7WJl8ftMi4diZ6NWlciOzQN88pUhSELEwflJht4oQDv0F0BMlwaYtA== +detect-libc@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/detect-libc/-/detect-libc-1.0.3.tgz#fa137c4bd698edf55cd5cd02ac559f91a4c4ba9b" + integrity sha1-+hN8S9aY7fVc1c0CrFWfkaTEups= + detect-newline@^3.0.0: version "3.1.0" resolved "https://registry.yarnpkg.com/detect-newline/-/detect-newline-3.1.0.tgz#576f5dfc63ae1a192ff192d8ad3af6308991b651" @@ -4899,6 +4976,13 @@ find-cache-dir@^2.0.0: make-dir "^2.0.0" pkg-dir "^3.0.0" +find-replace@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/find-replace/-/find-replace-3.0.0.tgz#3e7e23d3b05167a76f770c9fbd5258b0def68c38" + integrity sha512-6Tb2myMioCAgv5kfvP5/PkZZ/ntTpVK39fHY7WkWBgvbeE+VHd/tZuZ4mrC+bxh4cfOZeYKVPaJIZtZXV7GNCQ== + dependencies: + array-back "^3.0.1" + find-up@^2.0.0, find-up@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/find-up/-/find-up-2.1.0.tgz#45d1b7e506c717ddd482775a2b77920a3c0c57a7" @@ -5177,6 +5261,13 @@ getpass@^0.1.1: dependencies: assert-plus "^1.0.0" +git-config@0.0.7: + version "0.0.7" + resolved "https://registry.yarnpkg.com/git-config/-/git-config-0.0.7.tgz#a9c8a3ef07a776c3d72261356d8b727b62202b28" + integrity sha1-qcij7wendsPXImE1bYtye2IgKyg= + dependencies: + iniparser "~1.0.5" + git-raw-commits@^2.0.8: version "2.0.11" resolved "https://registry.yarnpkg.com/git-raw-commits/-/git-raw-commits-2.0.11.tgz#bc3576638071d18655e1cc60d7f524920008d723" @@ -5274,7 +5365,7 @@ graceful-fs@^4.1.11, graceful-fs@^4.1.15, graceful-fs@^4.1.2, graceful-fs@^4.1.3 resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.10.tgz#147d3a006da4ca3ce14728c7aefc287c367d7a6c" integrity sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA== -handlebars@^4.7.7: +handlebars@^4.7.6, handlebars@^4.7.7: version "4.7.7" resolved "https://registry.yarnpkg.com/handlebars/-/handlebars-4.7.7.tgz#9ce33416aad02dbd6c8fafa8240d5d98004945a1" integrity sha512-aAcXm5OAfE/8IXkcZvCepKU3VzW1/39Fb5ZuqMtgI/hT8X2YgoMvBY5dLhq/cpOvw7Lk1nK/UF71aLG/ZnVYRA== @@ -5476,7 +5567,7 @@ husky@^7.0.1: resolved "https://registry.yarnpkg.com/husky/-/husky-7.0.4.tgz#242048245dc49c8fb1bf0cc7cfb98dd722531535" integrity sha512-vbaCKN2QLtP/vD4yvs6iz6hBEo6wkSzs8HpRah1Z6aGmF2KW5PdYuAd7uX5a+OyBZHBhd+TFLqgjUgytQr4RvQ== -iconv-lite@0.4.24, iconv-lite@^0.4.24: +iconv-lite@0.4.24, iconv-lite@^0.4.24, iconv-lite@^0.4.4: version "0.4.24" resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.24.tgz#2022b4b25fbddc21d2f524974a474aafe733908b" integrity sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA== @@ -5495,7 +5586,7 @@ ieee754@^1.1.13, ieee754@^1.2.1: resolved "https://registry.yarnpkg.com/ieee754/-/ieee754-1.2.1.tgz#8eb7a10a63fff25d15a57b001586d177d1b0d352" integrity sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA== -ignore-walk@^3.0.3: +ignore-walk@^3.0.1, ignore-walk@^3.0.3: version "3.0.4" resolved "https://registry.yarnpkg.com/ignore-walk/-/ignore-walk-3.0.4.tgz#c9a09f69b7c7b479a5d74ac1a3c0d4236d2a6335" integrity sha512-PY6Ii8o1jMRA1z4F2hRkH/xN59ox43DavKvD3oDpfurRlOJyAHpifIwpbdv1n4jt4ov0jSpw3kQ4GhJnpBL6WQ== @@ -5585,11 +5676,16 @@ inherits@2, inherits@2.0.4, inherits@^2.0.3, inherits@~2.0.3: resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c" integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== -ini@^1.3.2, ini@^1.3.4: +ini@^1.3.2, ini@^1.3.4, ini@~1.3.0: version "1.3.8" resolved "https://registry.yarnpkg.com/ini/-/ini-1.3.8.tgz#a29da425b48806f34767a4efce397269af28432c" integrity sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew== +iniparser@~1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/iniparser/-/iniparser-1.0.5.tgz#836d6befe6dfbfcee0bccf1cf9f2acc7027f783d" + integrity sha1-g21r7+bfv87gvM8c+fKsxwJ/eD0= + init-package-json@^2.0.2: version "2.0.5" resolved "https://registry.yarnpkg.com/init-package-json/-/init-package-json-2.0.5.tgz#78b85f3c36014db42d8f32117252504f68022646" @@ -6862,6 +6958,11 @@ lodash._reinterpolate@^3.0.0: resolved "https://registry.yarnpkg.com/lodash._reinterpolate/-/lodash._reinterpolate-3.0.0.tgz#0ccf2d89166af03b3663c796538b75ac6e114d9d" integrity sha1-DM8tiRZq8Ds2Y8eWU4t1rG4RTZ0= +lodash.camelcase@^4.3.0: + version "4.3.0" + resolved "https://registry.yarnpkg.com/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz#b28aa6288a2b9fc651035c7711f65ab6190331a6" + integrity sha1-soqmKIorn8ZRA1x3EfZathkDMaY= + lodash.debounce@^4.0.8: version "4.0.8" resolved "https://registry.yarnpkg.com/lodash.debounce/-/lodash.debounce-4.0.8.tgz#82d79bff30a67c4005ffd5e2515300ad9ca4d7af" @@ -7015,6 +7116,11 @@ make-fetch-happen@^9.0.1, make-fetch-happen@^9.1.0: socks-proxy-agent "^6.0.0" ssri "^8.0.0" +make-promises-safe@^5.1.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/make-promises-safe/-/make-promises-safe-5.1.0.tgz#dd9d311f555bcaa144f12e225b3d37785f0aa8f2" + integrity sha512-AfdZ49rtyhQR/6cqVKGoH7y4ql7XkS5HJI1lZm0/5N6CQosy1eYbBJ/qbhkKHzo17UH7M918Bysf6XB9f3kS1g== + makeerror@1.0.12: version "1.0.12" resolved "https://registry.yarnpkg.com/makeerror/-/makeerror-1.0.12.tgz#3e5dd2079a82e812e983cc6610c4a2cb0eaa801a" @@ -7602,6 +7708,15 @@ natural-compare@^1.4.0: resolved "https://registry.yarnpkg.com/natural-compare/-/natural-compare-1.4.0.tgz#4abebfeed7541f2c27acfb29bdbbd15c8d5ba4f7" integrity sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc= +needle@^2.5.2: + version "2.9.1" + resolved "https://registry.yarnpkg.com/needle/-/needle-2.9.1.tgz#22d1dffbe3490c2b83e301f7709b6736cd8f2684" + integrity sha512-6R9fqJ5Zcmf+uYaFgdIHmLwNldn5HbK8L5ybn7Uz+ylX/rnOsSp1AHcvQSrCaFN+qNM1wpymHqD7mVasEOlHGQ== + dependencies: + debug "^3.2.6" + iconv-lite "^0.4.4" + sax "^1.2.4" + negotiator@0.6.3, negotiator@^0.6.2: version "0.6.3" resolved "https://registry.yarnpkg.com/negotiator/-/negotiator-0.6.3.tgz#58e323a72fedc0d6f9cd4d31fe49f51479590ccd" @@ -7612,6 +7727,26 @@ neo-async@^2.5.0, neo-async@^2.6.0: resolved "https://registry.yarnpkg.com/neo-async/-/neo-async-2.6.2.tgz#b4aafb93e3aeb2d8174ca53cf163ab7d7308305f" integrity sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw== +neon-cli@0.8.2: + version "0.8.2" + resolved "https://registry.yarnpkg.com/neon-cli/-/neon-cli-0.8.2.tgz#5111b0e9d5d90273bdf85a9aa40a1a47a32df2ef" + integrity sha512-vYRBmiLiwPVeBvR9huCFXRAtdLYfsoSG3hgsXrcuyMSXk7yqpnZlgvOGGuxfhrRb/iNfcd0M0cEs0j22mDgZ+A== + dependencies: + chalk "^4.1.0" + command-line-args "^5.1.1" + command-line-commands "^3.0.1" + command-line-usage "^6.1.0" + git-config "0.0.7" + handlebars "^4.7.6" + inquirer "^7.3.3" + make-promises-safe "^5.1.0" + rimraf "^3.0.2" + semver "^7.3.2" + toml "^3.0.0" + ts-typed-json "^0.3.2" + validate-npm-package-license "^3.0.4" + validate-npm-package-name "^3.0.0" + nice-try@^1.0.4: version "1.0.5" resolved "https://registry.yarnpkg.com/nice-try/-/nice-try-1.0.5.tgz#a3378a7696ce7d223e88fc9b764bd7ef1089e366" @@ -7710,7 +7845,7 @@ node-stream-zip@^1.9.1: resolved "https://registry.yarnpkg.com/node-stream-zip/-/node-stream-zip-1.15.0.tgz#158adb88ed8004c6c49a396b50a6a5de3bca33ea" integrity sha512-LN4fydt9TqhZhThkZIVQnF9cwjU3qmUH9h78Mx/K7d3VvfRqqwthLwJEUOEL0QPZ0XQmNN7be5Ggit5+4dq3Bw== -nopt@^4.0.1: +nopt@^4.0.1, nopt@^4.0.3: version "4.0.3" resolved "https://registry.yarnpkg.com/nopt/-/nopt-4.0.3.tgz#a375cad9d02fd921278d954c2254d5aa57e15e48" integrity sha512-CvaGwVMztSMJLOeXPrez7fyfObdZqNUK1cPAEzLHrTybIua9pMdmmPR5YwtfNftIOMv3DPUhFaxsZMNTQO20Kg== @@ -7762,7 +7897,7 @@ normalize-url@^6.1.0: resolved "https://registry.yarnpkg.com/normalize-url/-/normalize-url-6.1.0.tgz#40d0885b535deffe3f3147bec877d05fe4c5668a" integrity sha512-DlL+XwOy3NxAQ8xuC0okPgK46iuVNAK01YN7RueYBqqFeGsBjV9XmCAzAdgt+667bCl5kPh9EqKKDwnaPG1I7A== -npm-bundled@^1.1.1: +npm-bundled@^1.0.1, npm-bundled@^1.1.1: version "1.1.2" resolved "https://registry.yarnpkg.com/npm-bundled/-/npm-bundled-1.1.2.tgz#944c78789bd739035b70baa2ca5cc32b8d860bc1" integrity sha512-x5DHup0SuyQcmL3s7Rx/YQ8sbw/Hzg0rj48eN0dV7hf5cmQq5PXIeioroH3raV1QC1yh3uTYuMThvEQF3iKgGQ== @@ -7804,6 +7939,15 @@ npm-package-arg@^8.0.0, npm-package-arg@^8.0.1, npm-package-arg@^8.1.0, npm-pack semver "^7.3.4" validate-npm-package-name "^3.0.0" +npm-packlist@^1.4.8: + version "1.4.8" + resolved "https://registry.yarnpkg.com/npm-packlist/-/npm-packlist-1.4.8.tgz#56ee6cc135b9f98ad3d51c1c95da22bbb9b2ef3e" + integrity sha512-5+AZgwru5IevF5ZdnFglB5wNlHG1AOOuw28WhUq8/8emhBmLv6jX5by4WJCh7lW0uSYZYS6DXqIsyZVIXRZU9A== + dependencies: + ignore-walk "^3.0.1" + npm-bundled "^1.0.1" + npm-normalize-package-bin "^1.0.1" + npm-packlist@^2.1.4: version "2.2.2" resolved "https://registry.yarnpkg.com/npm-packlist/-/npm-packlist-2.2.2.tgz#076b97293fa620f632833186a7a8f65aaa6148c8" @@ -8567,6 +8711,16 @@ raw-body@2.5.1: iconv-lite "0.4.24" unpipe "1.0.0" +rc@^1.2.8: + version "1.2.8" + resolved "https://registry.yarnpkg.com/rc/-/rc-1.2.8.tgz#cd924bf5200a075b83c188cd6b9e211b7fc0d3ed" + integrity sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw== + dependencies: + deep-extend "^0.6.0" + ini "~1.3.0" + minimist "^1.2.0" + strip-json-comments "~2.0.1" + react-devtools-core@^4.6.0: version "4.24.5" resolved "https://registry.yarnpkg.com/react-devtools-core/-/react-devtools-core-4.24.5.tgz#99b611ecb6dbe96d5de362ca2d1b0a1b9da06e0a" @@ -9032,7 +9186,7 @@ reusify@^1.0.4: resolved "https://registry.yarnpkg.com/reusify/-/reusify-1.0.4.tgz#90da382b1e126efc02146e90845a88db12925d76" integrity sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw== -rimraf@^2.5.4, rimraf@^2.6.3: +rimraf@^2.5.4, rimraf@^2.6.3, rimraf@^2.7.1: version "2.7.1" resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.7.1.tgz#35797f13a7fdadc566142c29d4f07ccad483e3ec" integrity sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w== @@ -9126,7 +9280,7 @@ sane@^4.0.3: minimist "^1.1.1" walker "~1.0.5" -sax@^1.2.1: +sax@^1.2.1, sax@^1.2.4: version "1.2.4" resolved "https://registry.yarnpkg.com/sax/-/sax-1.2.4.tgz#2816234e2378bddc4e5354fab5caa895df7100d9" integrity sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw== @@ -9684,6 +9838,11 @@ strip-json-comments@^3.1.0, strip-json-comments@^3.1.1: resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-3.1.1.tgz#31f1281b3832630434831c310c01cccda8cbe006" integrity sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig== +strip-json-comments@~2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-2.0.1.tgz#3c531942e908c2697c0ec344858c286c7ca0a60a" + integrity sha1-PFMZQukIwml8DsNEhYwobHygpgo= + strong-log-transformer@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/strong-log-transformer/-/strong-log-transformer-2.1.0.tgz#0f5ed78d325e0421ac6f90f7f10e691d6ae3ae10" @@ -9737,6 +9896,16 @@ symbol-tree@^3.2.4: resolved "https://registry.yarnpkg.com/symbol-tree/-/symbol-tree-3.2.4.tgz#430637d248ba77e078883951fb9aa0eed7c63fa2" integrity sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw== +table-layout@^1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/table-layout/-/table-layout-1.0.2.tgz#c4038a1853b0136d63365a734b6931cf4fad4a04" + integrity sha512-qd/R7n5rQTRFi+Zf2sk5XVVd9UQl6ZkduPFC3S7WEGJAmetDTjY3qPN50eSKzwuzEyQKy5TN2TiZdkIjos2L6A== + dependencies: + array-back "^4.0.1" + deep-extend "~0.6.0" + typical "^5.2.0" + wordwrapjs "^4.0.0" + table@^6.0.9: version "6.8.0" resolved "https://registry.yarnpkg.com/table/-/table-6.8.0.tgz#87e28f14fa4321c3377ba286f07b79b281a3b3ca" @@ -9748,7 +9917,7 @@ table@^6.0.9: string-width "^4.2.3" strip-ansi "^6.0.1" -tar@^4.4.12: +tar@^4.4.12, tar@^4.4.13: version "4.4.19" resolved "https://registry.yarnpkg.com/tar/-/tar-4.4.19.tgz#2e4d7263df26f2b914dee10c825ab132123742f3" integrity sha512-a20gEsvHnWe0ygBY8JbxoM4w3SJdhc7ZAuxkLqh+nvNQN2IOt0B5lLgM490X5Hl8FF0dl0tOf2ewFYAlIFgzVA== @@ -9915,6 +10084,11 @@ toidentifier@1.0.1: resolved "https://registry.yarnpkg.com/toidentifier/-/toidentifier-1.0.1.tgz#3be34321a88a820ed1bd80dfaa33e479fbb8dd35" integrity sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA== +toml@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/toml/-/toml-3.0.0.tgz#342160f1af1904ec9d204d03a5d61222d762c5ee" + integrity sha512-y/mWCZinnvxjTKYhJ+pYxwD0mRLVvOtdS2Awbgxln6iEnt4rk0yBxeSBHkGJcPucRiG0e55mwWp+g/05rsrd6w== + tough-cookie@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-4.0.0.tgz#d822234eeca882f991f0f908824ad2622ddbece4" @@ -10114,6 +10288,16 @@ typescript@~4.3.0: resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.3.5.tgz#4d1c37cc16e893973c45a06886b7113234f119f4" integrity sha512-DqQgihaQ9cUrskJo9kIyW/+g0Vxsk8cDtZ52a3NGh0YNTfpUSArXSohyUGnvbPazEPLu398C0UxmKSOrPumUzA== +typical@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/typical/-/typical-4.0.0.tgz#cbeaff3b9d7ae1e2bbfaf5a4e6f11eccfde94fc4" + integrity sha512-VAH4IvQ7BDFYglMd7BPRDfLgxZZX4O4TFcRDA6EN5X7erNJJq+McIEp8np9aVtxrCJ6qx4GTYVfOWNjcqwZgRw== + +typical@^5.2.0: + version "5.2.0" + resolved "https://registry.yarnpkg.com/typical/-/typical-5.2.0.tgz#4daaac4f2b5315460804f0acf6cb69c52bb93066" + integrity sha512-dvdQgNDNJo+8B2uBQoqdb11eUCE1JQXhvjC/CZtgvZseVd5TYMXnq0+vuUemXbd/Se29cTaUuPX3YIc2xgbvIg== + uglify-es@^3.1.9: version "3.3.9" resolved "https://registry.yarnpkg.com/uglify-es/-/uglify-es-3.3.9.tgz#0c1c4f0700bed8dbc124cdb304d2592ca203e677" @@ -10488,6 +10672,14 @@ wordwrap@^1.0.0: resolved "https://registry.yarnpkg.com/wordwrap/-/wordwrap-1.0.0.tgz#27584810891456a4171c8d0226441ade90cbcaeb" integrity sha1-J1hIEIkUVqQXHI0CJkQa3pDLyus= +wordwrapjs@^4.0.0: + version "4.0.1" + resolved "https://registry.yarnpkg.com/wordwrapjs/-/wordwrapjs-4.0.1.tgz#d9790bccfb110a0fc7836b5ebce0937b37a8b98f" + integrity sha512-kKlNACbvHrkpIw6oPeYDSmdCTu2hdMHoyXLTcUKala++lx5Y+wjJ/e474Jqv5abnVmwxw08DiTuHmw69lJGksA== + dependencies: + reduce-flatten "^2.0.0" + typical "^5.2.0" + wrap-ansi@^6.2.0: version "6.2.0" resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-6.2.0.tgz#e9393ba07102e6c91a3b221478f0257cd2856e53"