github.com/arieschain/arieschain@v0.0.0-20191023063405-37c074544356/crypto/ecies/ecies_test.go (about) 1 // Copyright (c) 2013 Kyle Isom <kyle@tyrfingr.is> 2 // Copyright (c) 2012 The Go Authors. All rights reserved. 3 // Redistribution and use in source and binary forms, with or without 4 // modification, are permitted provided that the following conditions are 5 // met: 6 // 7 // * Redistributions of source code must retain the above copyright 8 // notice, this list of conditions and the following disclaimer. 9 // * Redistributions in binary form must reproduce the above 10 // copyright notice, this list of conditions and the following disclaimer 11 // in the documentation and/or other materials provided with the 12 // distribution. 13 // * Neither the name of Google Inc. nor the names of its 14 // contributors may be used to endorse or promote products derived from 15 // this software without specific prior written permission. 16 // 17 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 18 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 19 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 20 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 21 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 22 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 23 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 24 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 25 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 27 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 29 package ecies 30 31 import ( 32 "bytes" 33 "crypto/elliptic" 34 "crypto/rand" 35 "crypto/sha256" 36 "encoding/hex" 37 "flag" 38 "fmt" 39 "math/big" 40 "testing" 41 42 "github.com/quickchainproject/quickchain/crypto" 43 ) 44 45 var dumpEnc bool 46 47 func init() { 48 flDump := flag.Bool("dump", false, "write encrypted test message to file") 49 flag.Parse() 50 dumpEnc = *flDump 51 } 52 53 // Ensure the KDF generates appropriately sized keys. 54 func TestKDF(t *testing.T) { 55 msg := []byte("Hello, world") 56 h := sha256.New() 57 58 k, err := concatKDF(h, msg, nil, 64) 59 if err != nil { 60 fmt.Println(err.Error()) 61 t.FailNow() 62 } 63 if len(k) != 64 { 64 fmt.Printf("KDF: generated key is the wrong size (%d instead of 64\n", len(k)) 65 t.FailNow() 66 } 67 } 68 69 var ErrBadSharedKeys = fmt.Errorf("ecies: shared keys don't match") 70 71 // cmpParams compares a set of ECIES parameters. We assume, as per the 72 // docs, that AES is the only supported symmetric encryption algorithm. 73 func cmpParams(p1, p2 *ECIESParams) bool { 74 return p1.hashAlgo == p2.hashAlgo && 75 p1.KeyLen == p2.KeyLen && 76 p1.BlockSize == p2.BlockSize 77 } 78 79 // cmpPublic returns true if the two public keys represent the same pojnt. 80 func cmpPublic(pub1, pub2 PublicKey) bool { 81 if pub1.X == nil || pub1.Y == nil { 82 fmt.Println(ErrInvalidPublicKey.Error()) 83 return false 84 } 85 if pub2.X == nil || pub2.Y == nil { 86 fmt.Println(ErrInvalidPublicKey.Error()) 87 return false 88 } 89 pub1Out := elliptic.Marshal(pub1.Curve, pub1.X, pub1.Y) 90 pub2Out := elliptic.Marshal(pub2.Curve, pub2.X, pub2.Y) 91 92 return bytes.Equal(pub1Out, pub2Out) 93 } 94 95 // cmpPrivate returns true if the two private keys are the same. 96 func cmpPrivate(prv1, prv2 *PrivateKey) bool { 97 if prv1 == nil || prv1.D == nil { 98 return false 99 } else if prv2 == nil || prv2.D == nil { 100 return false 101 } else if prv1.D.Cmp(prv2.D) != 0 { 102 return false 103 } else { 104 return cmpPublic(prv1.PublicKey, prv2.PublicKey) 105 } 106 } 107 108 // Validate the ECDH component. 109 func TestSharedKey(t *testing.T) { 110 prv1, err := GenerateKey(rand.Reader, DefaultCurve, nil) 111 if err != nil { 112 fmt.Println(err.Error()) 113 t.FailNow() 114 } 115 skLen := MaxSharedKeyLength(&prv1.PublicKey) / 2 116 117 prv2, err := GenerateKey(rand.Reader, DefaultCurve, nil) 118 if err != nil { 119 fmt.Println(err.Error()) 120 t.FailNow() 121 } 122 123 sk1, err := prv1.GenerateShared(&prv2.PublicKey, skLen, skLen) 124 if err != nil { 125 fmt.Println(err.Error()) 126 t.FailNow() 127 } 128 129 sk2, err := prv2.GenerateShared(&prv1.PublicKey, skLen, skLen) 130 if err != nil { 131 fmt.Println(err.Error()) 132 t.FailNow() 133 } 134 135 if !bytes.Equal(sk1, sk2) { 136 fmt.Println(ErrBadSharedKeys.Error()) 137 t.FailNow() 138 } 139 } 140 141 func TestSharedKeyPadding(t *testing.T) { 142 // sanity checks 143 prv0 := hexKey("1adf5c18167d96a1f9a0b1ef63be8aa27eaf6032c233b2b38f7850cf5b859fd9") 144 prv1 := hexKey("0097a076fc7fcd9208240668e31c9abee952cbb6e375d1b8febc7499d6e16f1a") 145 x0, _ := new(big.Int).SetString("1a8ed022ff7aec59dc1b440446bdda5ff6bcb3509a8b109077282b361efffbd8", 16) 146 x1, _ := new(big.Int).SetString("6ab3ac374251f638d0abb3ef596d1dc67955b507c104e5f2009724812dc027b8", 16) 147 y0, _ := new(big.Int).SetString("e040bd480b1deccc3bc40bd5b1fdcb7bfd352500b477cb9471366dbd4493f923", 16) 148 y1, _ := new(big.Int).SetString("8ad915f2b503a8be6facab6588731fefeb584fd2dfa9a77a5e0bba1ec439e4fa", 16) 149 150 if prv0.PublicKey.X.Cmp(x0) != 0 { 151 t.Errorf("mismatched prv0.X:\nhave: %x\nwant: %x\n", prv0.PublicKey.X.Bytes(), x0.Bytes()) 152 } 153 if prv0.PublicKey.Y.Cmp(y0) != 0 { 154 t.Errorf("mismatched prv0.Y:\nhave: %x\nwant: %x\n", prv0.PublicKey.Y.Bytes(), y0.Bytes()) 155 } 156 if prv1.PublicKey.X.Cmp(x1) != 0 { 157 t.Errorf("mismatched prv1.X:\nhave: %x\nwant: %x\n", prv1.PublicKey.X.Bytes(), x1.Bytes()) 158 } 159 if prv1.PublicKey.Y.Cmp(y1) != 0 { 160 t.Errorf("mismatched prv1.Y:\nhave: %x\nwant: %x\n", prv1.PublicKey.Y.Bytes(), y1.Bytes()) 161 } 162 163 // test shared secret generation 164 sk1, err := prv0.GenerateShared(&prv1.PublicKey, 16, 16) 165 if err != nil { 166 fmt.Println(err.Error()) 167 } 168 169 sk2, err := prv1.GenerateShared(&prv0.PublicKey, 16, 16) 170 if err != nil { 171 t.Fatal(err.Error()) 172 } 173 174 if !bytes.Equal(sk1, sk2) { 175 t.Fatal(ErrBadSharedKeys.Error()) 176 } 177 } 178 179 // Verify that the key generation code fails when too much key data is 180 // requested. 181 func TestTooBigSharedKey(t *testing.T) { 182 prv1, err := GenerateKey(rand.Reader, DefaultCurve, nil) 183 if err != nil { 184 fmt.Println(err.Error()) 185 t.FailNow() 186 } 187 188 prv2, err := GenerateKey(rand.Reader, DefaultCurve, nil) 189 if err != nil { 190 fmt.Println(err.Error()) 191 t.FailNow() 192 } 193 194 _, err = prv1.GenerateShared(&prv2.PublicKey, 32, 32) 195 if err != ErrSharedKeyTooBig { 196 fmt.Println("ecdh: shared key should be too large for curve") 197 t.FailNow() 198 } 199 200 _, err = prv2.GenerateShared(&prv1.PublicKey, 32, 32) 201 if err != ErrSharedKeyTooBig { 202 fmt.Println("ecdh: shared key should be too large for curve") 203 t.FailNow() 204 } 205 } 206 207 // Benchmark the generation of P256 keys. 208 func BenchmarkGenerateKeyP256(b *testing.B) { 209 for i := 0; i < b.N; i++ { 210 if _, err := GenerateKey(rand.Reader, elliptic.P256(), nil); err != nil { 211 fmt.Println(err.Error()) 212 b.FailNow() 213 } 214 } 215 } 216 217 // Benchmark the generation of P256 shared keys. 218 func BenchmarkGenSharedKeyP256(b *testing.B) { 219 prv, err := GenerateKey(rand.Reader, elliptic.P256(), nil) 220 if err != nil { 221 fmt.Println(err.Error()) 222 b.FailNow() 223 } 224 b.ResetTimer() 225 for i := 0; i < b.N; i++ { 226 _, err := prv.GenerateShared(&prv.PublicKey, 16, 16) 227 if err != nil { 228 fmt.Println(err.Error()) 229 b.FailNow() 230 } 231 } 232 } 233 234 // Benchmark the generation of S256 shared keys. 235 func BenchmarkGenSharedKeyS256(b *testing.B) { 236 prv, err := GenerateKey(rand.Reader, crypto.S256(), nil) 237 if err != nil { 238 fmt.Println(err.Error()) 239 b.FailNow() 240 } 241 b.ResetTimer() 242 for i := 0; i < b.N; i++ { 243 _, err := prv.GenerateShared(&prv.PublicKey, 16, 16) 244 if err != nil { 245 fmt.Println(err.Error()) 246 b.FailNow() 247 } 248 } 249 } 250 251 // Verify that an encrypted message can be successfully decrypted. 252 func TestEncryptDecrypt(t *testing.T) { 253 prv1, err := GenerateKey(rand.Reader, DefaultCurve, nil) 254 if err != nil { 255 fmt.Println(err.Error()) 256 t.FailNow() 257 } 258 259 prv2, err := GenerateKey(rand.Reader, DefaultCurve, nil) 260 if err != nil { 261 fmt.Println(err.Error()) 262 t.FailNow() 263 } 264 265 message := []byte("Hello, world.") 266 ct, err := Encrypt(rand.Reader, &prv2.PublicKey, message, nil, nil) 267 if err != nil { 268 fmt.Println(err.Error()) 269 t.FailNow() 270 } 271 272 pt, err := prv2.Decrypt(ct, nil, nil) 273 if err != nil { 274 fmt.Println(err.Error()) 275 t.FailNow() 276 } 277 278 if !bytes.Equal(pt, message) { 279 fmt.Println("ecies: plaintext doesn't match message") 280 t.FailNow() 281 } 282 283 _, err = prv1.Decrypt(ct, nil, nil) 284 if err == nil { 285 fmt.Println("ecies: encryption should not have succeeded") 286 t.FailNow() 287 } 288 } 289 290 func TestDecryptShared2(t *testing.T) { 291 prv, err := GenerateKey(rand.Reader, DefaultCurve, nil) 292 if err != nil { 293 t.Fatal(err) 294 } 295 message := []byte("Hello, world.") 296 shared2 := []byte("shared data 2") 297 ct, err := Encrypt(rand.Reader, &prv.PublicKey, message, nil, shared2) 298 if err != nil { 299 t.Fatal(err) 300 } 301 302 // Check that decrypting with correct shared data works. 303 pt, err := prv.Decrypt(ct, nil, shared2) 304 if err != nil { 305 t.Fatal(err) 306 } 307 if !bytes.Equal(pt, message) { 308 t.Fatal("ecies: plaintext doesn't match message") 309 } 310 311 // Decrypting without shared data or incorrect shared data fails. 312 if _, err = prv.Decrypt(ct, nil, nil); err == nil { 313 t.Fatal("ecies: decrypting without shared data didn't fail") 314 } 315 if _, err = prv.Decrypt(ct, nil, []byte("garbage")); err == nil { 316 t.Fatal("ecies: decrypting with incorrect shared data didn't fail") 317 } 318 } 319 320 type testCase struct { 321 Curve elliptic.Curve 322 Name string 323 Expected *ECIESParams 324 } 325 326 var testCases = []testCase{ 327 { 328 Curve: elliptic.P256(), 329 Name: "P256", 330 Expected: ECIES_AES128_SHA256, 331 }, 332 { 333 Curve: elliptic.P384(), 334 Name: "P384", 335 Expected: ECIES_AES256_SHA384, 336 }, 337 { 338 Curve: elliptic.P521(), 339 Name: "P521", 340 Expected: ECIES_AES256_SHA512, 341 }, 342 } 343 344 // Test parameter selection for each curve, and that P224 fails automatic 345 // parameter selection (see README for a discussion of P224). Ensures that 346 // selecting a set of parameters automatically for the given curve works. 347 func TestParamSelection(t *testing.T) { 348 for _, c := range testCases { 349 testParamSelection(t, c) 350 } 351 } 352 353 func testParamSelection(t *testing.T, c testCase) { 354 params := ParamsFromCurve(c.Curve) 355 if params == nil && c.Expected != nil { 356 fmt.Printf("%s (%s)\n", ErrInvalidParams.Error(), c.Name) 357 t.FailNow() 358 } else if params != nil && !cmpParams(params, c.Expected) { 359 fmt.Printf("ecies: parameters should be invalid (%s)\n", 360 c.Name) 361 t.FailNow() 362 } 363 364 prv1, err := GenerateKey(rand.Reader, DefaultCurve, nil) 365 if err != nil { 366 fmt.Printf("%s (%s)\n", err.Error(), c.Name) 367 t.FailNow() 368 } 369 370 prv2, err := GenerateKey(rand.Reader, DefaultCurve, nil) 371 if err != nil { 372 fmt.Printf("%s (%s)\n", err.Error(), c.Name) 373 t.FailNow() 374 } 375 376 message := []byte("Hello, world.") 377 ct, err := Encrypt(rand.Reader, &prv2.PublicKey, message, nil, nil) 378 if err != nil { 379 fmt.Printf("%s (%s)\n", err.Error(), c.Name) 380 t.FailNow() 381 } 382 383 pt, err := prv2.Decrypt(ct, nil, nil) 384 if err != nil { 385 fmt.Printf("%s (%s)\n", err.Error(), c.Name) 386 t.FailNow() 387 } 388 389 if !bytes.Equal(pt, message) { 390 fmt.Printf("ecies: plaintext doesn't match message (%s)\n", 391 c.Name) 392 t.FailNow() 393 } 394 395 _, err = prv1.Decrypt(ct, nil, nil) 396 if err == nil { 397 fmt.Printf("ecies: encryption should not have succeeded (%s)\n", 398 c.Name) 399 t.FailNow() 400 } 401 402 } 403 404 // Ensure that the basic public key validation in the decryption operation 405 // works. 406 func TestBasicKeyValidation(t *testing.T) { 407 badBytes := []byte{0, 1, 5, 6, 7, 8, 9} 408 409 prv, err := GenerateKey(rand.Reader, DefaultCurve, nil) 410 if err != nil { 411 fmt.Println(err.Error()) 412 t.FailNow() 413 } 414 415 message := []byte("Hello, world.") 416 ct, err := Encrypt(rand.Reader, &prv.PublicKey, message, nil, nil) 417 if err != nil { 418 fmt.Println(err.Error()) 419 t.FailNow() 420 } 421 422 for _, b := range badBytes { 423 ct[0] = b 424 _, err := prv.Decrypt(ct, nil, nil) 425 if err != ErrInvalidPublicKey { 426 fmt.Println("ecies: validated an invalid key") 427 t.FailNow() 428 } 429 } 430 } 431 432 func TestBox(t *testing.T) { 433 prv1 := hexKey("4b50fa71f5c3eeb8fdc452224b2395af2fcc3d125e06c32c82e048c0559db03f") 434 prv2 := hexKey("d0b043b4c5d657670778242d82d68a29d25d7d711127d17b8e299f156dad361a") 435 pub2 := &prv2.PublicKey 436 437 message := []byte("Hello, world.") 438 ct, err := Encrypt(rand.Reader, pub2, message, nil, nil) 439 if err != nil { 440 t.Fatal(err) 441 } 442 443 pt, err := prv2.Decrypt(ct, nil, nil) 444 if err != nil { 445 t.Fatal(err) 446 } 447 if !bytes.Equal(pt, message) { 448 t.Fatal("ecies: plaintext doesn't match message") 449 } 450 if _, err = prv1.Decrypt(ct, nil, nil); err == nil { 451 t.Fatal("ecies: encryption should not have succeeded") 452 } 453 } 454 455 // Verify GenerateShared against static values - useful when 456 // debugging changes in underlying libs 457 func TestSharedKeyStatic(t *testing.T) { 458 prv1 := hexKey("7ebbc6a8358bc76dd73ebc557056702c8cfc34e5cfcd90eb83af0347575fd2ad") 459 prv2 := hexKey("6a3d6396903245bba5837752b9e0348874e72db0c4e11e9c485a81b4ea4353b9") 460 461 skLen := MaxSharedKeyLength(&prv1.PublicKey) / 2 462 463 sk1, err := prv1.GenerateShared(&prv2.PublicKey, skLen, skLen) 464 if err != nil { 465 fmt.Println(err.Error()) 466 t.FailNow() 467 } 468 469 sk2, err := prv2.GenerateShared(&prv1.PublicKey, skLen, skLen) 470 if err != nil { 471 fmt.Println(err.Error()) 472 t.FailNow() 473 } 474 475 if !bytes.Equal(sk1, sk2) { 476 fmt.Println(ErrBadSharedKeys.Error()) 477 t.FailNow() 478 } 479 480 sk, _ := hex.DecodeString("167ccc13ac5e8a26b131c3446030c60fbfac6aa8e31149d0869f93626a4cdf62") 481 if !bytes.Equal(sk1, sk) { 482 t.Fatalf("shared secret mismatch: want: %x have: %x", sk, sk1) 483 } 484 } 485 486 func hexKey(prv string) *PrivateKey { 487 key, err := crypto.HexToECDSA(prv) 488 if err != nil { 489 panic(err) 490 } 491 return ImportECDSA(key) 492 }