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 }