github.com/tenywen/fabric@v1.0.0-beta.0.20170620030522-a5b1ed380643/gossip/identity/identity_test.go (about)

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