github.com/avahowell/sia@v0.5.1-beta.0.20160524050156-83dcc3d37c94/crypto/signatures_test.go (about) 1 package crypto 2 3 import ( 4 "bytes" 5 "crypto/rand" 6 "errors" 7 "testing" 8 9 "github.com/NebulousLabs/Sia/encoding" 10 "github.com/NebulousLabs/ed25519" 11 ) 12 13 // mockKeyDeriver is a mock implementation of keyDeriver that saves its provided 14 // entropy and allows the client to specify the returned SecretKey and 15 // PublicKey. 16 type mockKeyDeriver struct { 17 called bool 18 entropy [EntropySize]byte 19 sk ed25519.SecretKey 20 pk ed25519.PublicKey 21 } 22 23 // deriveKeyPair is a mocked key deriver operating on the mockKeyDeriver 24 // struct. 25 func (kd *mockKeyDeriver) deriveKeyPair(entropy [EntropySize]byte) (ed25519.SecretKey, ed25519.PublicKey) { 26 kd.called = true 27 kd.entropy = entropy 28 return kd.sk, kd.pk 29 } 30 31 // TestUnitGenerateRandomKeyPair checks that the Generate method is properly 32 // calling its dependencies and returning the expected key pair. 33 func TestUnitGenerateRandomKeyPair(t *testing.T) { 34 var mockEntropy [EntropySize]byte 35 mockEntropy[0] = 5 36 mockEntropy[EntropySize-1] = 5 37 entropyReader := bytes.NewReader(mockEntropy[:]) 38 39 sk := ed25519.SecretKey(&[SecretKeySize]byte{}) 40 sk[0] = 7 41 sk[32] = 8 42 pk := ed25519.PublicKey(&[PublicKeySize]byte{}) 43 pk[0] = sk[32] 44 kd := mockKeyDeriver{sk: sk, pk: pk} 45 46 // Create a SignatureKeyGenerator using mocks. 47 g := sigKeyGen{entropyReader, &kd} 48 49 // Create key pair. 50 skActual, pkActual, err := g.generate() 51 52 // Verify that we got back the expected results. 53 if err != nil { 54 t.Error(err) 55 } 56 if *sk != skActual { 57 t.Errorf("Generated secret key does not match expected! expected = %v, actual = %v", sk, skActual) 58 } 59 if *pk != pkActual { 60 t.Errorf("Generated public key does not match expected! expected = %v, actual = %v", pk, pkActual) 61 } 62 63 // Verify the dependencies were called correctly 64 if !kd.called { 65 t.Error("keyDeriver was never called.") 66 } 67 if mockEntropy != kd.entropy { 68 t.Errorf("keyDeriver was called with the wrong entropy. expected = %v, actual = %v", mockEntropy, kd.entropy) 69 } 70 } 71 72 // failingReader is a mock implementation of io.Reader that fails with a client- 73 // defined error. 74 type failingReader struct { 75 err error 76 } 77 78 // Read satisfies the entropySource of the stdKeyGen, but always fails, 79 // resulting in errors that must be handled by the generate function. 80 func (fr failingReader) Read([]byte) (int, error) { 81 return 0, fr.err 82 } 83 84 // TestUnitGenerateRandomKeyBadRand checks that the Generate method fails if 85 // the call to entropy source fails 86 func TestUnitGenerateRandomKeyBadRand(t *testing.T) { 87 fr := failingReader{err: errors.New("mock error from entropy reader")} 88 g := sigKeyGen{entropySource: &fr} 89 if _, _, err := g.generate(); err == nil { 90 t.Error("Generate should fail when entropy source fails.") 91 } 92 } 93 94 // TestUnitGenerateDeterministicKeyPari checks that the GenerateDeterministic 95 // method is properly calling its dependencies and returning the expected key 96 // pair. 97 func TestUnitGenerateDeterministicKeyPair(t *testing.T) { 98 // Create entropy bytes, setting a few bytes explicitly instead of using a 99 // buffer of random bytes. 100 var mockEntropy [EntropySize]byte 101 mockEntropy[0] = 4 102 mockEntropy[EntropySize-1] = 5 103 104 sk := ed25519.SecretKey(&[SecretKeySize]byte{}) 105 sk[0] = 7 106 sk[32] = 8 107 pk := ed25519.PublicKey(&[PublicKeySize]byte{}) 108 pk[0] = sk[32] 109 kd := mockKeyDeriver{sk: sk, pk: pk} 110 g := sigKeyGen{keyDeriver: &kd} 111 112 // Create key pair. 113 skActual, pkActual := g.generateDeterministic(mockEntropy) 114 115 // Verify that we got back the right results. 116 if *sk != skActual { 117 t.Errorf("Generated secret key does not match expected! expected = %v, actual = %v", sk, skActual) 118 } 119 if *pk != pkActual { 120 t.Errorf("Generated public key does not match expected! expected = %v, actual = %v", pk, pkActual) 121 } 122 123 // Verify the dependencies were called correctly. 124 if !kd.called { 125 t.Error("keyDeriver was never called.") 126 } 127 if mockEntropy != kd.entropy { 128 t.Errorf("keyDeriver was called with the wrong entropy. expected = %v, actual = %v", mockEntropy, kd.entropy) 129 } 130 } 131 132 // TestUnitSignatureEncoding creates and encodes a public key, and verifies 133 // that it decodes correctly, does the same with a signature. 134 func TestUnitSignatureEncoding(t *testing.T) { 135 // Create a dummy key pair. 136 var sk SecretKey 137 sk[0] = 4 138 sk[32] = 5 139 pk := sk.PublicKey() 140 141 // Marshal and unmarshal the public key. 142 marshalledPK := encoding.Marshal(pk) 143 var unmarshalledPK PublicKey 144 err := encoding.Unmarshal(marshalledPK, &unmarshalledPK) 145 if err != nil { 146 t.Fatal(err) 147 } 148 149 // Test the public keys for equality. 150 if pk != unmarshalledPK { 151 t.Error("pubkey not the same after marshalling and unmarshalling") 152 } 153 154 // Create a signature using the secret key. 155 var signedData Hash 156 rand.Read(signedData[:]) 157 sig, err := SignHash(signedData, sk) 158 if err != nil { 159 t.Fatal(err) 160 } 161 162 // Marshal and unmarshal the signature. 163 marshalledSig := encoding.Marshal(sig) 164 var unmarshalledSig Signature 165 err = encoding.Unmarshal(marshalledSig, &unmarshalledSig) 166 if err != nil { 167 t.Fatal(err) 168 } 169 170 // Test signatures for equality. 171 if sig != unmarshalledSig { 172 t.Error("signature not same after marshalling and unmarshalling") 173 } 174 175 } 176 177 // TestUnitSigning creates a bunch of keypairs and signs random data with each of 178 // them. 179 func TestUnitSigning(t *testing.T) { 180 if testing.Short() { 181 t.SkipNow() 182 } 183 184 // Try a bunch of signatures because at one point there was a library that 185 // worked around 98% of the time. Tests would usually pass, but 200 186 // iterations would normally cause a failure. 187 iterations := 200 188 for i := 0; i < iterations; i++ { 189 // Create dummy key pair. 190 sk, pk, err := GenerateKeyPair() 191 if err != nil { 192 t.Fatal(err) 193 } 194 195 // Generate and sign the data. 196 var randData Hash 197 rand.Read(randData[:]) 198 sig, err := SignHash(randData, sk) 199 if err != nil { 200 t.Fatal(err) 201 } 202 203 // Verify the signature. 204 err = VerifyHash(randData, pk, sig) 205 if err != nil { 206 t.Fatal(err) 207 } 208 209 // Attempt to verify after the data has been altered. 210 randData[0] += 1 211 err = VerifyHash(randData, pk, sig) 212 if err != ErrInvalidSignature { 213 t.Fatal(err) 214 } 215 216 // Restore the data and make sure the signature is valid again. 217 randData[0] -= 1 218 err = VerifyHash(randData, pk, sig) 219 if err != nil { 220 t.Fatal(err) 221 } 222 223 // Attempt to verify after the signature has been altered. 224 sig[0] += 1 225 err = VerifyHash(randData, pk, sig) 226 if err != ErrInvalidSignature { 227 t.Fatal(err) 228 } 229 } 230 } 231 232 // TestIntegrationSigKeyGenerate is an integration test checking that 233 // GenerateKeyPair and GenerateKeyPairDeterminisitc accurately create keys. 234 func TestIntegrationSigKeyGeneration(t *testing.T) { 235 if testing.Short() { 236 t.SkipNow() 237 } 238 message := HashBytes([]byte{'m', 's', 'g'}) 239 240 // Create a random key and use it. 241 randSecKey, randPubKey, err := GenerateKeyPair() 242 if err != nil { 243 t.Fatal(err) 244 } 245 sig, err := SignHash(message, randSecKey) 246 if err != nil { 247 t.Fatal(err) 248 } 249 err = VerifyHash(message, randPubKey, sig) 250 if err != nil { 251 t.Error(err) 252 } 253 // Corrupt the signature 254 sig[0]++ 255 err = VerifyHash(message, randPubKey, sig) 256 if err == nil { 257 t.Error("corruption failed") 258 } 259 260 // Create a deterministic key and use it. 261 var detEntropy [EntropySize]byte 262 detEntropy[0] = 35 263 detSecKey, detPubKey := GenerateKeyPairDeterministic(detEntropy) 264 sig, err = SignHash(message, detSecKey) 265 if err != nil { 266 t.Fatal(err) 267 } 268 err = VerifyHash(message, detPubKey, sig) 269 if err != nil { 270 t.Error(err) 271 } 272 // Corrupt the signature 273 sig[0]++ 274 err = VerifyHash(message, detPubKey, sig) 275 if err == nil { 276 t.Error("corruption failed") 277 } 278 } 279 280 // TestReadWriteSignedObject tests the ReadSignObject and WriteSignedObject 281 // functions, which are inverses of each other. 282 func TestReadWriteSignedObject(t *testing.T) { 283 sk, pk, err := GenerateKeyPair() 284 if err != nil { 285 t.Fatal(err) 286 } 287 288 // Write signed object into buffer. 289 b := new(bytes.Buffer) 290 err = WriteSignedObject(b, "foo", sk) 291 if err != nil { 292 t.Fatal(err) 293 } 294 // Keep a copy of b's bytes. 295 buf := b.Bytes() 296 297 // Read and verify object. 298 var read string 299 err = ReadSignedObject(b, &read, 11, pk) 300 if err != nil { 301 t.Fatal(err) 302 } 303 if read != "foo" { 304 t.Fatal("encode/decode mismatch: expected 'foo', got", []byte(read)) 305 } 306 307 // Check that maxlen is being respected. 308 b = bytes.NewBuffer(buf) // reset b 309 err = ReadSignedObject(b, &read, 10, pk) 310 if err == nil || err.Error() != "length 11 exceeds maxLen of 10" { 311 t.Fatal("expected length error, got", err) 312 } 313 314 // Disrupt the decoding to get coverage on the failure branch. 315 err = ReadSignedObject(b, &read, 11, pk) 316 if err == nil || err.Error() != "could not decode type crypto.Signature: unexpected EOF" { 317 t.Fatal(err) 318 } 319 320 // Try with an invalid signature. 321 buf[0]++ // alter the first byte of the signature, invalidating it. 322 b = bytes.NewBuffer(buf) // reset b 323 err = ReadSignedObject(b, &read, 11, pk) 324 if err != ErrInvalidSignature { 325 t.Fatal(err) 326 } 327 } 328 329 // TestUnitPublicKey tests the PublicKey method 330 func TestUnitPublicKey(t *testing.T) { 331 for i := 0; i < 1000; i++ { 332 sk, pk, err := GenerateKeyPair() 333 if err != nil { 334 t.Fatal(err) 335 } 336 if sk.PublicKey() != pk { 337 t.Error("PublicKey does not match actual public key:", pk, sk.PublicKey()) 338 } 339 } 340 }