github.com/hyperledger/aries-framework-go@v0.3.2/pkg/didcomm/common/service/destination_default.go (about) 1 //go:build !ACAPyInterop 2 // +build !ACAPyInterop 3 4 /* 5 Copyright SecureKey Technologies Inc. All Rights Reserved. 6 Copyright Avast Software. All Rights Reserved. 7 8 SPDX-License-Identifier: Apache-2.0 9 */ 10 11 package service 12 13 import ( 14 "fmt" 15 "strings" 16 17 "github.com/hyperledger/aries-framework-go/pkg/common/model" 18 diddoc "github.com/hyperledger/aries-framework-go/pkg/doc/did" 19 "github.com/hyperledger/aries-framework-go/pkg/internal/didkeyutil" 20 ) 21 22 // CreateDestination makes a DIDComm Destination object from a DID Doc as per the DIDComm service conventions: 23 // https://github.com/hyperledger/aries-rfcs/blob/master/features/0067-didcomm-diddoc-conventions/README.md. 24 func CreateDestination(didDoc *diddoc.Doc) (*Destination, error) { 25 // try DIDComm v2 first 26 if didCommService, ok := diddoc.LookupService(didDoc, didCommV2ServiceType); ok { 27 return createDIDCommV2Destination(didDoc, didCommService) 28 } 29 // try DIDComm v1 30 if didCommService, ok := diddoc.LookupService(didDoc, didCommServiceType); ok { 31 return createDIDCommV1Destination(didDoc, didCommService) 32 } 33 // try DIDComm v1 legacy 34 if didCommService, ok := diddoc.LookupService(didDoc, legacyDIDCommServiceType); ok { 35 return createLegacyDestination(didDoc, didCommService) 36 } 37 38 return nil, fmt.Errorf("create destination: missing DID doc service") 39 } 40 41 func createDIDCommV2Destination(didDoc *diddoc.Doc, didCommService *diddoc.Service) (*Destination, error) { 42 var ( 43 sp model.Endpoint 44 accept, routingKeys []string 45 uri string 46 err error 47 recKeys []string 48 ) 49 50 for _, ka := range didDoc.KeyAgreement { 51 keyID := ka.VerificationMethod.ID 52 if strings.HasPrefix(keyID, "#") { 53 keyID = didDoc.ID + keyID 54 } 55 56 recKeys = append(recKeys, keyID) 57 } 58 59 if len(recKeys) == 0 { 60 return nil, fmt.Errorf("create destination: no keyAgreements in diddoc for didcomm v2 service bloc. "+ 61 "DIDDoc: %+v", didDoc) 62 } 63 64 // if Accept is missing, ensure DIDCommV2 is at least added for packer selection based on MediaTypeProfile. 65 if accept, err = didCommService.ServiceEndpoint.Accept(); len(accept) == 0 || err != nil { 66 accept = []string{defaultDIDCommV2Profile} 67 } 68 69 uri, err = didCommService.ServiceEndpoint.URI() 70 if err != nil { // uri is required. 71 return nil, fmt.Errorf("create destination: service endpoint URI for didcomm v2 service block "+ 72 "error: %+v, %w", didDoc, err) 73 } 74 75 routingKeys, err = didCommService.ServiceEndpoint.RoutingKeys() 76 if err != nil { // routingKeys can be optional. 77 routingKeys = nil 78 } 79 80 sp = model.NewDIDCommV2Endpoint([]model.DIDCommV2Endpoint{{URI: uri, Accept: accept, RoutingKeys: routingKeys}}) 81 82 return &Destination{ 83 RecipientKeys: recKeys, 84 ServiceEndpoint: sp, 85 RoutingKeys: didCommService.RoutingKeys, 86 MediaTypeProfiles: didCommService.Accept, 87 DIDDoc: didDoc, 88 }, nil 89 } 90 91 func createDIDCommV1Destination(didDoc *diddoc.Doc, didCommService *diddoc.Service) (*Destination, error) { 92 uri, err := didCommService.ServiceEndpoint.URI() 93 if err != nil { // uri is required. 94 return nil, fmt.Errorf("create destination: service endpoint URI on didcomm v1 service block "+ 95 "in diddoc error: %+v, %w", didDoc, err) 96 } 97 98 if len(didCommService.RecipientKeys) == 0 { 99 return nil, fmt.Errorf("create destination: no recipient keys on didcomm service block in diddoc: %+v", didDoc) 100 } 101 102 for i, k := range didCommService.RecipientKeys { 103 if !strings.HasPrefix(k, "did:") { 104 return nil, fmt.Errorf("create destination: recipient key %d:[%v] of didComm '%s' not a did:key", i+1, 105 k, didCommService.ID) 106 } 107 } 108 109 // if Accept is missing, ensure DIDCommV1 is at least added for packer selection based on MediaTypeProfile. 110 if len(didCommService.Accept) == 0 { 111 didCommService.Accept = []string{defaultDIDCommProfile} 112 } 113 114 sp := model.NewDIDCommV1Endpoint(uri) 115 116 return &Destination{ 117 RecipientKeys: didCommService.RecipientKeys, 118 ServiceEndpoint: sp, 119 RoutingKeys: didCommService.RoutingKeys, 120 MediaTypeProfiles: didCommService.Accept, 121 DIDDoc: didDoc, 122 }, nil 123 } 124 125 func createLegacyDestination(didDoc *diddoc.Doc, didCommService *diddoc.Service) (*Destination, error) { 126 uri, err := didCommService.ServiceEndpoint.URI() 127 if uri == "" || err != nil { 128 return nil, fmt.Errorf("create destination: no service endpoint on didcomm service block in diddoc: %#v", didDoc) 129 } 130 131 if len(didCommService.RecipientKeys) == 0 { 132 return nil, fmt.Errorf("create destination: no recipient keys on didcomm service block in diddoc: %#v", didDoc) 133 } 134 135 // if Accept is missing, ensure IndyAgent is at least added for packer selection based on MediaTypeProfile. 136 if len(didCommService.Accept) == 0 { 137 didCommService.Accept = []string{legacyDIDCommServiceType} 138 } 139 140 return &Destination{ 141 RecipientKeys: didkeyutil.ConvertBase58KeysToDIDKeys(didCommService.RecipientKeys), 142 ServiceEndpoint: model.NewDIDCommV1Endpoint(uri), 143 RoutingKeys: didkeyutil.ConvertBase58KeysToDIDKeys(didCommService.RoutingKeys), 144 MediaTypeProfiles: didCommService.Accept, 145 }, nil 146 }