mirror of
https://github.com/fluencelabs/tendermint
synced 2025-07-30 19:51:58 +00:00
Add secp256k1 support
This commit is contained in:
73
priv_key.go
73
priv_key.go
@@ -1,6 +1,7 @@
|
||||
package crypto
|
||||
|
||||
import (
|
||||
secp256k1 "github.com/btcsuite/btcd/btcec"
|
||||
"github.com/tendermint/ed25519"
|
||||
"github.com/tendermint/ed25519/extra25519"
|
||||
. "github.com/tendermint/go-common"
|
||||
@@ -16,13 +17,15 @@ type PrivKey interface {
|
||||
|
||||
// Types of PrivKey implementations
|
||||
const (
|
||||
PrivKeyTypeEd25519 = byte(0x01)
|
||||
PrivKeyTypeEd25519 = byte(0x01)
|
||||
PrivKeyTypeSecp256k1 = byte(0x02)
|
||||
)
|
||||
|
||||
// for wire.readReflect
|
||||
var _ = wire.RegisterInterface(
|
||||
struct{ PrivKey }{},
|
||||
wire.ConcreteType{PrivKeyEd25519{}, PrivKeyTypeEd25519},
|
||||
wire.ConcreteType{PrivKeySecp256k1{}, PrivKeyTypeSecp256k1},
|
||||
)
|
||||
|
||||
func PrivKeyFromBytes(privKeyBytes []byte) (privKey PrivKey, err error) {
|
||||
@@ -39,8 +42,8 @@ func (privKey PrivKeyEd25519) Bytes() []byte {
|
||||
return wire.BinaryBytes(struct{ PrivKey }{privKey})
|
||||
}
|
||||
|
||||
func (key PrivKeyEd25519) Sign(msg []byte) Signature {
|
||||
privKeyBytes := [64]byte(key)
|
||||
func (privKey PrivKeyEd25519) Sign(msg []byte) Signature {
|
||||
privKeyBytes := [64]byte(privKey)
|
||||
signatureBytes := ed25519.Sign(&privKeyBytes, msg)
|
||||
return SignatureEd25519(*signatureBytes)
|
||||
}
|
||||
@@ -62,11 +65,11 @@ func (privKey PrivKeyEd25519) String() string {
|
||||
}
|
||||
|
||||
// Deterministically generates new priv-key bytes from key.
|
||||
func (key PrivKeyEd25519) Generate(index int) PrivKeyEd25519 {
|
||||
func (privKey PrivKeyEd25519) Generate(index int) PrivKeyEd25519 {
|
||||
newBytes := wire.BinarySha256(struct {
|
||||
PrivKey [64]byte
|
||||
Index int
|
||||
}{key, index})
|
||||
}{privKey, index})
|
||||
var newKey [64]byte
|
||||
copy(newKey[:], newBytes)
|
||||
return PrivKeyEd25519(newKey)
|
||||
@@ -88,3 +91,63 @@ func GenPrivKeyEd25519FromSecret(secret []byte) PrivKeyEd25519 {
|
||||
ed25519.MakePublicKey(privKeyBytes)
|
||||
return PrivKeyEd25519(*privKeyBytes)
|
||||
}
|
||||
|
||||
//-------------------------------------
|
||||
|
||||
// Implements PrivKey
|
||||
type PrivKeySecp256k1 [32]byte
|
||||
|
||||
func (privKey PrivKeySecp256k1) Bytes() []byte {
|
||||
return wire.BinaryBytes(struct{ PrivKey }{privKey})
|
||||
}
|
||||
|
||||
func (privKey PrivKeySecp256k1) Sign(msg []byte) Signature {
|
||||
priv__, _ := secp256k1.PrivKeyFromBytes(secp256k1.S256(), privKey[:])
|
||||
sig__, err := priv__.Sign(Sha256(msg))
|
||||
if err != nil {
|
||||
PanicSanity(err)
|
||||
}
|
||||
return SignatureSecp256k1(sig__.Serialize())
|
||||
}
|
||||
|
||||
func (privKey PrivKeySecp256k1) PubKey() PubKey {
|
||||
_, pub__ := secp256k1.PrivKeyFromBytes(secp256k1.S256(), privKey[:])
|
||||
pub := [65]byte{}
|
||||
copy(pub[:], pub__.SerializeUncompressed())
|
||||
return PubKeySecp256k1(pub)
|
||||
}
|
||||
|
||||
func (privKey PrivKeySecp256k1) String() string {
|
||||
return Fmt("PrivKeySecp256k1{*****}")
|
||||
}
|
||||
|
||||
/*
|
||||
// Deterministically generates new priv-key bytes from key.
|
||||
func (key PrivKeySecp256k1) Generate(index int) PrivKeySecp256k1 {
|
||||
newBytes := wire.BinarySha256(struct {
|
||||
PrivKey [64]byte
|
||||
Index int
|
||||
}{key, index})
|
||||
var newKey [64]byte
|
||||
copy(newKey[:], newBytes)
|
||||
return PrivKeySecp256k1(newKey)
|
||||
}
|
||||
*/
|
||||
|
||||
func GenPrivKeySecp256k1() PrivKeySecp256k1 {
|
||||
privKeyBytes := [32]byte{}
|
||||
copy(privKeyBytes[:], CRandBytes(32))
|
||||
priv, _ := secp256k1.PrivKeyFromBytes(secp256k1.S256(), privKeyBytes[:])
|
||||
copy(privKeyBytes[:], priv.Serialize())
|
||||
return PrivKeySecp256k1(privKeyBytes)
|
||||
}
|
||||
|
||||
// NOTE: secret should be the output of a KDF like bcrypt,
|
||||
// if it's derived from user input.
|
||||
func GenPrivKeySecp256k1FromSecret(secret []byte) PrivKeySecp256k1 {
|
||||
privKey32 := Sha256(secret) // Not Ripemd160 because we want 32 bytes.
|
||||
priv, _ := secp256k1.PrivKeyFromBytes(secp256k1.S256(), privKey32)
|
||||
privKeyBytes := [32]byte{}
|
||||
copy(privKeyBytes[:], priv.Serialize())
|
||||
return PrivKeySecp256k1(privKeyBytes)
|
||||
}
|
||||
|
64
pub_key.go
64
pub_key.go
@@ -3,6 +3,7 @@ package crypto
|
||||
import (
|
||||
"bytes"
|
||||
|
||||
secp256k1 "github.com/btcsuite/btcd/btcec"
|
||||
"github.com/tendermint/ed25519"
|
||||
"github.com/tendermint/ed25519/extra25519"
|
||||
. "github.com/tendermint/go-common"
|
||||
@@ -21,13 +22,15 @@ type PubKey interface {
|
||||
|
||||
// Types of PubKey implementations
|
||||
const (
|
||||
PubKeyTypeEd25519 = byte(0x01)
|
||||
PubKeyTypeEd25519 = byte(0x01)
|
||||
PubKeyTypeSecp256k1 = byte(0x02)
|
||||
)
|
||||
|
||||
// for wire.readReflect
|
||||
var _ = wire.RegisterInterface(
|
||||
struct{ PubKey }{},
|
||||
wire.ConcreteType{PubKeyEd25519{}, PubKeyTypeEd25519},
|
||||
wire.ConcreteType{PubKeySecp256k1{}, PubKeyTypeSecp256k1},
|
||||
)
|
||||
|
||||
func PubKeyFromBytes(pubKeyBytes []byte) (pubKey PubKey, err error) {
|
||||
@@ -47,7 +50,7 @@ func (pubKey PubKeyEd25519) Address() []byte {
|
||||
PanicCrisis(*err)
|
||||
}
|
||||
// append type byte
|
||||
encodedPubkey := append([]byte{1}, w.Bytes()...)
|
||||
encodedPubkey := append([]byte{PubKeyTypeEd25519}, w.Bytes()...)
|
||||
hasher := ripemd160.New()
|
||||
hasher.Write(encodedPubkey) // does not error
|
||||
return hasher.Sum(nil)
|
||||
@@ -57,7 +60,6 @@ func (pubKey PubKeyEd25519) Bytes() []byte {
|
||||
return wire.BinaryBytes(struct{ PubKey }{pubKey})
|
||||
}
|
||||
|
||||
// TODO: Consider returning a reason for failure, or logging a runtime type mismatch.
|
||||
func (pubKey PubKeyEd25519) VerifyBytes(msg []byte, sig_ Signature) bool {
|
||||
sig, ok := sig_.(SignatureEd25519)
|
||||
if !ok {
|
||||
@@ -96,3 +98,59 @@ func (pubKey PubKeyEd25519) Equals(other PubKey) bool {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
//-------------------------------------
|
||||
|
||||
// Implements PubKey
|
||||
type PubKeySecp256k1 [65]byte
|
||||
|
||||
func (pubKey PubKeySecp256k1) Address() []byte {
|
||||
w, n, err := new(bytes.Buffer), new(int), new(error)
|
||||
wire.WriteBinary(pubKey[:], w, n, err)
|
||||
if *err != nil {
|
||||
PanicCrisis(*err)
|
||||
}
|
||||
// append type byte
|
||||
encodedPubkey := append([]byte{PubKeyTypeSecp256k1}, w.Bytes()...)
|
||||
hasher := ripemd160.New()
|
||||
hasher.Write(encodedPubkey) // does not error
|
||||
return hasher.Sum(nil)
|
||||
}
|
||||
|
||||
func (pubKey PubKeySecp256k1) Bytes() []byte {
|
||||
return wire.BinaryBytes(struct{ PubKey }{pubKey})
|
||||
}
|
||||
|
||||
func (pubKey PubKeySecp256k1) VerifyBytes(msg []byte, sig_ Signature) bool {
|
||||
pub__, err := secp256k1.ParsePubKey(pubKey[:], secp256k1.S256())
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
sig, ok := sig_.(SignatureSecp256k1)
|
||||
if !ok {
|
||||
return false
|
||||
}
|
||||
sig__, err := secp256k1.ParseDERSignature(sig[:], secp256k1.S256())
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
return sig__.Verify(Sha256(msg), pub__)
|
||||
}
|
||||
|
||||
func (pubKey PubKeySecp256k1) String() string {
|
||||
return Fmt("PubKeySecp256k1{%X}", pubKey[:])
|
||||
}
|
||||
|
||||
// Must return the full bytes in hex.
|
||||
// Used for map keying, etc.
|
||||
func (pubKey PubKeySecp256k1) KeyString() string {
|
||||
return Fmt("%X", pubKey[:])
|
||||
}
|
||||
|
||||
func (pubKey PubKeySecp256k1) Equals(other PubKey) bool {
|
||||
if otherEd, ok := other.(PubKeySecp256k1); ok {
|
||||
return bytes.Equal(pubKey[:], otherEd[:])
|
||||
} else {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
17
signature.go
17
signature.go
@@ -16,13 +16,15 @@ type Signature interface {
|
||||
|
||||
// Types of Signature implementations
|
||||
const (
|
||||
SignatureTypeEd25519 = byte(0x01)
|
||||
SignatureTypeEd25519 = byte(0x01)
|
||||
SignatureTypeSecp256k1 = byte(0x02)
|
||||
)
|
||||
|
||||
// for wire.readReflect
|
||||
var _ = wire.RegisterInterface(
|
||||
struct{ Signature }{},
|
||||
wire.ConcreteType{SignatureEd25519{}, SignatureTypeEd25519},
|
||||
wire.ConcreteType{SignatureSecp256k1{}, SignatureTypeSecp256k1},
|
||||
)
|
||||
|
||||
//-------------------------------------
|
||||
@@ -37,3 +39,16 @@ func (sig SignatureEd25519) Bytes() []byte {
|
||||
func (sig SignatureEd25519) IsZero() bool { return len(sig) == 0 }
|
||||
|
||||
func (sig SignatureEd25519) String() string { return fmt.Sprintf("/%X.../", Fingerprint(sig[:])) }
|
||||
|
||||
//-------------------------------------
|
||||
|
||||
// Implements Signature
|
||||
type SignatureSecp256k1 []byte
|
||||
|
||||
func (sig SignatureSecp256k1) Bytes() []byte {
|
||||
return wire.BinaryBytes(struct{ Signature }{sig})
|
||||
}
|
||||
|
||||
func (sig SignatureSecp256k1) IsZero() bool { return len(sig) == 0 }
|
||||
|
||||
func (sig SignatureSecp256k1) String() string { return fmt.Sprintf("/%X.../", Fingerprint(sig[:])) }
|
||||
|
@@ -8,7 +8,7 @@ import (
|
||||
"github.com/tendermint/go-wire"
|
||||
)
|
||||
|
||||
func TestSignAndValidate(t *testing.T) {
|
||||
func TestSignAndValidateEd25519(t *testing.T) {
|
||||
|
||||
privKey := GenPrivKeyEd25519()
|
||||
pubKey := privKey.PubKey()
|
||||
@@ -32,7 +32,31 @@ func TestSignAndValidate(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestBinaryDecode(t *testing.T) {
|
||||
func TestSignAndValidateSecp256k1(t *testing.T) {
|
||||
|
||||
privKey := GenPrivKeySecp256k1()
|
||||
pubKey := privKey.PubKey()
|
||||
|
||||
msg := CRandBytes(128)
|
||||
sig := privKey.Sign(msg)
|
||||
t.Logf("msg: %X, sig: %X", msg, sig)
|
||||
|
||||
// Test the signature
|
||||
if !pubKey.VerifyBytes(msg, sig) {
|
||||
t.Errorf("Account message signature verification failed")
|
||||
}
|
||||
|
||||
// Mutate the signature, just one bit.
|
||||
sigEd := sig.(SignatureSecp256k1)
|
||||
sigEd[0] ^= byte(0x01)
|
||||
sig = Signature(sigEd)
|
||||
|
||||
if pubKey.VerifyBytes(msg, sig) {
|
||||
t.Errorf("Account message signature verification should have failed but passed instead")
|
||||
}
|
||||
}
|
||||
|
||||
func TestBinaryDecodeEd25519(t *testing.T) {
|
||||
|
||||
privKey := GenPrivKeyEd25519()
|
||||
pubKey := privKey.PubKey()
|
||||
@@ -66,3 +90,34 @@ func TestBinaryDecode(t *testing.T) {
|
||||
t.Errorf("Account message signature verification failed")
|
||||
}
|
||||
}
|
||||
|
||||
func TestBinaryDecodeSecp256k1(t *testing.T) {
|
||||
|
||||
privKey := GenPrivKeySecp256k1()
|
||||
pubKey := privKey.PubKey()
|
||||
|
||||
msg := CRandBytes(128)
|
||||
sig := privKey.Sign(msg)
|
||||
t.Logf("msg: %X, sig: %X", msg, sig)
|
||||
|
||||
buf, n, err := new(bytes.Buffer), new(int), new(error)
|
||||
wire.WriteBinary(struct{ Signature }{sig}, buf, n, err)
|
||||
if *err != nil {
|
||||
t.Fatalf("Failed to write Signature: %v", err)
|
||||
}
|
||||
|
||||
if buf.Bytes()[0] != SignatureTypeSecp256k1 {
|
||||
t.Fatalf("Unexpected signature type byte")
|
||||
}
|
||||
|
||||
sigStruct := struct{ Signature }{}
|
||||
sig2 := wire.ReadBinary(sigStruct, buf, 0, n, err)
|
||||
if *err != nil {
|
||||
t.Fatalf("Failed to read Signature: %v", err)
|
||||
}
|
||||
|
||||
// Test the signature
|
||||
if !pubKey.VerifyBytes(msg, sig2.(struct{ Signature }).Signature.(SignatureSecp256k1)) {
|
||||
t.Errorf("Account message signature verification failed")
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user