-
Notifications
You must be signed in to change notification settings - Fork 236
feat: Added support for DIDComm V2 messaging #1096
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
feat: Added support for DIDComm V2 messaging #1096
Conversation
c3616f6
to
6197fe0
Compare
Wow that's a big PR! Thanks for the effort here. I've stated with the PR review and have reviewed 100 of the total 240 files for now. Will continue later. I see you made the PR against the 0.3.0-pre branch, but we've recently merged that into main, can you point your PR towards the main branch instead? |
Woah! That is a nice PR to receive, great work @Artemkaaas and the entire team behind it. I do have one concern and I am not sure how the other maintainers feel about this. We want to make a very modular core. I believe the idea was to start with a DIDComm v1 or v2 implementation and the connected RFCs (discover features, OOB, etc.) and leave everything else outside of the core (like what we did with the bbs stuff, multitenancy, etc.). If we merge this PR it will likely be a lot more complex to strip it out of core again and into a separate package that can be added to the So my main question I guess of the the other maintainers, what would we like to be inside of the core for now? Would it be based on DIDComm v1 or v2? If DIDComm V2 will be in the core, how will we handle the underlying DIDComm dependency as right now I believe you used the WASM dependency right in core. Can elaborate further on this if required during a WG call. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Incredible work! I couldn't be happier to see this. SICPA DIDComm contributions have been much appreciated.
I think when this was originally developed, AFJ 0.3.0 and the move towards Indy-pendence and modularization hadn't gained momentum. In that context the formulation of this PR would be spot on.
In the post 0.3.0 AFJ context, this PR prompts important discussion points. There are opportunities to reduce overlap between messaging, crypto, etc. Can we discuss that together in an upcoming AFJ meeting? I admit I'll be out this coming Thursday for IIW and then again the next Thursday for Thanksgiving. But I think @genaris , @TimoGlastra , @blu3beri, @NB-MikeRichardson, @karimStekelenburg, etc. would agree that this would be a great opportunity to continue the momentum to modularize AFJ and contributions like these, in a way that makes both easier to fit, maintain, upgrade, and provide support for multiple platforms and use cases.
6197fe0
to
f7839e9
Compare
f7839e9
to
b58bbc2
Compare
Expanding a bit what we've discussed in yesterday's WG call, this is definitely an important contribution and we want to make it part of the codebase, although we'll need to figure out the best way to do so because of the reasons you are saying. The main problems we find at the moment are the dependency of a native library on the core (SICPA's didcomm in this case) and the need of extracting private keys from the wallet, which is something not desirable from security perspective. Apart from providing means to create/store keys and records securely, the Wallet should provide methods for using crypto material stored there. At the moment, it provides the pack and unpack method, which receives some input data referencing stored keys and returns some output, but private keys never leave the Wallet. This concept can become important in the future because the "Wallet" could be implemented as an HSM or Secure Element/Enclave or even remotely. In such cases it would be either impossible or insecure to retrieve secrets directly. The issue about dependency could be solved if we define an interface for EnvelopeService (like we did for Proofs and Credentials modules) where different implementations could be dynamically loaded, including in this case the DIDCommV2 one provided by SICPA native library. About the 'keys never leave the wallet' situation, it will be a bit more tricky because my understanding is that SICPA didcomm-rust uses the I'm not completely sure how this model would fit in current architecture but I'll think on some alternatives while reviewing and playing a bit on this such interesting PR! |
@genaris Yeah you are making some good points. Regarding the keys and keeping it inside the wallet, I think it should not be so complex as we make it out to be. I do not think that moving keys from the underlying wallet to a higher is so a big risk. When we have the keys in the lower level (without a Secure Enclave) we have a risk of another process reading the memory of the device. So whether the keys leave the wallet I would not see as a big increase in risk as they already are in memory, if that makes sense. Now, HSM / Secure Enclave is very interesting and 100000% something we should be looking at. However, I think we can just create a wallet implementation when we want to integrate this and leaving it for later. Also PS, since I have seen some interest in my, unfinished, didcomm-ts library, I have open sourced it so people can see my architecture in mind. It is heavily based on the rust implementation from sicpa, but with a crypto provider. |
Codecov Report
@@ Coverage Diff @@
## main #1096 +/- ##
==========================================
- Coverage 88.82% 87.36% -1.47%
==========================================
Files 707 751 +44
Lines 16593 17373 +780
Branches 2804 2977 +173
==========================================
+ Hits 14739 15178 +439
- Misses 1744 2056 +312
- Partials 110 139 +29
Help us with your feedback. Take ten seconds to tell us how you rate us. Have a feature suggestion? Share it here. |
9c565ad
to
85109e2
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Overall the PR looks really good and I don't think we're far away from merging. I've left a bunch of comments that nail down to the following topics:
- Consistency with existing AFJ codebase (property names, casing, etc...)
- Extending/modularizing existing APIs instead of adding new methods (with e.g. a V2 suffix)
- Not adding the sicpa didcomm library to the core package
- Splitting the didcomm v1 and v2 library as much as possible
I've also added a lot of questions for things that were unclear to me.
Anyway thanks a lot for this huge contribution!
@@ -0,0 +1 @@ | |||
@sicpa-dlab:registry=https://npm.pkg.github.com |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this needed?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This doesn't seem resolved. Can we remove this file?
@@ -39,7 +39,7 @@ interface TransportSessionTable { | |||
export interface TransportSession { | |||
id: string | |||
type: string | |||
keys?: EnvelopeKeys | |||
keys?: PackMessageParams |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this still keys now? For didcomm v2 it will be the dids right?
Also I'm not sure if this type is the right type to use for the transport keys. This is also used before packing which means it doesn't include the exact key, which it does for v1. I think we should come up with a type that work for both v1 and v2 and don't try to reuse when not applicable
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I agree it can be confusing. But the cause might be the whole design of the Didcomm v1 vs v2 solution 🤔
Problem is that if we add an API to get keys out of the wallet now, people will start using it and it will become MUCH harder to add HSM / secure enclave support later on. |
I don't think that we should provide an API that will get the keys out. The wallet implementation which exposes some This was just the first thing that popped up in my head, but I am sure we can provide all the functionality, without the user of the framework / developers of other modules, to sign/verify/encrypt/etc without exposing keys. |
Actually that's what I meant when saying that the Wallet should provide methods for using its crypto material. Now it's exposing wrap and unwrap (because it's tied to Indy's way of creating DIDComm messages) but it can be exposing sign methods that would be called by the DIDComm library. Or exposing a crypto provider object (or implementing its interface) used by didcomm-ts. |
b71f883
to
b951b60
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Congrats guys, it is looking pretty nice! I know you are still working on it and more discussions are ongoing but I left a few comments regarding the latest changes in MessageSender and the generic usage of OutboundMessageContext (which might reduce the need of files changed in the PR).
Signed-off-by: Artemkaaas <artem.ivanov@evernym.com>
1372edb
to
58ab2e7
Compare
Signed-off-by: Artemkaaas <artem.ivanov@evernym.com>
10a91fb
to
50236e2
Compare
# Conflicts: # packages/core/src/agent/Dispatcher.ts # packages/core/src/agent/Handler.ts # packages/core/src/agent/MessageReceiver.ts # packages/core/src/agent/MessageSender.ts # packages/core/src/agent/__tests__/MessageSender.test.ts # packages/core/src/modules/connections/services/TrustPingService.ts # packages/core/src/modules/credentials/formats/__tests__/IndyCredentialFormatService.test.ts # packages/core/src/modules/credentials/formats/__tests__/JsonLdCredentialFormatService.test.ts # packages/core/src/modules/credentials/formats/jsonld/JsonLdCredentialFormatService.ts # packages/core/src/modules/dids/__tests__/dids-registrar.e2e.test.ts # packages/core/src/modules/dids/methods/sov/__tests__/IndySdkSovDidResolver.test.ts # packages/core/src/modules/ledger/__tests__/IndyLedgerService.test.ts # packages/core/src/modules/oob/OutOfBandApi.ts # packages/core/src/modules/oob/protocols/v1/handlers/HandshakeReuseHandler.ts # packages/core/src/types.ts # packages/core/src/utils/parseInvitation.ts
The first approach would have my preference as in general I try to follow the composition over inheritance model. It's easier to create consistent behaviour with a base message sender (or message sender coordinator or whatever we want to call it) that calls the specific message sender implementations than by having the logic logic inside of the message senders |
#1096 (comment) |
Nice video from the latest Aries Javascript meeting, to catchup on the status of this PR: |
Signed-off-by: Artemkaaas <artem.ivanov@dsr-corporation.com>
…ipt into didcommv2-contribution
Signed-off-by: Darko Kulic <darko.kulic@sicpa.com>
…ipt into didcommv2-contribution
Signed-off-by: Darko Kulic <darko.kulic@sicpa.com>
…ipt into didcommv2-contribution
Signed-off-by: Sacha Kozma <sacha.kozma@sicpa.com>
48dccc2
to
37310d2
Compare
import { DidCommV1EnvelopeService } from '../index' | ||
|
||
@injectable() | ||
export class DidCommV1EnvelopeServiceImpl implements DidCommV1EnvelopeService { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The naming XxxImpl
may suggest that there is no need for having a separate interface and implementation.
} | ||
|
||
public async packMessage( | ||
agentContext: AgentContext, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pass it via DI?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I see that the concept it's used across the framework, not sure what's the exact reason.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We discussed this on the last AFJ call, but still, it seems a bit harder to understand what's the difference between DI container and AgentContext and when to use one over another.
export { isDidCommV1Message } from './helpers' | ||
export { DidCommV1Algorithms } from './types' | ||
export { DidCommV1Types } from './types' | ||
export { PlaintextDidCommV1Message } from './types' |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would rather avoid adding definitions to the index. It's harder to see what objects are in a particular module (folder) when looking at folder tree. To me, indexes should be used only as export of internal items
@@ -39,7 +39,7 @@ interface TransportSessionTable { | |||
export interface TransportSession { | |||
id: string | |||
type: string | |||
keys?: EnvelopeKeys | |||
keys?: PackMessageParams |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I agree it can be confusing. But the cause might be the whole design of the Didcomm v1 vs v2 solution 🤔
…ipt into didcommv2-contribution
Signed-off-by: Darko Kulic <darko.kulic@sicpa.com>
Signed-off-by: Darko Kulic <darko.kulic@sicpa.com>
…chment, V2Attachment) Added tests for V2Attachment Signed-off-by: Darko Kulic <darko.kulic@sicpa.com>
Signed-off-by: Darko Kulic <darko.kulic@sicpa.com>
Signed-off-by: Darko Kulic <darko.kulic@sicpa.com>
Signed-off-by: Darko Kulic <darko.kulic@sicpa.com>
…ipt into didcommv2-contribution
Signed-off-by: Darko Kulic <darko.kulic@sicpa.com>
Signed-off-by: Darko Kulic <darko.kulic@sicpa.com>
Co-authored-by: Timo Glastra <timo@animo.id> Signed-off-by: Darko Kulic <36031644+dkulic@users.noreply.github.com>
Signed-off-by: Darko Kulic <darko.kulic@sicpa.com>
Signed-off-by: Darko Kulic <darko.kulic@sicpa.com>
Signed-off-by: Darko Kulic <darko.kulic@sicpa.com>
Signed-off-by: Darko Kulic <darko.kulic@sicpa.com>
…ipt into didcommv2-contribution
There is now a feature branch in AFJ where we can continue the work: https://github.com/hyperledger/aries-framework-javascript/tree/feat/didcomm-v2 |
Closing as it's superseded by other PRs |
This PR introduces the initial implementation supporting DIDComm V2 messaging.
There are several
fixme's
in the code for resolving which I need recommendations.The PR is huge( I could not find a way how to split it into parts.
What is included in this PR:
AgentMessage
moved toDIDCommV1
message and also addedDIDCommV2
message structure.EnvelopService
provides encryption for both message types V1/V2.MessageSender
andMessageReceiver
to support both types of messages.signing-provider
tokey-provider
and addedX25519
key provider as it is needed for DIDComm V2 messaging.Trust Ping
protocol. Right now DIDComm V2 does not require the creation ofConnection
state object (there is not DID Exchange protocol adoption). Messages are sent just by passingDIDs
of the sender and receiver.Alice/Faber
demo to create DIDComm V2 DIDs and send Ping.Next steps:
Document reflecting the current state of the PR