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