github.com/chain5j/chain5j-pkg@v1.0.7/crypto/signature/prime256v1/signature_test.go (about) 1 package prime256v1 2 3 import ( 4 "bytes" 5 "crypto/elliptic" 6 "crypto/rand" 7 "crypto/sha256" 8 "encoding/hex" 9 "fmt" 10 "testing" 11 12 "github.com/chain5j/chain5j-pkg/util/hexutil" 13 ) 14 15 type signatureTest struct { 16 name string 17 sig []byte 18 der bool 19 isValid bool 20 } 21 22 var curve = elliptic.P256() 23 24 // decodeHex decodes the passed hex string and returns the resulting bytes. It 25 // panics if an error occurs. This is only used in the tests as a helper since 26 // the only way it can fail is if there is an error in the test source code. 27 func decodeHex(hexStr string) []byte { 28 b, err := hex.DecodeString(hexStr) 29 if err != nil { 30 panic("invalid hex string in test source: err " + err.Error() + 31 ", hex: " + hexStr) 32 } 33 34 return b 35 } 36 37 func testSignCompact(priv *PrivateKey, tag string, data []byte, isCompressed bool) { 38 // priv, _ := GeneratePrivateKey() 39 40 hashed := []byte("testing") 41 sig, err := SignCompact(priv, hashed, isCompressed) 42 if err != nil { 43 fmt.Println(" error signing: ", tag, err) 44 return 45 } 46 fmt.Printf("签名长度%x,%d \n", sig, len(sig)) 47 48 // 校验签名内容 49 key := priv.PublicKey 50 publicKey := NewPublicKey(curve, key.X, key.Y) 51 verify := VerifySignature(publicKey.ToECDSA(), hashed, sig[:64]) 52 53 fmt.Println("签名校验", verify) 54 55 // fmt.Println("签名内容", hexutil.Encode(sig)) 56 57 pk, wasCompressed, err := RecoverCompact(curve, sig, hashed) 58 59 fmt.Println("公钥", pk) 60 if err != nil { 61 fmt.Println(" error recovering: ", tag, err) 62 return 63 } 64 if pk.X.Cmp(priv.X) != 0 || pk.Y.Cmp(priv.Y) != 0 { 65 fmt.Println("%s: recovered pubkey doesn't match original "+ 66 "(%v,%v) vs (%v,%v) ", tag, pk.X, pk.Y, priv.X, priv.Y) 67 return 68 } 69 if wasCompressed != isCompressed { 70 fmt.Println("%s: recovered pubkey doesn't match compressed state "+ 71 "(%v vs %v)", tag, isCompressed, wasCompressed) 72 return 73 } 74 75 // If we change the compressed bit we should get the same key back, 76 // but the compressed flag should be reversed. 77 if isCompressed { 78 sig[len(sig)-1] -= 4 79 } else { 80 sig[len(sig)-1] += 4 81 } 82 83 pk, wasCompressed, err = RecoverCompact(curve, sig, hashed) 84 fmt.Println("恢复的公钥", pk) 85 if err != nil { 86 fmt.Println(" error recovering (2):", tag, err) 87 return 88 } 89 if pk.X.Cmp(priv.X) != 0 || pk.Y.Cmp(priv.Y) != 0 { 90 fmt.Println("%s: recovered pubkey (2) doesn't match original "+ 91 "(%v,%v) vs (%v,%v) ", tag, pk.X, pk.Y, priv.X, priv.Y) 92 return 93 } 94 if wasCompressed == isCompressed { 95 fmt.Println("%s: recovered pubkey doesn't match reversed "+ 96 "compressed state (%v vs %v)", tag, isCompressed, 97 wasCompressed) 98 return 99 } 100 } 101 102 func TestSignCompact(t *testing.T) { 103 priv1, _ := GeneratePrivateKey(curve) 104 t.Log("priv1.Serialize()", hexutil.Encode(priv1.Serialize())) 105 106 key := "cca9fbcc1b41e5a95d369eaa6ddcff73b61a4efaa279cfc6567e8daa39cbaf50" 107 priv, _ := PrivKeyFromBytes(curve, decodeHex(key)) 108 109 s := hex.EncodeToString(priv.Serialize()) 110 fmt.Println("私钥String", s) 111 112 fmt.Println("私钥", priv.D) 113 fmt.Println("公钥", priv.PublicKey) 114 // fmt.Println("地址", crypto.PubkeyToAddress(priv.PublicKey)) 115 116 // for i := 0; i < 256; i++ { 117 for i := 0; i < 1; i++ { 118 name := fmt.Sprintf("test %d", i) 119 data := make([]byte, 32) 120 _, err := rand.Read(data) 121 if err != nil { 122 t.Errorf("failed to read random data for %s", name) 123 continue 124 } 125 compressed := i%2 != 0 126 testSignCompact(priv, name, data, compressed) 127 } 128 } 129 130 func TestRFC6979(t *testing.T) { 131 // Test vectors matching Trezor and CoreBitcoin implementations. 132 // - https://github.com/trezor/trezor-crypto/blob/9fea8f8ab377dc514e40c6fd1f7c89a74c1d8dc6/tests.c#L432-L453 133 // - https://github.com/oleganza/CoreBitcoin/blob/e93dd71207861b5bf044415db5fa72405e7d8fbc/CoreBitcoin/BTCKey%2BTests.m#L23-L49 134 tests := []struct { 135 key string 136 msg string 137 nonce string 138 signature string 139 }{ 140 { 141 "cca9fbcc1b41e5a95d369eaa6ddcff73b61a4efaa279cfc6567e8daa39cbaf50", 142 "sample", 143 "2df40ca70e639d89528a6b670d9d48d9165fdc0febc0974056bdce192b8e16a3", 144 "3045022100af340daf02cc15c8d5d08d7735dfe6b98a474ed373bdb5fbecf7571be52b384202205009fb27f37034a9b24b707b7c6b79ca23ddef9e25f7282e8a797efe53a8f124", 145 }, 146 { 147 // This signature hits the case when S is higher than halforder. 148 // If S is not canonicalized (lowered by halforder), this test will fail. 149 "0000000000000000000000000000000000000000000000000000000000000001", 150 "Satoshi Nakamoto", 151 "8f8a276c19f4149656b280621e358cce24f5f52542772691ee69063b74f15d15", 152 "3045022100934b1ea10a4b3c1757e2b0c017d0b6143ce3c9a7e6a4a49860d7a6ab210ee3d802202442ce9d2b916064108014783e923ec36b49743e2ffa1c4496f01a512aafd9e5", 153 }, 154 { 155 "fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364140", 156 "Satoshi Nakamoto", 157 "33a19b60e25fb6f4435af53a3d42d493644827367e6453928554f43e49aa6f90", 158 "3045022100fd567d121db66e382991534ada77a6bd3106f0a1098c231e47993447cd6af2d002206b39cd0eb1bc8603e159ef5c20a5c8ad685a45b06ce9bebed3f153d10d93bed5", 159 }, 160 { 161 "f8b8af8ce3c7cca5e300d33939540c10d45ce001b8f252bfbc57ba0342904181", 162 "Alan Turing", 163 "525a82b70e67874398067543fd84c83d30c175fdc45fdeee082fe13b1d7cfdf1", 164 "304402207063ae83e7f62bbb171798131b4a0564b956930092b33b07b395615d9ec7e15c022058dfcc1e00a35e1572f366ffe34ba0fc47db1e7189759b9fb233c5b05ab388ea", 165 }, 166 { 167 "0000000000000000000000000000000000000000000000000000000000000001", 168 "All those moments will be lost in time, like tears in rain. Time to die...", 169 "38aa22d72376b4dbc472e06c3ba403ee0a394da63fc58d88686c611aba98d6b3", 170 "30450221008600dbd41e348fe5c9465ab92d23e3db8b98b873beecd930736488696438cb6b0220547fe64427496db33bf66019dacbf0039c04199abb0122918601db38a72cfc21", 171 }, 172 { 173 "e91671c46231f833a6406ccbea0e3e392c76c167bac1cb013f6f1013980455c2", 174 "There is a computer disease that anybody who works with computers knows about. It's a very serious disease and it interferes completely with the work. The trouble with computers is that you 'play' with them!", 175 "1f4b84c23a86a221d233f2521be018d9318639d5b8bbd6374a8a59232d16ad3d", 176 "3045022100b552edd27580141f3b2a5463048cb7cd3e047b97c9f98076c32dbdf85a68718b0220279fa72dd19bfae05577e06c7c0c1900c371fcd5893f7e1d56a37d30174671f6", 177 }, 178 } 179 180 for i, test := range tests { 181 privKey, _ := PrivKeyFromBytes(curve, decodeHex(test.key)) 182 hash := sha256.Sum256([]byte(test.msg)) 183 184 // Ensure deterministically generated nonce is the expected value. 185 gotNonce := NonceRFC6979(curve, privKey.D, hash[:], nil, nil).Bytes() 186 wantNonce := decodeHex(test.nonce) 187 if !bytes.Equal(gotNonce, wantNonce) { 188 t.Errorf("NonceRFC6979 #%d (%s): Nonce is incorrect: "+ 189 "%x (expected %x)", i, test.msg, gotNonce, 190 wantNonce) 191 continue 192 } 193 194 // Ensure deterministically generated signature is the expected value. 195 gotSig, err := privKey.Sign(hash[:]) 196 if err != nil { 197 t.Errorf("Sign #%d (%s): unexpected error: %v", i, 198 test.msg, err) 199 continue 200 } 201 gotSigBytes := gotSig.Serialize() 202 wantSigBytes := decodeHex(test.signature) 203 if !bytes.Equal(gotSigBytes, wantSigBytes) { 204 t.Errorf("Sign #%d (%s): mismatched signature: %x "+ 205 "(expected %x)", i, test.msg, gotSigBytes, 206 wantSigBytes) 207 continue 208 } 209 } 210 }