github.com/hyperledger/aries-framework-go@v0.3.2/pkg/doc/signature/suite/bbsblssignatureproof2020/signer_test.go (about) 1 /* 2 Copyright SecureKey Technologies Inc. All Rights Reserved. 3 4 SPDX-License-Identifier: Apache-2.0 5 */ 6 7 package bbsblssignatureproof2020_test 8 9 import ( 10 _ "embed" 11 "encoding/base64" 12 "encoding/json" 13 "errors" 14 "testing" 15 16 "github.com/btcsuite/btcutil/base58" 17 "github.com/stretchr/testify/require" 18 19 "github.com/hyperledger/aries-framework-go/component/models/ld/testutil" 20 "github.com/hyperledger/aries-framework-go/component/models/signature/suite/bbsblssignatureproof2020" 21 "github.com/hyperledger/aries-framework-go/component/models/signature/verifier" 22 23 "github.com/hyperledger/aries-framework-go/pkg/doc/verifiable" 24 ) 25 26 //nolint:gochecknoglobals 27 var ( 28 //go:embed testdata/case16_vc.jsonld 29 case16VC string // Case 16 (https://github.com/w3c-ccg/vc-http-api/pull/128) 30 //go:embed testdata/case16_reveal_doc.jsonld 31 case16RevealDoc string 32 //go:embed testdata/case18_vc.jsonld 33 case18VC string // Case 18 (https://github.com/w3c-ccg/vc-http-api/pull/128) 34 //go:embed testdata/case18_reveal_doc.jsonld 35 case18RevealDoc string 36 //go:embed testdata/doc_with_many_proofs.jsonld 37 docWithManyProofsJSON string //nolint:unused // re-enable test that uses this var (#2562) 38 ) 39 40 // nolint 41 func TestSuite_SelectiveDisclosure(t *testing.T) { 42 // pkBase58 from did:key:zUC724vuGvHpnCGFG1qqpXb81SiBLu3KLSqVzenwEZNPoY35i2Bscb8DLaVwHvRFs6F2NkNNXRcPWvqnPDUd9ukdjLkjZd3u9zzL4wDZDUpkPAatLDGLEYVo8kkAzuAKJQMr7N2 43 pkBase58 := "nEP2DEdbRaQ2r5Azeatui9MG6cj7JUHa8GD7khub4egHJREEuvj4Y8YG8w51LnhPEXxVV1ka93HpSLkVzeQuuPE1mH9oCMrqoHXAKGBsuDT1yJvj9cKgxxLCXiRRirCycki" 44 pubKeyBytes := base58.Decode(pkBase58) 45 46 nonce, err := base64.StdEncoding.DecodeString("G/hn9Ca9bIWZpJGlhnr/41r8RB0OO0TLChZASr3QJVztdri/JzS8Zf/xWJT5jW78zlM=") 47 require.NoError(t, err) 48 49 docMap := toMap(t, case16VC) 50 revealDocMap := toMap(t, case16RevealDoc) 51 52 s := bbsblssignatureproof2020.New() 53 54 const proofField = "proof" 55 56 pubKeyResolver := &testKeyResolver{ 57 publicKey: &verifier.PublicKey{ 58 Type: "Bls12381G2Key2020", 59 Value: pubKeyBytes, 60 }, 61 } 62 63 t.Run("single BBS+ signature", func(t *testing.T) { 64 docWithSelectiveDisclosure, err := s.SelectiveDisclosure(docMap, revealDocMap, nonce, 65 pubKeyResolver, testutil.WithDocumentLoader(t)) 66 require.NoError(t, err) 67 require.NotEmpty(t, docWithSelectiveDisclosure) 68 require.Contains(t, docWithSelectiveDisclosure, proofField) 69 70 proofs, ok := docWithSelectiveDisclosure[proofField].([]map[string]interface{}) 71 require.True(t, ok) 72 73 require.Len(t, proofs, 1) 74 require.Equal(t, "BbsBlsSignatureProof2020", proofs[0]["type"]) 75 require.NotEmpty(t, proofs[0]["proofValue"]) 76 }) 77 78 t.Run("several proofs including BBS+ signature", func(t *testing.T) { 79 // TODO re-enable (#2562). 80 t.Skip() 81 docWithSeveralProofsMap := toMap(t, docWithManyProofsJSON) 82 83 pubKeyBytes2 := base58.Decode("tPTWWeUm8yT3aR9HtMvo2pLLvAdyV9Z4nJYZ2ZsyoLVpTupVb7NaRJ3tZePF6YsCN1nw7McqJ38tvpmQxKQxrTbyzjiewUDaj5jbD8gVfpfXJL2SfPBw4TGjYPA6zg6Jrxn") 84 85 compositeResolver := &testKeyResolver{ 86 variants: map[string]*verifier.PublicKey{ 87 "did:example:489398593#test": { 88 Type: "Bls12381G2Key2020", 89 Value: pubKeyBytes}, 90 "did:example:123456#key2": { 91 Type: "Bls12381G2Key2020", 92 Value: pubKeyBytes2}, 93 }, 94 } 95 96 docWithSelectiveDisclosure, err := s.SelectiveDisclosure(docWithSeveralProofsMap, revealDocMap, nonce, 97 compositeResolver, testutil.WithDocumentLoader(t)) 98 require.NoError(t, err) 99 require.NotEmpty(t, docWithSelectiveDisclosure) 100 require.Contains(t, docWithSelectiveDisclosure, proofField) 101 102 proofs, ok := docWithSelectiveDisclosure[proofField].([]map[string]interface{}) 103 require.True(t, ok) 104 105 require.Len(t, proofs, 2) 106 require.Equal(t, "BbsBlsSignatureProof2020", proofs[0]["type"]) 107 require.NotEmpty(t, proofs[0]["proofValue"]) 108 require.Equal(t, "BbsBlsSignatureProof2020", proofs[1]["type"]) 109 require.NotEmpty(t, proofs[1]["proofValue"]) 110 }) 111 112 t.Run("malformed input", func(t *testing.T) { 113 docMap := make(map[string]interface{}) 114 docMap["@context"] = "http://localhost/nocontext" 115 docMap["bad"] = "example" 116 docMap["proof"] = "example" 117 118 _, err := s.SelectiveDisclosure(docMap, revealDocMap, nonce, pubKeyResolver, testutil.WithDocumentLoader(t)) 119 require.Error(t, err) 120 }) 121 122 t.Run("no proof", func(t *testing.T) { 123 docMapWithoutProof := make(map[string]interface{}, len(docMap)-1) 124 125 for k, v := range docMap { 126 if k != proofField { 127 docMapWithoutProof[k] = v 128 } 129 } 130 131 docWithSelectiveDisclosure, err := s.SelectiveDisclosure(docMapWithoutProof, revealDocMap, nonce, 132 pubKeyResolver, testutil.WithDocumentLoader(t)) 133 require.Error(t, err) 134 require.Contains(t, err.Error(), "document does not have a proof") 135 require.Empty(t, docWithSelectiveDisclosure) 136 }) 137 138 t.Run("invalid proof", func(t *testing.T) { 139 docMapWithInvalidProof := make(map[string]interface{}, len(docMap)-1) 140 141 for k, v := range docMap { 142 if k != proofField { 143 docMapWithInvalidProof[k] = v 144 } else { 145 docMapWithInvalidProof[k] = "invalid proof" 146 } 147 } 148 149 docWithSelectiveDisclosure, err := s.SelectiveDisclosure(docMapWithInvalidProof, revealDocMap, nonce, 150 pubKeyResolver, testutil.WithDocumentLoader(t)) 151 require.Error(t, err) 152 require.EqualError(t, err, "get BLS proofs: read document proofs: proof is not map or array of maps") 153 require.Empty(t, docWithSelectiveDisclosure) 154 }) 155 156 t.Run("invalid proof value", func(t *testing.T) { 157 docMapWithInvalidProofValue := make(map[string]interface{}, len(docMap)) 158 159 for k, v := range docMap { 160 if k == proofField { 161 proofMap := make(map[string]interface{}) 162 163 for k1, v1 := range v.(map[string]interface{}) { 164 if k1 == "proofValue" { 165 proofMap[k1] = "invalid" 166 } else { 167 proofMap[k1] = v1 168 } 169 } 170 171 docMapWithInvalidProofValue[proofField] = proofMap 172 } else { 173 docMapWithInvalidProofValue[k] = v 174 } 175 } 176 177 docWithSelectiveDisclosure, err := s.SelectiveDisclosure(docMapWithInvalidProofValue, revealDocMap, nonce, 178 pubKeyResolver, testutil.WithDocumentLoader(t)) 179 require.Error(t, err) 180 require.EqualError(t, err, "generate signature proof: derive BBS+ proof: parse signature: invalid size of signature") //nolint:lll 181 require.Empty(t, docWithSelectiveDisclosure) 182 }) 183 184 t.Run("invalid input BBS+ proof value", func(t *testing.T) { 185 docMapWithInvalidProofType := make(map[string]interface{}, len(docMap)-1) 186 187 for k, v := range docMap { 188 if k == proofField { 189 proofMap := make(map[string]interface{}) 190 191 for k1, v1 := range v.(map[string]interface{}) { 192 if k1 == "type" { 193 proofMap[k1] = "invalid" 194 } else { 195 proofMap[k1] = v1 196 } 197 } 198 199 docMapWithInvalidProofType[proofField] = proofMap 200 } else { 201 docMapWithInvalidProofType[k] = v 202 } 203 } 204 205 docWithSelectiveDisclosure, err := s.SelectiveDisclosure(docMapWithInvalidProofType, revealDocMap, nonce, 206 pubKeyResolver, testutil.WithDocumentLoader(t)) 207 require.Error(t, err) 208 require.EqualError(t, err, "no BbsBlsSignature2020 proof present") 209 require.Empty(t, docWithSelectiveDisclosure) 210 }) 211 212 t.Run("failed to resolve public key", func(t *testing.T) { 213 failingPublicKeyResolver := &testKeyResolver{ 214 err: errors.New("public key not found"), 215 } 216 217 docWithSelectiveDisclosure, err := s.SelectiveDisclosure(docMap, revealDocMap, nonce, 218 failingPublicKeyResolver, testutil.WithDocumentLoader(t)) 219 require.Error(t, err) 220 require.EqualError(t, err, "generate signature proof: get public key and signature: resolve public key of BBS+ signature: public key not found") //nolint:lll 221 require.Empty(t, docWithSelectiveDisclosure) 222 }) 223 224 t.Run("Case 18 derives into Case 19", func(t *testing.T) { 225 case18DocMap := toMap(t, case18VC) 226 case18RevealDocMap := toMap(t, case18RevealDoc) 227 228 case19Nonce, err := base64.StdEncoding.DecodeString("lEixQKDQvRecCifKl789TQj+Ii6YWDLSwn3AxR0VpPJ1QV5htod/0VCchVf1zVM0y2E=") 229 require.NoError(t, err) 230 231 docWithSelectiveDisclosure, err := s.SelectiveDisclosure(case18DocMap, case18RevealDocMap, case19Nonce, 232 pubKeyResolver, testutil.WithDocumentLoader(t)) 233 require.NoError(t, err) 234 require.NotEmpty(t, docWithSelectiveDisclosure) 235 require.Contains(t, docWithSelectiveDisclosure, proofField) 236 237 proofs, ok := docWithSelectiveDisclosure[proofField].([]map[string]interface{}) 238 require.True(t, ok) 239 240 require.Len(t, proofs, 1) 241 require.Equal(t, "BbsBlsSignatureProof2020", proofs[0]["type"]) 242 require.NotEmpty(t, proofs[0]["proofValue"]) 243 244 case18DerivationBytes, err := json.Marshal(docWithSelectiveDisclosure) 245 246 pubKeyFetcher := verifiable.SingleKey(pubKeyBytes, "Bls12381G2Key2020") 247 248 loader, err := testutil.DocumentLoader() 249 require.NoError(t, err) 250 251 _, err = verifiable.ParseCredential(case18DerivationBytes, verifiable.WithPublicKeyFetcher(pubKeyFetcher), 252 verifiable.WithJSONLDDocumentLoader(loader)) 253 require.NoError(t, err) 254 }) 255 } 256 257 func toMap(t *testing.T, doc string) map[string]interface{} { 258 var docMap map[string]interface{} 259 err := json.Unmarshal([]byte(doc), &docMap) 260 require.NoError(t, err) 261 262 return docMap 263 } 264 265 type testKeyResolver struct { 266 publicKey *verifier.PublicKey 267 variants map[string]*verifier.PublicKey 268 err error 269 } 270 271 func (r *testKeyResolver) Resolve(id string) (*verifier.PublicKey, error) { 272 if r.err != nil { 273 return nil, r.err 274 } 275 276 if len(r.variants) > 0 { 277 return r.variants[id], nil 278 } 279 280 return r.publicKey, r.err 281 }