github.com/Finschia/finschia-sdk@v0.48.1/crypto/keys/secp256k1/secp256k1_test.go (about) 1 package secp256k1_test 2 3 import ( 4 "crypto/ecdsa" 5 "encoding/base64" 6 "encoding/hex" 7 "math/big" 8 "testing" 9 10 btcSecp256k1 "github.com/btcsuite/btcd/btcec" 11 "github.com/cosmos/btcutil/base58" 12 "github.com/stretchr/testify/assert" 13 "github.com/stretchr/testify/require" 14 15 "github.com/Finschia/ostracon/crypto" 16 ostsecp256k1 "github.com/Finschia/ostracon/crypto/secp256k1" 17 18 "github.com/Finschia/finschia-sdk/codec" 19 "github.com/Finschia/finschia-sdk/crypto/keys/ed25519" 20 "github.com/Finschia/finschia-sdk/crypto/keys/secp256k1" 21 cryptotypes "github.com/Finschia/finschia-sdk/crypto/types" 22 ) 23 24 type keyData struct { 25 priv string 26 pub string 27 addr string 28 } 29 30 var secpDataTable = []keyData{ 31 { 32 priv: "a96e62ed3955e65be32703f12d87b6b5cf26039ecfa948dc5107a495418e5330", 33 pub: "02950e1cdfcb133d6024109fd489f734eeb4502418e538c28481f22bce276f248c", 34 addr: "1CKZ9Nx4zgds8tU7nJHotKSDr4a9bYJCa3", 35 }, 36 } 37 38 func TestPubKeySecp256k1Address(t *testing.T) { 39 for _, d := range secpDataTable { 40 privB, _ := hex.DecodeString(d.priv) 41 pubB, _ := hex.DecodeString(d.pub) 42 addrBbz, _, _ := base58.CheckDecode(d.addr) 43 addrB := crypto.Address(addrBbz) 44 45 priv := secp256k1.PrivKey{Key: privB} 46 47 pubKey := priv.PubKey() 48 pubT, _ := pubKey.(*secp256k1.PubKey) 49 50 addr := pubKey.Address() 51 assert.Equal(t, pubT, &secp256k1.PubKey{Key: pubB}, "Expected pub keys to match") 52 assert.Equal(t, addr, addrB, "Expected addresses to match") 53 } 54 } 55 56 func TestSignAndValidateSecp256k1(t *testing.T) { 57 privKey := secp256k1.GenPrivKey() 58 pubKey := privKey.PubKey() 59 60 msg := crypto.CRandBytes(1000) 61 sig, err := privKey.Sign(msg) 62 require.Nil(t, err) 63 assert.True(t, pubKey.VerifySignature(msg, sig)) 64 65 // ---- 66 // Test cross packages verification 67 msgHash := crypto.Sha256(msg) 68 btcPrivKey, btcPubKey := btcSecp256k1.PrivKeyFromBytes(btcSecp256k1.S256(), privKey.Key) 69 // This fails: malformed signature: no header magic 70 // btcSig, err := secp256k1.ParseSignature(sig, secp256k1.S256()) 71 // require.NoError(t, err) 72 // assert.True(t, btcSig.Verify(msgHash, btcPubKey)) 73 // So we do a hacky way: 74 r := new(big.Int) 75 s := new(big.Int) 76 r.SetBytes(sig[:32]) 77 s.SetBytes(sig[32:]) 78 ok := ecdsa.Verify(btcPubKey.ToECDSA(), msgHash, r, s) 79 require.True(t, ok) 80 81 sig2, err := btcPrivKey.Sign(msgHash) 82 require.NoError(t, err) 83 pubKey.VerifySignature(msg, sig2.Serialize()) 84 85 // ---- 86 // Mutate the signature, just one bit. 87 sig[3] ^= byte(0x01) 88 assert.False(t, pubKey.VerifySignature(msg, sig)) 89 } 90 91 // This test is intended to justify the removal of calls to the underlying library 92 // in creating the privkey. 93 func TestSecp256k1LoadPrivkeyAndSerializeIsIdentity(t *testing.T) { 94 numberOfTests := 256 95 for i := 0; i < numberOfTests; i++ { 96 // Seed the test case with some random bytes 97 privKeyBytes := [32]byte{} 98 copy(privKeyBytes[:], crypto.CRandBytes(32)) 99 100 // This function creates a private and public key in the underlying libraries format. 101 // The private key is basically calling new(big.Int).SetBytes(pk), which removes leading zero bytes 102 priv, _ := btcSecp256k1.PrivKeyFromBytes(btcSecp256k1.S256(), privKeyBytes[:]) 103 // this takes the bytes returned by `(big int).Bytes()`, and if the length is less than 32 bytes, 104 // pads the bytes from the left with zero bytes. Therefore these two functions composed 105 // result in the identity function on privKeyBytes, hence the following equality check 106 // always returning true. 107 serializedBytes := priv.Serialize() 108 require.Equal(t, privKeyBytes[:], serializedBytes) 109 } 110 } 111 112 func TestGenPrivKeyFromSecret(t *testing.T) { 113 // curve oder N 114 N := btcSecp256k1.S256().N 115 tests := []struct { 116 name string 117 secret []byte 118 }{ 119 {"empty secret", []byte{}}, 120 { 121 "some long secret", 122 []byte("We live in a society exquisitely dependent on science and technology, " + 123 "in which hardly anyone knows anything about science and technology."), 124 }, 125 {"another seed used in cosmos tests #1", []byte{0}}, 126 {"another seed used in cosmos tests #2", []byte("mySecret")}, 127 {"another seed used in cosmos tests #3", []byte("")}, 128 } 129 for _, tt := range tests { 130 tt := tt 131 t.Run(tt.name, func(t *testing.T) { 132 gotPrivKey := secp256k1.GenPrivKeyFromSecret(tt.secret) 133 require.NotNil(t, gotPrivKey) 134 // interpret as a big.Int and make sure it is a valid field element: 135 fe := new(big.Int).SetBytes(gotPrivKey.Key[:]) 136 require.True(t, fe.Cmp(N) < 0) 137 require.True(t, fe.Sign() > 0) 138 }) 139 } 140 } 141 142 func TestPubKeyEquals(t *testing.T) { 143 secp256K1PubKey := secp256k1.GenPrivKey().PubKey().(*secp256k1.PubKey) 144 145 testCases := []struct { 146 msg string 147 pubKey cryptotypes.PubKey 148 other cryptotypes.PubKey 149 expectEq bool 150 }{ 151 { 152 "different bytes", 153 secp256K1PubKey, 154 secp256k1.GenPrivKey().PubKey(), 155 false, 156 }, 157 { 158 "equals", 159 secp256K1PubKey, 160 &secp256k1.PubKey{ 161 Key: secp256K1PubKey.Key, 162 }, 163 true, 164 }, 165 { 166 "different types", 167 secp256K1PubKey, 168 ed25519.GenPrivKey().PubKey(), 169 false, 170 }, 171 } 172 173 for _, tc := range testCases { 174 t.Run(tc.msg, func(t *testing.T) { 175 eq := tc.pubKey.Equals(tc.other) 176 require.Equal(t, eq, tc.expectEq) 177 }) 178 } 179 } 180 181 func TestPrivKeyEquals(t *testing.T) { 182 secp256K1PrivKey := secp256k1.GenPrivKey() 183 184 testCases := []struct { 185 msg string 186 privKey cryptotypes.PrivKey 187 other cryptotypes.PrivKey 188 expectEq bool 189 }{ 190 { 191 "different bytes", 192 secp256K1PrivKey, 193 secp256k1.GenPrivKey(), 194 false, 195 }, 196 { 197 "equals", 198 secp256K1PrivKey, 199 &secp256k1.PrivKey{ 200 Key: secp256K1PrivKey.Key, 201 }, 202 true, 203 }, 204 { 205 "different types", 206 secp256K1PrivKey, 207 ed25519.GenPrivKey(), 208 false, 209 }, 210 } 211 212 for _, tc := range testCases { 213 t.Run(tc.msg, func(t *testing.T) { 214 eq := tc.privKey.Equals(tc.other) 215 require.Equal(t, eq, tc.expectEq) 216 }) 217 } 218 } 219 220 func TestMarshalAmino(t *testing.T) { 221 aminoCdc := codec.NewLegacyAmino() 222 privKey := secp256k1.GenPrivKey() 223 pubKey := privKey.PubKey().(*secp256k1.PubKey) 224 225 testCases := []struct { 226 desc string 227 msg codec.AminoMarshaler 228 typ interface{} 229 expBinary []byte 230 expJSON string 231 }{ 232 { 233 "secp256k1 private key", 234 privKey, 235 &secp256k1.PrivKey{}, 236 append([]byte{32}, privKey.Bytes()...), // Length-prefixed. 237 "\"" + base64.StdEncoding.EncodeToString(privKey.Bytes()) + "\"", 238 }, 239 { 240 "secp256k1 public key", 241 pubKey, 242 &secp256k1.PubKey{}, 243 append([]byte{33}, pubKey.Bytes()...), // Length-prefixed. 244 "\"" + base64.StdEncoding.EncodeToString(pubKey.Bytes()) + "\"", 245 }, 246 } 247 248 for _, tc := range testCases { 249 t.Run(tc.desc, func(t *testing.T) { 250 // Do a round trip of encoding/decoding binary. 251 bz, err := aminoCdc.Marshal(tc.msg) 252 require.NoError(t, err) 253 require.Equal(t, tc.expBinary, bz) 254 255 err = aminoCdc.Unmarshal(bz, tc.typ) 256 require.NoError(t, err) 257 258 require.Equal(t, tc.msg, tc.typ) 259 260 // Do a round trip of encoding/decoding JSON. 261 bz, err = aminoCdc.MarshalJSON(tc.msg) 262 require.NoError(t, err) 263 require.Equal(t, tc.expJSON, string(bz)) 264 265 err = aminoCdc.UnmarshalJSON(bz, tc.typ) 266 require.NoError(t, err) 267 268 require.Equal(t, tc.msg, tc.typ) 269 }) 270 } 271 } 272 273 func TestMarshalAmino_BackwardsCompatibility(t *testing.T) { 274 aminoCdc := codec.NewLegacyAmino() 275 // Create Tendermint keys. 276 ostPrivKey := ostsecp256k1.GenPrivKey() 277 ostPubKey := ostPrivKey.PubKey() 278 // Create our own keys, with the same private key as Tendermint's. 279 privKey := &secp256k1.PrivKey{Key: []byte(ostPrivKey)} 280 pubKey := privKey.PubKey().(*secp256k1.PubKey) 281 282 testCases := []struct { 283 desc string 284 ostKey interface{} 285 ourKey interface{} 286 marshalFn func(o interface{}) ([]byte, error) 287 }{ 288 { 289 "secp256k1 private key, binary", 290 ostPrivKey, 291 privKey, 292 aminoCdc.Marshal, 293 }, 294 { 295 "secp256k1 private key, JSON", 296 ostPrivKey, 297 privKey, 298 aminoCdc.MarshalJSON, 299 }, 300 { 301 "secp256k1 public key, binary", 302 ostPubKey, 303 pubKey, 304 aminoCdc.Marshal, 305 }, 306 { 307 "secp256k1 public key, JSON", 308 ostPubKey, 309 pubKey, 310 aminoCdc.MarshalJSON, 311 }, 312 } 313 314 for _, tc := range testCases { 315 t.Run(tc.desc, func(t *testing.T) { 316 // Make sure Amino encoding override is not breaking backwards compatibility. 317 bz1, err := tc.marshalFn(tc.ostKey) 318 require.NoError(t, err) 319 bz2, err := tc.marshalFn(tc.ourKey) 320 require.NoError(t, err) 321 require.Equal(t, bz1, bz2) 322 }) 323 } 324 }