Skip to content

Commit 54b271a

Browse files
authored
crypto: add SignatureLength constant and use it everywhere (#19996)
Original change by @jpeletier
1 parent b90cdba commit 54b271a

File tree

11 files changed

+46
-33
lines changed

11 files changed

+46
-33
lines changed

accounts/usbwallet/ledger.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ import (
3232
"github.com/ethereum/go-ethereum/common"
3333
"github.com/ethereum/go-ethereum/common/hexutil"
3434
"github.com/ethereum/go-ethereum/core/types"
35+
"github.com/ethereum/go-ethereum/crypto"
3536
"github.com/ethereum/go-ethereum/log"
3637
"github.com/ethereum/go-ethereum/rlp"
3738
)
@@ -341,7 +342,7 @@ func (w *ledgerDriver) ledgerSign(derivationPath []uint32, tx *types.Transaction
341342
op = ledgerP1ContTransactionData
342343
}
343344
// Extract the Ethereum signature and do a sanity validation
344-
if len(reply) != 65 {
345+
if len(reply) != crypto.SignatureLength {
345346
return common.Address{}, nil, errors.New("reply lacks signature")
346347
}
347348
signature := append(reply[1:], reply[0])

consensus/clique/clique.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -55,8 +55,8 @@ const (
5555
var (
5656
epochLength = uint64(30000) // Default number of blocks after which to checkpoint and reset the pending votes
5757

58-
extraVanity = 32 // Fixed number of extra-data prefix bytes reserved for signer vanity
59-
extraSeal = 65 // Fixed number of extra-data suffix bytes reserved for signer seal
58+
extraVanity = 32 // Fixed number of extra-data prefix bytes reserved for signer vanity
59+
extraSeal = crypto.SignatureLength // Fixed number of extra-data suffix bytes reserved for signer seal
6060

6161
nonceAuthVote = hexutil.MustDecode("0xffffffffffffffff") // Magic nonce number to vote on adding a new signer
6262
nonceDropVote = hexutil.MustDecode("0x0000000000000000") // Magic nonce number to vote on removing a signer.
@@ -728,7 +728,7 @@ func encodeSigHeader(w io.Writer, header *types.Header) {
728728
header.GasLimit,
729729
header.GasUsed,
730730
header.Time,
731-
header.Extra[:len(header.Extra)-65], // Yes, this will panic if extra is too short
731+
header.Extra[:len(header.Extra)-crypto.SignatureLength], // Yes, this will panic if extra is too short
732732
header.MixDigest,
733733
header.Nonce,
734734
})

core/genesis.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ import (
3131
"github.com/ethereum/go-ethereum/core/rawdb"
3232
"github.com/ethereum/go-ethereum/core/state"
3333
"github.com/ethereum/go-ethereum/core/types"
34+
"github.com/ethereum/go-ethereum/crypto"
3435
"github.com/ethereum/go-ethereum/ethdb"
3536
"github.com/ethereum/go-ethereum/log"
3637
"github.com/ethereum/go-ethereum/params"
@@ -377,7 +378,7 @@ func DeveloperGenesisBlock(period uint64, faucet common.Address) *Genesis {
377378
// Assemble and return the genesis with the precompiles and faucet pre-funded
378379
return &Genesis{
379380
Config: &config,
380-
ExtraData: append(append(make([]byte, 32), faucet[:]...), make([]byte, 65)...),
381+
ExtraData: append(append(make([]byte, 32), faucet[:]...), make([]byte, crypto.SignatureLength)...),
381382
GasLimit: 6283185,
382383
Difficulty: big.NewInt(1),
383384
Alloc: map[common.Address]GenesisAccount{

core/types/transaction_signing.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -193,8 +193,8 @@ func (s FrontierSigner) Equal(s2 Signer) bool {
193193
// SignatureValues returns signature values. This signature
194194
// needs to be in the [R || S || V] format where V is 0 or 1.
195195
func (fs FrontierSigner) SignatureValues(tx *Transaction, sig []byte) (r, s, v *big.Int, err error) {
196-
if len(sig) != 65 {
197-
panic(fmt.Sprintf("wrong size for signature: got %d, want 65", len(sig)))
196+
if len(sig) != crypto.SignatureLength {
197+
panic(fmt.Sprintf("wrong size for signature: got %d, want %d", len(sig), crypto.SignatureLength))
198198
}
199199
r = new(big.Int).SetBytes(sig[:32])
200200
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
229229
}
230230
// encode the signature in uncompressed format
231231
r, s := R.Bytes(), S.Bytes()
232-
sig := make([]byte, 65)
232+
sig := make([]byte, crypto.SignatureLength)
233233
copy(sig[32-len(r):32], r)
234234
copy(sig[64-len(s):64], s)
235235
sig[64] = V

crypto/crypto.go

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,15 @@ import (
3434
"golang.org/x/crypto/sha3"
3535
)
3636

37+
//SignatureLength indicates the byte length required to carry a signature with recovery id.
38+
const SignatureLength = 64 + 1 // 64 bytes ECDSA signature + 1 byte recovery id
39+
40+
// RecoveryIDOffset points to the byte offset within the signature that contains the recovery id.
41+
const RecoveryIDOffset = 64
42+
43+
// DigestLength sets the signature digest exact length
44+
const DigestLength = 32
45+
3746
var (
3847
secp256k1N, _ = new(big.Int).SetString("fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141", 16)
3948
secp256k1halfN = new(big.Int).Div(secp256k1N, big.NewInt(2))

crypto/signature_cgo.go

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -47,24 +47,24 @@ func SigToPub(hash, sig []byte) (*ecdsa.PublicKey, error) {
4747
//
4848
// This function is susceptible to chosen plaintext attacks that can leak
4949
// information about the private key that is used for signing. Callers must
50-
// be aware that the given hash cannot be chosen by an adversery. Common
50+
// be aware that the given digest cannot be chosen by an adversery. Common
5151
// solution is to hash any input before calculating the signature.
5252
//
5353
// The produced signature is in the [R || S || V] format where V is 0 or 1.
54-
func Sign(hash []byte, prv *ecdsa.PrivateKey) (sig []byte, err error) {
55-
if len(hash) != 32 {
56-
return nil, fmt.Errorf("hash is required to be exactly 32 bytes (%d)", len(hash))
54+
func Sign(digestHash []byte, prv *ecdsa.PrivateKey) (sig []byte, err error) {
55+
if len(digestHash) != DigestLength {
56+
return nil, fmt.Errorf("hash is required to be exactly %d bytes (%d)", DigestLength, len(digestHash))
5757
}
5858
seckey := math.PaddedBigBytes(prv.D, prv.Params().BitSize/8)
5959
defer zeroBytes(seckey)
60-
return secp256k1.Sign(hash, seckey)
60+
return secp256k1.Sign(digestHash, seckey)
6161
}
6262

63-
// VerifySignature checks that the given public key created signature over hash.
63+
// VerifySignature checks that the given public key created signature over digest.
6464
// The public key should be in compressed (33 bytes) or uncompressed (65 bytes) format.
6565
// The signature should have the 64 byte [R || S] format.
66-
func VerifySignature(pubkey, hash, signature []byte) bool {
67-
return secp256k1.VerifySignature(pubkey, hash, signature)
66+
func VerifySignature(pubkey, digestHash, signature []byte) bool {
67+
return secp256k1.VerifySignature(pubkey, digestHash, signature)
6868
}
6969

7070
// DecompressPubkey parses a public key in the 33-byte compressed format.

crypto/signature_nocgo.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ func Ecrecover(hash, sig []byte) ([]byte, error) {
4141
// SigToPub returns the public key that created the given signature.
4242
func SigToPub(hash, sig []byte) (*ecdsa.PublicKey, error) {
4343
// Convert to btcec input format with 'recovery id' v at the beginning.
44-
btcsig := make([]byte, 65)
44+
btcsig := make([]byte, SignatureLength)
4545
btcsig[0] = sig[64] + 27
4646
copy(btcsig[1:], sig)
4747

internal/ethapi/api.go

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -427,7 +427,7 @@ func (s *PrivateAccountAPI) Sign(ctx context.Context, data hexutil.Bytes, addr c
427427
log.Warn("Failed data sign attempt", "address", addr, "err", err)
428428
return nil, err
429429
}
430-
signature[64] += 27 // Transform V from 0/1 to 27/28 according to the yellow paper
430+
signature[crypto.RecoveryIDOffset] += 27 // Transform V from 0/1 to 27/28 according to the yellow paper
431431
return signature, nil
432432
}
433433

@@ -442,13 +442,13 @@ func (s *PrivateAccountAPI) Sign(ctx context.Context, data hexutil.Bytes, addr c
442442
//
443443
// https://github.com/ethereum/go-ethereum/wiki/Management-APIs#personal_ecRecover
444444
func (s *PrivateAccountAPI) EcRecover(ctx context.Context, data, sig hexutil.Bytes) (common.Address, error) {
445-
if len(sig) != 65 {
446-
return common.Address{}, fmt.Errorf("signature must be 65 bytes long")
445+
if len(sig) != crypto.SignatureLength {
446+
return common.Address{}, fmt.Errorf("signature must be %d bytes long", crypto.SignatureLength)
447447
}
448-
if sig[64] != 27 && sig[64] != 28 {
448+
if sig[crypto.RecoveryIDOffset] != 27 && sig[crypto.RecoveryIDOffset] != 28 {
449449
return common.Address{}, fmt.Errorf("invalid Ethereum signature (V is not 27 or 28)")
450450
}
451-
sig[64] -= 27 // Transform yellow paper V from 27/28 to 0/1
451+
sig[crypto.RecoveryIDOffset] -= 27 // Transform yellow paper V from 27/28 to 0/1
452452

453453
rpk, err := crypto.SigToPub(accounts.TextHash(data), sig)
454454
if err != nil {

miner/worker_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -95,7 +95,7 @@ func newTestWorkerBackend(t *testing.T, chainConfig *params.ChainConfig, engine
9595

9696
switch engine.(type) {
9797
case *clique.Clique:
98-
gspec.ExtraData = make([]byte, 32+common.AddressLength+65)
98+
gspec.ExtraData = make([]byte, 32+common.AddressLength+crypto.SignatureLength)
9999
copy(gspec.ExtraData[32:], testBankAddress[:])
100100
case *ethash.Ethash:
101101
default:

p2p/rlpx.go

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -46,10 +46,10 @@ import (
4646
const (
4747
maxUint24 = ^uint32(0) >> 8
4848

49-
sskLen = 16 // ecies.MaxSharedKeyLength(pubKey) / 2
50-
sigLen = 65 // elliptic S256
51-
pubLen = 64 // 512 bit pubkey in uncompressed representation without format byte
52-
shaLen = 32 // hash length (for nonce etc)
49+
sskLen = 16 // ecies.MaxSharedKeyLength(pubKey) / 2
50+
sigLen = crypto.SignatureLength // elliptic S256
51+
pubLen = 64 // 512 bit pubkey in uncompressed representation without format byte
52+
shaLen = 32 // hash length (for nonce etc)
5353

5454
authMsgLen = sigLen + shaLen + pubLen + shaLen + 1
5555
authRespLen = pubLen + shaLen + 1

0 commit comments

Comments
 (0)