github.com/digdeepmining/go-atheios@v1.5.13-0.20180902133602-d5687a2e6f43/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 "crypto/ecdsa" 22 "crypto/elliptic" 23 "crypto/rand" 24 "encoding/hex" 25 "testing" 26 27 "github.com/atheioschain/go-atheios/crypto/randentropy" 28 ) 29 30 const TestCount = 1000 31 32 func generateKeyPair() (pubkey, privkey []byte) { 33 key, err := ecdsa.GenerateKey(S256(), rand.Reader) 34 if err != nil { 35 panic(err) 36 } 37 pubkey = elliptic.Marshal(S256(), key.X, key.Y) 38 privkey = make([]byte, 32) 39 readBits(privkey, key.D) 40 return pubkey, privkey 41 } 42 43 func randSig() []byte { 44 sig := randentropy.GetEntropyCSPRNG(65) 45 sig[32] &= 0x70 46 sig[64] %= 4 47 return sig 48 } 49 50 // tests for malleability 51 // highest bit of signature ECDSA s value must be 0, in the 33th byte 52 func compactSigCheck(t *testing.T, sig []byte) { 53 var b int = int(sig[32]) 54 if b < 0 { 55 t.Errorf("highest bit is negative: %d", b) 56 } 57 if ((b >> 7) == 1) != ((b & 0x80) == 0x80) { 58 t.Errorf("highest bit: %d bit >> 7: %d", b, b>>7) 59 } 60 if (b & 0x80) == 0x80 { 61 t.Errorf("highest bit: %d bit & 0x80: %d", b, b&0x80) 62 } 63 } 64 65 func TestSignatureValidity(t *testing.T) { 66 pubkey, seckey := generateKeyPair() 67 msg := randentropy.GetEntropyCSPRNG(32) 68 sig, err := Sign(msg, seckey) 69 if err != nil { 70 t.Errorf("signature error: %s", err) 71 } 72 compactSigCheck(t, sig) 73 if len(pubkey) != 65 { 74 t.Errorf("pubkey length mismatch: want: 65 have: %d", len(pubkey)) 75 } 76 if len(seckey) != 32 { 77 t.Errorf("seckey length mismatch: want: 32 have: %d", len(seckey)) 78 } 79 if len(sig) != 65 { 80 t.Errorf("sig length mismatch: want: 65 have: %d", len(sig)) 81 } 82 recid := int(sig[64]) 83 if recid > 4 || recid < 0 { 84 t.Errorf("sig recid mismatch: want: within 0 to 4 have: %d", int(sig[64])) 85 } 86 } 87 88 func TestInvalidRecoveryID(t *testing.T) { 89 _, seckey := generateKeyPair() 90 msg := randentropy.GetEntropyCSPRNG(32) 91 sig, _ := Sign(msg, seckey) 92 sig[64] = 99 93 _, err := RecoverPubkey(msg, sig) 94 if err != ErrInvalidRecoveryID { 95 t.Fatalf("got %q, want %q", err, ErrInvalidRecoveryID) 96 } 97 } 98 99 func TestSignAndRecover(t *testing.T) { 100 pubkey1, seckey := generateKeyPair() 101 msg := randentropy.GetEntropyCSPRNG(32) 102 sig, err := Sign(msg, seckey) 103 if err != nil { 104 t.Errorf("signature error: %s", err) 105 } 106 pubkey2, err := RecoverPubkey(msg, sig) 107 if err != nil { 108 t.Errorf("recover error: %s", err) 109 } 110 if !bytes.Equal(pubkey1, pubkey2) { 111 t.Errorf("pubkey mismatch: want: %x have: %x", pubkey1, pubkey2) 112 } 113 } 114 115 func TestSignDeterministic(t *testing.T) { 116 _, seckey := generateKeyPair() 117 msg := make([]byte, 32) 118 copy(msg, "hi there") 119 120 sig1, err := Sign(msg, seckey) 121 if err != nil { 122 t.Fatal(err) 123 } 124 sig2, err := Sign(msg, seckey) 125 if err != nil { 126 t.Fatal(err) 127 } 128 if !bytes.Equal(sig1, sig2) { 129 t.Fatal("signatures not equal") 130 } 131 } 132 133 func TestRandomMessagesWithSameKey(t *testing.T) { 134 pubkey, seckey := generateKeyPair() 135 keys := func() ([]byte, []byte) { 136 return pubkey, seckey 137 } 138 signAndRecoverWithRandomMessages(t, keys) 139 } 140 141 func TestRandomMessagesWithRandomKeys(t *testing.T) { 142 keys := func() ([]byte, []byte) { 143 pubkey, seckey := generateKeyPair() 144 return pubkey, seckey 145 } 146 signAndRecoverWithRandomMessages(t, keys) 147 } 148 149 func signAndRecoverWithRandomMessages(t *testing.T, keys func() ([]byte, []byte)) { 150 for i := 0; i < TestCount; i++ { 151 pubkey1, seckey := keys() 152 msg := randentropy.GetEntropyCSPRNG(32) 153 sig, err := Sign(msg, seckey) 154 if err != nil { 155 t.Fatalf("signature error: %s", err) 156 } 157 if sig == nil { 158 t.Fatal("signature is nil") 159 } 160 compactSigCheck(t, sig) 161 162 // TODO: why do we flip around the recovery id? 163 sig[len(sig)-1] %= 4 164 165 pubkey2, err := RecoverPubkey(msg, sig) 166 if err != nil { 167 t.Fatalf("recover error: %s", err) 168 } 169 if pubkey2 == nil { 170 t.Error("pubkey is nil") 171 } 172 if !bytes.Equal(pubkey1, pubkey2) { 173 t.Fatalf("pubkey mismatch: want: %x have: %x", pubkey1, pubkey2) 174 } 175 } 176 } 177 178 func TestRecoveryOfRandomSignature(t *testing.T) { 179 pubkey1, _ := generateKeyPair() 180 msg := randentropy.GetEntropyCSPRNG(32) 181 182 for i := 0; i < TestCount; i++ { 183 // recovery can sometimes work, but if so should always give wrong pubkey 184 pubkey2, _ := RecoverPubkey(msg, randSig()) 185 if bytes.Equal(pubkey1, pubkey2) { 186 t.Fatalf("iteration: %d: pubkey mismatch: do NOT want %x: ", i, pubkey2) 187 } 188 } 189 } 190 191 func TestRandomMessagesAgainstValidSig(t *testing.T) { 192 pubkey1, seckey := generateKeyPair() 193 msg := randentropy.GetEntropyCSPRNG(32) 194 sig, _ := Sign(msg, seckey) 195 196 for i := 0; i < TestCount; i++ { 197 msg = randentropy.GetEntropyCSPRNG(32) 198 pubkey2, _ := RecoverPubkey(msg, sig) 199 // recovery can sometimes work, but if so should always give wrong pubkey 200 if bytes.Equal(pubkey1, pubkey2) { 201 t.Fatalf("iteration: %d: pubkey mismatch: do NOT want %x: ", i, pubkey2) 202 } 203 } 204 } 205 206 // Useful when the underlying libsecp256k1 API changes to quickly 207 // check only recover function without use of signature function 208 func TestRecoverSanity(t *testing.T) { 209 msg, _ := hex.DecodeString("ce0677bb30baa8cf067c88db9811f4333d131bf8bcf12fe7065d211dce971008") 210 sig, _ := hex.DecodeString("90f27b8b488db00b00606796d2987f6a5f59ae62ea05effe84fef5b8b0e549984a691139ad57a3f0b906637673aa2f63d1f55cb1a69199d4009eea23ceaddc9301") 211 pubkey1, _ := hex.DecodeString("04e32df42865e97135acfb65f3bae71bdc86f4d49150ad6a440b6f15878109880a0a2b2667f7e725ceea70c673093bf67663e0312623c8e091b13cf2c0f11ef652") 212 pubkey2, err := RecoverPubkey(msg, sig) 213 if err != nil { 214 t.Fatalf("recover error: %s", err) 215 } 216 if !bytes.Equal(pubkey1, pubkey2) { 217 t.Errorf("pubkey mismatch: want: %x have: %x", pubkey1, pubkey2) 218 } 219 } 220 221 func BenchmarkSign(b *testing.B) { 222 _, seckey := generateKeyPair() 223 msg := randentropy.GetEntropyCSPRNG(32) 224 b.ResetTimer() 225 226 for i := 0; i < b.N; i++ { 227 Sign(msg, seckey) 228 } 229 } 230 231 func BenchmarkRecover(b *testing.B) { 232 msg := randentropy.GetEntropyCSPRNG(32) 233 _, seckey := generateKeyPair() 234 sig, _ := Sign(msg, seckey) 235 b.ResetTimer() 236 237 for i := 0; i < b.N; i++ { 238 RecoverPubkey(msg, sig) 239 } 240 }