From b765384046c36e022dd60fb81381c9febecc1778 Mon Sep 17 00:00:00 2001 From: Javier Peletier Date: Thu, 20 Dec 2018 09:06:07 +0100 Subject: [PATCH] all: Refactor code throughout to use new crypto.SignatureLength constant --- accounts/usbwallet/ledger.go | 3 ++- consensus/clique/clique.go | 6 +++--- core/genesis.go | 5 +++-- core/types/transaction_signing.go | 6 +++--- crypto/signature_cgo.go | 16 ++++++++-------- crypto/signature_nocgo.go | 2 +- internal/ethapi/api.go | 10 +++++----- miner/worker_test.go | 2 +- p2p/rlpx.go | 8 ++++---- signer/core/api_test.go | 5 +++-- swarm/storage/feed/request.go | 13 +++++++------ swarm/storage/feed/request_test.go | 2 +- swarm/storage/feed/sign.go | 4 +--- swarm/storage/feed/update.go | 3 ++- whisper/whisperv5/doc.go | 4 +++- whisper/whisperv6/doc.go | 14 ++++++++------ 16 files changed, 55 insertions(+), 48 deletions(-) diff --git a/accounts/usbwallet/ledger.go b/accounts/usbwallet/ledger.go index c30903b5b7..17ca9223ff 100644 --- a/accounts/usbwallet/ledger.go +++ b/accounts/usbwallet/ledger.go @@ -32,6 +32,7 @@ import ( "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common/hexutil" "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/rlp" ) @@ -341,7 +342,7 @@ func (w *ledgerDriver) ledgerSign(derivationPath []uint32, tx *types.Transaction op = ledgerP1ContTransactionData } // Extract the Ethereum signature and do a sanity validation - if len(reply) != 65 { + if len(reply) != crypto.SignatureLength { return common.Address{}, nil, errors.New("reply lacks signature") } signature := append(reply[1:], reply[0]) diff --git a/consensus/clique/clique.go b/consensus/clique/clique.go index 0cb72c35c7..71c68385ae 100644 --- a/consensus/clique/clique.go +++ b/consensus/clique/clique.go @@ -54,8 +54,8 @@ const ( var ( epochLength = uint64(30000) // Default number of blocks after which to checkpoint and reset the pending votes - extraVanity = 32 // Fixed number of extra-data prefix bytes reserved for signer vanity - extraSeal = 65 // Fixed number of extra-data suffix bytes reserved for signer seal + extraVanity = 32 // Fixed number of extra-data prefix bytes reserved for signer vanity + extraSeal = crypto.SignatureLength // Fixed number of extra-data suffix bytes reserved for signer seal nonceAuthVote = hexutil.MustDecode("0xffffffffffffffff") // Magic nonce number to vote on adding a new signer nonceDropVote = hexutil.MustDecode("0x0000000000000000") // Magic nonce number to vote on removing a signer. @@ -163,7 +163,7 @@ func sigHash(header *types.Header) (hash common.Hash) { header.GasLimit, header.GasUsed, header.Time, - header.Extra[:len(header.Extra)-65], // Yes, this will panic if extra is too short + header.Extra[:len(header.Extra)-crypto.SignatureLength], // Yes, this will panic if extra is too short header.MixDigest, header.Nonce, }) diff --git a/core/genesis.go b/core/genesis.go index c96cb17a36..6c61a53bd0 100644 --- a/core/genesis.go +++ b/core/genesis.go @@ -31,6 +31,7 @@ import ( "github.com/ethereum/go-ethereum/core/rawdb" "github.com/ethereum/go-ethereum/core/state" "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/ethdb" "github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/params" @@ -349,7 +350,7 @@ func DeveloperGenesisBlock(period uint64, faucet common.Address) *Genesis { // Assemble and return the genesis with the precompiles and faucet pre-funded return &Genesis{ Config: &config, - ExtraData: append(append(make([]byte, 32), faucet[:]...), make([]byte, 65)...), + ExtraData: append(append(make([]byte, 32), faucet[:]...), make([]byte, crypto.SignatureLength)...), GasLimit: 6283185, Difficulty: big.NewInt(1), Alloc: map[common.Address]GenesisAccount{ @@ -361,7 +362,7 @@ func DeveloperGenesisBlock(period uint64, faucet common.Address) *Genesis { common.BytesToAddress([]byte{6}): {Balance: big.NewInt(1)}, // ECAdd common.BytesToAddress([]byte{7}): {Balance: big.NewInt(1)}, // ECScalarMul common.BytesToAddress([]byte{8}): {Balance: big.NewInt(1)}, // ECPairing - faucet: {Balance: new(big.Int).Sub(new(big.Int).Lsh(big.NewInt(1), 256), big.NewInt(9))}, + faucet: {Balance: new(big.Int).Sub(new(big.Int).Lsh(big.NewInt(1), 256), big.NewInt(9))}, }, } } diff --git a/core/types/transaction_signing.go b/core/types/transaction_signing.go index 63132048ee..842fedbd03 100644 --- a/core/types/transaction_signing.go +++ b/core/types/transaction_signing.go @@ -193,8 +193,8 @@ func (s FrontierSigner) Equal(s2 Signer) bool { // SignatureValues returns signature values. This signature // needs to be in the [R || S || V] format where V is 0 or 1. func (fs FrontierSigner) SignatureValues(tx *Transaction, sig []byte) (r, s, v *big.Int, err error) { - if len(sig) != 65 { - panic(fmt.Sprintf("wrong size for signature: got %d, want 65", len(sig))) + if len(sig) != crypto.SignatureLength { + panic(fmt.Sprintf("wrong size for signature: got %d, want %d", len(sig), crypto.SignatureLength)) } r = new(big.Int).SetBytes(sig[:32]) s = new(big.Int).SetBytes(sig[32:64]) @@ -229,7 +229,7 @@ func recoverPlain(sighash common.Hash, R, S, Vb *big.Int, homestead bool) (commo } // encode the signature in uncompressed format r, s := R.Bytes(), S.Bytes() - sig := make([]byte, 65) + sig := make([]byte, crypto.SignatureLength) copy(sig[32-len(r):32], r) copy(sig[64-len(s):64], s) sig[64] = V diff --git a/crypto/signature_cgo.go b/crypto/signature_cgo.go index 340bfc221e..908dbba68f 100644 --- a/crypto/signature_cgo.go +++ b/crypto/signature_cgo.go @@ -47,24 +47,24 @@ func SigToPub(hash, sig []byte) (*ecdsa.PublicKey, error) { // // 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 +// be aware that the given digest 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 Sign(hash []byte, prv *ecdsa.PrivateKey) (sig []byte, err error) { - if len(hash) != 32 { - return nil, fmt.Errorf("hash is required to be exactly 32 bytes (%d)", len(hash)) +func Sign(digestHash []byte, prv *ecdsa.PrivateKey) (sig []byte, err error) { + if len(digestHash) != DigestLength { + return nil, fmt.Errorf("hash is required to be exactly %d bytes (%d)", DigestLength, len(digestHash)) } seckey := math.PaddedBigBytes(prv.D, prv.Params().BitSize/8) defer zeroBytes(seckey) - return secp256k1.Sign(hash, seckey) + return secp256k1.Sign(digestHash, seckey) } -// VerifySignature checks that the given public key created signature over hash. +// VerifySignature checks that the given public key created signature over digest. // 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 VerifySignature(pubkey, hash, signature []byte) bool { - return secp256k1.VerifySignature(pubkey, hash, signature) +func VerifySignature(pubkey, digestHash, signature []byte) bool { + return secp256k1.VerifySignature(pubkey, digestHash, signature) } // DecompressPubkey parses a public key in the 33-byte compressed format. diff --git a/crypto/signature_nocgo.go b/crypto/signature_nocgo.go index e8fa18ed47..55d6e0f72f 100644 --- a/crypto/signature_nocgo.go +++ b/crypto/signature_nocgo.go @@ -41,7 +41,7 @@ func Ecrecover(hash, sig []byte) ([]byte, error) { // SigToPub returns the public key that created the given signature. func SigToPub(hash, sig []byte) (*ecdsa.PublicKey, error) { // Convert to btcec input format with 'recovery id' v at the beginning. - btcsig := make([]byte, 65) + btcsig := make([]byte, SignatureLength) btcsig[0] = sig[64] + 27 copy(btcsig[1:], sig) diff --git a/internal/ethapi/api.go b/internal/ethapi/api.go index 656555b3ba..c9b347ed8d 100644 --- a/internal/ethapi/api.go +++ b/internal/ethapi/api.go @@ -444,7 +444,7 @@ func (s *PrivateAccountAPI) Sign(ctx context.Context, data hexutil.Bytes, addr c log.Warn("Failed data sign attempt", "address", addr, "err", err) return nil, err } - signature[64] += 27 // Transform V from 0/1 to 27/28 according to the yellow paper + signature[crypto.RecoveryIDOffset] += 27 // Transform V from 0/1 to 27/28 according to the yellow paper return signature, nil } @@ -459,13 +459,13 @@ func (s *PrivateAccountAPI) Sign(ctx context.Context, data hexutil.Bytes, addr c // // https://github.com/ethereum/go-ethereum/wiki/Management-APIs#personal_ecRecover func (s *PrivateAccountAPI) EcRecover(ctx context.Context, data, sig hexutil.Bytes) (common.Address, error) { - if len(sig) != 65 { - return common.Address{}, fmt.Errorf("signature must be 65 bytes long") + if len(sig) != crypto.SignatureLength { + return common.Address{}, fmt.Errorf("signature must be %d bytes long", crypto.SignatureLength) } - if sig[64] != 27 && sig[64] != 28 { + if sig[crypto.RecoveryIDOffset] != 27 && sig[crypto.RecoveryIDOffset] != 28 { return common.Address{}, fmt.Errorf("invalid Ethereum signature (V is not 27 or 28)") } - sig[64] -= 27 // Transform yellow paper V from 27/28 to 0/1 + sig[crypto.RecoveryIDOffset] -= 27 // Transform yellow paper V from 27/28 to 0/1 rpk, err := crypto.SigToPub(signHash(data), sig) if err != nil { diff --git a/miner/worker_test.go b/miner/worker_test.go index 7c8f167a12..893928717f 100644 --- a/miner/worker_test.go +++ b/miner/worker_test.go @@ -88,7 +88,7 @@ func newTestWorkerBackend(t *testing.T, chainConfig *params.ChainConfig, engine switch engine.(type) { case *clique.Clique: - gspec.ExtraData = make([]byte, 32+common.AddressLength+65) + gspec.ExtraData = make([]byte, 32+common.AddressLength+crypto.SignatureLength) copy(gspec.ExtraData[32:], testBankAddress[:]) case *ethash.Ethash: default: diff --git a/p2p/rlpx.go b/p2p/rlpx.go index 22a27dd96a..3faceaf407 100644 --- a/p2p/rlpx.go +++ b/p2p/rlpx.go @@ -47,10 +47,10 @@ import ( const ( maxUint24 = ^uint32(0) >> 8 - sskLen = 16 // ecies.MaxSharedKeyLength(pubKey) / 2 - sigLen = 65 // elliptic S256 - pubLen = 64 // 512 bit pubkey in uncompressed representation without format byte - shaLen = 32 // hash length (for nonce etc) + sskLen = 16 // ecies.MaxSharedKeyLength(pubKey) / 2 + sigLen = crypto.SignatureLength // elliptic S256 + pubLen = 64 // 512 bit pubkey in uncompressed representation without format byte + shaLen = 32 // hash length (for nonce etc) authMsgLen = sigLen + shaLen + pubLen + shaLen + 1 authRespLen = pubLen + shaLen + 1 diff --git a/signer/core/api_test.go b/signer/core/api_test.go index a8aa23896e..8ef740c7d6 100644 --- a/signer/core/api_test.go +++ b/signer/core/api_test.go @@ -33,6 +33,7 @@ import ( "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common/hexutil" "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/internal/ethapi" "github.com/ethereum/go-ethereum/rlp" ) @@ -280,8 +281,8 @@ func TestSignData(t *testing.T) { if err != nil { t.Fatal(err) } - if h == nil || len(h) != 65 { - t.Errorf("Expected 65 byte signature (got %d bytes)", len(h)) + if h == nil || len(h) != crypto.SignatureLength { + t.Errorf("Expected %d byte signature (got %d bytes)", crypto.SignatureLength, len(h)) } } func mkTestTx(from common.MixedcaseAddress) SendTxArgs { diff --git a/swarm/storage/feed/request.go b/swarm/storage/feed/request.go index dd91a7cf45..9118a8696d 100644 --- a/swarm/storage/feed/request.go +++ b/swarm/storage/feed/request.go @@ -23,6 +23,7 @@ import ( "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common/hexutil" + "github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/swarm/storage" "github.com/ethereum/go-ethereum/swarm/storage/feed/lookup" ) @@ -46,7 +47,7 @@ type updateRequestJSON struct { // Request layout // Update bytes // SignatureLength bytes -const minimumSignedUpdateLength = minimumUpdateDataLength + signatureLength +const minimumSignedUpdateLength = minimumUpdateDataLength + crypto.SignatureLength // NewFirstRequest returns a ready to sign request to publish a first feed update func NewFirstRequest(topic Topic) *Request { @@ -141,7 +142,7 @@ func (r *Request) GetDigest() (result common.Hash, err error) { hasher.Reset() dataLength := r.Update.binaryLength() if r.binaryData == nil { - r.binaryData = make([]byte, dataLength+signatureLength) + r.binaryData = make([]byte, dataLength+crypto.SignatureLength) if err := r.Update.binaryPut(r.binaryData[:dataLength]); err != nil { return result, err } @@ -177,14 +178,14 @@ func (r *Request) fromChunk(chunk storage.Chunk) error { chunkdata := chunk.Data() //deserialize the feed update portion - if err := r.Update.binaryGet(chunkdata[:len(chunkdata)-signatureLength]); err != nil { + if err := r.Update.binaryGet(chunkdata[:len(chunkdata)-crypto.SignatureLength]); err != nil { return err } // Extract the signature var signature *Signature cursor := r.Update.binaryLength() - sigdata := chunkdata[cursor : cursor+signatureLength] + sigdata := chunkdata[cursor : cursor+crypto.SignatureLength] if len(sigdata) > 0 { signature = &Signature{} copy(signature[:], sigdata) @@ -205,7 +206,7 @@ func (r *Request) FromValues(values Values, data []byte) error { if err != nil { r.Signature = nil } else { - if len(signatureBytes) != signatureLength { + if len(signatureBytes) != crypto.SignatureLength { return NewError(ErrInvalidSignature, "Incorrect signature length") } r.Signature = new(Signature) @@ -244,7 +245,7 @@ func (r *Request) fromJSON(j *updateRequestJSON) error { if j.Signature != "" { sigBytes, err := hexutil.Decode(j.Signature) - if err != nil || len(sigBytes) != signatureLength { + if err != nil || len(sigBytes) != crypto.SignatureLength { return NewError(ErrInvalidSignature, "Cannot decode signature") } r.Signature = new(Signature) diff --git a/swarm/storage/feed/request_test.go b/swarm/storage/feed/request_test.go index c30158fddf..df1afba0f4 100644 --- a/swarm/storage/feed/request_test.go +++ b/swarm/storage/feed/request_test.go @@ -197,7 +197,7 @@ func TestUpdateChunkSerializationErrorChecking(t *testing.T) { // Test that parseUpdate fails if the chunk is too small var r Request - if err := r.fromChunk(storage.NewChunk(storage.ZeroAddr, make([]byte, minimumUpdateDataLength-1+signatureLength))); err == nil { + if err := r.fromChunk(storage.NewChunk(storage.ZeroAddr, make([]byte, minimumUpdateDataLength-1+crypto.SignatureLength))); err == nil { t.Fatalf("Expected request.fromChunk to fail when chunkData contains less than %d bytes", minimumUpdateDataLength) } diff --git a/swarm/storage/feed/sign.go b/swarm/storage/feed/sign.go index 5f0ea0b33c..9cba0b6642 100644 --- a/swarm/storage/feed/sign.go +++ b/swarm/storage/feed/sign.go @@ -23,10 +23,8 @@ import ( "github.com/ethereum/go-ethereum/crypto" ) -const signatureLength = 65 - // Signature is an alias for a static byte array with the size of a signature -type Signature [signatureLength]byte +type Signature [crypto.SignatureLength]byte // Signer signs feed update payloads type Signer interface { diff --git a/swarm/storage/feed/update.go b/swarm/storage/feed/update.go index 21c004ca42..7b76e9051b 100644 --- a/swarm/storage/feed/update.go +++ b/swarm/storage/feed/update.go @@ -20,6 +20,7 @@ import ( "fmt" "strconv" + "github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/swarm/chunk" ) @@ -44,7 +45,7 @@ type Update struct { const minimumUpdateDataLength = idLength + headerLength + 1 //MaxUpdateDataLength indicates the maximum payload size for a feed update -const MaxUpdateDataLength = chunk.DefaultSize - signatureLength - idLength - headerLength +const MaxUpdateDataLength = chunk.DefaultSize - crypto.SignatureLength - idLength - headerLength // binaryPut serializes the feed update information into the given slice func (r *Update) binaryPut(serializedData []byte) error { diff --git a/whisper/whisperv5/doc.go b/whisper/whisperv5/doc.go index 8161db8ed6..d1725b69ec 100644 --- a/whisper/whisperv5/doc.go +++ b/whisper/whisperv5/doc.go @@ -32,6 +32,8 @@ package whisperv5 import ( "fmt" "time" + + "github.com/ethereum/go-ethereum/crypto" ) const ( @@ -50,7 +52,7 @@ const ( signatureFlag = byte(4) TopicLength = 4 - signatureLength = 65 + signatureLength = crypto.SignatureLength aesKeyLength = 32 AESNonceLength = 12 keyIdSize = 32 diff --git a/whisper/whisperv6/doc.go b/whisper/whisperv6/doc.go index 529bf3d2de..44c0c3271c 100644 --- a/whisper/whisperv6/doc.go +++ b/whisper/whisperv6/doc.go @@ -34,6 +34,8 @@ package whisperv6 import ( "time" + + "github.com/ethereum/go-ethereum/crypto" ) // Whisper protocol parameters @@ -54,12 +56,12 @@ const ( SizeMask = byte(3) // mask used to extract the size of payload size field from the flags signatureFlag = byte(4) - TopicLength = 4 // in bytes - signatureLength = 65 // in bytes - aesKeyLength = 32 // in bytes - aesNonceLength = 12 // in bytes; for more info please see cipher.gcmStandardNonceSize & aesgcm.NonceSize() - keyIDSize = 32 // in bytes - BloomFilterSize = 64 // in bytes + TopicLength = 4 // in bytes + signatureLength = crypto.SignatureLength // in bytes + aesKeyLength = 32 // in bytes + aesNonceLength = 12 // in bytes; for more info please see cipher.gcmStandardNonceSize & aesgcm.NonceSize() + keyIDSize = 32 // in bytes + BloomFilterSize = 64 // in bytes flagsLength = 1 EnvelopeHeaderLength = 20