github.com/adecaro/fabric-ca@v2.0.0-alpha+incompatible/lib/server/idemix/revocationkey_test.go (about)

     1  /*
     2  Copyright IBM Corp. All Rights Reserved.
     3  
     4  SPDX-License-Identifier: Apache-2.0
     5  */
     6  
     7  package idemix_test
     8  
     9  import (
    10  	"crypto/ecdsa"
    11  	"io/ioutil"
    12  	"os"
    13  	"path"
    14  	"path/filepath"
    15  	"testing"
    16  
    17  	. "github.com/hyperledger/fabric-ca/lib/server/idemix"
    18  	"github.com/hyperledger/fabric-ca/lib/server/idemix/mocks"
    19  	"github.com/hyperledger/fabric-ca/util"
    20  	"github.com/hyperledger/fabric/idemix"
    21  	"github.com/stretchr/testify/assert"
    22  )
    23  
    24  const (
    25  	testRevocationPublicKeyFile  = "../../../testdata/IdemixRevocationPublicKey"
    26  	testRevocationPrivateKeyFile = "../../../testdata/IdemixRevocationPrivateKey"
    27  )
    28  
    29  func TestLoadNonExistentRevocationPublicKey(t *testing.T) {
    30  	testdir, err := ioutil.TempDir(".", "rkloadTest")
    31  	if err != nil {
    32  		t.Fatalf("Failed to create temp directory: %s", err.Error())
    33  	}
    34  	defer os.RemoveAll(testdir)
    35  	idemixLib := new(mocks.Lib)
    36  	rk := NewRevocationKey(path.Join(testdir, DefaultRevocationPublicKeyFile),
    37  		path.Join(testdir, "msp/keystore", DefaultRevocationPrivateKeyFile), idemixLib)
    38  	err = rk.Load()
    39  	assert.Error(t, err, "Should have failed to load non existent revocation public key")
    40  	if err != nil {
    41  		assert.Contains(t, err.Error(), "Failed to read revocation public key")
    42  	}
    43  }
    44  
    45  func TestLoadEmptyRevocationPublicKey(t *testing.T) {
    46  	testdir, err := ioutil.TempDir(".", "rkloadTest")
    47  	if err != nil {
    48  		t.Fatalf("Failed to create temp directory: %s", err.Error())
    49  	}
    50  	pubkeyfile, err := ioutil.TempFile(testdir, DefaultRevocationPublicKeyFile)
    51  	defer os.RemoveAll(testdir)
    52  	idemixLib := new(mocks.Lib)
    53  	rk := NewRevocationKey(pubkeyfile.Name(), path.Join(testdir, "msp/keystore", DefaultRevocationPrivateKeyFile), idemixLib)
    54  	err = rk.Load()
    55  	assert.Error(t, err, "Should have failed to load empty revocation public key")
    56  	if err != nil {
    57  		assert.Contains(t, err.Error(), "Revocation public key file is empty")
    58  	}
    59  }
    60  
    61  func TestLoadFakeRevocationPublicKey(t *testing.T) {
    62  	testdir, err := ioutil.TempDir(".", "rkloadTest")
    63  	if err != nil {
    64  		t.Fatalf("Failed to create temp directory: %s", err.Error())
    65  	}
    66  	defer os.RemoveAll(testdir)
    67  	pubkeyfile, err := ioutil.TempFile(testdir, DefaultRevocationPublicKeyFile)
    68  	if err != nil {
    69  		t.Fatalf("Failed to create temp file: %s", err.Error())
    70  	}
    71  	privkeyfile, err := ioutil.TempFile(testdir, DefaultRevocationPrivateKeyFile)
    72  	if err != nil {
    73  		t.Fatalf("Failed to create temp file: %s", err.Error())
    74  	}
    75  	key, err := idemix.GenerateLongTermRevocationKey()
    76  	if err != nil {
    77  		t.Fatalf("Failed to generate test revocation key: %s", err.Error())
    78  	}
    79  	privKey, _, err := EncodeKeys(key, &key.PublicKey)
    80  	if err != nil {
    81  		t.Fatalf("Failed to encode test revocation key: %s", err.Error())
    82  	}
    83  	err = util.WriteFile(privkeyfile.Name(), privKey, 0666)
    84  	if err != nil {
    85  		t.Fatalf("Failed to write test revocation private key: %s", err.Error())
    86  	}
    87  
    88  	_, err = pubkeyfile.WriteString("foo")
    89  	if err != nil {
    90  		t.Fatalf("Failed to write to the file %s", pubkeyfile.Name())
    91  	}
    92  	idemixLib := new(mocks.Lib)
    93  	rk := NewRevocationKey(pubkeyfile.Name(), privkeyfile.Name(), idemixLib)
    94  	err = rk.Load()
    95  	assert.Error(t, err, "Should have failed to load non existing revocation public key")
    96  	if err != nil {
    97  		assert.Contains(t, err.Error(), "Failed to decode ECDSA public key")
    98  	}
    99  }
   100  
   101  func TestLoadNonExistentRevocationPrivateKey(t *testing.T) {
   102  	testdir, err := ioutil.TempDir(".", "rkloadtest")
   103  	defer os.RemoveAll(testdir)
   104  	idemixLib := new(mocks.Lib)
   105  	rk := NewRevocationKey(testRevocationPublicKeyFile, filepath.Join(testdir, "IdemixRevocationPrivateKey"), idemixLib)
   106  	err = rk.Load()
   107  	assert.Error(t, err, "Should have failed to load non existing issuer revocation private key")
   108  	if err != nil {
   109  		assert.Contains(t, err.Error(), "Failed to read revocation private key")
   110  	}
   111  }
   112  
   113  func TestLoadEmptyRevocationPrivateKey(t *testing.T) {
   114  	testdir, err := ioutil.TempDir(".", "rkloadtest")
   115  	privkeyfile, err := ioutil.TempFile(testdir, "")
   116  	defer os.RemoveAll(testdir)
   117  	idemixLib := new(mocks.Lib)
   118  	rk := NewRevocationKey(testRevocationPublicKeyFile, privkeyfile.Name(), idemixLib)
   119  	err = rk.Load()
   120  	assert.Error(t, err, "Should have failed to load empty issuer revocation private key")
   121  	if err != nil {
   122  		assert.Contains(t, err.Error(), "Revocation private key file is empty")
   123  	}
   124  }
   125  
   126  func TestRevocationKeyLoad(t *testing.T) {
   127  	idemixLib := new(mocks.Lib)
   128  	rk := NewRevocationKey(testRevocationPublicKeyFile, testRevocationPrivateKeyFile, idemixLib)
   129  	err := rk.Load()
   130  	assert.NoError(t, err, "Failed to load Idemix issuer revocation key")
   131  
   132  	err = rk.Store()
   133  	assert.NoError(t, err, "Failed to store Idemix issuer revocation key")
   134  }
   135  
   136  func TestStoreNilRevocationKey(t *testing.T) {
   137  	idemixLib := new(mocks.Lib)
   138  	rk := NewRevocationKey(testRevocationPublicKeyFile, testRevocationPrivateKeyFile, idemixLib)
   139  	err := rk.Store()
   140  	assert.Error(t, err, "Should fail if store is called without setting or loading the revocation key from disk")
   141  	if err != nil {
   142  		assert.Equal(t, err.Error(), "Revocation key is not set")
   143  	}
   144  }
   145  
   146  func TestStoreNilRevocationPublicKey(t *testing.T) {
   147  	idemixLib := new(mocks.Lib)
   148  	rk := NewRevocationKey(testRevocationPublicKeyFile, testRevocationPrivateKeyFile, idemixLib)
   149  	key, err := idemix.GenerateLongTermRevocationKey()
   150  	if err != nil {
   151  		t.Fatalf("Failed to create test revocation key: %s", err.Error())
   152  	}
   153  	key.PublicKey = ecdsa.PublicKey{}
   154  	rk.SetKey(key)
   155  	err = rk.Store()
   156  	assert.Error(t, err, "Should fail if store is called with empty revocation public key")
   157  	if err != nil {
   158  		assert.Contains(t, err.Error(), "Failed to encode revocation public key")
   159  	}
   160  }
   161  
   162  func TestEncodeKeys(t *testing.T) {
   163  	privateKey, err := idemix.GenerateLongTermRevocationKey()
   164  	if err != nil {
   165  		t.Fatalf("Failed to generate ECDSA key for revocation authority")
   166  	}
   167  	pkstr, pubkeystr, err := EncodeKeys(privateKey, &privateKey.PublicKey)
   168  	assert.NoError(t, err)
   169  
   170  	_, _, err = DecodeKeys([]byte(""), pubkeystr)
   171  	assert.Error(t, err)
   172  	assert.Equal(t, "Failed to decode ECDSA private key", err.Error())
   173  
   174  	_, _, err = DecodeKeys(pubkeystr, pkstr)
   175  	assert.Error(t, err, "DecodeKeys should fail as encoded public key string is passed as private key")
   176  
   177  	_, _, err = DecodeKeys(pkstr, []byte(""))
   178  	assert.Error(t, err, "DecodeKeys should fail as empty string is passed for encoded public key string")
   179  	assert.Contains(t, err.Error(), "Failed to decode ECDSA public key")
   180  
   181  	_, _, err = DecodeKeys(pkstr, pkstr)
   182  	assert.Error(t, err, "DecodeKeys should fail as encoded private key string is passed as public key")
   183  	assert.Contains(t, err.Error(), "Failed to parse ECDSA public key bytes")
   184  
   185  	privateKey1, pubKey, err := DecodeKeys(pkstr, pubkeystr)
   186  	assert.NoError(t, err)
   187  	assert.NotNil(t, privateKey1)
   188  	assert.NotNil(t, pubKey)
   189  }
   190  
   191  func TestStoreReadonlyRevocationPublicKeyFilepath(t *testing.T) {
   192  	testdir, err := ioutil.TempDir(".", "rkloadTest")
   193  	if err != nil {
   194  		t.Fatalf("Failed to create temp directory: %s", err.Error())
   195  	}
   196  	defer os.RemoveAll(testdir)
   197  
   198  	privkeyfile, err := ioutil.TempFile(testdir, DefaultRevocationPrivateKeyFile)
   199  	if err != nil {
   200  		t.Fatalf("Failed to create temp file: %s", err.Error())
   201  	}
   202  	key, err := idemix.GenerateLongTermRevocationKey()
   203  	if err != nil {
   204  		t.Fatalf("Failed to generate test revocation key: %s", err.Error())
   205  	}
   206  	privKey, _, err := EncodeKeys(key, &key.PublicKey)
   207  	if err != nil {
   208  		t.Fatalf("Failed to encode test revocation key: %s", err.Error())
   209  	}
   210  	err = util.WriteFile(privkeyfile.Name(), privKey, 0666)
   211  	if err != nil {
   212  		t.Fatalf("Failed to write test revocation private key: %s", err.Error())
   213  	}
   214  
   215  	pubkeyfile := path.Join(testdir, "testdata1/RevocationPublicKey")
   216  	err = os.MkdirAll(path.Dir(pubkeyfile), 4444)
   217  	if err != nil {
   218  		t.Fatalf("Failed to create read only directory: %s", err.Error())
   219  	}
   220  	idemixLib := new(mocks.Lib)
   221  	rk := NewRevocationKey(pubkeyfile, privkeyfile.Name(), idemixLib)
   222  	rk.SetKey(key)
   223  	err = rk.Store()
   224  	assert.Error(t, err, "Should fail if issuer public key is being stored to read-only directory")
   225  	if err != nil {
   226  		assert.Contains(t, err.Error(), "Failed to store revocation public key")
   227  	}
   228  }