From 1c6aeae31ac57e83f4059f3dba35ccb1ca36926e Mon Sep 17 00:00:00 2001 From: Ariel Gentile Date: Tue, 21 Feb 2023 19:18:19 -0300 Subject: [PATCH] fix(askar): anoncrypt messages unpacking (#1332) Signed-off-by: Ariel Gentile --- .../anoncreds/tests/legacyAnonCredsSetup.ts | 68 +++++- packages/askar/src/wallet/AskarWallet.ts | 8 +- .../e2e-askar-indy-sdk-wallet-subject.test.ts | 199 +++++++----------- 3 files changed, 149 insertions(+), 126 deletions(-) diff --git a/packages/anoncreds/tests/legacyAnonCredsSetup.ts b/packages/anoncreds/tests/legacyAnonCredsSetup.ts index 9b6da7fd32..32e248f586 100644 --- a/packages/anoncreds/tests/legacyAnonCredsSetup.ts +++ b/packages/anoncreds/tests/legacyAnonCredsSetup.ts @@ -28,10 +28,16 @@ import { } from '@aries-framework/core' import { randomUUID } from 'crypto' +import { AnonCredsRsModule } from '../../anoncreds-rs/src' +import { AskarModule } from '../../askar/src' +import { uuid } from '../../core/src/utils/uuid' import { setupSubjectTransports, setupEventReplaySubjects } from '../../core/tests' import { getAgentOptions, makeConnection, + genesisTransactions, + taaVersion, + taaAcceptanceMechanism, waitForCredentialRecordSubject, waitForProofExchangeRecordSubject, } from '../../core/tests/helpers' @@ -43,6 +49,7 @@ import { IndySdkSovDidResolver, } from '../../indy-sdk/src' import { getIndySdkModuleConfig } from '../../indy-sdk/tests/setupIndySdkModule' +import { IndyVdrAnonCredsRegistry, IndyVdrSovDidResolver, IndyVdrModule } from '../../indy-vdr/src' import { V1CredentialProtocol, V1ProofProtocol, @@ -52,7 +59,9 @@ import { } from '../src' // Helper type to get the type of the agents (with the custom modules) for the credential tests -export type AnonCredsTestsAgent = Agent> +export type AnonCredsTestsAgent = + | Agent> + | Agent> export const getLegacyAnonCredsModules = ({ autoAcceptCredentials, @@ -97,6 +106,63 @@ export const getLegacyAnonCredsModules = ({ return modules } +export const getAskarAnonCredsIndyModules = ({ + autoAcceptCredentials, + autoAcceptProofs, +}: { autoAcceptCredentials?: AutoAcceptCredential; autoAcceptProofs?: AutoAcceptProof } = {}) => { + const legacyIndyCredentialFormatService = new LegacyIndyCredentialFormatService() + const legacyIndyProofFormatService = new LegacyIndyProofFormatService() + + const indyNetworkConfig = { + id: `localhost-${uuid()}`, + isProduction: false, + genesisTransactions, + indyNamespace: 'pool:localtest', + transactionAuthorAgreement: { version: taaVersion, acceptanceMechanism: taaAcceptanceMechanism }, + } + + const modules = { + credentials: new CredentialsModule({ + autoAcceptCredentials, + credentialProtocols: [ + new V1CredentialProtocol({ + indyCredentialFormat: legacyIndyCredentialFormatService, + }), + new V2CredentialProtocol({ + credentialFormats: [legacyIndyCredentialFormatService], + }), + ], + }), + proofs: new ProofsModule({ + autoAcceptProofs, + proofProtocols: [ + new V1ProofProtocol({ + indyProofFormat: legacyIndyProofFormatService, + }), + new V2ProofProtocol({ + proofFormats: [legacyIndyProofFormatService], + }), + ], + }), + anoncreds: new AnonCredsModule({ + registries: [new IndyVdrAnonCredsRegistry()], + }), + anoncredsRs: new AnonCredsRsModule(), + indyVdr: new IndyVdrModule({ + networks: [indyNetworkConfig], + }), + dids: new DidsModule({ + resolvers: [new IndyVdrSovDidResolver()], // TODO: Support Registrar for tests + }), + askar: new AskarModule(), + cache: new CacheModule({ + cache: new InMemoryLruCache({ limit: 100 }), + }), + } as const + + return modules +} + export async function presentLegacyAnonCredsProof({ verifierAgent, verifierReplay, diff --git a/packages/askar/src/wallet/AskarWallet.ts b/packages/askar/src/wallet/AskarWallet.ts index b11c5f9371..46b004006e 100644 --- a/packages/askar/src/wallet/AskarWallet.ts +++ b/packages/askar/src/wallet/AskarWallet.ts @@ -583,9 +583,7 @@ export class AskarWallet implements Wallet { const protectedJson = JsonEncoder.fromBase64(messagePackage.protected) const alg = protectedJson.alg - const isAuthcrypt = alg === 'Authcrypt' - - if (!isAuthcrypt && alg != 'Anoncrypt') { + if (!['Anoncrypt', 'Authcrypt'].includes(alg)) { throw new WalletError(`Unsupported pack algorithm: ${alg}`) } @@ -645,6 +643,8 @@ export class AskarWallet implements Wallet { message: recipient.encrypted_key, nonce: recipient.iv, }) + } else { + payloadKey = CryptoBox.sealOpen({ ciphertext: recipient.encrypted_key, recipientKey: recip_x }) } break } @@ -653,7 +653,7 @@ export class AskarWallet implements Wallet { throw new WalletError('No corresponding recipient key found') } - if (!senderKey && isAuthcrypt) { + if (!senderKey && alg === 'Authcrypt') { throw new WalletError('Sender public key not provided for Authcrypt') } diff --git a/tests/e2e-askar-indy-sdk-wallet-subject.test.ts b/tests/e2e-askar-indy-sdk-wallet-subject.test.ts index 199d57a314..d59263dfe2 100644 --- a/tests/e2e-askar-indy-sdk-wallet-subject.test.ts +++ b/tests/e2e-askar-indy-sdk-wallet-subject.test.ts @@ -1,141 +1,98 @@ import type { SubjectMessage } from './transport/SubjectInboundTransport' +import type { AnonCredsTestsAgent } from '../packages/anoncreds/tests/legacyAnonCredsSetup' -import indySdk from 'indy-sdk' import { Subject } from 'rxjs' -import { getAgentOptions, makeConnection, waitForBasicMessage } from '../packages/core/tests/helpers' +import { + getAskarAnonCredsIndyModules, + getLegacyAnonCredsModules, +} from '../packages/anoncreds/tests/legacyAnonCredsSetup' +import { getAgentOptions } from '../packages/core/tests/helpers' -import { AskarModule } from '@aries-framework/askar' -import { Agent, DependencyManager, InjectionSymbols } from '@aries-framework/core' -import { IndySdkModule, IndySdkStorageService, IndySdkWallet } from '@aries-framework/indy-sdk' +import { Agent, AutoAcceptCredential, MediatorPickupStrategy } from '@aries-framework/core' +import { e2eTest } from './e2e-test' import { SubjectInboundTransport } from './transport/SubjectInboundTransport' import { SubjectOutboundTransport } from './transport/SubjectOutboundTransport' -// FIXME: Re-include in tests when Askar NodeJS wrapper performance is improved -describe.skip('E2E Askar-Indy SDK Wallet Subject tests', () => { - let recipientAgent: Agent - let senderAgent: Agent - - afterEach(async () => { - if (recipientAgent) { - await recipientAgent.shutdown() - await recipientAgent.wallet.delete() - } - - if (senderAgent) { - await senderAgent.shutdown() - await senderAgent.wallet.delete() - } +const recipientAgentOptions = getAgentOptions( + 'E2E Askar Subject Recipient', + { + mediatorPickupStrategy: MediatorPickupStrategy.PickUpV1, + }, + getAskarAnonCredsIndyModules({ + autoAcceptCredentials: AutoAcceptCredential.ContentApproved, }) - - test('Wallet Subject flow - Indy Sender / Askar Receiver ', async () => { - // Sender is an Agent using Indy SDK Wallet - const senderDependencyManager = new DependencyManager() - senderDependencyManager.registerContextScoped(InjectionSymbols.Wallet, IndySdkWallet) - senderDependencyManager.registerSingleton(InjectionSymbols.StorageService, IndySdkStorageService) - senderAgent = new Agent( - getAgentOptions( - 'E2E Wallet Subject Sender Indy', - { endpoints: ['rxjs:sender'] }, - { indySdk: new IndySdkModule({ indySdk }) } - ), - senderDependencyManager - ) - - // Recipient is an Agent using Askar Wallet - recipientAgent = new Agent( - getAgentOptions( - 'E2E Wallet Subject Recipient Askar', - { endpoints: ['rxjs:recipient'] }, - { askar: new AskarModule() } - ) - ) - - await e2eWalletTest(senderAgent, recipientAgent) +) +const mediatorAgentOptions = getAgentOptions( + 'E2E Askar Subject Mediator', + { + endpoints: ['rxjs:mediator'], + autoAcceptMediationRequests: true, + }, + getAskarAnonCredsIndyModules({ + autoAcceptCredentials: AutoAcceptCredential.ContentApproved, }) - - test('Wallet Subject flow - Askar Sender / Askar Recipient ', async () => { - // Sender is an Agent using Askar Wallet - senderAgent = new Agent( - getAgentOptions('E2E Wallet Subject Sender Askar', { endpoints: ['rxjs:sender'] }, { askar: new AskarModule() }) - ) - - // Recipient is an Agent using Askar Wallet - recipientAgent = new Agent( - getAgentOptions( - 'E2E Wallet Subject Recipient Askar', - { endpoints: ['rxjs:recipient'] }, - { askar: new AskarModule() } - ) - ) - - await e2eWalletTest(senderAgent, recipientAgent) +) +const senderAgentOptions = getAgentOptions( + 'E2E Indy SDK Subject Sender', + { + endpoints: ['rxjs:sender'], + mediatorPollingInterval: 1000, + mediatorPickupStrategy: MediatorPickupStrategy.PickUpV1, + }, + getLegacyAnonCredsModules({ + autoAcceptCredentials: AutoAcceptCredential.ContentApproved, }) +) - test('Wallet Subject flow - Indy Sender / Indy Recipient ', async () => { - // Sender is an Agent using Indy SDK Wallet - const senderDependencyManager = new DependencyManager() - senderDependencyManager.registerContextScoped(InjectionSymbols.Wallet, IndySdkWallet) - senderDependencyManager.registerSingleton(InjectionSymbols.StorageService, IndySdkStorageService) - senderAgent = new Agent( - getAgentOptions( - 'E2E Wallet Subject Sender Indy', - { endpoints: ['rxjs:sender'] }, - { indySdk: new IndySdkModule({ indySdk }) } - ), - senderDependencyManager - ) +describe.skip('E2E Askar-AnonCredsRS-IndyVDR Subject tests', () => { + let recipientAgent: AnonCredsTestsAgent + let mediatorAgent: AnonCredsTestsAgent + let senderAgent: AnonCredsTestsAgent - // Recipient is an Agent using Indy Wallet - const recipientDependencyManager = new DependencyManager() - recipientDependencyManager.registerContextScoped(InjectionSymbols.Wallet, IndySdkWallet) - recipientDependencyManager.registerSingleton(InjectionSymbols.StorageService, IndySdkStorageService) - recipientAgent = new Agent( - getAgentOptions( - 'E2E Wallet Subject Recipient Indy', - { endpoints: ['rxjs:recipient'] }, - { indySdk: new IndySdkModule({ indySdk }) } - ), - recipientDependencyManager - ) - - await e2eWalletTest(senderAgent, recipientAgent) + beforeEach(async () => { + recipientAgent = new Agent(recipientAgentOptions) + mediatorAgent = new Agent(mediatorAgentOptions) + senderAgent = new Agent(senderAgentOptions) }) -}) - -export async function e2eWalletTest(senderAgent: Agent, recipientAgent: Agent) { - const recipientMessages = new Subject() - const senderMessages = new Subject() - - const subjectMap = { - 'rxjs:recipient': recipientMessages, - 'rxjs:sender': senderMessages, - } - - // Recipient Setup - recipientAgent.registerOutboundTransport(new SubjectOutboundTransport(subjectMap)) - recipientAgent.registerInboundTransport(new SubjectInboundTransport(recipientMessages)) - await recipientAgent.initialize() - // Sender Setup - senderAgent.registerOutboundTransport(new SubjectOutboundTransport(subjectMap)) - senderAgent.registerInboundTransport(new SubjectInboundTransport(senderMessages)) - await senderAgent.initialize() + afterEach(async () => { + await recipientAgent.shutdown() + await recipientAgent.wallet.delete() + await mediatorAgent.shutdown() + await mediatorAgent.wallet.delete() + await senderAgent.shutdown() + await senderAgent.wallet.delete() + }) - // Make connection between sender and recipient - const [recipientSenderConnection, senderRecipientConnection] = await makeConnection(recipientAgent, senderAgent) - expect(recipientSenderConnection).toBeConnectedWith(senderRecipientConnection) + test('Full Subject flow (connect, request mediation, issue, verify)', async () => { + const mediatorMessages = new Subject() + const senderMessages = new Subject() - // Sender sends a basic message and Recipient waits for it - await senderAgent.basicMessages.sendMessage(senderRecipientConnection.id, 'Hello') - await waitForBasicMessage(recipientAgent, { - content: 'Hello', - }) + const subjectMap = { + 'rxjs:mediator': mediatorMessages, + 'rxjs:sender': senderMessages, + } - // Recipient sends a basic message and Sender waits for it - await recipientAgent.basicMessages.sendMessage(recipientSenderConnection.id, 'How are you?') - await waitForBasicMessage(senderAgent, { - content: 'How are you?', + // Recipient Setup + recipientAgent.registerOutboundTransport(new SubjectOutboundTransport(subjectMap)) + await recipientAgent.initialize() + + // Mediator Setup + mediatorAgent.registerOutboundTransport(new SubjectOutboundTransport(subjectMap)) + mediatorAgent.registerInboundTransport(new SubjectInboundTransport(mediatorMessages)) + await mediatorAgent.initialize() + + // Sender Setup + senderAgent.registerOutboundTransport(new SubjectOutboundTransport(subjectMap)) + senderAgent.registerInboundTransport(new SubjectInboundTransport(senderMessages)) + await senderAgent.initialize() + + await e2eTest({ + mediatorAgent, + senderAgent, + recipientAgent, + }) }) -} +})