github.com/yinchengtsinghua/golang-Eos-dpos-Ethereum@v0.0.0-20190121132951-92cc4225ed8e/crypto/secp256k1/secp256_test.go (about) 1 2 //此源码被清华学神尹成大魔王专业翻译分析并修改 3 //尹成QQ77025077 4 //尹成微信18510341407 5 //尹成所在QQ群721929980 6 //尹成邮箱 yinc13@mails.tsinghua.edu.cn 7 //尹成毕业于清华大学,微软区块链领域全球最有价值专家 8 //https://mvp.microsoft.com/zh-cn/PublicProfile/4033620 9 //版权所有2015 Jeffrey Wilcke、Felix Lange、Gustav Simonsson。版权所有。 10 //此源代码的使用受BSD样式许可证的控制,该许可证可在 11 //许可证文件。 12 13 package secp256k1 14 15 import ( 16 "bytes" 17 "crypto/ecdsa" 18 "crypto/elliptic" 19 "crypto/rand" 20 "encoding/hex" 21 "io" 22 "testing" 23 ) 24 25 const TestCount = 1000 26 27 func generateKeyPair() (pubkey, privkey []byte) { 28 key, err := ecdsa.GenerateKey(S256(), rand.Reader) 29 if err != nil { 30 panic(err) 31 } 32 pubkey = elliptic.Marshal(S256(), key.X, key.Y) 33 34 privkey = make([]byte, 32) 35 blob := key.D.Bytes() 36 copy(privkey[32-len(blob):], blob) 37 38 return pubkey, privkey 39 } 40 41 func csprngEntropy(n int) []byte { 42 buf := make([]byte, n) 43 if _, err := io.ReadFull(rand.Reader, buf); err != nil { 44 panic("reading from crypto/rand failed: " + err.Error()) 45 } 46 return buf 47 } 48 49 func randSig() []byte { 50 sig := csprngEntropy(65) 51 sig[32] &= 0x70 52 sig[64] %= 4 53 return sig 54 } 55 56 //延展性试验 57 //签名ecdsa s值的最高位必须是0,在第33个字节中 58 func compactSigCheck(t *testing.T, sig []byte) { 59 var b = int(sig[32]) 60 if b < 0 { 61 t.Errorf("highest bit is negative: %d", b) 62 } 63 if ((b >> 7) == 1) != ((b & 0x80) == 0x80) { 64 t.Errorf("highest bit: %d bit >> 7: %d", b, b>>7) 65 } 66 if (b & 0x80) == 0x80 { 67 t.Errorf("highest bit: %d bit & 0x80: %d", b, b&0x80) 68 } 69 } 70 71 func TestSignatureValidity(t *testing.T) { 72 pubkey, seckey := generateKeyPair() 73 msg := csprngEntropy(32) 74 sig, err := Sign(msg, seckey) 75 if err != nil { 76 t.Errorf("signature error: %s", err) 77 } 78 compactSigCheck(t, sig) 79 if len(pubkey) != 65 { 80 t.Errorf("pubkey length mismatch: want: 65 have: %d", len(pubkey)) 81 } 82 if len(seckey) != 32 { 83 t.Errorf("seckey length mismatch: want: 32 have: %d", len(seckey)) 84 } 85 if len(sig) != 65 { 86 t.Errorf("sig length mismatch: want: 65 have: %d", len(sig)) 87 } 88 recid := int(sig[64]) 89 if recid > 4 || recid < 0 { 90 t.Errorf("sig recid mismatch: want: within 0 to 4 have: %d", int(sig[64])) 91 } 92 } 93 94 func TestInvalidRecoveryID(t *testing.T) { 95 _, seckey := generateKeyPair() 96 msg := csprngEntropy(32) 97 sig, _ := Sign(msg, seckey) 98 sig[64] = 99 99 _, err := RecoverPubkey(msg, sig) 100 if err != ErrInvalidRecoveryID { 101 t.Fatalf("got %q, want %q", err, ErrInvalidRecoveryID) 102 } 103 } 104 105 func TestSignAndRecover(t *testing.T) { 106 pubkey1, seckey := generateKeyPair() 107 msg := csprngEntropy(32) 108 sig, err := Sign(msg, seckey) 109 if err != nil { 110 t.Errorf("signature error: %s", err) 111 } 112 pubkey2, err := RecoverPubkey(msg, sig) 113 if err != nil { 114 t.Errorf("recover error: %s", err) 115 } 116 if !bytes.Equal(pubkey1, pubkey2) { 117 t.Errorf("pubkey mismatch: want: %x have: %x", pubkey1, pubkey2) 118 } 119 } 120 121 func TestSignDeterministic(t *testing.T) { 122 _, seckey := generateKeyPair() 123 msg := make([]byte, 32) 124 copy(msg, "hi there") 125 126 sig1, err := Sign(msg, seckey) 127 if err != nil { 128 t.Fatal(err) 129 } 130 sig2, err := Sign(msg, seckey) 131 if err != nil { 132 t.Fatal(err) 133 } 134 if !bytes.Equal(sig1, sig2) { 135 t.Fatal("signatures not equal") 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 := csprngEntropy(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 //托多:我们为什么要翻转恢复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, _ := generateKeyPair() 186 msg := csprngEntropy(32) 187 188 for i := 0; i < TestCount; i++ { 189 //恢复有时可以工作,但如果是这样,则应该始终给出错误的pubkey 190 pubkey2, _ := RecoverPubkey(msg, randSig()) 191 if bytes.Equal(pubkey1, pubkey2) { 192 t.Fatalf("iteration: %d: pubkey mismatch: do NOT want %x: ", i, pubkey2) 193 } 194 } 195 } 196 197 func TestRandomMessagesAgainstValidSig(t *testing.T) { 198 pubkey1, seckey := generateKeyPair() 199 msg := csprngEntropy(32) 200 sig, _ := Sign(msg, seckey) 201 202 for i := 0; i < TestCount; i++ { 203 msg = csprngEntropy(32) 204 pubkey2, _ := RecoverPubkey(msg, sig) 205 //恢复有时可以工作,但如果是这样,则应该始终给出错误的pubkey 206 if bytes.Equal(pubkey1, pubkey2) { 207 t.Fatalf("iteration: %d: pubkey mismatch: do NOT want %x: ", i, pubkey2) 208 } 209 } 210 } 211 212 //当基础libsecp256k1 API更改为“快速”时很有用 213 //只检查恢复函数而不使用签名函数 214 func TestRecoverSanity(t *testing.T) { 215 msg, _ := hex.DecodeString("ce0677bb30baa8cf067c88db9811f4333d131bf8bcf12fe7065d211dce971008") 216 sig, _ := hex.DecodeString("90f27b8b488db00b00606796d2987f6a5f59ae62ea05effe84fef5b8b0e549984a691139ad57a3f0b906637673aa2f63d1f55cb1a69199d4009eea23ceaddc9301") 217 pubkey1, _ := hex.DecodeString("04e32df42865e97135acfb65f3bae71bdc86f4d49150ad6a440b6f15878109880a0a2b2667f7e725ceea70c673093bf67663e0312623c8e091b13cf2c0f11ef652") 218 pubkey2, err := RecoverPubkey(msg, sig) 219 if err != nil { 220 t.Fatalf("recover error: %s", err) 221 } 222 if !bytes.Equal(pubkey1, pubkey2) { 223 t.Errorf("pubkey mismatch: want: %x have: %x", pubkey1, pubkey2) 224 } 225 } 226 227 func BenchmarkSign(b *testing.B) { 228 _, seckey := generateKeyPair() 229 msg := csprngEntropy(32) 230 b.ResetTimer() 231 232 for i := 0; i < b.N; i++ { 233 Sign(msg, seckey) 234 } 235 } 236 237 func BenchmarkRecover(b *testing.B) { 238 msg := csprngEntropy(32) 239 _, seckey := generateKeyPair() 240 sig, _ := Sign(msg, seckey) 241 b.ResetTimer() 242 243 for i := 0; i < b.N; i++ { 244 RecoverPubkey(msg, sig) 245 } 246 }