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 }