github.com/aigarnetwork/aigar@v0.0.0-20191115204914-d59a6eb70f8e/crypto/ecies/ecies_test.go (about) 1 // Copyright 2018 The go-ethereum Authors 2 // Copyright 2019 The go-aigar Authors 3 // This file is part of the go-aigar library. 4 // 5 // The go-aigar library is free software: you can redistribute it and/or modify 6 // it under the terms of the GNU Lesser General Public License as published by 7 // the Free Software Foundation, either version 3 of the License, or 8 // (at your option) any later version. 9 // 10 // The go-aigar library is distributed in the hope that it will be useful, 11 // but WITHOUT ANY WARRANTY; without even the implied warranty of 12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 // GNU Lesser General Public License for more details. 14 // 15 // You should have received a copy of the GNU Lesser General Public License 16 // along with the go-aigar library. If not, see <http://www.gnu.org/licenses/>. 17 18 package ecies 19 20 import ( 21 "bytes" 22 "crypto/elliptic" 23 "crypto/rand" 24 "crypto/sha256" 25 "encoding/hex" 26 "fmt" 27 "math/big" 28 "testing" 29 30 "github.com/AigarNetwork/aigar/crypto" 31 ) 32 33 // Ensure the KDF generates appropriately sized keys. 34 func TestKDF(t *testing.T) { 35 msg := []byte("Hello, world") 36 h := sha256.New() 37 38 k, err := concatKDF(h, msg, nil, 64) 39 if err != nil { 40 t.Fatal(err) 41 } 42 if len(k) != 64 { 43 t.Fatalf("KDF: generated key is the wrong size (%d instead of 64\n", len(k)) 44 } 45 } 46 47 var ErrBadSharedKeys = fmt.Errorf("ecies: shared keys don't match") 48 49 // cmpParams compares a set of ECIES parameters. We assume, as per the 50 // docs, that AES is the only supported symmetric encryption algorithm. 51 func cmpParams(p1, p2 *ECIESParams) bool { 52 return p1.hashAlgo == p2.hashAlgo && 53 p1.KeyLen == p2.KeyLen && 54 p1.BlockSize == p2.BlockSize 55 } 56 57 // cmpPublic returns true if the two public keys represent the same pojnt. 58 func cmpPublic(pub1, pub2 PublicKey) bool { 59 if pub1.X == nil || pub1.Y == nil { 60 fmt.Println(ErrInvalidPublicKey.Error()) 61 return false 62 } 63 if pub2.X == nil || pub2.Y == nil { 64 fmt.Println(ErrInvalidPublicKey.Error()) 65 return false 66 } 67 pub1Out := elliptic.Marshal(pub1.Curve, pub1.X, pub1.Y) 68 pub2Out := elliptic.Marshal(pub2.Curve, pub2.X, pub2.Y) 69 70 return bytes.Equal(pub1Out, pub2Out) 71 } 72 73 // Validate the ECDH component. 74 func TestSharedKey(t *testing.T) { 75 prv1, err := GenerateKey(rand.Reader, DefaultCurve, nil) 76 if err != nil { 77 t.Fatal(err) 78 } 79 skLen := MaxSharedKeyLength(&prv1.PublicKey) / 2 80 81 prv2, err := GenerateKey(rand.Reader, DefaultCurve, nil) 82 if err != nil { 83 t.Fatal(err) 84 } 85 86 sk1, err := prv1.GenerateShared(&prv2.PublicKey, skLen, skLen) 87 if err != nil { 88 t.Fatal(err) 89 } 90 91 sk2, err := prv2.GenerateShared(&prv1.PublicKey, skLen, skLen) 92 if err != nil { 93 t.Fatal(err) 94 } 95 96 if !bytes.Equal(sk1, sk2) { 97 t.Fatal(ErrBadSharedKeys) 98 } 99 } 100 101 func TestSharedKeyPadding(t *testing.T) { 102 // sanity checks 103 prv0 := hexKey("1adf5c18167d96a1f9a0b1ef63be8aa27eaf6032c233b2b38f7850cf5b859fd9") 104 prv1 := hexKey("0097a076fc7fcd9208240668e31c9abee952cbb6e375d1b8febc7499d6e16f1a") 105 x0, _ := new(big.Int).SetString("1a8ed022ff7aec59dc1b440446bdda5ff6bcb3509a8b109077282b361efffbd8", 16) 106 x1, _ := new(big.Int).SetString("6ab3ac374251f638d0abb3ef596d1dc67955b507c104e5f2009724812dc027b8", 16) 107 y0, _ := new(big.Int).SetString("e040bd480b1deccc3bc40bd5b1fdcb7bfd352500b477cb9471366dbd4493f923", 16) 108 y1, _ := new(big.Int).SetString("8ad915f2b503a8be6facab6588731fefeb584fd2dfa9a77a5e0bba1ec439e4fa", 16) 109 110 if prv0.PublicKey.X.Cmp(x0) != 0 { 111 t.Errorf("mismatched prv0.X:\nhave: %x\nwant: %x\n", prv0.PublicKey.X.Bytes(), x0.Bytes()) 112 } 113 if prv0.PublicKey.Y.Cmp(y0) != 0 { 114 t.Errorf("mismatched prv0.Y:\nhave: %x\nwant: %x\n", prv0.PublicKey.Y.Bytes(), y0.Bytes()) 115 } 116 if prv1.PublicKey.X.Cmp(x1) != 0 { 117 t.Errorf("mismatched prv1.X:\nhave: %x\nwant: %x\n", prv1.PublicKey.X.Bytes(), x1.Bytes()) 118 } 119 if prv1.PublicKey.Y.Cmp(y1) != 0 { 120 t.Errorf("mismatched prv1.Y:\nhave: %x\nwant: %x\n", prv1.PublicKey.Y.Bytes(), y1.Bytes()) 121 } 122 123 // test shared secret generation 124 sk1, err := prv0.GenerateShared(&prv1.PublicKey, 16, 16) 125 if err != nil { 126 t.Log(err.Error()) 127 } 128 129 sk2, err := prv1.GenerateShared(&prv0.PublicKey, 16, 16) 130 if err != nil { 131 t.Fatal(err.Error()) 132 } 133 134 if !bytes.Equal(sk1, sk2) { 135 t.Fatal(ErrBadSharedKeys.Error()) 136 } 137 } 138 139 // Verify that the key generation code fails when too much key data is 140 // requested. 141 func TestTooBigSharedKey(t *testing.T) { 142 prv1, err := GenerateKey(rand.Reader, DefaultCurve, nil) 143 if err != nil { 144 t.Fatal(err) 145 } 146 147 prv2, err := GenerateKey(rand.Reader, DefaultCurve, nil) 148 if err != nil { 149 t.Fatal(err) 150 } 151 152 _, err = prv1.GenerateShared(&prv2.PublicKey, 32, 32) 153 if err != ErrSharedKeyTooBig { 154 t.Fatal("ecdh: shared key should be too large for curve") 155 } 156 157 _, err = prv2.GenerateShared(&prv1.PublicKey, 32, 32) 158 if err != ErrSharedKeyTooBig { 159 t.Fatal("ecdh: shared key should be too large for curve") 160 } 161 } 162 163 // Benchmark the generation of P256 keys. 164 func BenchmarkGenerateKeyP256(b *testing.B) { 165 for i := 0; i < b.N; i++ { 166 if _, err := GenerateKey(rand.Reader, elliptic.P256(), nil); err != nil { 167 b.Fatal(err) 168 } 169 } 170 } 171 172 // Benchmark the generation of P256 shared keys. 173 func BenchmarkGenSharedKeyP256(b *testing.B) { 174 prv, err := GenerateKey(rand.Reader, elliptic.P256(), nil) 175 if err != nil { 176 b.Fatal(err) 177 } 178 b.ResetTimer() 179 for i := 0; i < b.N; i++ { 180 _, err := prv.GenerateShared(&prv.PublicKey, 16, 16) 181 if err != nil { 182 b.Fatal(err) 183 } 184 } 185 } 186 187 // Benchmark the generation of S256 shared keys. 188 func BenchmarkGenSharedKeyS256(b *testing.B) { 189 prv, err := GenerateKey(rand.Reader, crypto.S256(), nil) 190 if err != nil { 191 b.Fatal(err) 192 } 193 b.ResetTimer() 194 for i := 0; i < b.N; i++ { 195 _, err := prv.GenerateShared(&prv.PublicKey, 16, 16) 196 if err != nil { 197 b.Fatal(err) 198 } 199 } 200 } 201 202 // Verify that an encrypted message can be successfully decrypted. 203 func TestEncryptDecrypt(t *testing.T) { 204 prv1, err := GenerateKey(rand.Reader, DefaultCurve, nil) 205 if err != nil { 206 t.Fatal(err) 207 } 208 209 prv2, err := GenerateKey(rand.Reader, DefaultCurve, nil) 210 if err != nil { 211 t.Fatal(err) 212 } 213 214 message := []byte("Hello, world.") 215 ct, err := Encrypt(rand.Reader, &prv2.PublicKey, message, nil, nil) 216 if err != nil { 217 t.Fatal(err) 218 } 219 220 pt, err := prv2.Decrypt(ct, nil, nil) 221 if err != nil { 222 t.Fatal(err) 223 } 224 225 if !bytes.Equal(pt, message) { 226 t.Fatal("ecies: plaintext doesn't match message") 227 } 228 229 _, err = prv1.Decrypt(ct, nil, nil) 230 if err == nil { 231 t.Fatal("ecies: encryption should not have succeeded") 232 } 233 } 234 235 func TestDecryptShared2(t *testing.T) { 236 prv, err := GenerateKey(rand.Reader, DefaultCurve, nil) 237 if err != nil { 238 t.Fatal(err) 239 } 240 message := []byte("Hello, world.") 241 shared2 := []byte("shared data 2") 242 ct, err := Encrypt(rand.Reader, &prv.PublicKey, message, nil, shared2) 243 if err != nil { 244 t.Fatal(err) 245 } 246 247 // Check that decrypting with correct shared data works. 248 pt, err := prv.Decrypt(ct, nil, shared2) 249 if err != nil { 250 t.Fatal(err) 251 } 252 if !bytes.Equal(pt, message) { 253 t.Fatal("ecies: plaintext doesn't match message") 254 } 255 256 // Decrypting without shared data or incorrect shared data fails. 257 if _, err = prv.Decrypt(ct, nil, nil); err == nil { 258 t.Fatal("ecies: decrypting without shared data didn't fail") 259 } 260 if _, err = prv.Decrypt(ct, nil, []byte("garbage")); err == nil { 261 t.Fatal("ecies: decrypting with incorrect shared data didn't fail") 262 } 263 } 264 265 type testCase struct { 266 Curve elliptic.Curve 267 Name string 268 Expected *ECIESParams 269 } 270 271 var testCases = []testCase{ 272 { 273 Curve: elliptic.P256(), 274 Name: "P256", 275 Expected: ECIES_AES128_SHA256, 276 }, 277 { 278 Curve: elliptic.P384(), 279 Name: "P384", 280 Expected: ECIES_AES256_SHA384, 281 }, 282 { 283 Curve: elliptic.P521(), 284 Name: "P521", 285 Expected: ECIES_AES256_SHA512, 286 }, 287 } 288 289 // Test parameter selection for each curve, and that P224 fails automatic 290 // parameter selection (see README for a discussion of P224). Ensures that 291 // selecting a set of parameters automatically for the given curve works. 292 func TestParamSelection(t *testing.T) { 293 for _, c := range testCases { 294 testParamSelection(t, c) 295 } 296 } 297 298 func testParamSelection(t *testing.T, c testCase) { 299 params := ParamsFromCurve(c.Curve) 300 if params == nil && c.Expected != nil { 301 t.Fatalf("%s (%s)\n", ErrInvalidParams.Error(), c.Name) 302 } else if params != nil && !cmpParams(params, c.Expected) { 303 t.Fatalf("ecies: parameters should be invalid (%s)\n", c.Name) 304 } 305 306 prv1, err := GenerateKey(rand.Reader, DefaultCurve, nil) 307 if err != nil { 308 t.Fatalf("%s (%s)\n", err.Error(), c.Name) 309 } 310 311 prv2, err := GenerateKey(rand.Reader, DefaultCurve, nil) 312 if err != nil { 313 t.Fatalf("%s (%s)\n", err.Error(), c.Name) 314 } 315 316 message := []byte("Hello, world.") 317 ct, err := Encrypt(rand.Reader, &prv2.PublicKey, message, nil, nil) 318 if err != nil { 319 t.Fatalf("%s (%s)\n", err.Error(), c.Name) 320 } 321 322 pt, err := prv2.Decrypt(ct, nil, nil) 323 if err != nil { 324 t.Fatalf("%s (%s)\n", err.Error(), c.Name) 325 } 326 327 if !bytes.Equal(pt, message) { 328 t.Fatalf("ecies: plaintext doesn't match message (%s)\n", c.Name) 329 } 330 331 _, err = prv1.Decrypt(ct, nil, nil) 332 if err == nil { 333 t.Fatalf("ecies: encryption should not have succeeded (%s)\n", c.Name) 334 } 335 336 } 337 338 // Ensure that the basic public key validation in the decryption operation 339 // works. 340 func TestBasicKeyValidation(t *testing.T) { 341 badBytes := []byte{0, 1, 5, 6, 7, 8, 9} 342 343 prv, err := GenerateKey(rand.Reader, DefaultCurve, nil) 344 if err != nil { 345 t.Fatal(err) 346 } 347 348 message := []byte("Hello, world.") 349 ct, err := Encrypt(rand.Reader, &prv.PublicKey, message, nil, nil) 350 if err != nil { 351 t.Fatal(err) 352 } 353 354 for _, b := range badBytes { 355 ct[0] = b 356 _, err := prv.Decrypt(ct, nil, nil) 357 if err != ErrInvalidPublicKey { 358 t.Fatal("ecies: validated an invalid key") 359 } 360 } 361 } 362 363 func TestBox(t *testing.T) { 364 prv1 := hexKey("4b50fa71f5c3eeb8fdc452224b2395af2fcc3d125e06c32c82e048c0559db03f") 365 prv2 := hexKey("d0b043b4c5d657670778242d82d68a29d25d7d711127d17b8e299f156dad361a") 366 pub2 := &prv2.PublicKey 367 368 message := []byte("Hello, world.") 369 ct, err := Encrypt(rand.Reader, pub2, message, nil, nil) 370 if err != nil { 371 t.Fatal(err) 372 } 373 374 pt, err := prv2.Decrypt(ct, nil, nil) 375 if err != nil { 376 t.Fatal(err) 377 } 378 if !bytes.Equal(pt, message) { 379 t.Fatal("ecies: plaintext doesn't match message") 380 } 381 if _, err = prv1.Decrypt(ct, nil, nil); err == nil { 382 t.Fatal("ecies: encryption should not have succeeded") 383 } 384 } 385 386 // Verify GenerateShared against static values - useful when 387 // debugging changes in underlying libs 388 func TestSharedKeyStatic(t *testing.T) { 389 prv1 := hexKey("7ebbc6a8358bc76dd73ebc557056702c8cfc34e5cfcd90eb83af0347575fd2ad") 390 prv2 := hexKey("6a3d6396903245bba5837752b9e0348874e72db0c4e11e9c485a81b4ea4353b9") 391 392 skLen := MaxSharedKeyLength(&prv1.PublicKey) / 2 393 394 sk1, err := prv1.GenerateShared(&prv2.PublicKey, skLen, skLen) 395 if err != nil { 396 t.Fatal(err) 397 } 398 399 sk2, err := prv2.GenerateShared(&prv1.PublicKey, skLen, skLen) 400 if err != nil { 401 t.Fatal(err) 402 } 403 404 if !bytes.Equal(sk1, sk2) { 405 t.Fatal(ErrBadSharedKeys) 406 } 407 408 sk, _ := hex.DecodeString("167ccc13ac5e8a26b131c3446030c60fbfac6aa8e31149d0869f93626a4cdf62") 409 if !bytes.Equal(sk1, sk) { 410 t.Fatalf("shared secret mismatch: want: %x have: %x", sk, sk1) 411 } 412 } 413 414 func hexKey(prv string) *PrivateKey { 415 key, err := crypto.HexToECDSA(prv) 416 if err != nil { 417 panic(err) 418 } 419 return ImportECDSA(key) 420 }