diff options
author | Wei-Ning Huang <w@dexon.org> | 2018-09-26 18:19:12 +0800 |
---|---|---|
committer | GitHub <noreply@github.com> | 2018-09-26 18:19:12 +0800 |
commit | 9c2f700be09c27e8a8d12fc5bc0ccd017d408a32 (patch) | |
tree | bde8e80468af8535c8652210017553e2ed830d62 /core/crypto/ecdsa | |
parent | 0398468051068720688199442f53984b4071f4b2 (diff) | |
download | dexon-consensus-9c2f700be09c27e8a8d12fc5bc0ccd017d408a32.tar dexon-consensus-9c2f700be09c27e8a8d12fc5bc0ccd017d408a32.tar.gz dexon-consensus-9c2f700be09c27e8a8d12fc5bc0ccd017d408a32.tar.bz2 dexon-consensus-9c2f700be09c27e8a8d12fc5bc0ccd017d408a32.tar.lz dexon-consensus-9c2f700be09c27e8a8d12fc5bc0ccd017d408a32.tar.xz dexon-consensus-9c2f700be09c27e8a8d12fc5bc0ccd017d408a32.tar.zst dexon-consensus-9c2f700be09c27e8a8d12fc5bc0ccd017d408a32.zip |
core: rename crypto/eth to crypto/ecdsa (#144)
Diffstat (limited to 'core/crypto/ecdsa')
-rw-r--r-- | core/crypto/ecdsa/ecdsa.go | 130 | ||||
-rw-r--r-- | core/crypto/ecdsa/ecdsa_test.go | 93 |
2 files changed, 223 insertions, 0 deletions
diff --git a/core/crypto/ecdsa/ecdsa.go b/core/crypto/ecdsa/ecdsa.go new file mode 100644 index 0000000..5f98395 --- /dev/null +++ b/core/crypto/ecdsa/ecdsa.go @@ -0,0 +1,130 @@ +// Copyright 2018 The dexon-consensus-core Authors +// This file is part of the dexon-consensus-core library. +// +// The dexon-consensus-core library is free software: you can redistribute it +// and/or modify it under the terms of the GNU Lesser General Public License as +// published by the Free Software Foundation, either version 3 of the License, +// or (at your option) any later version. +// +// The dexon-consensus-core library is distributed in the hope that it will be +// useful, but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser +// General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with the dexon-consensus-core library. If not, see +// <http://www.gnu.org/licenses/>. + +package ecdsa + +import ( + "crypto/ecdsa" + + ethcrypto "github.com/dexon-foundation/dexon/crypto" + + "github.com/dexon-foundation/dexon-consensus-core/common" + "github.com/dexon-foundation/dexon-consensus-core/core/crypto" +) + +const cryptoType = "ecdsa" + +func init() { + crypto.RegisterSigToPub(cryptoType, SigToPub) +} + +// PrivateKey represents a private key structure used in geth and implments +// Crypto.PrivateKey interface. +type PrivateKey struct { + privateKey ecdsa.PrivateKey + publicKey publicKey +} + +// publicKey represents a public key structure used in geth and implements +// Crypto.PublicKey interface. +type publicKey struct { + publicKey []byte +} + +// NewPrivateKey creates a new PrivateKey structure. +func NewPrivateKey() (*PrivateKey, error) { + key, err := ethcrypto.GenerateKey() + if err != nil { + return nil, err + } + return &PrivateKey{ + privateKey: *key, + publicKey: *newPublicKey(key), + }, nil +} + +// newPublicKey creates a new PublicKey structure. +func newPublicKey(prvKey *ecdsa.PrivateKey) *publicKey { + return &publicKey{ + publicKey: ethcrypto.CompressPubkey(&prvKey.PublicKey), + } +} + +// decompressPubkey parses a public key in the 33-byte compressed format. +func decompressPubkey(pubkey []byte) (publicKey, error) { + _, err := ethcrypto.DecompressPubkey(pubkey) + return publicKey{ + publicKey: pubkey, + }, err +} + +// PublicKey returns the public key associate this private key. +func (prv *PrivateKey) PublicKey() crypto.PublicKey { + return prv.publicKey +} + +// Sign calculates an ECDSA signature. +// +// This function is susceptible to chosen plaintext attacks that can leak +// information about the private key that is used for signing. Callers must +// be aware that the given hash cannot be chosen by an adversery. Common +// solution is to hash any input before calculating the signature. +// +// The produced signature is in the [R || S || V] format where V is 0 or 1. +func (prv *PrivateKey) Sign(hash common.Hash) ( + sig crypto.Signature, err error) { + s, err := ethcrypto.Sign(hash[:], &prv.privateKey) + sig = crypto.Signature{ + Type: cryptoType, + Signature: s, + } + return +} + +// VerifySignature checks that the given public key created signature over hash. +// The public key should be in compressed (33 bytes) or uncompressed (65 bytes) +// format. +// The signature should have the 64 byte [R || S] format. +func (pub publicKey) VerifySignature( + hash common.Hash, signature crypto.Signature) bool { + sig := signature.Signature + if len(sig) == 65 { + // The last byte is for ecrecover. + sig = sig[:64] + } + return ethcrypto.VerifySignature(pub.publicKey, hash[:], sig) +} + +// Compress encodes a public key to the 33-byte compressed format. +func (pub publicKey) Compress() []byte { + return pub.publicKey +} + +// Bytes returns the []byte representation of public key. +func (pub publicKey) Bytes() []byte { + return pub.Compress() +} + +// SigToPub returns the PublicKey that created the given signature. +func SigToPub( + hash common.Hash, signature crypto.Signature) (crypto.PublicKey, error) { + key, err := ethcrypto.SigToPub(hash[:], signature.Signature[:]) + if err != nil { + return publicKey{}, err + } + return publicKey{publicKey: ethcrypto.CompressPubkey(key)}, nil +} diff --git a/core/crypto/ecdsa/ecdsa_test.go b/core/crypto/ecdsa/ecdsa_test.go new file mode 100644 index 0000000..3543b04 --- /dev/null +++ b/core/crypto/ecdsa/ecdsa_test.go @@ -0,0 +1,93 @@ +// Copyright 2018 The dexon-consensus-core Authors +// This file is part of the dexon-consensus-core library. +// +// The dexon-consensus-core library is free software: you can redistribute it +// and/or modify it under the terms of the GNU Lesser General Public License as +// published by the Free Software Foundation, either version 3 of the License, +// or (at your option) any later version. +// +// The dexon-consensus-core library is distributed in the hope that it will be +// useful, but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser +// General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with the dexon-consensus-core library. If not, see +// <http://www.gnu.org/licenses/>. + +package ecdsa + +import ( + "testing" + + "github.com/dexon-foundation/dexon-consensus-core/common" + "github.com/dexon-foundation/dexon-consensus-core/core/crypto" + "github.com/stretchr/testify/suite" +) + +type ETHCryptoTestSuite struct { + suite.Suite +} + +func (s *ETHCryptoTestSuite) TestSignature() { + prv1, err := NewPrivateKey() + s.Require().Nil(err) + hash1 := common.NewRandomHash() + hash2 := common.NewRandomHash() + + // Test that same private key should produce same signature. + sig11, err := prv1.Sign(hash1) + s.Require().Nil(err) + sig112, err := prv1.Sign(hash1) + s.Require().Nil(err) + s.Equal(sig11, sig112) + + // Test that different private key should produce different signature. + prv2, err := NewPrivateKey() + s.Require().Nil(err) + sig21, err := prv2.Sign(hash1) + s.Require().Nil(err) + s.NotEqual(sig11, sig21) + + // Test that different hash should produce different signature. + sig12, err := prv1.Sign(hash2) + s.Require().Nil(err) + s.NotEqual(sig11, sig12) + + // Test VerifySignature with correct public key. + pub1, ok := prv1.PublicKey().(publicKey) + s.Require().True(ok) + s.True(pub1.VerifySignature(hash1, sig11)) + + // Test VerifySignature with wrong hash. + s.False(pub1.VerifySignature(hash2, sig11)) + // Test VerifySignature with wrong signature. + s.False(pub1.VerifySignature(hash1, sig21)) + // Test VerifySignature with wrong public key. + pub2 := prv2.PublicKey() + s.False(pub2.VerifySignature(hash1, sig11)) + + // Test compress and decompress of public key. + compressPub1 := pub1.Compress() + decompressPub1, err := decompressPubkey(compressPub1) + s.Require().Nil(err) + s.Equal(pub1, decompressPub1) + s.True(decompressPub1.VerifySignature(hash1, sig11)) +} + +func (s *ETHCryptoTestSuite) TestSigToPub() { + prv, err := NewPrivateKey() + s.Require().Nil(err) + data := "DEXON is infinitely scalable and low-latency." + hash := crypto.Keccak256Hash([]byte(data)) + sigmsg, err := prv.Sign(hash) + s.Require().Nil(err) + + pubkey, err := SigToPub(hash, sigmsg) + s.Require().Nil(err) + s.Equal(pubkey, prv.PublicKey()) +} + +func TestCrypto(t *testing.T) { + suite.Run(t, new(ETHCryptoTestSuite)) +} |