From a90dec8374cf631074c72ed9f40a6aa97296aad0 Mon Sep 17 00:00:00 2001 From: jacksoom Date: Wed, 21 Apr 2021 16:42:21 +0800 Subject: [PATCH] Feat(ed25519): replace with crypto/ed25519 (#1907) * feat(ed25519): repalce with crypto/ed25519 * modify Makefile * ci Co-authored-by: Paladz --- Makefile | 4 +- api/message.go | 2 +- api/query.go | 2 +- asset/asset.go | 2 +- blockchain/pseudohsm/pseudohsm_test.go | 2 +- blockchain/txbuilder/txbuilder_test.go | 2 +- crypto/ed25519/chainkd/chainkd.go | 2 +- crypto/ed25519/chainkd/expanded_key.go | 2 +- crypto/ed25519/chainkd/expanded_key_test.go | 3 +- crypto/ed25519/chainkd/util.go | 3 +- crypto/ed25519/ed25519.go | 206 ---------------------------- crypto/ed25519/ed25519_test.go | 155 --------------------- go.mod | 2 - p2p/discover/dht/net.go | 6 +- p2p/discover/dht/udp.go | 4 +- p2p/switch.go | 2 +- protocol/vm/crypto.go | 2 +- protocol/vm/vmutil/script.go | 3 +- protocol/vm/vmutil/script_test.go | 2 +- testutil/keys.go | 3 +- 20 files changed, 23 insertions(+), 386 deletions(-) delete mode 100644 crypto/ed25519/ed25519.go delete mode 100644 crypto/ed25519/ed25519_test.go diff --git a/Makefile b/Makefile index 65719184..b9e8e9d3 100644 --- a/Makefile +++ b/Makefile @@ -9,7 +9,7 @@ $(error "$$GOOS is not defined. If you are using Windows, try to re-make using ' endif endif -PACKAGES := $(shell go list ./... | grep -v '/vendor/' | grep -v '/crypto/ed25519/chainkd') +PACKAGES := $(shell go list ./... | grep -v '/lib/') BUILD_FLAGS := -ldflags "-X github.com/bytom/bytom/version.GitCommit=`git rev-parse HEAD`" @@ -109,7 +109,7 @@ target/$(BYTOMCLI_BINARY64): test: @echo "====> Running go test" - @go test -tags "network" $(PACKAGES) + @go test $(PACKAGES) benchmark: @go test -bench $(PACKAGES) diff --git a/api/message.go b/api/message.go index 08c11845..22429208 100644 --- a/api/message.go +++ b/api/message.go @@ -2,6 +2,7 @@ package api import ( "context" + "crypto/ed25519" "encoding/hex" "strings" @@ -9,7 +10,6 @@ import ( "github.com/bytom/bytom/common" "github.com/bytom/bytom/consensus" "github.com/bytom/bytom/crypto" - "github.com/bytom/bytom/crypto/ed25519" "github.com/bytom/bytom/crypto/ed25519/chainkd" chainjson "github.com/bytom/bytom/encoding/json" ) diff --git a/api/query.go b/api/query.go index 59985b15..83154b34 100644 --- a/api/query.go +++ b/api/query.go @@ -2,6 +2,7 @@ package api import ( "context" + "crypto/ed25519" "encoding/hex" "fmt" @@ -13,7 +14,6 @@ import ( "github.com/bytom/bytom/blockchain/signers" "github.com/bytom/bytom/blockchain/txbuilder" "github.com/bytom/bytom/consensus" - "github.com/bytom/bytom/crypto/ed25519" "github.com/bytom/bytom/crypto/ed25519/chainkd" chainjson "github.com/bytom/bytom/encoding/json" "github.com/bytom/bytom/errors" diff --git a/asset/asset.go b/asset/asset.go index 7d87c0b9..719dfb4d 100644 --- a/asset/asset.go +++ b/asset/asset.go @@ -2,6 +2,7 @@ package asset import ( "context" + "crypto/ed25519" "encoding/json" "strings" "sync" @@ -12,7 +13,6 @@ import ( "github.com/bytom/bytom/blockchain/signers" "github.com/bytom/bytom/common" "github.com/bytom/bytom/consensus" - "github.com/bytom/bytom/crypto/ed25519" "github.com/bytom/bytom/crypto/ed25519/chainkd" dbm "github.com/bytom/bytom/database/leveldb" chainjson "github.com/bytom/bytom/encoding/json" diff --git a/blockchain/pseudohsm/pseudohsm_test.go b/blockchain/pseudohsm/pseudohsm_test.go index aace8112..779974ee 100644 --- a/blockchain/pseudohsm/pseudohsm_test.go +++ b/blockchain/pseudohsm/pseudohsm_test.go @@ -1,13 +1,13 @@ package pseudohsm import ( + "crypto/ed25519" "fmt" "io/ioutil" "os" "strings" "testing" - "github.com/bytom/bytom/crypto/ed25519" "github.com/bytom/bytom/errors" ) diff --git a/blockchain/txbuilder/txbuilder_test.go b/blockchain/txbuilder/txbuilder_test.go index f3a709d0..02a33d66 100644 --- a/blockchain/txbuilder/txbuilder_test.go +++ b/blockchain/txbuilder/txbuilder_test.go @@ -2,6 +2,7 @@ package txbuilder import ( "context" + "crypto/ed25519" "encoding/hex" "encoding/json" "math" @@ -14,7 +15,6 @@ import ( "github.com/bytom/bytom/common" "github.com/bytom/bytom/consensus" "github.com/bytom/bytom/crypto" - "github.com/bytom/bytom/crypto/ed25519" "github.com/bytom/bytom/crypto/ed25519/chainkd" chainjson "github.com/bytom/bytom/encoding/json" "github.com/bytom/bytom/errors" diff --git a/crypto/ed25519/chainkd/chainkd.go b/crypto/ed25519/chainkd/chainkd.go index c2cc25d6..a72895bd 100644 --- a/crypto/ed25519/chainkd/chainkd.go +++ b/crypto/ed25519/chainkd/chainkd.go @@ -1,12 +1,12 @@ package chainkd import ( + "crypto/ed25519" "crypto/hmac" "crypto/rand" "crypto/sha512" "io" - "github.com/bytom/bytom/crypto/ed25519" "github.com/bytom/bytom/crypto/ed25519/ecmath" ) diff --git a/crypto/ed25519/chainkd/expanded_key.go b/crypto/ed25519/chainkd/expanded_key.go index ed47a763..3f4e81cc 100644 --- a/crypto/ed25519/chainkd/expanded_key.go +++ b/crypto/ed25519/chainkd/expanded_key.go @@ -9,12 +9,12 @@ package chainkd import ( "crypto" + "crypto/ed25519" "crypto/sha512" "errors" "io" "strconv" - "github.com/bytom/bytom/crypto/ed25519" "github.com/bytom/bytom/crypto/ed25519/internal/edwards25519" ) diff --git a/crypto/ed25519/chainkd/expanded_key_test.go b/crypto/ed25519/chainkd/expanded_key_test.go index c80677d3..3cf1982a 100644 --- a/crypto/ed25519/chainkd/expanded_key_test.go +++ b/crypto/ed25519/chainkd/expanded_key_test.go @@ -3,9 +3,8 @@ package chainkd import ( "bytes" "crypto" + "crypto/ed25519" "testing" - - "github.com/bytom/bytom/crypto/ed25519" ) // Testing basic InnerSign+Verify and the invariants: diff --git a/crypto/ed25519/chainkd/util.go b/crypto/ed25519/chainkd/util.go index 6f1c82b1..d5b4e588 100644 --- a/crypto/ed25519/chainkd/util.go +++ b/crypto/ed25519/chainkd/util.go @@ -1,9 +1,8 @@ package chainkd import ( + "crypto/ed25519" "io" - - "github.com/bytom/bytom/crypto/ed25519" ) // Utility functions diff --git a/crypto/ed25519/ed25519.go b/crypto/ed25519/ed25519.go deleted file mode 100644 index 70c8cc9a..00000000 --- a/crypto/ed25519/ed25519.go +++ /dev/null @@ -1,206 +0,0 @@ -// Package ed25519 implements the Ed25519 signature algorithm. See -// http://ed25519.cr.yp.to/. -// -// These functions are also compatible with the “Ed25519” function defined in -// https://tools.ietf.org/html/draft-irtf-cfrg-eddsa-05. -package ed25519 - -// This code is a port of the public domain, “ref10” implementation of ed25519 -// from SUPERCOP. - -import ( - cryptorand "crypto/rand" - "crypto/sha512" - "crypto/subtle" - "encoding/hex" - "io" - "strconv" - - "github.com/bytom/bytom/crypto/ed25519/internal/edwards25519" -) - -const ( - // PublicKeySize is the size, in bytes, of public keys as used in this package. - PublicKeySize = 32 - // PrivateKeySize is the size, in bytes, of private keys as used in this package. - PrivateKeySize = 64 - // SignatureSize is the size, in bytes, of signatures generated and verified by this package. - SignatureSize = 64 - // SeedSize is the size, in bytes, of private key seeds. These are the private key representations used by RFC 8032. - SeedSize = 32 -) - -// PublicKey is the type of Ed25519 public keys. -type PublicKey []byte - -// PrivateKey is the type of Ed25519 private keys. It implements crypto.Signer. -type PrivateKey []byte - -// Public returns the PublicKey corresponding to priv. -func (priv PrivateKey) Public() PublicKey { - publicKey := make([]byte, PublicKeySize) - copy(publicKey, priv[32:]) - return PublicKey(publicKey) -} - -// Seed returns the private key seed corresponding to priv. It is provided for -// interoperability with RFC 8032. RFC 8032's private keys correspond to seeds -// in this package. -func (priv PrivateKey) Seed() []byte { - seed := make([]byte, SeedSize) - copy(seed, priv[:32]) - return seed -} - -func (priv PrivateKey) String() string { - return hex.EncodeToString(priv) -} - -// GenerateKey generates a public/private key pair using entropy from rand. -// If rand is nil, crypto/rand.Reader will be used. -func GenerateKey(rand io.Reader) (publicKey PublicKey, privateKey PrivateKey, err error) { - if rand == nil { - rand = cryptorand.Reader - } - - privateKey = make([]byte, PrivateKeySize) - publicKey = make([]byte, PublicKeySize) - _, err = io.ReadFull(rand, privateKey[:32]) - if err != nil { - return nil, nil, err - } - - digest := sha512.Sum512(privateKey[:32]) - digest[0] &= 248 - digest[31] &= 127 - digest[31] |= 64 - - var A edwards25519.ExtendedGroupElement - var hBytes [32]byte - copy(hBytes[:], digest[:]) - edwards25519.GeScalarMultBase(&A, &hBytes) - var publicKeyBytes [32]byte - A.ToBytes(&publicKeyBytes) - - copy(privateKey[32:], publicKeyBytes[:]) - copy(publicKey, publicKeyBytes[:]) - - return publicKey, privateKey, nil -} - -// NewKeyFromSeed calculates a private key from a seed. It will panic if -// len(seed) is not SeedSize. This function is provided for interoperability -// with RFC 8032. RFC 8032's private keys correspond to seeds in this -// package. -func NewKeyFromSeed(seed []byte) PrivateKey { - if l := len(seed); l != SeedSize { - panic("ed25519: bad seed length: " + strconv.Itoa(l)) - } - - digest := sha512.Sum512(seed) - digest[0] &= 248 - digest[31] &= 127 - digest[31] |= 64 - - var A edwards25519.ExtendedGroupElement - var hBytes [32]byte - copy(hBytes[:], digest[:]) - edwards25519.GeScalarMultBase(&A, &hBytes) - var publicKeyBytes [32]byte - A.ToBytes(&publicKeyBytes) - - privateKey := make([]byte, PrivateKeySize) - copy(privateKey, seed) - copy(privateKey[32:], publicKeyBytes[:]) - - return privateKey -} - -// Sign signs the message with privateKey and returns a signature. It will -// panic if len(privateKey) is not PrivateKeySize. -func Sign(privateKey PrivateKey, message []byte) []byte { - if l := len(privateKey); l != PrivateKeySize { - panic("ed25519: bad private key length: " + strconv.Itoa(l)) - } - - h := sha512.New() - h.Write(privateKey[:32]) - - var digest1, messageDigest, hramDigest [64]byte - var expandedSecretKey [32]byte - h.Sum(digest1[:0]) - copy(expandedSecretKey[:], digest1[:]) - expandedSecretKey[0] &= 248 - expandedSecretKey[31] &= 63 - expandedSecretKey[31] |= 64 - - h.Reset() - h.Write(digest1[32:]) - h.Write(message) - h.Sum(messageDigest[:0]) - - var messageDigestReduced [32]byte - edwards25519.ScReduce(&messageDigestReduced, &messageDigest) - var R edwards25519.ExtendedGroupElement - edwards25519.GeScalarMultBase(&R, &messageDigestReduced) - - var encodedR [32]byte - R.ToBytes(&encodedR) - - h.Reset() - h.Write(encodedR[:]) - h.Write(privateKey[32:]) - h.Write(message) - h.Sum(hramDigest[:0]) - var hramDigestReduced [32]byte - edwards25519.ScReduce(&hramDigestReduced, &hramDigest) - - var s [32]byte - edwards25519.ScMulAdd(&s, &hramDigestReduced, &expandedSecretKey, &messageDigestReduced) - - signature := make([]byte, SignatureSize) - copy(signature[:], encodedR[:]) - copy(signature[32:], s[:]) - - return signature -} - -// Verify reports whether sig is a valid signature of message by publicKey. It -// will panic if len(publicKey) is not PublicKeySize. -func Verify(publicKey PublicKey, message, sig []byte) bool { - if l := len(publicKey); l != PublicKeySize { - panic("ed25519: bad public key length: " + strconv.Itoa(l)) - } - - if len(sig) != SignatureSize || sig[63]&224 != 0 { - return false - } - - var A edwards25519.ExtendedGroupElement - var publicKeyBytes [32]byte - copy(publicKeyBytes[:], publicKey) - if !A.FromBytes(&publicKeyBytes) { - return false - } - edwards25519.FeNeg(&A.X, &A.X) - edwards25519.FeNeg(&A.T, &A.T) - - h := sha512.New() - h.Write(sig[:32]) - h.Write(publicKey[:]) - h.Write(message) - var digest [64]byte - h.Sum(digest[:0]) - - var hReduced [32]byte - edwards25519.ScReduce(&hReduced, &digest) - - var R edwards25519.ProjectiveGroupElement - var b [32]byte - copy(b[:], sig[32:]) - edwards25519.GeDoubleScalarMultVartime(&R, &hReduced, &A, &b) - - var checkR [32]byte - R.ToBytes(&checkR) - return subtle.ConstantTimeCompare(sig[:32], checkR[:]) == 1 -} diff --git a/crypto/ed25519/ed25519_test.go b/crypto/ed25519/ed25519_test.go deleted file mode 100644 index f4ceef2f..00000000 --- a/crypto/ed25519/ed25519_test.go +++ /dev/null @@ -1,155 +0,0 @@ -// Copyright 2016 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file at -// https://github.com/golang/crypto/blob/master/LICENSE. - -package ed25519 - -import ( - "bufio" - "bytes" - "compress/gzip" - "crypto/rand" - "encoding/hex" - "os" - "strings" - "testing" - - "github.com/bytom/bytom/crypto/ed25519/internal/edwards25519" -) - -type zeroReader struct{} - -func (zeroReader) Read(buf []byte) (int, error) { - for i := range buf { - buf[i] = 0 - } - return len(buf), nil -} - -func TestUnmarshalMarshal(t *testing.T) { - pub, _, _ := GenerateKey(rand.Reader) - - var A edwards25519.ExtendedGroupElement - var pubBytes [32]byte - copy(pubBytes[:], pub) - if !A.FromBytes(&pubBytes) { - t.Fatalf("ExtendedGroupElement.FromBytes failed") - } - - var pub2 [32]byte - A.ToBytes(&pub2) - - if pubBytes != pub2 { - t.Errorf("FromBytes(%v)->ToBytes does not round-trip, got %x\n", pubBytes, pub2) - } -} - -func TestSignVerify(t *testing.T) { - var zero zeroReader - public, private, _ := GenerateKey(zero) - - message := []byte("test message") - sig := Sign(private, message) - if !Verify(public, message, sig) { - t.Errorf("valid signature rejected") - } - - wrongMessage := []byte("wrong message") - if Verify(public, wrongMessage, sig) { - t.Errorf("signature of different message accepted") - } -} - -func TestGolden(t *testing.T) { - // sign.input.gz is a selection of test cases from - // http://ed25519.cr.yp.to/python/sign.input - testDataZ, err := os.Open("testdata/sign.input.gz") - if err != nil { - t.Fatal(err) - } - defer testDataZ.Close() - testData, err := gzip.NewReader(testDataZ) - if err != nil { - t.Fatal(err) - } - defer testData.Close() - - scanner := bufio.NewScanner(testData) - lineNo := 0 - - for scanner.Scan() { - lineNo++ - - line := scanner.Text() - parts := strings.Split(line, ":") - if len(parts) != 5 { - t.Fatalf("bad number of parts on line %d", lineNo) - } - - privBytes, _ := hex.DecodeString(parts[0]) - pubKey, _ := hex.DecodeString(parts[1]) - msg, _ := hex.DecodeString(parts[2]) - sig, _ := hex.DecodeString(parts[3]) - // The signatures in the test vectors also include the message - // at the end, but we just want R and S. - sig = sig[:SignatureSize] - - if l := len(pubKey); l != PublicKeySize { - t.Fatalf("bad public key length on line %d: got %d bytes", lineNo, l) - } - - var priv [PrivateKeySize]byte - copy(priv[:], privBytes) - copy(priv[32:], pubKey) - - sig2 := Sign(priv[:], msg) - if !bytes.Equal(sig, sig2[:]) { - t.Errorf("different signature result on line %d: %x vs %x", lineNo, sig, sig2) - } - - if !Verify(pubKey, msg, sig2) { - t.Errorf("signature failed to verify on line %d", lineNo) - } - } - - if err := scanner.Err(); err != nil { - t.Fatalf("error reading test data: %s", err) - } -} - -func BenchmarkKeyGeneration(b *testing.B) { - var zero zeroReader - for i := 0; i < b.N; i++ { - if _, _, err := GenerateKey(zero); err != nil { - b.Fatal(err) - } - } -} - -func BenchmarkSigning(b *testing.B) { - var zero zeroReader - _, priv, err := GenerateKey(zero) - if err != nil { - b.Fatal(err) - } - message := []byte("Hello, world!") - b.ResetTimer() - for i := 0; i < b.N; i++ { - Sign(priv, message) - } -} - -func BenchmarkVerification(b *testing.B) { - var zero zeroReader - pub, priv, err := GenerateKey(zero) - if err != nil { - b.Fatal(err) - } - message := []byte("Hello, world!") - signature := Sign(priv, message) - b.ResetTimer() - for i := 0; i < b.N; i++ { - Verify(pub, message, signature) - } -} diff --git a/go.mod b/go.mod index 641edccc..4ff9e3f7 100644 --- a/go.mod +++ b/go.mod @@ -3,7 +3,6 @@ module github.com/bytom/bytom go 1.16 replace ( - github.com/agl/ed25519 => ./lib/github.com/tendermint/ed25519 github.com/prometheus/prometheus/util/flock => ./lib/github.com/prometheus/prometheus/util/flock github.com/tendermint/go-wire => github.com/tendermint/go-amino v0.6.2 github.com/zondax/ledger-goclient => github.com/Zondax/ledger-cosmos-go v0.1.0 @@ -13,7 +12,6 @@ replace ( ) require ( - github.com/agl/ed25519 v0.0.0-00010101000000-000000000000 // indirect github.com/btcsuite/btcd v0.21.0-beta // indirect github.com/btcsuite/go-socks v0.0.0-20170105172521-4720035b7bfd github.com/cespare/cp v1.1.1 diff --git a/p2p/discover/dht/net.go b/p2p/discover/dht/net.go index a6442b02..4dc51a5c 100644 --- a/p2p/discover/dht/net.go +++ b/p2p/discover/dht/net.go @@ -2,6 +2,7 @@ package dht import ( "bytes" + "crypto" "encoding/hex" "errors" "fmt" @@ -13,7 +14,6 @@ import ( "golang.org/x/crypto/sha3" "github.com/bytom/bytom/common" - "github.com/bytom/bytom/crypto/ed25519" "github.com/bytom/bytom/p2p/netutil" ) @@ -115,9 +115,9 @@ type timeoutEvent struct { node *Node } -func newNetwork(conn transport, ourPubkey ed25519.PublicKey, dbPath string, netrestrict *netutil.Netlist) (*Network, error) { +func newNetwork(conn transport, ourPubkey crypto.PublicKey, dbPath string, netrestrict *netutil.Netlist) (*Network, error) { var ourID NodeID - copy(ourID[:], ourPubkey[:nodeIDBits]) + copy(ourID[:], ourPubkey.([]byte)[:nodeIDBits]) var db *nodeDB if dbPath != "" { diff --git a/p2p/discover/dht/udp.go b/p2p/discover/dht/udp.go index 912aa056..49ee82b7 100644 --- a/p2p/discover/dht/udp.go +++ b/p2p/discover/dht/udp.go @@ -3,6 +3,7 @@ package dht import ( "bytes" "crypto/ecdsa" + "crypto/ed25519" "encoding/hex" "errors" "fmt" @@ -17,7 +18,6 @@ import ( "github.com/bytom/bytom/common" cfg "github.com/bytom/bytom/config" "github.com/bytom/bytom/crypto" - "github.com/bytom/bytom/crypto/ed25519" "github.com/bytom/bytom/p2p/netutil" "github.com/bytom/bytom/version" ) @@ -428,7 +428,7 @@ func encodePacket(priv ed25519.PrivateKey, ptype byte, req interface{}) (p, hash nodeID := priv.Public() sig := ed25519.Sign(priv, common.BytesToHash(packet[headSize:]).Bytes()) copy(packet, versionPrefix) - copy(packet[versionPrefixSize:], nodeID[:]) + copy(packet[versionPrefixSize:], nodeID.([]byte)[:]) copy(packet[versionPrefixSize+nodeIDSize:], sig) hash = common.BytesToHash(packet[versionPrefixSize:]).Bytes() diff --git a/p2p/switch.go b/p2p/switch.go index a22f7ca7..9b4ff55a 100644 --- a/p2p/switch.go +++ b/p2p/switch.go @@ -1,6 +1,7 @@ package p2p import ( + "crypto/ed25519" "fmt" "net" "sync" @@ -12,7 +13,6 @@ import ( cfg "github.com/bytom/bytom/config" "github.com/bytom/bytom/consensus" - "github.com/bytom/bytom/crypto/ed25519" "github.com/bytom/bytom/errors" "github.com/bytom/bytom/event" "github.com/bytom/bytom/p2p/connection" diff --git a/protocol/vm/crypto.go b/protocol/vm/crypto.go index 9d09dce1..b430ef55 100644 --- a/protocol/vm/crypto.go +++ b/protocol/vm/crypto.go @@ -1,13 +1,13 @@ package vm import ( + "crypto/ed25519" "crypto/sha256" "hash" "golang.org/x/crypto/sha3" "github.com/bytom/bytom/crypto" - "github.com/bytom/bytom/crypto/ed25519" "github.com/bytom/bytom/math/checked" ) diff --git a/protocol/vm/vmutil/script.go b/protocol/vm/vmutil/script.go index b1c50727..07202cbd 100644 --- a/protocol/vm/vmutil/script.go +++ b/protocol/vm/vmutil/script.go @@ -1,8 +1,9 @@ package vmutil import ( + "crypto/ed25519" + "github.com/bytom/bytom/consensus/bcrp" - "github.com/bytom/bytom/crypto/ed25519" "github.com/bytom/bytom/errors" "github.com/bytom/bytom/protocol/vm" ) diff --git a/protocol/vm/vmutil/script_test.go b/protocol/vm/vmutil/script_test.go index 44045acd..1cee77be 100644 --- a/protocol/vm/vmutil/script_test.go +++ b/protocol/vm/vmutil/script_test.go @@ -1,10 +1,10 @@ package vmutil import ( + "crypto/ed25519" "encoding/hex" "testing" - "github.com/bytom/bytom/crypto/ed25519" "github.com/bytom/bytom/errors" ) diff --git a/testutil/keys.go b/testutil/keys.go index cc04032b..8189a77b 100644 --- a/testutil/keys.go +++ b/testutil/keys.go @@ -1,7 +1,8 @@ package testutil import ( - "github.com/bytom/bytom/crypto/ed25519" + "crypto/ed25519" + "github.com/bytom/bytom/crypto/ed25519/chainkd" ) -- 2.11.0