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

refactor: remove master secret id from wallet #1320

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
c8472b4
refactor(proofs)!: generalize proofs api and improve consistency with…
TimoGlastra Feb 9, 2023
0c6d091
chore: fix type issues
TimoGlastra Feb 9, 2023
e941d5a
feat: initial version legacy indy proof format
TimoGlastra Feb 9, 2023
205acf5
feat: legacy indy proof format service
TimoGlastra Feb 10, 2023
6b2d0a1
utterly broken
TimoGlastra Feb 10, 2023
0078863
Merge remote-tracking branch 'upstream/main' into refactor/remove-indy
TimoGlastra Feb 13, 2023
5855c34
temp
TimoGlastra Feb 13, 2023
ca7037a
Merge remote-tracking branch 'upstream/main' into refactor/remove-indy
TimoGlastra Feb 13, 2023
a7efd84
temp
TimoGlastra Feb 14, 2023
d24d426
temp
TimoGlastra Feb 14, 2023
4c0a27b
temp
TimoGlastra Feb 14, 2023
63b073c
Merge remote-tracking branch 'upstream/main' into refactor/remove-indy
TimoGlastra Feb 14, 2023
5d716e3
fix: types fixed
TimoGlastra Feb 14, 2023
eeb8914
style: eslint fixes
TimoGlastra Feb 14, 2023
f81f623
style: eslint fixes
TimoGlastra Feb 14, 2023
4104234
style: eslint fixes
TimoGlastra Feb 14, 2023
81288da
Merge remote-tracking branch 'upstream/main' into refactor/remove-indy
TimoGlastra Feb 14, 2023
12743df
fix: quite some tests
TimoGlastra Feb 15, 2023
4f520c2
temp
TimoGlastra Feb 17, 2023
acbc893
the end is here!
TimoGlastra Feb 17, 2023
f90e814
i lied
TimoGlastra Feb 17, 2023
92d2ff9
Merge remote-tracking branch 'upstream/main' into refactor/remove-indy
TimoGlastra Feb 17, 2023
3dd4def
style: eslint fixes
TimoGlastra Feb 17, 2023
02a07ab
Merge remote-tracking branch 'upstream/main' into refactor/remove-indy
TimoGlastra Feb 17, 2023
e7b00f5
refactor!: remove master secret id from wallet
TimoGlastra Feb 18, 2023
5a7187b
Merge remote-tracking branch 'upstream/main' into refactor/remove-indy
TimoGlastra Feb 19, 2023
3fb4d84
fixes after merge
TimoGlastra Feb 19, 2023
804c938
fix: broken postgres types
TimoGlastra Feb 19, 2023
133fdca
test: fix broken test
TimoGlastra Feb 19, 2023
db6801a
Merge branch 'refactor/remove-indy' into refactor/remove-master-secre…
TimoGlastra Feb 20, 2023
6a490fb
Merge remote-tracking branch 'upstream/main' into refactor/remove-mas…
TimoGlastra Feb 20, 2023
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
Original file line number Diff line number Diff line change
Expand Up @@ -199,7 +199,9 @@ export class AnonCredsRsHolderService implements AnonCredsHolderService {

if (!linkSecretRecord) {
// No default link secret
throw new AnonCredsRsError('No default link secret has been found')
throw new AnonCredsRsError(
'No link secret provided to createCredentialRequest and no default link secret has been found'
)
}

const { credentialRequest, credentialRequestMetadata } = CredentialRequest.create({
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,20 +6,24 @@ import {
CredentialPreviewAttribute,
ProofExchangeRecord,
ProofState,
EventEmitter,
} from '@aries-framework/core'
import * as indySdk from 'indy-sdk'
import { Subject } from 'rxjs'

import { getAgentConfig, getAgentContext } from '../../../../core/tests/helpers'
import { agentDependencies, getAgentConfig, getAgentContext } from '../../../../core/tests/helpers'
import {
IndySdkHolderService,
IndySdkIssuerService,
IndySdkStorageService,
IndySdkVerifierService,
IndySdkWallet,
} from '../../../../indy-sdk/src'
import { IndySdkRevocationService } from '../../../../indy-sdk/src/anoncreds/services/IndySdkRevocationService'
import { indyDidFromPublicKeyBase58 } from '../../../../indy-sdk/src/utils/did'
import { InMemoryAnonCredsRegistry } from '../../../tests/InMemoryAnonCredsRegistry'
import { AnonCredsModuleConfig } from '../../AnonCredsModuleConfig'
import { AnonCredsLinkSecretRecord, AnonCredsLinkSecretRepository } from '../../repository'
import {
AnonCredsHolderServiceSymbol,
AnonCredsIssuerServiceSymbol,
Expand All @@ -40,13 +44,17 @@ const anonCredsVerifierService = new IndySdkVerifierService(indySdk)
const anonCredsHolderService = new IndySdkHolderService(anonCredsRevocationService, indySdk)
const anonCredsIssuerService = new IndySdkIssuerService(indySdk)
const wallet = new IndySdkWallet(indySdk, agentConfig.logger, new SigningProviderRegistry([]))
const storageService = new IndySdkStorageService<AnonCredsLinkSecretRecord>(indySdk)
const eventEmitter = new EventEmitter(agentDependencies, new Subject())
const anonCredsLinkSecretRepository = new AnonCredsLinkSecretRepository(storageService, eventEmitter)
const agentContext = getAgentContext({
registerInstances: [
[AnonCredsIssuerServiceSymbol, anonCredsIssuerService],
[AnonCredsHolderServiceSymbol, anonCredsHolderService],
[AnonCredsVerifierServiceSymbol, anonCredsVerifierService],
[AnonCredsRegistryService, new AnonCredsRegistryService()],
[AnonCredsModuleConfig, anonCredsModuleConfig],
[AnonCredsLinkSecretRepository, anonCredsLinkSecretRepository],
],
agentConfig,
wallet,
Expand All @@ -71,6 +79,16 @@ describe('Legacy indy format services', () => {
const key = await wallet.createKey({ keyType: KeyType.Ed25519 })
const indyDid = indyDidFromPublicKeyBase58(key.publicKeyBase58)

// Create link secret
await anonCredsHolderService.createLinkSecret(agentContext, {
linkSecretId: 'link-secret-id',
})
const anonCredsLinkSecret = new AnonCredsLinkSecretRecord({
linkSecretId: 'link-secret-id',
})
anonCredsLinkSecret.setTag('isDefault', true)
await anonCredsLinkSecretRepository.save(agentContext, anonCredsLinkSecret)

const schema = await anonCredsIssuerService.createSchema(agentContext, {
attrNames: ['name', 'age'],
issuerId: indyDid,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -332,6 +332,11 @@ describe('V1 Proofs - Connectionless - Indy', () => {
expect(faberConnection.isReady).toBe(true)
expect(aliceConnection.isReady).toBe(true)

await aliceAgent.modules.anoncreds.createLinkSecret({
linkSecretId: 'default',
setAsDefault: true,
})

await issueLegacyAnonCredsCredential({
issuerAgent: faberAgent,
issuerReplay: faberReplay,
Expand Down
6 changes: 6 additions & 0 deletions packages/anoncreds/tests/legacyAnonCredsSetup.ts
Original file line number Diff line number Diff line change
Expand Up @@ -329,6 +329,12 @@ export async function setupAnonCredsTests<
await holderAgent.initialize()
if (verifierAgent) await verifierAgent.initialize()

// Create default link secret for holder
await holderAgent.modules.anoncreds.createLinkSecret({
linkSecretId: 'default',
setAsDefault: true,
})

const { credentialDefinition, schema } = await prepareForAnonCredsIssuance(issuerAgent, {
attributeNames,
// TODO: replace with more dynamic / generic value We should create a did using the dids module
Expand Down
12 changes: 0 additions & 12 deletions packages/askar/src/wallet/AskarWallet.ts
Original file line number Diff line number Diff line change
Expand Up @@ -110,16 +110,6 @@ export class AskarWallet implements Wallet {
return this._session
}

public get masterSecretId() {
if (!this.isInitialized || !(this.walletConfig?.id || this.walletConfig?.masterSecretId)) {
throw new AriesFrameworkError(
'Wallet has not been initialized yet. Make sure to await agent.initialize() before using the agent.'
)
}

return this.walletConfig?.masterSecretId ?? this.walletConfig.id
}

/**
* Dispose method is called when an agent context is disposed.
*/
Expand Down Expand Up @@ -156,8 +146,6 @@ export class AskarWallet implements Wallet {
})
this.walletConfig = walletConfig
this._session = await this._store.openSession()

// TODO: Master Secret creation (now part of IndyCredx/AnonCreds)
} catch (error) {
// FIXME: Askar should throw a Duplicate error code, but is currently returning Encryption
// And if we provide the very same wallet key, it will open it without any error
Expand Down
8 changes: 0 additions & 8 deletions packages/askar/src/wallet/__tests__/AskarWallet.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -49,10 +49,6 @@ describe('AskarWallet basic operations', () => {
await askarWallet.delete()
})

test('Get the Master Secret', () => {
expect(askarWallet.masterSecretId).toEqual('Wallet: AskarWalletTest')
})

test('Get the wallet store', () => {
expect(askarWallet.store).toEqual(expect.any(Store))
})
Expand Down Expand Up @@ -124,10 +120,6 @@ describe('AskarWallet basic operations', () => {
})
await expect(askarWallet.verify({ key: ed25519Key, data: message, signature })).resolves.toStrictEqual(true)
})

test('masterSecretId is equal to wallet ID by default', async () => {
expect(askarWallet.masterSecretId).toEqual(walletConfig.id)
})
})

describe.skip('Currently, all KeyTypes are supported by Askar natively', () => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,12 @@ describe('V2 Connectionless Credentials', () => {
aliceAgent.registerOutboundTransport(new SubjectOutboundTransport(subjectMap))
await aliceAgent.initialize()

// Create link secret for alice
await aliceAgent.modules.anoncreds.createLinkSecret({
linkSecretId: 'default',
setAsDefault: true,
})

const { credentialDefinition } = await prepareForAnonCredsIssuance(faberAgent, {
issuerId: faberAgent.publicDid?.did as string,
attributeNames: ['name', 'age'],
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -168,6 +168,12 @@ describe('V2 Credentials - JSON-LD - Ed25519', () => {
await aliceAgent.initialize()
;[, { id: aliceConnectionId }] = await makeConnection(faberAgent, aliceAgent)

// Create link secret for alice
await aliceAgent.modules.anoncreds.createLinkSecret({
linkSecretId: 'default',
setAsDefault: true,
})

const { credentialDefinition } = await prepareForAnonCredsIssuance(faberAgent, {
attributeNames: ['name', 'age', 'profile_picture', 'x-ray'],
issuerId: faberAgent.publicDid?.did as string,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -322,6 +322,11 @@ describe('V2 Connectionless Proofs - Indy', () => {
)
agents = [aliceAgent, faberAgent, mediatorAgent]

await aliceAgent.modules.anoncreds.createLinkSecret({
linkSecretId: 'default',
setAsDefault: true,
})

const { credentialDefinition } = await prepareForAnonCredsIssuance(faberAgent, {
attributeNames: ['name', 'age', 'image_0', 'image_1'],
issuerId: faberAgent.publicDid?.did as string,
Expand Down
1 change: 0 additions & 1 deletion packages/core/src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@ export interface WalletConfig {
key: string
keyDerivationMethod?: KeyDerivationMethod
storage?: WalletStorageConfig
masterSecretId?: string
}

export interface WalletConfigRekey {
Expand Down
33 changes: 28 additions & 5 deletions packages/indy-sdk/src/anoncreds/services/IndySdkHolderService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,8 @@ import type {
IndyProofRequest,
} from 'indy-sdk'

import { injectable, inject, utils } from '@aries-framework/core'
import { AnonCredsLinkSecretRepository } from '@aries-framework/anoncreds'
import { AriesFrameworkError, injectable, inject, utils } from '@aries-framework/core'

import { IndySdkError, isIndyError } from '../../error'
import { IndySdk, IndySdkSymbol } from '../../types'
Expand Down Expand Up @@ -80,6 +81,8 @@ export class IndySdkHolderService implements AnonCredsHolderService {

assertIndySdkWallet(agentContext.wallet)

const linkSecretRepository = agentContext.dependencyManager.resolve(AnonCredsLinkSecretRepository)

try {
agentContext.config.logger.debug('Creating Indy Proof')
const indyRevocationStates: RevStates = await this.indyRevocationService.createRevocationState(
Expand Down Expand Up @@ -114,11 +117,19 @@ export class IndySdkHolderService implements AnonCredsHolderService {
indySchemas[schemaId] = indySdkSchemaFromAnonCreds(schemaId, schema, seqNoMap[schemaId])
}

const linkSecretRecord = await linkSecretRepository.findDefault(agentContext)
if (!linkSecretRecord) {
// No default link secret
throw new AriesFrameworkError(
'No default link secret found. Indy SDK requires a default link secret to be created before creating a proof.'
)
}

const indyProof = await this.indySdk.proverCreateProof(
agentContext.wallet.handle,
proofRequest as IndyProofRequest,
this.parseSelectedCredentials(selectedCredentials),
agentContext.wallet.masterSecretId,
linkSecretRecord.linkSecretId,
indySchemas,
indyCredentialDefinitions,
indyRevocationStates
Expand Down Expand Up @@ -201,10 +212,24 @@ export class IndySdkHolderService implements AnonCredsHolderService {
): Promise<CreateCredentialRequestReturn> {
assertIndySdkWallet(agentContext.wallet)

const linkSecretRepository = agentContext.dependencyManager.resolve(AnonCredsLinkSecretRepository)

// We just generate a prover did like string, as it's not used for anything and we don't need
// to prove ownership of the did. It's deprecated in AnonCreds v1, but kept for backwards compatibility
const proverDid = generateLegacyProverDidLikeString()

// If a link secret is specified, use it. Otherwise, attempt to use default link secret
const linkSecretRecord = options.linkSecretId
? await linkSecretRepository.getByLinkSecretId(agentContext, options.linkSecretId)
: await linkSecretRepository.findDefault(agentContext)

if (!linkSecretRecord) {
// No default link secret
throw new AriesFrameworkError(
'No link secret provided to createCredentialRequest and no default link secret has been found'
)
}

try {
const result = await this.indySdk.proverCreateCredentialReq(
agentContext.wallet.handle,
Expand All @@ -213,9 +238,7 @@ export class IndySdkHolderService implements AnonCredsHolderService {
// NOTE: Is it safe to use the cred_def_id from the offer? I think so. You can't create a request
// for a cred def that is not in the offer
indySdkCredentialDefinitionFromAnonCreds(options.credentialOffer.cred_def_id, options.credentialDefinition),
// FIXME: we need to remove the masterSecret from the wallet, as it is AnonCreds specific
// Issue: https://github.com/hyperledger/aries-framework-javascript/issues/1198
agentContext.wallet.masterSecretId
linkSecretRecord.linkSecretId
)

return {
Expand Down
62 changes: 0 additions & 62 deletions packages/indy-sdk/src/wallet/IndySdkWallet.ts
Original file line number Diff line number Diff line change
Expand Up @@ -81,16 +81,6 @@ export class IndySdkWallet implements Wallet {
return this.walletHandle
}

public get masterSecretId() {
if (!this.isInitialized || !(this.walletConfig?.id || this.walletConfig?.masterSecretId)) {
throw new AriesFrameworkError(
'Wallet has not been initialized yet. Make sure to await agent.initialize() before using the agent.'
)
}

return this.walletConfig?.masterSecretId ?? this.walletConfig.id
}

/**
* Dispose method is called when an agent context is disposed.
*/
Expand Down Expand Up @@ -155,15 +145,8 @@ export class IndySdkWallet implements Wallet {
await this.indySdk.createWallet(this.walletStorageConfig(walletConfig), this.walletCredentials(walletConfig))
this.walletConfig = walletConfig

// We usually want to create master secret only once, therefore, we can to do so when creating a wallet.
await this.open(walletConfig)

// We need to open wallet before creating master secret because we need wallet handle here.
await this.createMasterSecret(this.handle, this.masterSecretId)
} catch (error) {
// If an error ocurred while creating the master secret, we should close the wallet
if (this.isInitialized) await this.close()

if (isIndyError(error, 'WalletAlreadyExistsError')) {
const errorMessage = `Wallet '${walletConfig.id}' already exists`
this.logger.debug(errorMessage)
Expand Down Expand Up @@ -394,51 +377,6 @@ export class IndySdkWallet implements Wallet {
}
}

/**
* Create master secret with specified id in currently opened wallet.
*
* If a master secret by this id already exists in the current wallet, the method
* will return without doing anything.
*
* @throws {WalletError} if an error occurs
*/
private async createMasterSecret(walletHandle: number, masterSecretId: string): Promise<string> {
this.logger.debug(`Creating master secret with id '${masterSecretId}' in wallet with handle '${walletHandle}'`)

try {
await this.indySdk.proverCreateMasterSecret(walletHandle, masterSecretId)

return masterSecretId
} catch (error) {
if (isIndyError(error, 'AnoncredsMasterSecretDuplicateNameError')) {
// master secret id is the same as the master secret id passed in the create function
// so if it already exists we can just assign it.
this.logger.debug(
`Master secret with id '${masterSecretId}' already exists in wallet with handle '${walletHandle}'`,
{
indyError: 'AnoncredsMasterSecretDuplicateNameError',
}
)

return masterSecretId
} else {
if (!isIndyError(error)) {
throw new AriesFrameworkError('Attempted to throw Indy error, but it was not an Indy error')
}

this.logger.error(`Error creating master secret with id ${masterSecretId}`, {
indyError: error.indyName,
error,
})

throw new WalletError(
`Error creating master secret with id ${masterSecretId} in wallet with handle '${walletHandle}'`,
{ cause: error }
)
}
}
}

public async initPublicDid(didConfig: DidConfig) {
const { did, verkey } = await this.createDid(didConfig)
this.publicDidInfo = {
Expand Down
Loading