Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(askar): anoncrypt messages unpacking #1332

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
68 changes: 67 additions & 1 deletion packages/anoncreds/tests/legacyAnonCredsSetup.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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'
Expand All @@ -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,
Expand All @@ -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<ReturnType<typeof getLegacyAnonCredsModules>>
export type AnonCredsTestsAgent =
| Agent<ReturnType<typeof getLegacyAnonCredsModules>>
| Agent<ReturnType<typeof getAskarAnonCredsIndyModules>>

export const getLegacyAnonCredsModules = ({
autoAcceptCredentials,
Expand Down Expand Up @@ -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,
Expand Down
8 changes: 4 additions & 4 deletions packages/askar/src/wallet/AskarWallet.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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}`)
}

Expand Down Expand Up @@ -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
}
Expand All @@ -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')
}

Expand Down
199 changes: 78 additions & 121 deletions tests/e2e-askar-indy-sdk-wallet-subject.test.ts
Original file line number Diff line number Diff line change
@@ -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<SubjectMessage>()
const senderMessages = new Subject<SubjectMessage>()

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<SubjectMessage>()
const senderMessages = new Subject<SubjectMessage>()

// 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,
})
})
}
})