github.com/yimialmonte/fabric@v2.1.1+incompatible/idemix/idemix_test.go (about)

     1  /*
     2  Copyright IBM Corp. All Rights Reserved.
     3  
     4  SPDX-License-Identifier: Apache-2.0
     5  */
     6  
     7  package idemix
     8  
     9  import (
    10  	"bytes"
    11  	"testing"
    12  
    13  	"github.com/hyperledger/fabric-amcl/amcl/FP256BN"
    14  	"github.com/stretchr/testify/assert"
    15  )
    16  
    17  func TestIdemix(t *testing.T) {
    18  	// Test weak BB sigs:
    19  	// Test KeyGen
    20  	rng, err := GetRand()
    21  	assert.NoError(t, err)
    22  	wbbsk, wbbpk := WBBKeyGen(rng)
    23  
    24  	// Get random message
    25  	testmsg := RandModOrder(rng)
    26  
    27  	// Test Signing
    28  	wbbsig := WBBSign(wbbsk, testmsg)
    29  
    30  	// Test Verification
    31  	err = WBBVerify(wbbpk, wbbsig, testmsg)
    32  	assert.NoError(t, err)
    33  
    34  	// Test idemix functionality
    35  	AttributeNames := []string{"Attr1", "Attr2", "Attr3", "Attr4", "Attr5"}
    36  	attrs := make([]*FP256BN.BIG, len(AttributeNames))
    37  	for i := range AttributeNames {
    38  		attrs[i] = FP256BN.NewBIGint(i)
    39  	}
    40  
    41  	// Test issuer key generation
    42  	if err != nil {
    43  		t.Fatalf("Error getting rng: \"%s\"", err)
    44  		return
    45  	}
    46  	// Create a new key pair
    47  	key, err := NewIssuerKey(AttributeNames, rng)
    48  	if err != nil {
    49  		t.Fatalf("Issuer key generation should have succeeded but gave error \"%s\"", err)
    50  		return
    51  	}
    52  
    53  	// Check that the key is valid
    54  	err = key.GetIpk().Check()
    55  	if err != nil {
    56  		t.Fatalf("Issuer public key should be valid")
    57  		return
    58  	}
    59  
    60  	// Make sure Check() is invalid for a public key with invalid proof
    61  	proofC := key.Ipk.GetProofC()
    62  	key.Ipk.ProofC = BigToBytes(RandModOrder(rng))
    63  	assert.Error(t, key.Ipk.Check(), "public key with broken zero-knowledge proof should be invalid")
    64  
    65  	// Make sure Check() is invalid for a public key with incorrect number of HAttrs
    66  	hAttrs := key.Ipk.GetHAttrs()
    67  	key.Ipk.HAttrs = key.Ipk.HAttrs[:0]
    68  	assert.Error(t, key.Ipk.Check(), "public key with incorrect number of HAttrs should be invalid")
    69  	key.Ipk.HAttrs = hAttrs
    70  
    71  	// Restore IPk to be valid
    72  	key.Ipk.ProofC = proofC
    73  	h := key.Ipk.GetHash()
    74  	assert.NoError(t, key.Ipk.Check(), "restored public key should be valid")
    75  	assert.Zero(t, bytes.Compare(h, key.Ipk.GetHash()), "IPK hash changed on ipk Check")
    76  
    77  	// Create public with duplicate attribute names should fail
    78  	_, err = NewIssuerKey([]string{"Attr1", "Attr2", "Attr1"}, rng)
    79  	assert.Error(t, err, "issuer key generation should fail with duplicate attribute names")
    80  
    81  	// Test issuance
    82  	sk := RandModOrder(rng)
    83  	ni := RandModOrder(rng)
    84  	m := NewCredRequest(sk, BigToBytes(ni), key.Ipk, rng)
    85  
    86  	cred, err := NewCredential(key, m, attrs, rng)
    87  	assert.NoError(t, err, "Failed to issue a credential: \"%s\"", err)
    88  
    89  	assert.NoError(t, cred.Ver(sk, key.Ipk), "credential should be valid")
    90  
    91  	// Issuing a credential with the incorrect amount of attributes should fail
    92  	_, err = NewCredential(key, m, []*FP256BN.BIG{}, rng)
    93  	assert.Error(t, err, "issuing a credential with the incorrect amount of attributes should fail")
    94  
    95  	// Breaking the ZK proof of the CredRequest should make it invalid
    96  	proofC = m.GetProofC()
    97  	m.ProofC = BigToBytes(RandModOrder(rng))
    98  	assert.Error(t, m.Check(key.Ipk), "CredRequest with broken ZK proof should not be valid")
    99  
   100  	// Creating a credential from a broken CredRequest should fail
   101  	_, err = NewCredential(key, m, attrs, rng)
   102  	assert.Error(t, err, "creating a credential from an invalid CredRequest should fail")
   103  	m.ProofC = proofC
   104  
   105  	// A credential with nil attribute should be invalid
   106  	attrsBackup := cred.GetAttrs()
   107  	cred.Attrs = [][]byte{nil, nil, nil, nil, nil}
   108  	assert.Error(t, cred.Ver(sk, key.Ipk), "credential with nil attribute should be invalid")
   109  	cred.Attrs = attrsBackup
   110  
   111  	// Generate a revocation key pair
   112  	revocationKey, err := GenerateLongTermRevocationKey()
   113  	assert.NoError(t, err)
   114  
   115  	// Create CRI that contains no revocation mechanism
   116  	epoch := 0
   117  	cri, err := CreateCRI(revocationKey, []*FP256BN.BIG{}, epoch, ALG_NO_REVOCATION, rng)
   118  	assert.NoError(t, err)
   119  	err = VerifyEpochPK(&revocationKey.PublicKey, cri.EpochPk, cri.EpochPkSig, int(cri.Epoch), RevocationAlgorithm(cri.RevocationAlg))
   120  	assert.NoError(t, err)
   121  
   122  	// make sure that epoch pk is not valid in future epoch
   123  	err = VerifyEpochPK(&revocationKey.PublicKey, cri.EpochPk, cri.EpochPkSig, int(cri.Epoch)+1, RevocationAlgorithm(cri.RevocationAlg))
   124  	assert.Error(t, err)
   125  
   126  	// Test bad input
   127  	_, err = CreateCRI(nil, []*FP256BN.BIG{}, epoch, ALG_NO_REVOCATION, rng)
   128  	assert.Error(t, err)
   129  	_, err = CreateCRI(revocationKey, []*FP256BN.BIG{}, epoch, ALG_NO_REVOCATION, nil)
   130  	assert.Error(t, err)
   131  
   132  	// Test signing no disclosure
   133  	Nym, RandNym := MakeNym(sk, key.Ipk, rng)
   134  
   135  	disclosure := []byte{0, 0, 0, 0, 0}
   136  	msg := []byte{1, 2, 3, 4, 5}
   137  	rhindex := 4
   138  	sig, err := NewSignature(cred, sk, Nym, RandNym, key.Ipk, disclosure, msg, rhindex, cri, rng)
   139  	assert.NoError(t, err)
   140  
   141  	err = sig.Ver(disclosure, key.Ipk, msg, nil, 0, &revocationKey.PublicKey, epoch)
   142  	if err != nil {
   143  		t.Fatalf("Signature should be valid but verification returned error: %s", err)
   144  		return
   145  	}
   146  
   147  	// Test signing selective disclosure
   148  	disclosure = []byte{0, 1, 1, 1, 0}
   149  	sig, err = NewSignature(cred, sk, Nym, RandNym, key.Ipk, disclosure, msg, rhindex, cri, rng)
   150  	assert.NoError(t, err)
   151  
   152  	err = sig.Ver(disclosure, key.Ipk, msg, attrs, rhindex, &revocationKey.PublicKey, epoch)
   153  	assert.NoError(t, err)
   154  
   155  	// Test NymSignatures
   156  	nymsig, err := NewNymSignature(sk, Nym, RandNym, key.Ipk, []byte("testing"), rng)
   157  	assert.NoError(t, err)
   158  
   159  	err = nymsig.Ver(Nym, key.Ipk, []byte("testing"))
   160  	if err != nil {
   161  		t.Fatalf("NymSig should be valid but verification returned error: %s", err)
   162  		return
   163  	}
   164  }