github.com/hyperledger/aries-framework-go@v0.3.2/pkg/doc/verifiable/embedded_proof.go (about) 1 /* 2 Copyright SecureKey Technologies Inc. All Rights Reserved. 3 SPDX-License-Identifier: Apache-2.0 4 */ 5 6 package verifiable 7 8 import ( 9 "encoding/base64" 10 "encoding/json" 11 "errors" 12 "fmt" 13 14 "github.com/hyperledger/aries-framework-go/pkg/doc/signature/jsonld" 15 "github.com/hyperledger/aries-framework-go/pkg/doc/signature/suite" 16 "github.com/hyperledger/aries-framework-go/pkg/doc/signature/suite/bbsblssignature2020" 17 "github.com/hyperledger/aries-framework-go/pkg/doc/signature/suite/bbsblssignatureproof2020" 18 "github.com/hyperledger/aries-framework-go/pkg/doc/signature/suite/ecdsasecp256k1signature2019" 19 "github.com/hyperledger/aries-framework-go/pkg/doc/signature/suite/ed25519signature2018" 20 "github.com/hyperledger/aries-framework-go/pkg/doc/signature/suite/ed25519signature2020" 21 "github.com/hyperledger/aries-framework-go/pkg/doc/signature/suite/jsonwebsignature2020" 22 "github.com/hyperledger/aries-framework-go/pkg/doc/signature/verifier" 23 ) 24 25 const ( 26 ed25519Signature2018 = "Ed25519Signature2018" 27 ed25519Signature2020 = "Ed25519Signature2020" 28 jsonWebSignature2020 = "JsonWebSignature2020" 29 ecdsaSecp256k1Signature2019 = "EcdsaSecp256k1Signature2019" 30 bbsBlsSignature2020 = "BbsBlsSignature2020" 31 bbsBlsSignatureProof2020 = "BbsBlsSignatureProof2020" 32 ) 33 34 func getProofType(proofMap map[string]interface{}) (string, error) { 35 proofType, ok := proofMap["type"] 36 if !ok { 37 return "", errors.New("proof type is missing") 38 } 39 40 proofTypeStr := safeStringValue(proofType) 41 switch proofTypeStr { 42 case ed25519Signature2018, jsonWebSignature2020, ecdsaSecp256k1Signature2019, 43 bbsBlsSignature2020, bbsBlsSignatureProof2020, ed25519Signature2020: 44 return proofTypeStr, nil 45 default: 46 return "", fmt.Errorf("unsupported proof type: %s", proofType) 47 } 48 } 49 50 type embeddedProofCheckOpts struct { 51 publicKeyFetcher PublicKeyFetcher 52 disabledProofCheck bool 53 54 ldpSuites []verifier.SignatureSuite 55 56 jsonldCredentialOpts 57 } 58 59 func checkEmbeddedProof(docBytes []byte, opts *embeddedProofCheckOpts) error { 60 if opts.disabledProofCheck { 61 return nil 62 } 63 64 var jsonldDoc map[string]interface{} 65 66 if err := json.Unmarshal(docBytes, &jsonldDoc); err != nil { 67 return fmt.Errorf("embedded proof is not JSON: %w", err) 68 } 69 70 delete(jsonldDoc, "jwt") 71 72 proofElement, ok := jsonldDoc["proof"] 73 if !ok || proofElement == nil { 74 // do not make a check if there is no proof defined as proof presence is not mandatory 75 return nil 76 } 77 78 proofs, err := getProofs(proofElement) 79 if err != nil { 80 return fmt.Errorf("check embedded proof: %w", err) 81 } 82 83 ldpSuites, err := getSuites(proofs, opts) 84 if err != nil { 85 return err 86 } 87 88 if opts.publicKeyFetcher == nil { 89 return errors.New("public key fetcher is not defined") 90 } 91 92 if len(opts.externalContext) > 0 { 93 // Use external contexts for check of the linked data proofs to enrich JSON-LD context vocabulary. 94 jsonldDoc["@context"] = jsonld.AppendExternalContexts(jsonldDoc["@context"], opts.externalContext...) 95 } 96 97 err = checkLinkedDataProof(jsonldDoc, ldpSuites, opts.publicKeyFetcher, &opts.jsonldCredentialOpts) 98 if err != nil { 99 return fmt.Errorf("check embedded proof: %w", err) 100 } 101 102 return nil 103 } 104 105 // nolint:gocyclo 106 func getSuites(proofs []map[string]interface{}, opts *embeddedProofCheckOpts) ([]verifier.SignatureSuite, error) { 107 ldpSuites := opts.ldpSuites 108 109 for i := range proofs { 110 t, err := getProofType(proofs[i]) 111 if err != nil { 112 return nil, fmt.Errorf("check embedded proof: %w", err) 113 } 114 115 if len(opts.ldpSuites) == 0 { 116 switch t { 117 case ed25519Signature2018: 118 ldpSuites = append(ldpSuites, ed25519signature2018.New( 119 suite.WithVerifier(ed25519signature2018.NewPublicKeyVerifier()))) 120 case ed25519Signature2020: 121 ldpSuites = append(ldpSuites, ed25519signature2020.New( 122 suite.WithVerifier(ed25519signature2020.NewPublicKeyVerifier()))) 123 case jsonWebSignature2020: 124 ldpSuites = append(ldpSuites, jsonwebsignature2020.New( 125 suite.WithVerifier(jsonwebsignature2020.NewPublicKeyVerifier()))) 126 case ecdsaSecp256k1Signature2019: 127 ldpSuites = append(ldpSuites, ecdsasecp256k1signature2019.New( 128 suite.WithVerifier(ecdsasecp256k1signature2019.NewPublicKeyVerifier()))) 129 case bbsBlsSignature2020: 130 ldpSuites = append(ldpSuites, bbsblssignature2020.New( 131 suite.WithVerifier(bbsblssignature2020.NewG2PublicKeyVerifier()))) 132 case bbsBlsSignatureProof2020: 133 nonce, err := getNonce(proofs[i]) 134 if err != nil { 135 return nil, err 136 } 137 138 ldpSuites = append(ldpSuites, bbsblssignatureproof2020.New( 139 suite.WithVerifier(bbsblssignatureproof2020.NewG2PublicKeyVerifier(nonce)))) 140 } 141 } 142 } 143 144 return ldpSuites, nil 145 } 146 147 func getNonce(proof map[string]interface{}) ([]byte, error) { 148 if nonce, ok := proof["nonce"]; ok { 149 n, err := base64.StdEncoding.DecodeString(nonce.(string)) 150 if err != nil { 151 return nil, err 152 } 153 154 return n, nil 155 } 156 157 return []byte{}, nil 158 } 159 160 func getProofs(proofElement interface{}) ([]map[string]interface{}, error) { 161 switch p := proofElement.(type) { 162 case map[string]interface{}: 163 return []map[string]interface{}{p}, nil 164 165 case []interface{}: 166 proofs := make([]map[string]interface{}, len(p)) 167 168 for i := range p { 169 proofMap, ok := p[i].(map[string]interface{}) 170 if !ok { 171 return nil, errors.New("invalid proof type") 172 } 173 174 proofs[i] = proofMap 175 } 176 177 return proofs, nil 178 } 179 180 return nil, errors.New("invalid proof type") 181 }