github.com/myafeier/fabric@v1.0.1-0.20170722181825-3a4b1f2bce86/gossip/identity/identity_test.go (about)

     1  /*
     2  Copyright IBM Corp. All Rights Reserved.
     3  
     4  SPDX-License-Identifier: Apache-2.0
     5  */
     6  
     7  package identity
     8  
     9  import (
    10  	"bytes"
    11  	"errors"
    12  	"fmt"
    13  	"testing"
    14  
    15  	"time"
    16  
    17  	"github.com/hyperledger/fabric/gossip/api"
    18  	"github.com/hyperledger/fabric/gossip/common"
    19  	"github.com/hyperledger/fabric/gossip/util"
    20  	"github.com/stretchr/testify/assert"
    21  )
    22  
    23  var (
    24  	msgCryptoService = &naiveCryptoService{revokedIdentities: map[string]struct{}{}}
    25  	dummyID          = api.PeerIdentityType{}
    26  )
    27  
    28  type naiveCryptoService struct {
    29  	revokedIdentities map[string]struct{}
    30  }
    31  
    32  func init() {
    33  	util.SetupTestLogging()
    34  }
    35  
    36  func (cs *naiveCryptoService) ValidateIdentity(peerIdentity api.PeerIdentityType) error {
    37  	if _, isRevoked := cs.revokedIdentities[string(cs.GetPKIidOfCert(peerIdentity))]; isRevoked {
    38  		return errors.New("revoked")
    39  	}
    40  	return nil
    41  }
    42  
    43  // GetPKIidOfCert returns the PKI-ID of a peer's identity
    44  func (*naiveCryptoService) GetPKIidOfCert(peerIdentity api.PeerIdentityType) common.PKIidType {
    45  	return common.PKIidType(peerIdentity)
    46  }
    47  
    48  // VerifyBlock returns nil if the block is properly signed,
    49  // else returns error
    50  func (*naiveCryptoService) VerifyBlock(chainID common.ChainID, seqNum uint64, signedBlock []byte) error {
    51  	return nil
    52  }
    53  
    54  // VerifyByChannel verifies a peer's signature on a message in the context
    55  // of a specific channel
    56  func (*naiveCryptoService) VerifyByChannel(_ common.ChainID, _ api.PeerIdentityType, _, _ []byte) error {
    57  	return nil
    58  }
    59  
    60  // Sign signs msg with this peer's signing key and outputs
    61  // the signature if no error occurred.
    62  func (*naiveCryptoService) Sign(msg []byte) ([]byte, error) {
    63  	return msg, nil
    64  }
    65  
    66  // Verify checks that signature is a valid signature of message under a peer's verification key.
    67  // If the verification succeeded, Verify returns nil meaning no error occurred.
    68  // If peerCert is nil, then the signature is verified against this peer's verification key.
    69  func (*naiveCryptoService) Verify(peerIdentity api.PeerIdentityType, signature, message []byte) error {
    70  	equal := bytes.Equal(signature, message)
    71  	if !equal {
    72  		return fmt.Errorf("Wrong certificate")
    73  	}
    74  	return nil
    75  }
    76  
    77  func TestPut(t *testing.T) {
    78  	idStore := NewIdentityMapper(msgCryptoService, dummyID)
    79  	identity := []byte("yacovm")
    80  	identity2 := []byte("not-yacovm")
    81  	pkiID := msgCryptoService.GetPKIidOfCert(api.PeerIdentityType(identity))
    82  	pkiID2 := msgCryptoService.GetPKIidOfCert(api.PeerIdentityType(identity2))
    83  	assert.NoError(t, idStore.Put(pkiID, identity))
    84  	assert.Error(t, idStore.Put(nil, identity))
    85  	assert.Error(t, idStore.Put(pkiID2, nil))
    86  	assert.Error(t, idStore.Put(pkiID2, identity))
    87  	assert.Error(t, idStore.Put(pkiID, identity2))
    88  }
    89  
    90  func TestGet(t *testing.T) {
    91  	idStore := NewIdentityMapper(msgCryptoService, dummyID)
    92  	identity := []byte("yacovm")
    93  	identity2 := []byte("not-yacovm")
    94  	pkiID := msgCryptoService.GetPKIidOfCert(api.PeerIdentityType(identity))
    95  	pkiID2 := msgCryptoService.GetPKIidOfCert(api.PeerIdentityType(identity2))
    96  	assert.NoError(t, idStore.Put(pkiID, identity))
    97  	cert, err := idStore.Get(pkiID)
    98  	assert.NoError(t, err)
    99  	assert.Equal(t, api.PeerIdentityType(identity), cert)
   100  	cert, err = idStore.Get(pkiID2)
   101  	assert.Nil(t, cert)
   102  	assert.Error(t, err)
   103  }
   104  
   105  func TestVerify(t *testing.T) {
   106  	idStore := NewIdentityMapper(msgCryptoService, dummyID)
   107  	identity := []byte("yacovm")
   108  	identity2 := []byte("not-yacovm")
   109  	pkiID := msgCryptoService.GetPKIidOfCert(api.PeerIdentityType(identity))
   110  	pkiID2 := msgCryptoService.GetPKIidOfCert(api.PeerIdentityType(identity2))
   111  	idStore.Put(pkiID, api.PeerIdentityType(identity))
   112  	signed, err := idStore.Sign([]byte("bla bla"))
   113  	assert.NoError(t, err)
   114  	assert.NoError(t, idStore.Verify(pkiID, signed, []byte("bla bla")))
   115  	assert.Error(t, idStore.Verify(pkiID2, signed, []byte("bla bla")))
   116  }
   117  
   118  func TestListInvalidIdentities(t *testing.T) {
   119  	idStore := NewIdentityMapper(msgCryptoService, dummyID)
   120  	identity := []byte("yacovm")
   121  	// Test for a revoked identity
   122  	pkiID := msgCryptoService.GetPKIidOfCert(api.PeerIdentityType(identity))
   123  	assert.NoError(t, idStore.Put(pkiID, api.PeerIdentityType(identity)))
   124  	cert, err := idStore.Get(pkiID)
   125  	assert.NoError(t, err)
   126  	assert.NotNil(t, cert)
   127  	// Revoke the certificate
   128  	msgCryptoService.revokedIdentities[string(pkiID)] = struct{}{}
   129  	idStore.ListInvalidIdentities(func(_ api.PeerIdentityType) bool {
   130  		return true
   131  	})
   132  	// Make sure it is not found anymore
   133  	cert, err = idStore.Get(pkiID)
   134  	assert.Error(t, err)
   135  	assert.Nil(t, cert)
   136  
   137  	// Clean the MCS revocation mock
   138  	msgCryptoService.revokedIdentities = map[string]struct{}{}
   139  	// Now, test for a certificate that has not been used
   140  	// for a long time
   141  
   142  	// Add back the identity
   143  	pkiID = msgCryptoService.GetPKIidOfCert(api.PeerIdentityType(identity))
   144  	assert.NoError(t, idStore.Put(pkiID, api.PeerIdentityType(identity)))
   145  	// set the time-based expiration time limit to something small
   146  	usageThreshold = time.Millisecond * 500
   147  	idStore.ListInvalidIdentities(func(_ api.PeerIdentityType) bool {
   148  		return false
   149  	})
   150  	// Check it exists in the meantime
   151  	cert, err = idStore.Get(pkiID)
   152  	assert.NoError(t, err)
   153  	assert.NotNil(t, cert)
   154  	time.Sleep(time.Second * 3)
   155  	idStore.ListInvalidIdentities(func(_ api.PeerIdentityType) bool {
   156  		return false
   157  	})
   158  	// Make sure it has expired
   159  	cert, err = idStore.Get(pkiID)
   160  	assert.Error(t, err)
   161  	assert.Nil(t, cert)
   162  
   163  	// Now test that an identity that is frequently used doesn't expire
   164  	// Add back the identity
   165  	pkiID = msgCryptoService.GetPKIidOfCert(api.PeerIdentityType(identity))
   166  	assert.NoError(t, idStore.Put(pkiID, api.PeerIdentityType(identity)))
   167  	stopChan := make(chan struct{})
   168  	go func() {
   169  		for {
   170  			select {
   171  			case <-stopChan:
   172  				return
   173  			case <-time.After(time.Millisecond * 10):
   174  				idStore.Get(pkiID)
   175  			}
   176  		}
   177  	}()
   178  	time.Sleep(time.Second * 3)
   179  	// Ensure it hasn't expired even though time has passed
   180  	cert, err = idStore.Get(pkiID)
   181  	assert.NoError(t, err)
   182  	assert.NotNil(t, cert)
   183  	stopChan <- struct{}{}
   184  }