github.com/hyperledger/aries-framework-go@v0.3.2/pkg/doc/verifiable/common.go (about)

     1  /*
     2  Copyright SecureKey Technologies Inc. All Rights Reserved.
     3  Copyright Avast Software. All Rights Reserved.
     4  
     5  SPDX-License-Identifier: Apache-2.0
     6  */
     7  
     8  // Package verifiable implements Verifiable Credential and Presentation data model
     9  // (https://www.w3.org/TR/vc-data-model).
    10  // It provides the data structures and functions which allow to process the Verifiable documents on different
    11  // sides and levels. For example, an Issuer can create verifiable.Credential structure and issue it to a
    12  // Holder in JWS form. The Holder can decode received Credential and make sure the signature is valid.
    13  // The Holder can present the Credential to the Verifier or combine one or more Credentials into a Verifiable
    14  // Presentation. The Verifier can decode and verify the received Credentials and Presentations.
    15  package verifiable
    16  
    17  import (
    18  	"encoding/json"
    19  	"errors"
    20  	"fmt"
    21  	"strings"
    22  
    23  	"github.com/piprate/json-gold/ld"
    24  	"github.com/xeipuuv/gojsonschema"
    25  
    26  	"github.com/hyperledger/aries-framework-go/pkg/doc/did"
    27  	"github.com/hyperledger/aries-framework-go/pkg/doc/signature/verifier"
    28  	jsonutil "github.com/hyperledger/aries-framework-go/pkg/doc/util/json"
    29  	vdrapi "github.com/hyperledger/aries-framework-go/pkg/framework/aries/api/vdr"
    30  	kmsapi "github.com/hyperledger/aries-framework-go/pkg/kms"
    31  )
    32  
    33  // TODO https://github.com/square/go-jose/issues/263 support ES256K
    34  
    35  // JWSAlgorithm defines JWT signature algorithms of Verifiable Credential.
    36  type JWSAlgorithm int
    37  
    38  const (
    39  	// RS256 JWT Algorithm.
    40  	RS256 JWSAlgorithm = iota
    41  
    42  	// PS256 JWT Algorithm.
    43  	PS256
    44  
    45  	// EdDSA JWT Algorithm.
    46  	EdDSA
    47  
    48  	// ECDSASecp256k1 JWT Algorithm.
    49  	ECDSASecp256k1
    50  
    51  	// ECDSASecp256r1 JWT Algorithm.
    52  	ECDSASecp256r1
    53  
    54  	// ECDSASecp384r1 JWT Algorithm.
    55  	ECDSASecp384r1
    56  
    57  	// ECDSASecp521r1 JWT Algorithm.
    58  	ECDSASecp521r1
    59  )
    60  
    61  // KeyTypeToJWSAlgo returns the JWSAlgorithm based on keyType.
    62  func KeyTypeToJWSAlgo(keyType kmsapi.KeyType) (JWSAlgorithm, error) {
    63  	switch keyType {
    64  	case kmsapi.ECDSAP256TypeDER, kmsapi.ECDSAP256TypeIEEEP1363:
    65  		return ECDSASecp256r1, nil
    66  	case kmsapi.ECDSAP384TypeDER, kmsapi.ECDSAP384TypeIEEEP1363:
    67  		return ECDSASecp384r1, nil
    68  	case kmsapi.ECDSAP521TypeDER, kmsapi.ECDSAP521TypeIEEEP1363:
    69  		return ECDSASecp521r1, nil
    70  	case kmsapi.ED25519Type:
    71  		return EdDSA, nil
    72  	case kmsapi.ECDSASecp256k1TypeIEEEP1363, kmsapi.ECDSASecp256k1DER:
    73  		return ECDSASecp256k1, nil
    74  	case kmsapi.RSARS256Type:
    75  		return RS256, nil
    76  	case kmsapi.RSAPS256Type:
    77  		return PS256, nil
    78  	default:
    79  		return 0, errors.New("unsupported key type")
    80  	}
    81  }
    82  
    83  // Name return the name of the signature algorithm.
    84  func (ja JWSAlgorithm) Name() (string, error) {
    85  	switch ja {
    86  	case RS256:
    87  		return "RS256", nil
    88  	case PS256:
    89  		return "PS256", nil
    90  	case EdDSA:
    91  		return "EdDSA", nil
    92  	case ECDSASecp256k1:
    93  		return "ES256K", nil
    94  	case ECDSASecp256r1:
    95  		return "ES256", nil
    96  	case ECDSASecp384r1:
    97  		return "ES384", nil
    98  	case ECDSASecp521r1:
    99  		return "ES521", nil
   100  	default:
   101  		return "", fmt.Errorf("unsupported algorithm: %v", ja)
   102  	}
   103  }
   104  
   105  type jsonldCredentialOpts struct {
   106  	jsonldDocumentLoader ld.DocumentLoader
   107  	externalContext      []string
   108  	jsonldOnlyValidRDF   bool
   109  }
   110  
   111  // PublicKeyFetcher fetches public key for JWT signing verification based on Issuer ID (possibly DID)
   112  // and Key ID.
   113  // If not defined, JWT encoding is not tested.
   114  type PublicKeyFetcher func(issuerID, keyID string) (*verifier.PublicKey, error)
   115  
   116  // SingleKey defines the case when only one verification key is used and we don't need to pick the one.
   117  func SingleKey(pubKey []byte, pubKeyType string) PublicKeyFetcher {
   118  	return func(_, _ string) (*verifier.PublicKey, error) {
   119  		return &verifier.PublicKey{
   120  			Type:  pubKeyType,
   121  			Value: pubKey,
   122  		}, nil
   123  	}
   124  }
   125  
   126  // VDRKeyResolver resolves DID in order to find public keys for VC verification using vdr.Registry.
   127  // A source of DID could be issuer of VC or holder of VP. It can be also obtained from
   128  // JWS "issuer" claim or "verificationMethod" of Linked Data Proof.
   129  type VDRKeyResolver struct {
   130  	vdr didResolver
   131  }
   132  
   133  type didResolver interface {
   134  	Resolve(did string, opts ...vdrapi.DIDMethodOption) (*did.DocResolution, error)
   135  }
   136  
   137  // NewVDRKeyResolver creates VDRKeyResolver.
   138  func NewVDRKeyResolver(vdr didResolver) *VDRKeyResolver {
   139  	return &VDRKeyResolver{vdr: vdr}
   140  }
   141  
   142  func (r *VDRKeyResolver) resolvePublicKey(issuerDID, keyID string) (*verifier.PublicKey, error) {
   143  	docResolution, err := r.vdr.Resolve(issuerDID)
   144  	if err != nil {
   145  		return nil, fmt.Errorf("resolve DID %s: %w", issuerDID, err)
   146  	}
   147  
   148  	for _, verifications := range docResolution.DIDDocument.VerificationMethods() {
   149  		for _, verification := range verifications {
   150  			if strings.Contains(verification.VerificationMethod.ID, keyID) &&
   151  				verification.Relationship != did.KeyAgreement {
   152  				return &verifier.PublicKey{
   153  					Type:  verification.VerificationMethod.Type,
   154  					Value: verification.VerificationMethod.Value,
   155  					JWK:   verification.VerificationMethod.JSONWebKey(),
   156  				}, nil
   157  			}
   158  		}
   159  	}
   160  
   161  	return nil, fmt.Errorf("public key with KID %s is not found for DID %s", keyID, issuerDID)
   162  }
   163  
   164  // PublicKeyFetcher returns Public Key Fetcher via DID resolution mechanism.
   165  func (r *VDRKeyResolver) PublicKeyFetcher() PublicKeyFetcher {
   166  	return r.resolvePublicKey
   167  }
   168  
   169  // Proof defines embedded proof of Verifiable Credential.
   170  type Proof map[string]interface{}
   171  
   172  // CustomFields is a map of extra fields of struct build when unmarshalling JSON which are not
   173  // mapped to the struct fields.
   174  type CustomFields map[string]interface{}
   175  
   176  // TypedID defines a flexible structure with id and name fields and arbitrary extra fields
   177  // kept in CustomFields.
   178  type TypedID struct {
   179  	ID   string `json:"id,omitempty"`
   180  	Type string `json:"type,omitempty"`
   181  
   182  	CustomFields `json:"-"`
   183  }
   184  
   185  // MarshalJSON defines custom marshalling of TypedID to JSON.
   186  func (tid TypedID) MarshalJSON() ([]byte, error) {
   187  	// TODO hide this exported method
   188  	type Alias TypedID
   189  
   190  	alias := Alias(tid)
   191  
   192  	data, err := jsonutil.MarshalWithCustomFields(alias, tid.CustomFields)
   193  	if err != nil {
   194  		return nil, fmt.Errorf("marshal TypedID: %w", err)
   195  	}
   196  
   197  	return data, nil
   198  }
   199  
   200  // UnmarshalJSON defines custom unmarshalling of TypedID from JSON.
   201  func (tid *TypedID) UnmarshalJSON(data []byte) error {
   202  	// TODO hide this exported method
   203  	type Alias TypedID
   204  
   205  	alias := (*Alias)(tid)
   206  
   207  	tid.CustomFields = make(CustomFields)
   208  
   209  	err := jsonutil.UnmarshalWithCustomFields(data, alias, tid.CustomFields)
   210  	if err != nil {
   211  		return fmt.Errorf("unmarshal TypedID: %w", err)
   212  	}
   213  
   214  	return nil
   215  }
   216  
   217  func newTypedID(v interface{}) (TypedID, error) {
   218  	bytes, err := json.Marshal(v)
   219  	if err != nil {
   220  		return TypedID{}, err
   221  	}
   222  
   223  	var tid TypedID
   224  	err = json.Unmarshal(bytes, &tid)
   225  
   226  	return tid, err
   227  }
   228  
   229  func describeSchemaValidationError(result *gojsonschema.Result, what string) string {
   230  	errMsg := what + " is not valid:\n"
   231  	for _, desc := range result.Errors() {
   232  		errMsg += fmt.Sprintf("- %s\n", desc)
   233  	}
   234  
   235  	return errMsg
   236  }
   237  
   238  func stringSlice(values []interface{}) ([]string, error) {
   239  	s := make([]string, len(values))
   240  
   241  	for i := range values {
   242  		t, valid := values[i].(string)
   243  		if !valid {
   244  			return nil, errors.New("array element is not a string")
   245  		}
   246  
   247  		s[i] = t
   248  	}
   249  
   250  	return s, nil
   251  }
   252  
   253  // decodeType decodes raw type(s).
   254  //
   255  // type can be defined as a single string value or array of strings.
   256  func decodeType(t interface{}) ([]string, error) {
   257  	switch rType := t.(type) {
   258  	case string:
   259  		return []string{rType}, nil
   260  	case []interface{}:
   261  		types, err := stringSlice(rType)
   262  		if err != nil {
   263  			return nil, fmt.Errorf("vc types: %w", err)
   264  		}
   265  
   266  		return types, nil
   267  	default:
   268  		return nil, errors.New("credential type of unknown structure")
   269  	}
   270  }
   271  
   272  // decodeContext decodes raw context(s).
   273  //
   274  // context can be defined as a single string value or array;
   275  // at the second case, the array can be a mix of string and object types
   276  // (objects can express context information); object context are
   277  // defined at the tail of the array.
   278  func decodeContext(c interface{}) ([]string, []interface{}, error) {
   279  	switch rContext := c.(type) {
   280  	case string:
   281  		return []string{rContext}, nil, nil
   282  	case []interface{}:
   283  		s := make([]string, 0)
   284  
   285  		for i := range rContext {
   286  			c, valid := rContext[i].(string)
   287  			if !valid {
   288  				// the remaining contexts are of custom type
   289  				return s, rContext[i:], nil
   290  			}
   291  
   292  			s = append(s, c)
   293  		}
   294  		// no contexts of custom type, just string contexts found
   295  		return s, nil, nil
   296  	default:
   297  		return nil, nil, errors.New("credential context of unknown type")
   298  	}
   299  }
   300  
   301  func safeStringValue(v interface{}) string {
   302  	if v == nil {
   303  		return ""
   304  	}
   305  
   306  	return v.(string)
   307  }
   308  
   309  func proofsToRaw(proofs []Proof) ([]byte, error) {
   310  	switch len(proofs) {
   311  	case 0:
   312  		return nil, nil
   313  	case 1:
   314  		return json.Marshal(proofs[0])
   315  	default:
   316  		return json.Marshal(proofs)
   317  	}
   318  }
   319  
   320  func parseProof(proofBytes json.RawMessage) ([]Proof, error) {
   321  	if len(proofBytes) == 0 {
   322  		return nil, nil
   323  	}
   324  
   325  	var singleProof Proof
   326  
   327  	err := json.Unmarshal(proofBytes, &singleProof)
   328  	if err == nil {
   329  		return []Proof{singleProof}, nil
   330  	}
   331  
   332  	var composedProof []Proof
   333  
   334  	err = json.Unmarshal(proofBytes, &composedProof)
   335  	if err == nil {
   336  		return composedProof, nil
   337  	}
   338  
   339  	return nil, err
   340  }