github.com/hyperledger/aries-framework-go@v0.3.2/pkg/doc/verifiable/common_test.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/json" 10 "errors" 11 "fmt" 12 "testing" 13 14 "github.com/stretchr/testify/require" 15 16 "github.com/hyperledger/aries-framework-go/pkg/doc/did" 17 mockvdr "github.com/hyperledger/aries-framework-go/pkg/mock/vdr" 18 "github.com/hyperledger/aries-framework-go/pkg/vdr" 19 ) 20 21 func TestJwtAlgorithm_Name(t *testing.T) { 22 alg, err := RS256.Name() 23 require.NoError(t, err) 24 require.Equal(t, "RS256", alg) 25 26 alg, err = EdDSA.Name() 27 require.NoError(t, err) 28 require.Equal(t, "EdDSA", alg) 29 30 // not supported alg 31 sa, err := JWSAlgorithm(-1).Name() 32 require.Error(t, err) 33 require.Contains(t, err.Error(), "unsupported algorithm") 34 require.Empty(t, sa) 35 } 36 37 func TestStringSlice(t *testing.T) { 38 strings, err := stringSlice([]interface{}{"str1", "str2"}) 39 require.NoError(t, err) 40 require.Equal(t, []string{"str1", "str2"}, strings) 41 42 strings, err = stringSlice([]interface{}{"str1", 15}) 43 require.Error(t, err) 44 require.Nil(t, strings) 45 } 46 47 func TestTypedID_MarshalJSON(t *testing.T) { 48 t.Run("Successful marshalling", func(t *testing.T) { 49 tid := TypedID{ 50 ID: "http://example.com/policies/credential/4", 51 Type: "IssuerPolicy", 52 CustomFields: map[string]interface{}{ 53 "profile": "http://example.com/profiles/credential", 54 }, 55 } 56 57 data, err := json.Marshal(&tid) 58 require.NoError(t, err) 59 60 var tidRecovered TypedID 61 err = json.Unmarshal(data, &tidRecovered) 62 require.NoError(t, err) 63 64 require.Equal(t, tid, tidRecovered) 65 }) 66 67 t.Run("Invalid marshalling", func(t *testing.T) { 68 tid := TypedID{ 69 CustomFields: map[string]interface{}{ 70 "invalid": make(chan int), 71 }, 72 } 73 74 b, err := json.Marshal(&tid) 75 require.Error(t, err) 76 require.Contains(t, err.Error(), "marshal TypedID") 77 require.Nil(t, b) 78 }) 79 } 80 81 func TestTypedID_UnmarshalJSON(t *testing.T) { 82 t.Run("Successful unmarshalling", func(t *testing.T) { 83 tidJSON := `{ 84 "type": "IssuerPolicy", 85 "id": "http://example.com/policies/credential/4", 86 "profile": "http://example.com/profiles/credential", 87 "prohibition": [{ 88 "assigner": "https://example.edu/issuers/14", 89 "assignee": "AllVerifiers", 90 "target": "http://example.edu/credentials/3732" 91 }] 92 }` 93 94 var tid TypedID 95 err := json.Unmarshal([]byte(tidJSON), &tid) 96 require.NoError(t, err) 97 98 require.Equal(t, "http://example.com/policies/credential/4", tid.ID) 99 require.Equal(t, "IssuerPolicy", tid.Type) 100 require.Equal(t, CustomFields{ 101 "profile": "http://example.com/profiles/credential", 102 "prohibition": []interface{}{ 103 map[string]interface{}{ 104 "assigner": "https://example.edu/issuers/14", 105 "assignee": "AllVerifiers", 106 "target": "http://example.edu/credentials/3732", 107 }, 108 }, 109 }, tid.CustomFields) 110 }) 111 112 t.Run("Invalid unmarshalling", func(t *testing.T) { 113 tidJSONWithInvalidType := `{ 114 "type": 77 115 }` 116 var tid TypedID 117 err := json.Unmarshal([]byte(tidJSONWithInvalidType), &tid) 118 require.Error(t, err) 119 require.Contains(t, err.Error(), "unmarshal TypedID") 120 }) 121 } 122 123 func TestDecodeType(t *testing.T) { 124 t.Run("Decode single type", func(t *testing.T) { 125 types, err := decodeType("VerifiableCredential") 126 require.NoError(t, err) 127 require.Equal(t, []string{"VerifiableCredential"}, types) 128 }) 129 130 t.Run("Decode several types", func(t *testing.T) { 131 types, err := decodeType([]interface{}{"VerifiableCredential", "UniversityDegreeCredential"}) 132 require.NoError(t, err) 133 require.Equal(t, []string{"VerifiableCredential", "UniversityDegreeCredential"}, types) 134 }) 135 136 t.Run("Error on decoding of invalid Verifiable Credential type", func(t *testing.T) { 137 types, err := decodeType(77) 138 require.Error(t, err) 139 require.Contains(t, err.Error(), "credential type of unknown structure") 140 require.Nil(t, types) 141 }) 142 143 t.Run("Error on decoding of invalid Verifiable Credential types", func(t *testing.T) { 144 types, err := decodeType([]interface{}{"VerifiableCredential", 777}) 145 require.Error(t, err) 146 require.Contains(t, err.Error(), "vc types: array element is not a string") 147 require.Nil(t, types) 148 }) 149 } 150 151 func TestDecodeContext(t *testing.T) { 152 t.Run("Decode single context", func(t *testing.T) { 153 contexts, extraContexts, err := decodeContext("https://www.w3.org/2018/credentials/v1") 154 require.NoError(t, err) 155 require.Equal(t, []string{"https://www.w3.org/2018/credentials/v1"}, contexts) 156 require.Empty(t, extraContexts) 157 }) 158 159 t.Run("Decode several contexts", func(t *testing.T) { 160 contexts, extraContexts, err := decodeContext([]interface{}{ 161 "https://www.w3.org/2018/credentials/v1", 162 "https://www.w3.org/2018/credentials/examples/v1", 163 }) 164 require.NoError(t, err) 165 require.Equal(t, 166 []string{"https://www.w3.org/2018/credentials/v1", "https://www.w3.org/2018/credentials/examples/v1"}, 167 contexts) 168 require.Empty(t, extraContexts) 169 }) 170 171 t.Run("Decode several contexts with custom objects", func(t *testing.T) { 172 customContext := map[string]interface{}{ 173 "image": map[string]interface{}{"@id": "schema:image", "@type": "@id"}, 174 } 175 contexts, extraContexts, err := decodeContext([]interface{}{ 176 "https://www.w3.org/2018/credentials/v1", 177 "https://www.w3.org/2018/credentials/examples/v1", 178 customContext, 179 }) 180 require.NoError(t, err) 181 require.Equal(t, 182 []string{"https://www.w3.org/2018/credentials/v1", "https://www.w3.org/2018/credentials/examples/v1"}, 183 contexts) 184 require.Equal(t, []interface{}{customContext}, extraContexts) 185 }) 186 187 t.Run("Decode context of invalid type", func(t *testing.T) { 188 contexts, extraContexts, err := decodeContext(55) 189 require.Error(t, err) 190 require.Nil(t, contexts) 191 require.Nil(t, extraContexts) 192 }) 193 } 194 195 func Test_safeStringValue(t *testing.T) { 196 var i interface{} = "str" 197 198 require.Equal(t, "str", safeStringValue(i)) 199 200 i = nil 201 require.Equal(t, "", safeStringValue(i)) 202 } 203 204 func Test_proofsToRaw(t *testing.T) { 205 singleProof := []Proof{{ 206 "proofValue": "eyJhbGciOiJFZERTQSIsImI2NCI6ZmFsc2UsImNyaXQiOlsiYjY0Il19..67TTULBvibJaJ2oZf3tGYhxZqxYS89qGQykL5hfCoh-MF0vrwQqzciZhjNrAGTAgHtDZsnSQVwJ8bO_7Sc0ECw", //nolint:lll 207 }} 208 209 singleProofBytes, err := proofsToRaw(singleProof) 210 require.NoError(t, err) 211 212 var singleProofMap map[string]interface{} 213 214 err = json.Unmarshal(singleProofBytes, &singleProofMap) 215 require.NoError(t, err) 216 217 severalProofs := []Proof{ 218 singleProof[0], 219 {"proofValue": "if8ooA+32YZc4SQBvIDDY9tgTatPoq4IZ8Kr+We1t38LR2RuURmaVu9D4shbi4VvND87PUqq5/0vsNFEGIIEDA=="}, 220 } 221 severalProofsBytes, err := proofsToRaw(severalProofs) 222 require.NoError(t, err) 223 224 var severalProofsMap []map[string]interface{} 225 err = json.Unmarshal(severalProofsBytes, &severalProofsMap) 226 require.NoError(t, err) 227 } 228 229 func TestNewVDRKeyResolver(t *testing.T) { 230 resolver := NewVDRKeyResolver(vdr.New()) 231 232 require.NotNil(t, resolver) 233 } 234 235 func TestDIDKeyResolver_Resolve(t *testing.T) { 236 r := require.New(t) 237 238 didDoc := createDIDDoc() 239 publicKey := didDoc.VerificationMethod[0] 240 authentication := didDoc.Authentication[0] 241 assertionMethod := didDoc.AssertionMethod[0] 242 243 v := &mockvdr.MockVDRegistry{ 244 ResolveValue: didDoc, 245 } 246 247 resolver := NewVDRKeyResolver(v) 248 r.NotNil(resolver) 249 250 pubKey, err := resolver.PublicKeyFetcher()(didDoc.ID, publicKey.ID) 251 r.NoError(err) 252 r.Equal(publicKey.Value, pubKey.Value) 253 r.Equal("Ed25519VerificationKey2018", pubKey.Type) 254 r.NotNil(pubKey.JWK) 255 r.Equal(pubKey.JWK.Algorithm, "EdDSA") 256 257 authPubKey, err := resolver.PublicKeyFetcher()(didDoc.ID, authentication.VerificationMethod.ID) 258 r.NoError(err) 259 r.Equal(authentication.VerificationMethod.Value, authPubKey.Value) 260 r.Equal("Ed25519VerificationKey2018", authPubKey.Type) 261 r.NotNil(authPubKey.JWK) 262 r.Equal(authPubKey.JWK.Algorithm, "EdDSA") 263 264 assertMethPubKey, err := resolver.PublicKeyFetcher()(didDoc.ID, assertionMethod.VerificationMethod.ID) 265 r.NoError(err) 266 r.Equal(assertionMethod.VerificationMethod.Value, assertMethPubKey.Value) 267 r.Equal("Ed25519VerificationKey2018", assertMethPubKey.Type) 268 269 pubKey, err = resolver.PublicKeyFetcher()(didDoc.ID, "invalid key") 270 r.Error(err) 271 r.EqualError(err, fmt.Sprintf("public key with KID invalid key is not found for DID %s", didDoc.ID)) 272 r.Nil(pubKey) 273 274 v.ResolveErr = errors.New("resolver error") 275 pubKey, err = resolver.PublicKeyFetcher()(didDoc.ID, "") 276 r.Error(err) 277 r.EqualError(err, fmt.Sprintf("resolve DID %s: resolver error", didDoc.ID)) 278 r.Nil(pubKey) 279 } 280 281 //nolint:lll 282 func createDIDDoc() *did.Doc { 283 didDocJSON := `{ 284 "@context": [ 285 "https://w3id.org/did/v1" 286 ], 287 "id": "did:test:2WxUJa8nVjXr5yS69JWoKZ", 288 "verificationMethod": [ 289 { 290 "controller": "did:test:8STcrCQFzFxKey7YSbj62A", 291 "id": "did:test:8STcrCQFzFxKey7YSbj62A#keys-1", 292 "publicKeyJwk": { 293 "kty": "OKP", 294 "crv": "Ed25519", 295 "alg": "EdDSA", 296 "x": "PD34BecP4G7UcAj2u1ygB9MX31jJnqtkJFvkR1o8nIE" 297 }, 298 "type": "Ed25519VerificationKey2018" 299 } 300 ], 301 "service": [ 302 { 303 "id": "did:test:8STcrCQFzFxKey7YSbj62A#endpoint-1", 304 "priority": 0, 305 "recipientKeys": [ 306 "did:test:8STcrCQFzFxKey7YSbj62A#keys-1" 307 ], 308 "routingKeys": null, 309 "serviceEndpoint": "http://localhost:47582", 310 "type": "did-communication" 311 } 312 ], 313 "authentication": [ 314 { 315 "controller": "did:test:2WxUJa8nVjXr5yS69JWoKZ", 316 "id": "did:test:2WxUJa8nVjXr5yS69JWoKZ#keys-1", 317 "publicKeyJwk": { 318 "kty": "OKP", 319 "crv": "Ed25519", 320 "alg": "EdDSA", 321 "x": "DEfkntM3vCV5WtS-1G9cBMmkNJSPlVdjwSdHmHbirTg" 322 }, 323 "type": "Ed25519VerificationKey2018" 324 } 325 ], 326 "assertionMethod": [ 327 { 328 "id": "did:v1:test:nym:z6MkfG5HTrBXzsAP8AbayNpG3ZaoyM4PCqNPrdWQRSpHDV6J#z6MkqfvdBsFw4QdGrZrnx7L1EKfY5zh9tT4gumUGsMMEZHY3", 329 "type": "Ed25519VerificationKey2018", 330 "controller": "did:v1:test:nym:z6MkfG5HTrBXzsAP8AbayNpG3ZaoyM4PCqNPrdWQRSpHDV6J", 331 "publicKeyBase58": "CDfabd1Vis8ok526GYNAPE7YGRRJUZpLDkZM35PDe4kf" 332 } 333 ], 334 "created": "2020-04-13T12:51:08.274813+03:00", 335 "updated": "2020-04-13T12:51:08.274813+03:00" 336 }` 337 338 didDoc, err := did.ParseDocument([]byte(didDocJSON)) 339 if err != nil { 340 panic(err) 341 } 342 343 return didDoc 344 }