From df4a167400f80ea5f5e1b6e756cf7a44f82b2281 Mon Sep 17 00:00:00 2001 From: Abdulbois Date: Fri, 8 Jul 2022 19:02:06 +0500 Subject: [PATCH] refactor: Enable usage of legacy Anoncrypt packer. Make nested forwards while creating forward message. Add legacyForward model - Add legacy Anoncrypt packer while creating packers - Add ability to create nested packed forwards (one nested forward for each routing key) - Check and convert msg field of Forward to Envelope in order to support DIDComm V1 Forward types - Revert part of 04bfea80427b3d2ae374ddad2ced84b77c70a179 commit related to generating keys inside mediator service. Because with previous changes (having two types of generated keys belonging to the same router) it breaks Route Coordination protocol (while creating nested forwards it will pack two times to the same mediator then mediator cannot handle second forward message) Signed-off-by: Abdulbois --- pkg/didcomm/dispatcher/outbound/outbound.go | 70 ++++++++++++--------- pkg/didcomm/packager/packager.go | 34 ++++++---- pkg/didcomm/protocol/mediator/service.go | 45 +++++++------ pkg/framework/aries/default.go | 11 +++- 4 files changed, 91 insertions(+), 69 deletions(-) diff --git a/pkg/didcomm/dispatcher/outbound/outbound.go b/pkg/didcomm/dispatcher/outbound/outbound.go index d46e260461..15897c260e 100644 --- a/pkg/didcomm/dispatcher/outbound/outbound.go +++ b/pkg/didcomm/dispatcher/outbound/outbound.go @@ -24,7 +24,6 @@ import ( "github.com/hyperledger/aries-framework-go/pkg/framework/aries/api/vdr" "github.com/hyperledger/aries-framework-go/pkg/kms" "github.com/hyperledger/aries-framework-go/pkg/store/connection" - "github.com/hyperledger/aries-framework-go/pkg/vdr/fingerprint" "github.com/hyperledger/aries-framework-go/spi/storage" ) @@ -66,6 +65,15 @@ type Dispatcher struct { didcommV2Handler *middleware.DIDCommMessageMiddleware } +// legacyForward is DIDComm V1 route Forward msg as declared in +// https://github.com/hyperledger/aries-rfcs/blob/main/concepts/0094-cross-domain-messaging/README.md#corerouting10forward +type legacyForward struct { + Type string `json:"@type,omitempty"` + ID string `json:"@id,omitempty"` + To string `json:"to,omitempty"` + Msg *model.Envelope `json:"msg,omitempty"` +} + var logger = log.New("aries-framework/didcomm/dispatcher") // NewOutbound return new dispatcher outbound instance. @@ -341,13 +349,11 @@ func (o *Dispatcher) Forward(msg interface{}, des *service.Destination) error { } func (o *Dispatcher) createForwardMessage(msg []byte, des *service.Destination) ([]byte, error) { - forwardMsgType := service.ForwardMsgType - mtProfile := o.mediaTypeProfile(des) var ( - senderKey []byte - err error + forwardMsgType string + err error ) switch mtProfile { @@ -355,16 +361,8 @@ func (o *Dispatcher) createForwardMessage(msg []byte, des *service.Destination) transport.MediaTypeAIP2RFC0587Profile, transport.MediaTypeV2PlaintextPayload, transport.MediaTypeDIDCommV2Profile: // for DIDComm V2, do not set senderKey to force Anoncrypt packing. Only set the V2 forwardMsgType. forwardMsgType = service.ForwardMsgTypeV2 - default: // default is DIDComm V1, create a dummy key as senderKey - // create key set - _, senderKey, err = o.kms.CreateAndExportPubKeyBytes(kms.ED25519Type) - if err != nil { - return nil, fmt.Errorf("failed Create and export Encryption Key: %w", err) - } - - senderDIDKey, _ := fingerprint.CreateDIDKey(senderKey) - - senderKey = []byte(senderDIDKey) + default: // default is DIDComm V1 + forwardMsgType = service.ForwardMsgType } routingKeys, err := des.ServiceEndpoint.RoutingKeys() @@ -383,7 +381,7 @@ func (o *Dispatcher) createForwardMessage(msg []byte, des *service.Destination) fwdKeys := append([]string{des.RecipientKeys[0]}, routingKeys...) - packedMsg, err := o.createPackedNestedForwards(msg, senderKey, fwdKeys, forwardMsgType, mtProfile) + packedMsg, err := o.createPackedNestedForwards(msg, fwdKeys, forwardMsgType, mtProfile) if err != nil { return nil, fmt.Errorf("failed to create packed nested forwards: %w", err) } @@ -391,28 +389,21 @@ func (o *Dispatcher) createForwardMessage(msg []byte, des *service.Destination) return packedMsg, nil } -func (o *Dispatcher) createPackedNestedForwards(msg, senderKey []byte, routingKeys []string, fwdMsgType, mtProfile string) ([]byte, error) { //nolint: lll +func (o *Dispatcher) createPackedNestedForwards(msg []byte, routingKeys []string, fwdMsgType, mtProfile string) ([]byte, error) { //nolint: lll for i, key := range routingKeys { if i+1 >= len(routingKeys) { break } - - msgEnv := &model.Envelope{} - - err := json.Unmarshal(msg, msgEnv) - if err != nil { - return nil, fmt.Errorf("failed unmarshal to Envelope: %w", err) - } - // create forward message forward := model.Forward{ Type: fwdMsgType, ID: uuid.New().String(), To: key, - Msg: msgEnv, + Msg: msg, } + var err error - msg, err = o.packForward(forward, []string{routingKeys[i+1]}, senderKey, mtProfile) + msg, err = o.packForward(forward, []string{routingKeys[i+1]}, mtProfile) if err != nil { return nil, fmt.Errorf("failed to pack forward msg: %w", err) } @@ -421,9 +412,28 @@ func (o *Dispatcher) createPackedNestedForwards(msg, senderKey []byte, routingKe return msg, nil } -func (o *Dispatcher) packForward(fwd model.Forward, toKeys []string, senderKey []byte, mtProfile string) ([]byte, error) { //nolint: lll +func (o *Dispatcher) packForward(fwd model.Forward, toKeys []string, mtProfile string) ([]byte, error) { + env := &model.Envelope{} + + var ( + forward interface{} + err error + req []byte + ) + // try to convert msg to Envelope + err = json.Unmarshal(fwd.Msg, env) + if err == nil { + forward = legacyForward{ + Type: fwd.Type, + ID: fwd.ID, + To: fwd.To, + Msg: env, + } + } else { + forward = fwd + } // convert forward message to bytes - req, err := json.Marshal(fwd) + req, err = json.Marshal(forward) if err != nil { return nil, fmt.Errorf("failed marshal to bytes: %w", err) } @@ -432,7 +442,7 @@ func (o *Dispatcher) packForward(fwd model.Forward, toKeys []string, senderKey [ packedMsg, err = o.packager.PackMessage(&transport.Envelope{ MediaTypeProfile: mtProfile, Message: req, - FromKey: senderKey, + FromKey: []byte{}, ToKeys: toKeys, }) diff --git a/pkg/didcomm/packager/packager.go b/pkg/didcomm/packager/packager.go index 89cef71673..6da92a4a6d 100644 --- a/pkg/didcomm/packager/packager.go +++ b/pkg/didcomm/packager/packager.go @@ -12,6 +12,7 @@ import ( "encoding/json" "errors" "fmt" + legacyAuthCrypt "github.com/hyperledger/aries-framework-go/pkg/didcomm/packer/legacy/authcrypt" "strings" "github.com/hyperledger/aries-framework-go/pkg/common/log" @@ -83,8 +84,9 @@ func New(ctx Provider) (*Packager, error) { func (bp *Packager) addPacker(pack packer.Packer) { packerID := pack.EncodingType() - _, ok := pack.(*authcrypt.Packer) - if ok { + _, isAuthCrypt := pack.(*authcrypt.Packer) + _, isLegacyAuthCrypt := pack.(*legacyAuthCrypt.Packer) + if isAuthCrypt || isLegacyAuthCrypt { // anoncrypt and authcrypt have the same encoding type // so authcrypt will have an appended suffix packerID += authSuffix @@ -276,6 +278,7 @@ type envelopeStub struct { type headerStub struct { Type string `json:"typ,omitempty"` SKID string `json:"skid,omitempty"` + Alg string `json:"alg,omitempty"` } //nolint:funlen, gocyclo @@ -349,7 +352,7 @@ func getEncodingType(encMessage []byte) (string, []byte, error) { packerID := prot.Type - if prot.SKID != "" { + if prot.SKID != "" || prot.Alg == "Authcrypt" { // since Type protected header is the same for authcrypt and anoncrypt, the differentiating factor is SKID. // If it is present, then it's authcrypt. packerID += authSuffix @@ -385,22 +388,20 @@ func (bp *Packager) UnpackMessage(encMessage []byte) (*transport.Envelope, error func (bp *Packager) getCTYAndPacker(envelope *transport.Envelope) (string, packer.Packer, error) { switch envelope.MediaTypeProfile { case transport.MediaTypeAIP2RFC0019Profile, transport.MediaTypeProfileDIDCommAIP1: - return transport.MediaTypeRFC0019EncryptedEnvelope, bp.packers[transport.MediaTypeRFC0019EncryptedEnvelope], nil + packerName := addAuthcryptSuffix(envelope.FromKey, transport.MediaTypeRFC0019EncryptedEnvelope) + + return transport.MediaTypeRFC0019EncryptedEnvelope, bp.packers[packerName], nil case transport.MediaTypeRFC0019EncryptedEnvelope: - return envelope.MediaTypeProfile, bp.packers[transport.MediaTypeRFC0019EncryptedEnvelope], nil + packerName := addAuthcryptSuffix(envelope.FromKey, transport.MediaTypeRFC0019EncryptedEnvelope) + + return envelope.MediaTypeProfile, bp.packers[packerName], nil case transport.MediaTypeV2EncryptedEnvelope, transport.MediaTypeV2PlaintextPayload, transport.MediaTypeAIP2RFC0587Profile, transport.MediaTypeDIDCommV2Profile: - packerName := transport.MediaTypeV2EncryptedEnvelope - if len(envelope.FromKey) > 0 { - packerName += authSuffix - } + packerName := addAuthcryptSuffix(envelope.FromKey, transport.MediaTypeV2EncryptedEnvelope) return transport.MediaTypeV2PlaintextPayload, bp.packers[packerName], nil case transport.MediaTypeV2EncryptedEnvelopeV1PlaintextPayload, transport.MediaTypeV1PlaintextPayload: - packerName := transport.MediaTypeV2EncryptedEnvelope - if len(envelope.FromKey) > 0 { - packerName += authSuffix - } + packerName := addAuthcryptSuffix(envelope.FromKey, transport.MediaTypeV2EncryptedEnvelope) return transport.MediaTypeV1PlaintextPayload, bp.packers[packerName], nil default: @@ -415,6 +416,13 @@ func (bp *Packager) getCTYAndPacker(envelope *transport.Envelope) (string, packe return "", nil, fmt.Errorf("no packer found for mediatype profile: '%v'", envelope.MediaTypeProfile) } +func addAuthcryptSuffix(fromKey []byte, packerName string) string { + if len(fromKey) > 0 { + packerName += authSuffix + } + return packerName +} + func (bp *Packager) resolveKeyAgreementFromDIDDoc(keyAgrID string) (*crypto.PublicKey, error) { i := strings.Index(keyAgrID, "#") diff --git a/pkg/didcomm/protocol/mediator/service.go b/pkg/didcomm/protocol/mediator/service.go index 24ea18f74f..8484c4ce0c 100644 --- a/pkg/didcomm/protocol/mediator/service.go +++ b/pkg/didcomm/protocol/mediator/service.go @@ -22,6 +22,7 @@ import ( "github.com/hyperledger/aries-framework-go/pkg/didcomm/dispatcher" "github.com/hyperledger/aries-framework-go/pkg/didcomm/protocol/decorator" "github.com/hyperledger/aries-framework-go/pkg/didcomm/protocol/messagepickup" + "github.com/hyperledger/aries-framework-go/pkg/didcomm/transport" "github.com/hyperledger/aries-framework-go/pkg/doc/util/kmsdidkey" "github.com/hyperledger/aries-framework-go/pkg/framework/aries/api/vdr" "github.com/hyperledger/aries-framework-go/pkg/internal/logutil" @@ -391,31 +392,29 @@ func (s *Service) handleInboundRequest(c *callback) error { c.msg.ID(), c.options, s.endpoint, - func() ([]string, error) { - if len(s.mediaTypeProfiles) > 0 { - _, pubKeyBytes, e := s.kms.CreateAndExportPubKeyBytes(s.keyAgreementType) - if e != nil { - return nil, fmt.Errorf("outboundGrant from handleInboundRequest: kms failed to create "+ - "and export %v key: %w", s.keyAgreementType, e) + func() (string, error) { + for _, mtp := range s.mediaTypeProfiles { + switch mtp { + case transport.MediaTypeDIDCommV2Profile, transport.MediaTypeAIP2RFC0587Profile: + _, pubKeyBytes, e := s.kms.CreateAndExportPubKeyBytes(s.keyAgreementType) + if e != nil { + return "", fmt.Errorf("outboundGrant from handleInboundRequest: kms failed to create "+ + "and export %v key: %w", s.keyAgreementType, e) + } + + return kmsdidkey.BuildDIDKeyByKeyType(pubKeyBytes, s.keyAgreementType) } + } - didCommV2Key, errBuild := kmsdidkey.BuildDIDKeyByKeyType(pubKeyBytes, s.keyAgreementType) - if errBuild != nil { - return nil, errBuild - } - - _, pubKeyBytes, er := s.kms.CreateAndExportPubKeyBytes(kms.ED25519Type) - if er != nil { - return nil, fmt.Errorf("outboundGrant from handleInboundRequest: kms failed to create and "+ - "export ED25519 key: %w", er) - } - - didKey, _ := fingerprint.CreateDIDKey(pubKeyBytes) - - return []string{didKey, didCommV2Key}, nil + _, pubKeyBytes, er := s.kms.CreateAndExportPubKeyBytes(kms.ED25519Type) + if er != nil { + return "", fmt.Errorf("outboundGrant from handleInboundRequest: kms failed to create and "+ + "export ED25519 key: %w", er) } - return nil, nil + didKey, _ := fingerprint.CreateDIDKey(pubKeyBytes) + + return didKey, er }, ) if err != nil { @@ -427,7 +426,7 @@ func (s *Service) handleInboundRequest(c *callback) error { func outboundGrant( msgID string, opts *Options, - defaultEndpoint string, defaultKey func() ([]string, error)) (*Grant, error) { + defaultEndpoint string, defaultKey func() (string, error)) (*Grant, error) { grant := &Grant{ ID: msgID, Type: GrantMsgType, @@ -445,7 +444,7 @@ func outboundGrant( return nil, fmt.Errorf("outboundGrant: failed to create keys : %w", err) } - grant.RoutingKeys = keys + grant.RoutingKeys = []string{keys} } logger.Debugf("outbound grant: %+v", grant) diff --git a/pkg/framework/aries/default.go b/pkg/framework/aries/default.go index 101a0afa12..f02b1dd492 100644 --- a/pkg/framework/aries/default.go +++ b/pkg/framework/aries/default.go @@ -16,7 +16,8 @@ import ( "github.com/hyperledger/aries-framework-go/pkg/didcomm/packer" "github.com/hyperledger/aries-framework-go/pkg/didcomm/packer/anoncrypt" "github.com/hyperledger/aries-framework-go/pkg/didcomm/packer/authcrypt" - legacy "github.com/hyperledger/aries-framework-go/pkg/didcomm/packer/legacy/authcrypt" + legacyAnonCrypt "github.com/hyperledger/aries-framework-go/pkg/didcomm/packer/legacy/anoncrypt" + legacyAuthCrypt "github.com/hyperledger/aries-framework-go/pkg/didcomm/packer/legacy/authcrypt" "github.com/hyperledger/aries-framework-go/pkg/didcomm/protocol/didexchange" "github.com/hyperledger/aries-framework-go/pkg/didcomm/protocol/introduce" "github.com/hyperledger/aries-framework-go/pkg/didcomm/protocol/issuecredential" @@ -244,13 +245,17 @@ func setAdditionalDefaultOpts(frameworkOpts *Aries) error { if frameworkOpts.packerCreator == nil { frameworkOpts.packerCreator = func(provider packer.Provider) (packer.Packer, error) { - return legacy.New(provider), nil + return legacyAuthCrypt.New(provider), nil } frameworkOpts.packerCreators = []packer.Creator{ func(provider packer.Provider) (packer.Packer, error) { - return legacy.New(provider), nil + return legacyAuthCrypt.New(provider), nil }, + func(provider packer.Provider) (packer.Packer, error) { + return legacyAnonCrypt.New(provider), nil + }, + func(provider packer.Provider) (packer.Packer, error) { return authcrypt.New(provider, jose.A256CBCHS512) },