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  }