2018-07-18 08:38:44 -07:00
package secp256k1_test
2018-06-20 15:30:44 -07:00
import (
"encoding/hex"
2019-04-01 19:45:57 -04:00
"math/big"
2018-06-20 15:30:44 -07:00
"testing"
"github.com/btcsuite/btcutil/base58"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
2018-07-18 08:38:44 -07:00
"github.com/tendermint/tendermint/crypto"
"github.com/tendermint/tendermint/crypto/secp256k1"
2018-07-20 21:52:04 -07:00
2019-02-04 09:24:54 +01:00
underlyingSecp256k1 "github.com/btcsuite/btcd/btcec"
2018-06-20 15:30:44 -07:00
)
type keyData struct {
priv string
pub string
addr string
}
var secpDataTable = [ ] keyData {
{
priv : "a96e62ed3955e65be32703f12d87b6b5cf26039ecfa948dc5107a495418e5330" ,
pub : "02950e1cdfcb133d6024109fd489f734eeb4502418e538c28481f22bce276f248c" ,
addr : "1CKZ9Nx4zgds8tU7nJHotKSDr4a9bYJCa3" ,
} ,
}
func TestPubKeySecp256k1Address ( t * testing . T ) {
for _ , d := range secpDataTable {
privB , _ := hex . DecodeString ( d . priv )
pubB , _ := hex . DecodeString ( d . pub )
addrBbz , _ , _ := base58 . CheckDecode ( d . addr )
2018-07-18 08:38:44 -07:00
addrB := crypto . Address ( addrBbz )
2018-06-20 15:30:44 -07:00
2018-07-18 08:38:44 -07:00
var priv secp256k1 . PrivKeySecp256k1
2018-06-20 15:30:44 -07:00
copy ( priv [ : ] , privB )
pubKey := priv . PubKey ( )
2018-07-18 08:38:44 -07:00
pubT , _ := pubKey . ( secp256k1 . PubKeySecp256k1 )
2018-06-20 15:30:44 -07:00
pub := pubT [ : ]
addr := pubKey . Address ( )
assert . Equal ( t , pub , pubB , "Expected pub keys to match" )
assert . Equal ( t , addr , addrB , "Expected addresses to match" )
}
}
2018-07-18 08:38:44 -07:00
func TestSignAndValidateSecp256k1 ( t * testing . T ) {
2018-07-20 10:44:21 -07:00
privKey := secp256k1 . GenPrivKey ( )
2018-07-18 08:38:44 -07:00
pubKey := privKey . PubKey ( )
msg := crypto . CRandBytes ( 128 )
sig , err := privKey . Sign ( msg )
require . Nil ( t , err )
assert . True ( t , pubKey . VerifyBytes ( msg , sig ) )
// Mutate the signature, just one bit.
2018-08-01 17:02:05 -07:00
sig [ 3 ] ^ = byte ( 0x01 )
2018-07-18 08:38:44 -07:00
assert . False ( t , pubKey . VerifyBytes ( msg , sig ) )
2018-06-20 15:30:44 -07:00
}
2018-07-20 21:52:04 -07:00
// This test is intended to justify the removal of calls to the underlying library
// in creating the privkey.
func TestSecp256k1LoadPrivkeyAndSerializeIsIdentity ( t * testing . T ) {
numberOfTests := 256
for i := 0 ; i < numberOfTests ; i ++ {
// Seed the test case with some random bytes
privKeyBytes := [ 32 ] byte { }
copy ( privKeyBytes [ : ] , crypto . CRandBytes ( 32 ) )
// This function creates a private and public key in the underlying libraries format.
// The private key is basically calling new(big.Int).SetBytes(pk), which removes leading zero bytes
priv , _ := underlyingSecp256k1 . PrivKeyFromBytes ( underlyingSecp256k1 . S256 ( ) , privKeyBytes [ : ] )
// this takes the bytes returned by `(big int).Bytes()`, and if the length is less than 32 bytes,
// pads the bytes from the left with zero bytes. Therefore these two functions composed
// result in the identity function on privKeyBytes, hence the following equality check
// always returning true.
serializedBytes := priv . Serialize ( )
require . Equal ( t , privKeyBytes [ : ] , serializedBytes )
}
}
2019-04-01 19:45:57 -04:00
func TestGenPrivKeySecp256k1 ( t * testing . T ) {
// curve oder N
N := underlyingSecp256k1 . S256 ( ) . N
tests := [ ] struct {
name string
secret [ ] byte
} {
{ "empty secret" , [ ] byte { } } ,
{ "some long secret" , [ ] byte ( "We live in a society exquisitely dependent on science and technology, in which hardly anyone knows anything about science and technology." ) } ,
{ "another seed used in cosmos tests #1" , [ ] byte { 0 } } ,
{ "another seed used in cosmos tests #2" , [ ] byte ( "mySecret" ) } ,
{ "another seed used in cosmos tests #3" , [ ] byte ( "" ) } ,
}
for _ , tt := range tests {
t . Run ( tt . name , func ( t * testing . T ) {
gotPrivKey := secp256k1 . GenPrivKeySecp256k1 ( tt . secret )
require . NotNil ( t , gotPrivKey )
// interpret as a big.Int and make sure it is a valid field element:
fe := new ( big . Int ) . SetBytes ( gotPrivKey [ : ] )
require . True ( t , fe . Cmp ( N ) < 0 )
require . True ( t , fe . Sign ( ) > 0 )
} )
}
}