crypto: add SignatureLength constant and use it everywhere (#19996)
Original change by @jpeletier
This commit is contained in:
		@@ -32,6 +32,7 @@ import (
 | 
				
			|||||||
	"github.com/ethereum/go-ethereum/common"
 | 
						"github.com/ethereum/go-ethereum/common"
 | 
				
			||||||
	"github.com/ethereum/go-ethereum/common/hexutil"
 | 
						"github.com/ethereum/go-ethereum/common/hexutil"
 | 
				
			||||||
	"github.com/ethereum/go-ethereum/core/types"
 | 
						"github.com/ethereum/go-ethereum/core/types"
 | 
				
			||||||
 | 
						"github.com/ethereum/go-ethereum/crypto"
 | 
				
			||||||
	"github.com/ethereum/go-ethereum/log"
 | 
						"github.com/ethereum/go-ethereum/log"
 | 
				
			||||||
	"github.com/ethereum/go-ethereum/rlp"
 | 
						"github.com/ethereum/go-ethereum/rlp"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
@@ -341,7 +342,7 @@ func (w *ledgerDriver) ledgerSign(derivationPath []uint32, tx *types.Transaction
 | 
				
			|||||||
		op = ledgerP1ContTransactionData
 | 
							op = ledgerP1ContTransactionData
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	// Extract the Ethereum signature and do a sanity validation
 | 
						// 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")
 | 
							return common.Address{}, nil, errors.New("reply lacks signature")
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	signature := append(reply[1:], reply[0])
 | 
						signature := append(reply[1:], reply[0])
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -56,7 +56,7 @@ var (
 | 
				
			|||||||
	epochLength = uint64(30000) // Default number of blocks after which to checkpoint and reset the pending votes
 | 
						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
 | 
						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
 | 
						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
 | 
						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.
 | 
						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) {
 | 
				
			|||||||
		header.GasLimit,
 | 
							header.GasLimit,
 | 
				
			||||||
		header.GasUsed,
 | 
							header.GasUsed,
 | 
				
			||||||
		header.Time,
 | 
							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.MixDigest,
 | 
				
			||||||
		header.Nonce,
 | 
							header.Nonce,
 | 
				
			||||||
	})
 | 
						})
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -31,6 +31,7 @@ import (
 | 
				
			|||||||
	"github.com/ethereum/go-ethereum/core/rawdb"
 | 
						"github.com/ethereum/go-ethereum/core/rawdb"
 | 
				
			||||||
	"github.com/ethereum/go-ethereum/core/state"
 | 
						"github.com/ethereum/go-ethereum/core/state"
 | 
				
			||||||
	"github.com/ethereum/go-ethereum/core/types"
 | 
						"github.com/ethereum/go-ethereum/core/types"
 | 
				
			||||||
 | 
						"github.com/ethereum/go-ethereum/crypto"
 | 
				
			||||||
	"github.com/ethereum/go-ethereum/ethdb"
 | 
						"github.com/ethereum/go-ethereum/ethdb"
 | 
				
			||||||
	"github.com/ethereum/go-ethereum/log"
 | 
						"github.com/ethereum/go-ethereum/log"
 | 
				
			||||||
	"github.com/ethereum/go-ethereum/params"
 | 
						"github.com/ethereum/go-ethereum/params"
 | 
				
			||||||
@@ -377,7 +378,7 @@ func DeveloperGenesisBlock(period uint64, faucet common.Address) *Genesis {
 | 
				
			|||||||
	// Assemble and return the genesis with the precompiles and faucet pre-funded
 | 
						// Assemble and return the genesis with the precompiles and faucet pre-funded
 | 
				
			||||||
	return &Genesis{
 | 
						return &Genesis{
 | 
				
			||||||
		Config:     &config,
 | 
							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,
 | 
							GasLimit:   6283185,
 | 
				
			||||||
		Difficulty: big.NewInt(1),
 | 
							Difficulty: big.NewInt(1),
 | 
				
			||||||
		Alloc: map[common.Address]GenesisAccount{
 | 
							Alloc: map[common.Address]GenesisAccount{
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -193,8 +193,8 @@ func (s FrontierSigner) Equal(s2 Signer) bool {
 | 
				
			|||||||
// SignatureValues returns signature values. This signature
 | 
					// SignatureValues returns signature values. This signature
 | 
				
			||||||
// needs to be in the [R || S || V] format where V is 0 or 1.
 | 
					// 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) {
 | 
					func (fs FrontierSigner) SignatureValues(tx *Transaction, sig []byte) (r, s, v *big.Int, err error) {
 | 
				
			||||||
	if len(sig) != 65 {
 | 
						if len(sig) != crypto.SignatureLength {
 | 
				
			||||||
		panic(fmt.Sprintf("wrong size for signature: got %d, want 65", len(sig)))
 | 
							panic(fmt.Sprintf("wrong size for signature: got %d, want %d", len(sig), crypto.SignatureLength))
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	r = new(big.Int).SetBytes(sig[:32])
 | 
						r = new(big.Int).SetBytes(sig[:32])
 | 
				
			||||||
	s = new(big.Int).SetBytes(sig[32:64])
 | 
						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
 | 
						// encode the signature in uncompressed format
 | 
				
			||||||
	r, s := R.Bytes(), S.Bytes()
 | 
						r, s := R.Bytes(), S.Bytes()
 | 
				
			||||||
	sig := make([]byte, 65)
 | 
						sig := make([]byte, crypto.SignatureLength)
 | 
				
			||||||
	copy(sig[32-len(r):32], r)
 | 
						copy(sig[32-len(r):32], r)
 | 
				
			||||||
	copy(sig[64-len(s):64], s)
 | 
						copy(sig[64-len(s):64], s)
 | 
				
			||||||
	sig[64] = V
 | 
						sig[64] = V
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -34,6 +34,15 @@ import (
 | 
				
			|||||||
	"golang.org/x/crypto/sha3"
 | 
						"golang.org/x/crypto/sha3"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					//SignatureLength indicates the byte length required to carry a signature with recovery id.
 | 
				
			||||||
 | 
					const SignatureLength = 64 + 1 // 64 bytes ECDSA signature + 1 byte recovery id
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// RecoveryIDOffset points to the byte offset within the signature that contains the recovery id.
 | 
				
			||||||
 | 
					const RecoveryIDOffset = 64
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// DigestLength sets the signature digest exact length
 | 
				
			||||||
 | 
					const DigestLength = 32
 | 
				
			||||||
 | 
					
 | 
				
			||||||
var (
 | 
					var (
 | 
				
			||||||
	secp256k1N, _  = new(big.Int).SetString("fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141", 16)
 | 
						secp256k1N, _  = new(big.Int).SetString("fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141", 16)
 | 
				
			||||||
	secp256k1halfN = new(big.Int).Div(secp256k1N, big.NewInt(2))
 | 
						secp256k1halfN = new(big.Int).Div(secp256k1N, big.NewInt(2))
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -47,24 +47,24 @@ func SigToPub(hash, sig []byte) (*ecdsa.PublicKey, error) {
 | 
				
			|||||||
//
 | 
					//
 | 
				
			||||||
// This function is susceptible to chosen plaintext attacks that can leak
 | 
					// This function is susceptible to chosen plaintext attacks that can leak
 | 
				
			||||||
// information about the private key that is used for signing. Callers must
 | 
					// 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.
 | 
					// 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.
 | 
					// 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) {
 | 
					func Sign(digestHash []byte, prv *ecdsa.PrivateKey) (sig []byte, err error) {
 | 
				
			||||||
	if len(hash) != 32 {
 | 
						if len(digestHash) != DigestLength {
 | 
				
			||||||
		return nil, fmt.Errorf("hash is required to be exactly 32 bytes (%d)", len(hash))
 | 
							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)
 | 
						seckey := math.PaddedBigBytes(prv.D, prv.Params().BitSize/8)
 | 
				
			||||||
	defer zeroBytes(seckey)
 | 
						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 public key should be in compressed (33 bytes) or uncompressed (65 bytes) format.
 | 
				
			||||||
// The signature should have the 64 byte [R || S] format.
 | 
					// The signature should have the 64 byte [R || S] format.
 | 
				
			||||||
func VerifySignature(pubkey, hash, signature []byte) bool {
 | 
					func VerifySignature(pubkey, digestHash, signature []byte) bool {
 | 
				
			||||||
	return secp256k1.VerifySignature(pubkey, hash, signature)
 | 
						return secp256k1.VerifySignature(pubkey, digestHash, signature)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// DecompressPubkey parses a public key in the 33-byte compressed format.
 | 
					// DecompressPubkey parses a public key in the 33-byte compressed format.
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -41,7 +41,7 @@ func Ecrecover(hash, sig []byte) ([]byte, error) {
 | 
				
			|||||||
// SigToPub returns the public key that created the given signature.
 | 
					// SigToPub returns the public key that created the given signature.
 | 
				
			||||||
func SigToPub(hash, sig []byte) (*ecdsa.PublicKey, error) {
 | 
					func SigToPub(hash, sig []byte) (*ecdsa.PublicKey, error) {
 | 
				
			||||||
	// Convert to btcec input format with 'recovery id' v at the beginning.
 | 
						// 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
 | 
						btcsig[0] = sig[64] + 27
 | 
				
			||||||
	copy(btcsig[1:], sig)
 | 
						copy(btcsig[1:], sig)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -427,7 +427,7 @@ func (s *PrivateAccountAPI) Sign(ctx context.Context, data hexutil.Bytes, addr c
 | 
				
			|||||||
		log.Warn("Failed data sign attempt", "address", addr, "err", err)
 | 
							log.Warn("Failed data sign attempt", "address", addr, "err", err)
 | 
				
			||||||
		return nil, 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
 | 
						return signature, nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -442,13 +442,13 @@ func (s *PrivateAccountAPI) Sign(ctx context.Context, data hexutil.Bytes, addr c
 | 
				
			|||||||
//
 | 
					//
 | 
				
			||||||
// https://github.com/ethereum/go-ethereum/wiki/Management-APIs#personal_ecRecover
 | 
					// 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) {
 | 
					func (s *PrivateAccountAPI) EcRecover(ctx context.Context, data, sig hexutil.Bytes) (common.Address, error) {
 | 
				
			||||||
	if len(sig) != 65 {
 | 
						if len(sig) != crypto.SignatureLength {
 | 
				
			||||||
		return common.Address{}, fmt.Errorf("signature must be 65 bytes long")
 | 
							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)")
 | 
							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(accounts.TextHash(data), sig)
 | 
						rpk, err := crypto.SigToPub(accounts.TextHash(data), sig)
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -95,7 +95,7 @@ func newTestWorkerBackend(t *testing.T, chainConfig *params.ChainConfig, engine
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
	switch engine.(type) {
 | 
						switch engine.(type) {
 | 
				
			||||||
	case *clique.Clique:
 | 
						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[:])
 | 
							copy(gspec.ExtraData[32:], testBankAddress[:])
 | 
				
			||||||
	case *ethash.Ethash:
 | 
						case *ethash.Ethash:
 | 
				
			||||||
	default:
 | 
						default:
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -47,7 +47,7 @@ const (
 | 
				
			|||||||
	maxUint24 = ^uint32(0) >> 8
 | 
						maxUint24 = ^uint32(0) >> 8
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	sskLen = 16                     // ecies.MaxSharedKeyLength(pubKey) / 2
 | 
						sskLen = 16                     // ecies.MaxSharedKeyLength(pubKey) / 2
 | 
				
			||||||
	sigLen = 65 // elliptic S256
 | 
						sigLen = crypto.SignatureLength // elliptic S256
 | 
				
			||||||
	pubLen = 64                     // 512 bit pubkey in uncompressed representation without format byte
 | 
						pubLen = 64                     // 512 bit pubkey in uncompressed representation without format byte
 | 
				
			||||||
	shaLen = 32                     // hash length (for nonce etc)
 | 
						shaLen = 32                     // hash length (for nonce etc)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -34,6 +34,8 @@ package whisperv6
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
import (
 | 
					import (
 | 
				
			||||||
	"time"
 | 
						"time"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						"github.com/ethereum/go-ethereum/crypto"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Whisper protocol parameters
 | 
					// Whisper protocol parameters
 | 
				
			||||||
@@ -55,7 +57,7 @@ const (
 | 
				
			|||||||
	signatureFlag = byte(4)
 | 
						signatureFlag = byte(4)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	TopicLength     = 4                      // in bytes
 | 
						TopicLength     = 4                      // in bytes
 | 
				
			||||||
	signatureLength = 65 // in bytes
 | 
						signatureLength = crypto.SignatureLength // in bytes
 | 
				
			||||||
	aesKeyLength    = 32                     // in bytes
 | 
						aesKeyLength    = 32                     // in bytes
 | 
				
			||||||
	aesNonceLength  = 12                     // in bytes; for more info please see cipher.gcmStandardNonceSize & aesgcm.NonceSize()
 | 
						aesNonceLength  = 12                     // in bytes; for more info please see cipher.gcmStandardNonceSize & aesgcm.NonceSize()
 | 
				
			||||||
	keyIDSize       = 32                     // in bytes
 | 
						keyIDSize       = 32                     // in bytes
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user