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 }