Skip to content

Commit

Permalink
add priv/pub key for ethereum (#40)
Browse files Browse the repository at this point in the history
Add wrapper for ethereum private/pub key

Add is ethereum check

When no option given, default as no applyHash

Add option for sign: applyHash sign the raw mesaage or sign the hash
of the msg

Change pubkey to pointer type

Update signature_test

Add hasher input test

When sign input is already a hash, don't hash again

Add signature for keccak256

Add eth keccak256ecdsa
  • Loading branch information
rongyi authored and laizy committed Jul 7, 2021
1 parent 7eba89b commit e79254d
Show file tree
Hide file tree
Showing 9 changed files with 277 additions and 7 deletions.
8 changes: 8 additions & 0 deletions ec/key.go
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,14 @@ type PublicKey struct {
*ecdsa.PublicKey
}

type EthereumPrivateKey struct {
*ecdsa.PrivateKey
}

type EthereumPublicKey struct {
*ecdsa.PublicKey
}

func (this *PrivateKey) Public() crypto.PublicKey {
return &PublicKey{Algorithm: this.Algorithm, PublicKey: &this.PublicKey}
}
Expand Down
1 change: 1 addition & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ require (
github.com/btcsuite/btcd v0.20.1-beta
github.com/ethereum/go-ethereum v1.9.13
github.com/itchyny/base58-go v0.1.0
github.com/stretchr/testify v1.4.0
golang.org/x/crypto v0.0.0-20200311171314-f7b00557c8c4
)

Expand Down
5 changes: 5 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ github.com/cloudflare/cloudflare-go v0.10.2-0.20190916151808-a80f83b9add9/go.mod
github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
github.com/davecgh/go-spew v0.0.0-20171005155431-ecdeabc65495/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/deckarep/golang-set v0.0.0-20180603214616-504e848d77ea/go.mod h1:93vsz/8Wt4joVM7c2AVqh+YRMiUSc14yDtF28KmMOgQ=
github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ=
Expand Down Expand Up @@ -109,6 +110,7 @@ github.com/pborman/uuid v0.0.0-20170112150404-1b00554d8222/go.mod h1:VyrYX9gd7ir
github.com/peterh/liner v1.1.1-0.20190123174540-a2c9a5303de7/go.mod h1:CRroGNssyjTd/qIG2FyxByd2S8JEAZXBl4qUrZf8GS0=
github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw=
github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo=
Expand All @@ -128,6 +130,7 @@ github.com/steakknife/hamming v0.0.0-20180906055917-c99c65617cd3/go.mod h1:hpGUW
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJyk=
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
github.com/syndtr/goleveldb v1.0.1-0.20190923125748-758128399b1d/go.mod h1:9OrXJhf154huy1nPWmuSrkgjPUtUNhA+Zmy+6AESzuA=
github.com/tyler-smith/go-bip39 v1.0.1-0.20181017060643-dbb3b84ba2ef/go.mod h1:sJ5fKU0s6JVwZjjcUEX2zFOnvq0ASQ2K9Zr6cf67kNs=
Expand All @@ -142,6 +145,7 @@ golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5h
golang.org/x/sys v0.0.0-20181107165924-66b7b1311ac8/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527 h1:uYVVQ9WP/Ds2ROhcaGPeIdVq0RIXVLwsHlnvJ+cT1So=
golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
Expand All @@ -156,5 +160,6 @@ gopkg.in/olebedev/go-duktape.v3 v3.0.0-20200316214253-d7b0ff38cac9/go.mod h1:uAJ
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=
gopkg.in/urfave/cli.v1 v1.20.0/go.mod h1:vuBzUtMdQeixQj8LVd+/98pzhxNGQoyuPBlsXHOQNO0=
gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw=
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gotest.tools v2.2.0+incompatible/go.mod h1:DsYFclhRJ6vuDpmuTbkuFWG+y2sxOXAzmJt81HFBacw=
62 changes: 58 additions & 4 deletions keypair/key.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ package keypair
import (
"bytes"
"crypto"
"crypto/ecdsa"
"crypto/elliptic"
"crypto/rand"
"crypto/sha256"
Expand All @@ -37,9 +38,9 @@ import (
"math/big"
"reflect"

ethcrypto "github.com/ethereum/go-ethereum/crypto"
base58 "github.com/itchyny/base58-go"
"github.com/ontio/ontology-crypto/ec"

"golang.org/x/crypto/ed25519"
)

Expand All @@ -54,15 +55,20 @@ type KeyType byte

// Supported key types
const (
PK_ECDSA KeyType = 0x12
PK_SM2 KeyType = 0x13
PK_EDDSA KeyType = 0x14
PK_ECDSA KeyType = 0x12
PK_SM2 KeyType = 0x13
PK_EDDSA KeyType = 0x14
PK_ETHECDSA KeyType = 0x15

PK_P256_E KeyType = 0x02
PK_P256_O KeyType = 0x03
PK_P256_NC KeyType = 0x04
)

var (
notEtherErr = errors.New("pubkey is not ethereum publickey")
)

const err_generate = "key pair generation failed, "

// GenerateKeyPair generates a pair of private and public keys in type t.
Expand Down Expand Up @@ -100,6 +106,15 @@ func GenerateKeyPair(t KeyType, opts interface{}) (PrivateKey, PublicKey, error)
} else {
return nil, nil, errors.New(err_generate + "unsupported EdDSA scheme")
}
case PK_ETHECDSA:
privateKeyECDSA, err := ecdsa.GenerateKey(ethcrypto.S256(), rand.Reader)
if err != nil {
return nil, nil, err
}
priWrapper := &ec.EthereumPrivateKey{privateKeyECDSA}
pubWrapper := &ec.EthereumPublicKey{&privateKeyECDSA.PublicKey}
return priWrapper, pubWrapper, nil

default:
return nil, nil, errors.New(err_generate + "unknown algorithm")
}
Expand All @@ -118,11 +133,23 @@ func GetKeyType(p PublicKey) KeyType {
}
case ed25519.PublicKey:
return PK_EDDSA
case *ec.EthereumPublicKey:
return PK_ETHECDSA
default:
panic("unknown public key type")
}
}

// GetEthereumPubKey get the underline key
func GetEthereumPubKey(p PublicKey) (*ec.EthereumPublicKey, error) {
switch ep := p.(type) {
case *ec.EthereumPublicKey:
return ep, nil
default:
return nil, notEtherErr
}
}

// SerializePublicKey serializes the public key to a byte sequence as the
// following format:
// |--------------------|-----------------|
Expand Down Expand Up @@ -171,6 +198,9 @@ func SerializePublicKey(key PublicKey) []byte {
buf.WriteByte(byte(PK_EDDSA))
buf.WriteByte(ED25519)
buf.Write([]byte(t))
case *ec.EthereumPublicKey:
buf.WriteByte(byte(PK_ETHECDSA))
buf.Write(ethcrypto.FromECDSAPub(t.PublicKey))
default:
panic("unknown public key type")
}
Expand Down Expand Up @@ -228,6 +258,13 @@ func DeserializePublicKey(data []byte) (PublicKey, error) {
PublicKey: pub,
}
return pk, nil
case PK_ETHECDSA:
epub, err := ethcrypto.UnmarshalPubkey(data[1:])
if err != nil {
return nil, err
}
w := &ec.EthereumPublicKey{epub}
return w, nil

default:
return nil, errors.New("deserializing public key failed: unrecognized algorithm label")
Expand Down Expand Up @@ -283,6 +320,10 @@ func SerializePrivateKey(pri PrivateKey) []byte {
buf.WriteByte(byte(PK_EDDSA))
buf.WriteByte(byte(ED25519))
buf.Write(t)
case *ec.EthereumPrivateKey:
buf.WriteByte(byte(PK_ETHECDSA))
buf.Write(ethcrypto.FromECDSA(t.PrivateKey))

default:
panic("unkown private key type")
}
Expand Down Expand Up @@ -338,7 +379,16 @@ func DeserializePrivateKey(data []byte) (pri PrivateKey, err error) {
err = errors.New("deserializing private key failed: unknown EdDSA curve type")
return
}
case PK_ETHECDSA:
epri, err := ethcrypto.ToECDSA(data[1:])
if err != nil {
return nil, err
}
w := &ec.EthereumPrivateKey{epri}
return w, nil

}

return
}

Expand All @@ -360,6 +410,10 @@ func ComparePublicKey(k0, k1 PublicKey) bool {
if bytes.Compare(v0, v1) == 0 {
return true
}
case *ec.EthereumPublicKey:
right := k1.(*ec.EthereumPublicKey)

return v0.PublicKey.Equal(right.PublicKey)
}

return false
Expand Down
39 changes: 39 additions & 0 deletions keypair/key_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,10 @@ import (
"math/big"
"testing"

"github.com/ethereum/go-ethereum/crypto"
"github.com/ontio/ontology-crypto/ec"
"github.com/ontio/ontology-crypto/sm2"
"github.com/stretchr/testify/require"
)

func TestKeyPairGeneration(t *testing.T) {
Expand Down Expand Up @@ -235,3 +237,40 @@ func TestSecp256k1Key(t *testing.T) {
t.Fatal("deserialized public key not equal")
}
}

func TestGenerateEth(t *testing.T) {
a := require.New(t)
pri, pub, err := GenerateKeyPair(PK_ETHECDSA, nil)
a.Nil(err, "fail")

tp := GetKeyType(pub)
a.Equal(tp, PK_ETHECDSA, "fail")

b := SerializePublicKey(pub)
seriPub, err := DeserializePublicKey(b)
a.Nil(err, "fail")
a.True(ComparePublicKey(pub, seriPub), "fail")

epub, ok := pub.(*ec.EthereumPublicKey)
a.True(ok, "fail cast")
eb := crypto.FromECDSAPub(epub.PublicKey)
a.Equal(b[1:], eb, "fail")
a.Equal(b[0], byte(PK_ETHECDSA), "fail")

epri, ok := pri.(*ec.EthereumPrivateKey)
a.True(ok, "fail to cast")

eprib := crypto.FromECDSA(epri.PrivateKey)
b = SerializePrivateKey(pri)
a.Equal(b[1:], eprib, "fail")
a.Equal(b[0], byte(PK_ETHECDSA), "fail")

_, err = DeserializePrivateKey(b)
a.Nil(err, "fail")

a.True(ComparePublicKey(pub, pub))

_, pub2, err := GenerateKeyPair(PK_ETHECDSA, nil)
a.Nil(err, "fail")
a.False(ComparePublicKey(pub, pub2))
}
9 changes: 8 additions & 1 deletion signature/scheme.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,9 @@ import (
// the following blank imports ensures these packages are linked
_ "crypto/sha256"
_ "crypto/sha512"

_ "golang.org/x/crypto/ripemd160"
"golang.org/x/crypto/sha3"
_ "golang.org/x/crypto/sha3"
)

Expand All @@ -50,6 +52,8 @@ const (
SM3withSM2

SHA512withEDDSA

KECCAK256WithECDSA // ethereum method
)

var names []string = []string{
Expand All @@ -64,6 +68,7 @@ var names []string = []string{
"RIPEMD160withECDSA",
"SM3withSM2",
"SHA512withEdDSA",
"KECCAK256WithECDSA",
}

func (s SignatureScheme) Name() string {
Expand All @@ -75,7 +80,7 @@ func (s SignatureScheme) Name() string {

func GetScheme(name string) (SignatureScheme, error) {
for i, v := range names {
if strings.ToUpper(v) == strings.ToUpper(name) {
if strings.EqualFold(v, name) {
return SignatureScheme(i), nil
}
}
Expand Down Expand Up @@ -107,6 +112,8 @@ func GetHash(scheme SignatureScheme) hash.Hash {
return sm3.New()
case SHA512withEDDSA:
return crypto.SHA512.New()
case KECCAK256WithECDSA:
return sha3.NewLegacyKeccak256()
}
return nil
}
24 changes: 24 additions & 0 deletions signature/scheme_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package signature

import (
"encoding/hex"
"testing"

"github.com/stretchr/testify/require"
)

func TestScheme(t *testing.T) {
a := require.New(t)
a.Equal(KECCAK256WithECDSA, SignatureScheme(0x0b), "fail")
s := KECCAK256WithECDSA
a.Equal(s.Name(), "KECCAK256WithECDSA", "fail")
}

func TestGetHash(t *testing.T) {
a := require.New(t)

hasher := GetHash(KECCAK256WithECDSA)
h := hasher.Sum(nil)
// empty hash of keccak256 is value below: https://www.oreilly.com/library/view/mastering-ethereum/9781491971932/ch04.html
a.Equal("c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", hex.EncodeToString(h), "fail")
}
Loading

0 comments on commit e79254d

Please sign in to comment.