github.com/ethereumproject/go-ethereum@v5.5.2+incompatible/crypto/secp256k1/secp256_test.go (about) 1 // Copyright 2015 The go-ethereum Authors 2 // This file is part of the go-ethereum library. 3 // 4 // The go-ethereum library is free software: you can redistribute it and/or modify 5 // it under the terms of the GNU Lesser General Public License as published by 6 // the Free Software Foundation, either version 3 of the License, or 7 // (at your option) any later version. 8 // 9 // The go-ethereum library is distributed in the hope that it will be useful, 10 // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 // GNU Lesser General Public License for more details. 13 // 14 // You should have received a copy of the GNU Lesser General Public License 15 // along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>. 16 17 package secp256k1 18 19 import ( 20 "bytes" 21 "encoding/hex" 22 "testing" 23 24 "github.com/ethereumproject/go-ethereum/common/hexutil" 25 "github.com/ethereumproject/go-ethereum/crypto/randentropy" 26 ) 27 28 const TestCount = 1000 29 30 func TestPrivkeyGenerate(t *testing.T) { 31 _, seckey := GenerateKeyPair() 32 if err := VerifySeckeyValidity(seckey); err != nil { 33 t.Errorf("seckey not valid: %s", err) 34 } 35 } 36 37 func TestSignatureValidity(t *testing.T) { 38 pubkey, seckey := GenerateKeyPair() 39 msg := randentropy.GetEntropyCSPRNG(32) 40 sig, err := Sign(msg, seckey) 41 if err != nil { 42 t.Errorf("signature error: %s", err) 43 } 44 compactSigCheck(t, sig) 45 if len(pubkey) != 65 { 46 t.Errorf("pubkey length mismatch: want: 65 have: %d", len(pubkey)) 47 } 48 if len(seckey) != 32 { 49 t.Errorf("seckey length mismatch: want: 32 have: %d", len(seckey)) 50 } 51 if len(sig) != 65 { 52 t.Errorf("sig length mismatch: want: 65 have: %d", len(sig)) 53 } 54 recid := int(sig[64]) 55 if recid > 4 || recid < 0 { 56 t.Errorf("sig recid mismatch: want: within 0 to 4 have: %d", int(sig[64])) 57 } 58 } 59 60 func TestInvalidRecoveryID(t *testing.T) { 61 _, seckey := GenerateKeyPair() 62 msg := randentropy.GetEntropyCSPRNG(32) 63 sig, _ := Sign(msg, seckey) 64 sig[64] = 99 65 _, err := RecoverPubkey(msg, sig) 66 if err != ErrInvalidRecoveryID { 67 t.Fatalf("got %q, want %q", err, ErrInvalidRecoveryID) 68 } 69 } 70 71 func TestSignDeterministic(t *testing.T) { 72 _, seckey := GenerateKeyPair() 73 msg := randentropy.GetEntropyCSPRNG(32) 74 sig1, err := Sign(msg, seckey) 75 if err != nil { 76 t.Errorf("signature 1 error: %s", err) 77 } 78 sig2, err := Sign(msg, seckey) 79 if err != nil { 80 t.Errorf("signature 2 error: %s", err) 81 } 82 if !bytes.Equal(sig1, sig2) { 83 t.Fatal("sig1 != sig2", hexutil.Encode(sig1), hexutil.Encode(sig2)) 84 } 85 } 86 87 // TestSignNondeterministic shows that TestSignNondeterministic does not generate deterministic signatures. 88 func TestSignNondeterministic(t *testing.T) { 89 _, seckey := GenerateKeyPair() 90 msg := randentropy.GetEntropyCSPRNG(32) 91 sig1, err := SignNondeterministic(msg, seckey) 92 if err != nil { 93 t.Errorf("signature 1 error: %s", err) 94 } 95 sig2, err := SignNondeterministic(msg, seckey) 96 if err != nil { 97 t.Errorf("signature 2 error: %s", err) 98 } 99 // Of course the signatures should be the same (1:1), but they are not. 100 if bytes.Equal(sig1, sig2) { 101 t.Error("sig1 == sig2", hexutil.Encode(sig1), hexutil.Encode(sig2)) 102 } 103 } 104 105 // TestSignNondeterministic2 shows that TestSignNondeterministic does not generate the same signature as deterministic Sign. 106 func TestSignNondeterministic2(t *testing.T) { 107 _, seckey := GenerateKeyPair() 108 msg := randentropy.GetEntropyCSPRNG(32) 109 sig1, err := SignNondeterministic(msg, seckey) 110 if err != nil { 111 t.Errorf("signature 1 error: %s", err) 112 } 113 sig2, err := Sign(msg, seckey) 114 if err != nil { 115 t.Errorf("signature 2 error: %s", err) 116 } 117 // Of course the signatures should be the same (1:1), but they are not. 118 if bytes.Equal(sig1, sig2) { 119 t.Error("sig1 == sig2", hexutil.Encode(sig1), hexutil.Encode(sig2)) 120 } 121 } 122 123 func TestSignAndRecover(t *testing.T) { 124 pubkey1, seckey := GenerateKeyPair() 125 msg := randentropy.GetEntropyCSPRNG(32) 126 sig, err := Sign(msg, seckey) 127 if err != nil { 128 t.Errorf("signature error: %s", err) 129 } 130 pubkey2, err := RecoverPubkey(msg, sig) 131 if err != nil { 132 t.Errorf("recover error: %s", err) 133 } 134 if !bytes.Equal(pubkey1, pubkey2) { 135 t.Errorf("pubkey mismatch: want: %x have: %x", pubkey1, pubkey2) 136 } 137 } 138 139 func TestRandomMessagesWithSameKey(t *testing.T) { 140 pubkey, seckey := GenerateKeyPair() 141 keys := func() ([]byte, []byte) { 142 return pubkey, seckey 143 } 144 signAndRecoverWithRandomMessages(t, keys) 145 } 146 147 func TestRandomMessagesWithRandomKeys(t *testing.T) { 148 keys := func() ([]byte, []byte) { 149 pubkey, seckey := GenerateKeyPair() 150 return pubkey, seckey 151 } 152 signAndRecoverWithRandomMessages(t, keys) 153 } 154 155 func signAndRecoverWithRandomMessages(t *testing.T, keys func() ([]byte, []byte)) { 156 for i := 0; i < TestCount; i++ { 157 pubkey1, seckey := keys() 158 msg := randentropy.GetEntropyCSPRNG(32) 159 sig, err := Sign(msg, seckey) 160 if err != nil { 161 t.Fatalf("signature error: %s", err) 162 } 163 if sig == nil { 164 t.Fatal("signature is nil") 165 } 166 compactSigCheck(t, sig) 167 168 // TODO: why do we flip around the recovery id? 169 sig[len(sig)-1] %= 4 170 171 pubkey2, err := RecoverPubkey(msg, sig) 172 if err != nil { 173 t.Fatalf("recover error: %s", err) 174 } 175 if pubkey2 == nil { 176 t.Error("pubkey is nil") 177 } 178 if !bytes.Equal(pubkey1, pubkey2) { 179 t.Fatalf("pubkey mismatch: want: %x have: %x", pubkey1, pubkey2) 180 } 181 } 182 } 183 184 func TestRecoveryOfRandomSignature(t *testing.T) { 185 pubkey1, seckey := GenerateKeyPair() 186 msg := randentropy.GetEntropyCSPRNG(32) 187 sig, err := Sign(msg, seckey) 188 if err != nil { 189 t.Errorf("signature error: %s", err) 190 } 191 192 for i := 0; i < TestCount; i++ { 193 sig = randSig() 194 pubkey2, _ := RecoverPubkey(msg, sig) 195 // recovery can sometimes work, but if so should always give wrong pubkey 196 if bytes.Equal(pubkey1, pubkey2) { 197 t.Fatalf("iteration: %d: pubkey mismatch: do NOT want %x: ", i, pubkey2) 198 } 199 } 200 } 201 202 func randSig() []byte { 203 sig := randentropy.GetEntropyCSPRNG(65) 204 sig[32] &= 0x70 205 sig[64] %= 4 206 return sig 207 } 208 209 func TestRandomMessagesAgainstValidSig(t *testing.T) { 210 pubkey1, seckey := GenerateKeyPair() 211 msg := randentropy.GetEntropyCSPRNG(32) 212 sig, _ := Sign(msg, seckey) 213 214 for i := 0; i < TestCount; i++ { 215 msg = randentropy.GetEntropyCSPRNG(32) 216 pubkey2, _ := RecoverPubkey(msg, sig) 217 // recovery can sometimes work, but if so should always give wrong pubkey 218 if bytes.Equal(pubkey1, pubkey2) { 219 t.Fatalf("iteration: %d: pubkey mismatch: do NOT want %x: ", i, pubkey2) 220 } 221 } 222 } 223 224 func TestZeroPrivkey(t *testing.T) { 225 zeroedBytes := make([]byte, 32) 226 err := VerifySeckeyValidity(zeroedBytes) 227 if err == nil { 228 t.Errorf("zeroed bytes should have returned error") 229 } 230 } 231 232 // Useful when the underlying libsecp256k1 API changes to quickly 233 // check only recover function without use of signature function 234 func TestRecoverSanity(t *testing.T) { 235 msg, _ := hex.DecodeString("ce0677bb30baa8cf067c88db9811f4333d131bf8bcf12fe7065d211dce971008") 236 sig, _ := hex.DecodeString("90f27b8b488db00b00606796d2987f6a5f59ae62ea05effe84fef5b8b0e549984a691139ad57a3f0b906637673aa2f63d1f55cb1a69199d4009eea23ceaddc9301") 237 pubkey1, _ := hex.DecodeString("04e32df42865e97135acfb65f3bae71bdc86f4d49150ad6a440b6f15878109880a0a2b2667f7e725ceea70c673093bf67663e0312623c8e091b13cf2c0f11ef652") 238 pubkey2, err := RecoverPubkey(msg, sig) 239 if err != nil { 240 t.Fatalf("recover error: %s", err) 241 } 242 if !bytes.Equal(pubkey1, pubkey2) { 243 t.Errorf("pubkey mismatch: want: %x have: %x", pubkey1, pubkey2) 244 } 245 } 246 247 // tests for malleability 248 // highest bit of signature ECDSA s value must be 0, in the 33th byte 249 func compactSigCheck(t *testing.T, sig []byte) { 250 var b int = int(sig[32]) 251 if b < 0 { 252 t.Errorf("highest bit is negative: %d", b) 253 } 254 if ((b >> 7) == 1) != ((b & 0x80) == 0x80) { 255 t.Errorf("highest bit: %d bit >> 7: %d", b, b>>7) 256 } 257 if (b & 0x80) == 0x80 { 258 t.Errorf("highest bit: %d bit & 0x80: %d", b, b&0x80) 259 } 260 } 261 262 // godep go test -v -run=XXX -bench=BenchmarkSign 263 // add -benchtime=10s to benchmark longer for more accurate average 264 265 // to avoid compiler optimizing the benchmarked function call 266 var err error 267 268 func BenchmarkSign(b *testing.B) { 269 for i := 0; i < b.N; i++ { 270 _, seckey := GenerateKeyPair() 271 msg := randentropy.GetEntropyCSPRNG(32) 272 b.StartTimer() 273 _, e := Sign(msg, seckey) 274 err = e 275 b.StopTimer() 276 } 277 } 278 279 //godep go test -v -run=XXX -bench=BenchmarkECRec 280 func BenchmarkRecover(b *testing.B) { 281 for i := 0; i < b.N; i++ { 282 _, seckey := GenerateKeyPair() 283 msg := randentropy.GetEntropyCSPRNG(32) 284 sig, _ := Sign(msg, seckey) 285 b.StartTimer() 286 _, e := RecoverPubkey(msg, sig) 287 err = e 288 b.StopTimer() 289 } 290 }