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/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]) | ||||
|   | ||||
| @@ -55,8 +55,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. | ||||
| @@ -728,7 +728,7 @@ func encodeSigHeader(w io.Writer, header *types.Header) { | ||||
| 		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, | ||||
| 	}) | ||||
|   | ||||
| @@ -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" | ||||
| @@ -377,7 +378,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{ | ||||
|   | ||||
| @@ -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 | ||||
|   | ||||
| @@ -34,6 +34,15 @@ import ( | ||||
| 	"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 ( | ||||
| 	secp256k1N, _  = new(big.Int).SetString("fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141", 16) | ||||
| 	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 | ||||
| // 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. | ||||
|   | ||||
| @@ -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) | ||||
|  | ||||
|   | ||||
| @@ -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) | ||||
| 		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 | ||||
| } | ||||
|  | ||||
| @@ -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 | ||||
| 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(accounts.TextHash(data), sig) | ||||
| 	if err != nil { | ||||
|   | ||||
| @@ -95,7 +95,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: | ||||
|   | ||||
| @@ -46,10 +46,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 | ||||
|   | ||||
| @@ -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 | ||||
|   | ||||
		Reference in New Issue
	
	Block a user