Skip to content

Commit

Permalink
feat!: Use did:peer:4 by default for DID Exchange (openwallet-foundat…
Browse files Browse the repository at this point in the history
…ion#2166)

Signed-off-by: Ariel Gentile <[email protected]>
  • Loading branch information
genaris authored Jan 31, 2025
1 parent 27f971d commit 0d877f5
Show file tree
Hide file tree
Showing 7 changed files with 49 additions and 39 deletions.
7 changes: 7 additions & 0 deletions .changeset/loud-kiwis-bake.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
---
'@credo-ts/didcomm': minor
---

Now using did:peer:4 by default when creating DID Exchange Requests as response to an Out of Band invitation.

It is possible to return to previous behaviour by manually setting `peerNumAlgoForDidExchangeRequests` option in DIDComm Connections module config.
3 changes: 2 additions & 1 deletion packages/core/tests/oob.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -766,8 +766,9 @@ describe('out of band', () => {
expect(faberAliceConnection?.state).toBe(DidExchangeState.Completed)

// Use the invitation did from the first connection to create the second connection
// (first connection's did matches the one used in invitation, since no rotation has been done (multiUse=false))
const outOfBandRecord2 = await faberAgent.modules.oob.createInvitation({
invitationDid: outOfBandRecord1.outOfBandInvitation.invitationDids[0],
invitationDid: faberAliceConnection.did,
})

let { connectionRecord: aliceFaberConnection2 } = await aliceAgent.modules.oob.receiveInvitation(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ export class ConnectionsModuleConfig {

/** See {@link ConnectionsModuleConfigOptions.peerNumAlgoForDidExchangeRequests} */
public get peerNumAlgoForDidExchangeRequests() {
return this.#peerNumAlgoForDidExchangeRequests ?? PeerDidNumAlgo.GenesisDoc
return this.#peerNumAlgoForDidExchangeRequests ?? PeerDidNumAlgo.ShortFormAndLongForm
}

/** See {@link ConnectionsModuleConfigOptions.peerNumAlgoForDidExchangeRequests} */
Expand Down
36 changes: 20 additions & 16 deletions packages/didcomm/src/modules/connections/DidExchangeProtocol.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,8 @@ import {
tryParseDid,
didKeyToInstanceOfKey,
DidRepository,
didKeyToVerkey,
parseDid,
} from '@credo-ts/core'

import { Attachment, AttachmentData } from '../../decorators/attachment/Attachment'
Expand Down Expand Up @@ -284,32 +286,33 @@ export class DidExchangeProtocol {
const didDocument = await createPeerDidFromServices(agentContext, services, numAlgo)
const message = new DidExchangeResponseMessage({ did: didDocument.id, threadId })

// DID Rotate attachment should be signed with invitation keys
const invitationRecipientKeys = outOfBandRecord.outOfBandInvitation
.getInlineServices()
.map((s) => s.recipientKeys)
.reduce((acc, curr) => acc.concat(curr), [])

// Consider also pure-DID services, used when DID Exchange is started with an implicit invitation or a public DID
for (const did of outOfBandRecord.outOfBandInvitation.getDidServices()) {
invitationRecipientKeys.push(
...(await getDidDocumentForCreatedDid(agentContext, parseDid(did).did)).recipientKeys.map(
(key) => key.publicKeyBase58
)
)
}

if (numAlgo === PeerDidNumAlgo.GenesisDoc) {
message.didDoc = await this.createSignedAttachment(
agentContext,
didDocument.toJSON(),
Array.from(
new Set(
services
.map((s) => s.recipientKeys)
.reduce((acc, curr) => acc.concat(curr), [])
.map((key) => key.publicKeyBase58)
)
)
Array.from(new Set(invitationRecipientKeys.map(didKeyToVerkey)))
)
} else {
// We assume any other case is a resolvable did (e.g. did:peer:2 or did:peer:4)
message.didRotate = await this.createSignedAttachment(
agentContext,
didDocument.id,
Array.from(
new Set(
services
.map((s) => s.recipientKeys)
.reduce((acc, curr) => acc.concat(curr), [])
.map((key) => key.publicKeyBase58)
)
)
Array.from(new Set(invitationRecipientKeys.map(didKeyToVerkey)))
)
}

Expand Down Expand Up @@ -462,6 +465,7 @@ export class DidExchangeProtocol {
data: string | Record<string, unknown>,
verkeys: string[]
) {
this.logger.debug(`Creating signed attachment with keys ${JSON.stringify(verkeys)}`)
const signedAttach = new Attachment({
mimeType: typeof data === 'string' ? undefined : 'application/json',
data: new AttachmentData({
Expand Down
10 changes: 6 additions & 4 deletions packages/didcomm/src/modules/connections/services/helpers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -132,12 +132,14 @@ export function routingToServices(routing: Routing): ResolvedDidCommService[] {
}

export async function getDidDocumentForCreatedDid(agentContext: AgentContext, did: string) {
// Ensure that the DID has been created by us
const didRecord = await agentContext.dependencyManager.resolve(DidRepository).findCreatedDid(agentContext, did)

if (!didRecord?.didDocument) {
throw new CredoError(`Could not get DidDocument for created did ${did}`)
if (!didRecord) {
throw new CredoError(`Could not find created did ${did}`)
}
return didRecord.didDocument

const didsApi = agentContext.dependencyManager.resolve(DidsApi)
return await didsApi.resolveDidDocument(did)
}

/**
Expand Down
2 changes: 1 addition & 1 deletion packages/didcomm/src/modules/oob/OutOfBandApi.ts
Original file line number Diff line number Diff line change
Expand Up @@ -396,7 +396,7 @@ export class OutOfBandApi {

const invitation = new OutOfBandInvitation({
id: config.did,
label: config.label ?? '',
label: config.alias ?? '',
services: [config.did],
handshakeProtocols,
})
Expand Down
28 changes: 12 additions & 16 deletions packages/didcomm/src/modules/oob/__tests__/implicit.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -46,8 +46,8 @@ const aliceAgentOptions = getInMemoryAgentOptions(
)

describe('out of band implicit', () => {
let faberAgent: Agent
let aliceAgent: Agent
let faberAgent: Agent<typeof faberAgentOptions.modules>
let aliceAgent: Agent<typeof aliceAgentOptions.modules>

beforeAll(async () => {
faberAgent = new Agent(faberAgentOptions)
Expand Down Expand Up @@ -80,7 +80,7 @@ describe('out of band implicit', () => {
let { connectionRecord: aliceFaberConnection } = await aliceAgent.modules.oob.receiveImplicitInvitation({
did: inMemoryDid,
alias: 'Faber public',
label: 'Alice',
label: 'Custom Alice',
handshakeProtocols: [HandshakeProtocol.DidExchange],
})

Expand All @@ -96,8 +96,8 @@ describe('out of band implicit', () => {

expect(aliceFaberConnection).toBeConnectedWith(faberAliceConnection)
expect(faberAliceConnection).toBeConnectedWith(aliceFaberConnection)
expect(faberAliceConnection.theirLabel).toBe('Alice')
expect(aliceFaberConnection.alias).toBe('Faber public')
expect(faberAliceConnection.theirLabel).toBe('Custom Alice')
expect(aliceFaberConnection.theirLabel).toBe('Faber public')
expect(aliceFaberConnection.invitationDid).toBe(inMemoryDid)

// It is possible for an agent to check if it has already a connection to a certain public entity
Expand All @@ -112,7 +112,6 @@ describe('out of band implicit', () => {
let { connectionRecord: aliceFaberConnection } = await aliceAgent.modules.oob.receiveImplicitInvitation({
did: serviceUrl,
alias: 'Faber public',
label: 'Alice',
handshakeProtocols: [HandshakeProtocol.DidExchange],
})

Expand All @@ -128,8 +127,8 @@ describe('out of band implicit', () => {

expect(aliceFaberConnection).toBeConnectedWith(faberAliceConnection)
expect(faberAliceConnection).toBeConnectedWith(aliceFaberConnection)
expect(faberAliceConnection.theirLabel).toBe('Alice')
expect(aliceFaberConnection.alias).toBe('Faber public')
expect(faberAliceConnection.theirLabel).toBe(aliceAgent.config.label)
expect(aliceFaberConnection.theirLabel).toBe('Faber public')
expect(aliceFaberConnection.invitationDid).toBe(serviceUrl)

// It is possible for an agent to check if it has already a connection to a certain public entity
Expand All @@ -142,7 +141,6 @@ describe('out of band implicit', () => {
let { connectionRecord: aliceFaberConnection } = await aliceAgent.modules.oob.receiveImplicitInvitation({
did: inMemoryDid,
alias: 'Faber public',
label: 'Alice',
handshakeProtocols: [HandshakeProtocol.Connections],
})

Expand All @@ -158,8 +156,8 @@ describe('out of band implicit', () => {

expect(aliceFaberConnection).toBeConnectedWith(faberAliceConnection)
expect(faberAliceConnection).toBeConnectedWith(aliceFaberConnection)
expect(faberAliceConnection.theirLabel).toBe('Alice')
expect(aliceFaberConnection.alias).toBe('Faber public')
expect(faberAliceConnection.theirLabel).toBe(aliceAgent.config.label)
expect(aliceFaberConnection.theirLabel).toBe('Faber public')
expect(aliceFaberConnection.invitationDid).toBe(inMemoryDid)

// It is possible for an agent to check if it has already a connection to a certain public entity
Expand All @@ -171,7 +169,6 @@ describe('out of band implicit', () => {
aliceAgent.modules.oob.receiveImplicitInvitation({
did: 'did:sov:ZSEqSci581BDZCFPa29ScB',
alias: 'Faber public',
label: 'Alice',
handshakeProtocols: [HandshakeProtocol.DidExchange],
})
).rejects.toThrow(/Unable to resolve did/)
Expand All @@ -183,7 +180,6 @@ describe('out of band implicit', () => {
let { connectionRecord: aliceFaberConnection } = await aliceAgent.modules.oob.receiveImplicitInvitation({
did: inMemoryDid,
alias: 'Faber public',
label: 'Alice',
handshakeProtocols: [HandshakeProtocol.Connections],
})

Expand All @@ -199,8 +195,8 @@ describe('out of band implicit', () => {

expect(aliceFaberConnection).toBeConnectedWith(faberAliceConnection)
expect(faberAliceConnection).toBeConnectedWith(aliceFaberConnection)
expect(faberAliceConnection.theirLabel).toBe('Alice')
expect(aliceFaberConnection.alias).toBe('Faber public')
expect(faberAliceConnection.theirLabel).toBe(aliceAgent.config.label)
expect(aliceFaberConnection.theirLabel).toBe('Faber public')
expect(aliceFaberConnection.invitationDid).toBe(inMemoryDid)

// Repeat implicit invitation procedure
Expand All @@ -224,7 +220,7 @@ describe('out of band implicit', () => {
expect(aliceFaberNewConnection).toBeConnectedWith(faberAliceNewConnection)
expect(faberAliceNewConnection).toBeConnectedWith(aliceFaberNewConnection)
expect(faberAliceNewConnection.theirLabel).toBe('Alice New')
expect(aliceFaberNewConnection.alias).toBe('Faber public New')
expect(aliceFaberNewConnection.theirLabel).toBe('Faber public New')
expect(aliceFaberNewConnection.invitationDid).toBe(inMemoryDid)

// Both connections will be associated to the same invitation did
Expand Down

0 comments on commit 0d877f5

Please sign in to comment.