github.com/hyperledger/aries-framework-go@v0.3.2/pkg/doc/cl/ursa/crypto_test.go (about)

     1  //go:build ursa
     2  // +build ursa
     3  
     4  /*
     5  Copyright SecureKey Technologies Inc. All Rights Reserved.
     6  
     7  SPDX-License-Identifier: Apache-2.0
     8  */
     9  
    10  package ursa
    11  
    12  import (
    13  	"testing"
    14  
    15  	"github.com/google/tink/go/keyset"
    16  	"github.com/stretchr/testify/require"
    17  
    18  	"github.com/hyperledger/aries-framework-go/pkg/crypto"
    19  	"github.com/hyperledger/aries-framework-go/pkg/crypto/tinkcrypto"
    20  	bld "github.com/hyperledger/aries-framework-go/pkg/crypto/tinkcrypto/primitive/cl/blinder"
    21  	sgn "github.com/hyperledger/aries-framework-go/pkg/crypto/tinkcrypto/primitive/cl/signer"
    22  	"github.com/hyperledger/aries-framework-go/pkg/doc/cl"
    23  	"github.com/hyperledger/aries-framework-go/pkg/kms"
    24  	mockkms "github.com/hyperledger/aries-framework-go/pkg/mock/kms"
    25  )
    26  
    27  func TestCL(t *testing.T) {
    28  	km := &mockkms.KeyManager{}
    29  	c := &tinkcrypto.Crypto{}
    30  	provider := newProvider(km, c)
    31  
    32  	values := map[string]interface{}{"attr1": 5, "attr2": "aaa"}
    33  	values2 := map[string]interface{}{"attr3": 5, "attr4": "aaa"}
    34  
    35  	presentaionItems := []*cl.PresentationRequestItem{{
    36  		RevealedAttrs: []string{"attr2"},
    37  		Predicates: []*cl.Predicate{
    38  			{
    39  				PType: "GE",
    40  				Attr:  "attr1",
    41  				Value: 4,
    42  			},
    43  		},
    44  	}}
    45  
    46  	var (
    47  		issuer   *Issuer
    48  		prover   *Prover
    49  		verifier *Verifier
    50  
    51  		credDef    *cl.CredentialDefinition
    52  		offer      *cl.CredentialOffer
    53  		request    *cl.CredentialRequest
    54  		credential *cl.Credential
    55  
    56  		originalSignature []byte
    57  
    58  		presentation *cl.PresentationRequest
    59  		proof        *cl.Proof
    60  	)
    61  
    62  	t.Run("test CL services creation", func(t *testing.T) {
    63  		var err error
    64  
    65  		issKh, issPubKey := createAndExportSignerKey(t, []string{"attr1", "attr2"})
    66  		km.GetKeyValue = issKh
    67  		km.ExportPubKeyBytesValue = issPubKey
    68  		km.ExportPubKeyTypeValue = kms.CLCredDefType
    69  
    70  		issuer, err = NewIssuer(provider, "credDefKID", []string{"attr1", "attr2"})
    71  		require.NoError(t, err)
    72  
    73  		prvKh := createBlinderKey(t)
    74  		km.GetKeyValue = prvKh
    75  
    76  		prover, err = NewProver(provider, "msKID")
    77  		require.NoError(t, err)
    78  
    79  		verifier, err = NewVerifier()
    80  		require.NoError(t, err)
    81  	})
    82  
    83  	t.Run("test CL issue credential flow", func(t *testing.T) {
    84  		var err error
    85  
    86  		// 0. Issuer expose CredDef
    87  		credDef, err = issuer.GetCredentialDefinition()
    88  		require.NoError(t, err)
    89  		require.NotEmpty(t, credDef.CredPubKey)
    90  		require.NotEmpty(t, credDef.CredDefCorrectnessProof)
    91  
    92  		// 1. Issuer offers credential
    93  		offer, err = issuer.OfferCredential()
    94  		require.NoError(t, err)
    95  		require.NotEmpty(t, offer.Nonce)
    96  
    97  		// 2. Prover requests credential
    98  		request, err = prover.RequestCredential(offer, credDef, "proverDID")
    99  		require.NoError(t, err)
   100  		require.NotEmpty(t, request.Nonce)
   101  		require.NotEmpty(t, request.ProverID)
   102  		require.NotEmpty(t, request.BlindedCredentialSecrets)
   103  
   104  		// 3. Issuer issues credential
   105  		credential, err = issuer.IssueCredential(values, request, offer)
   106  		require.NoError(t, err)
   107  		require.NotEmpty(t, credential.Signature)
   108  		require.NotEmpty(t, credential.SigProof)
   109  		require.NotEmpty(t, credential.Values)
   110  
   111  		// 4. Prover verifies credential
   112  		originalSignature = credential.Signature
   113  
   114  		err = prover.ProcessCredential(credential, request, credDef)
   115  		require.NoError(t, err)
   116  		require.NotEmpty(t, credential.Signature)
   117  		require.NotEmpty(t, credential.SigProof)
   118  		require.NotEmpty(t, credential.Values)
   119  
   120  		require.NotEqual(t, originalSignature, credential.Signature)
   121  	})
   122  
   123  	t.Run("test CL present proof flow", func(t *testing.T) {
   124  		var err error
   125  
   126  		// 1. Verifier makes presentation request
   127  		presentation, err = verifier.RequestPresentation(presentaionItems)
   128  		require.NoError(t, err)
   129  		require.NotEmpty(t, presentation.Items)
   130  		require.NotEmpty(t, presentation.Nonce)
   131  
   132  		// 2. Prover creates proof accordingly
   133  		proof, err = prover.CreateProof(presentation, []*cl.Credential{credential}, []*cl.CredentialDefinition{credDef})
   134  		require.NoError(t, err)
   135  		require.NotEmpty(t, proof.Proof)
   136  
   137  		// 3. Verifier verifies resulting proof
   138  		err = verifier.VerifyProof(proof, presentation, []*cl.CredentialDefinition{credDef})
   139  		require.NoError(t, err)
   140  	})
   141  
   142  	t.Run("test CL failures", func(t *testing.T) {
   143  		var err error
   144  
   145  		issKh2, issPubKey2 := createAndExportSignerKey(t, []string{"attr3", "attr4"})
   146  		km.GetKeyValue = issKh2
   147  		km.ExportPubKeyBytesValue = issPubKey2
   148  		km.ExportPubKeyTypeValue = kms.CLCredDefType
   149  
   150  		issuer2, err := NewIssuer(provider, "credDefKID2", []string{"attr3", "attr4"})
   151  		require.NoError(t, err)
   152  		credDef2, err := issuer2.GetCredentialDefinition()
   153  		require.NoError(t, err)
   154  
   155  		// Issuer fails to issue credential for unknown credDef
   156  		_, err = issuer2.IssueCredential(values, request, offer)
   157  		require.Error(t, err)
   158  
   159  		// Issuer fails to issue credential for invalid values
   160  		_, err = issuer.IssueCredential(values2, request, offer)
   161  		require.Error(t, err)
   162  
   163  		// Prover fails to process credential with unmatched credDef
   164  		err = prover.ProcessCredential(credential, request, credDef2)
   165  		require.Error(t, err)
   166  
   167  		// Prover fails to create proof with unmatched credDefs
   168  		_, err = prover.CreateProof(presentation, []*cl.Credential{credential}, []*cl.CredentialDefinition{credDef2})
   169  		require.Error(t, err)
   170  
   171  		// Verifier fails to verify proof for unprocessed credential
   172  		unprocessed := &cl.Credential{
   173  			Signature: originalSignature,
   174  			SigProof:  credential.SigProof,
   175  			Values:    credential.Values,
   176  		}
   177  
   178  		invalid, err := prover.CreateProof(presentation, []*cl.Credential{unprocessed}, []*cl.CredentialDefinition{credDef})
   179  		require.NoError(t, err)
   180  
   181  		err = verifier.VerifyProof(invalid, presentation, []*cl.CredentialDefinition{credDef})
   182  		require.Error(t, err)
   183  
   184  		//  Verifier fails to verify proof for other credDef
   185  		err = verifier.VerifyProof(proof, presentation, []*cl.CredentialDefinition{credDef2})
   186  		require.Error(t, err)
   187  	})
   188  }
   189  
   190  func createAndExportSignerKey(t *testing.T, attrs []string) (*keyset.Handle, []byte) {
   191  	kh, err := keyset.NewHandle(sgn.CredDefKeyTemplate(attrs))
   192  	require.NoError(t, err)
   193  
   194  	pKh, err := kh.Public()
   195  	require.NoError(t, err)
   196  
   197  	pubKey, err := sgn.ExportCredDefPubKey(pKh)
   198  	require.NoError(t, err)
   199  
   200  	return kh, pubKey
   201  }
   202  
   203  func createBlinderKey(t *testing.T) *keyset.Handle {
   204  	kh, err := keyset.NewHandle(bld.MasterSecretKeyTemplate())
   205  	require.NoError(t, err)
   206  
   207  	return kh
   208  }
   209  
   210  type mockProvider struct {
   211  	km kms.KeyManager
   212  	cr crypto.Crypto
   213  }
   214  
   215  func (p *mockProvider) KMS() kms.KeyManager {
   216  	return p.km
   217  }
   218  
   219  func (p *mockProvider) Crypto() crypto.Crypto {
   220  	return p.cr
   221  }
   222  
   223  func newProvider(km kms.KeyManager, cr crypto.Crypto) *mockProvider {
   224  	return &mockProvider{
   225  		km: km,
   226  		cr: cr,
   227  	}
   228  }