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  }