crypto/ecies: improve concatKDF (#20836)
This removes a bunch of weird code around the counter overflow check in concatKDF and makes it actually work for different hash output sizes. The overflow check worked as follows: concatKDF applies the hash function N times, where N is roundup(kdLen, hashsize) / hashsize. N should not overflow 32 bits because that would lead to a repetition in the KDF output. A couple issues with the overflow check: - It used the hash.BlockSize, which is wrong because the block size is about the input of the hash function. Luckily, all standard hash functions have a block size that's greater than the output size, so concatKDF didn't crash, it just generated too much key material. - The check used big.Int to compare against 2^32-1. - The calculation could still overflow before reaching the check. The new code in concatKDF doesn't check for overflow. Instead, there is a new check on ECIESParams which ensures that params.KeyLen is < 512. This removes any possibility of overflow. There are a couple of miscellaneous improvements bundled in with this change: - The key buffer is pre-allocated instead of appending the hash output to an initially empty slice. - The code that uses concatKDF to derive keys is now shared between Encrypt and Decrypt. - There was a redundant invocation of IsOnCurve in Decrypt. This is now removed because elliptic.Unmarshal already checks whether the input is a valid curve point since Go 1.5. Co-authored-by: Felix Lange <fjl@twurst.com>
This commit is contained in:
@ -49,8 +49,14 @@ var (
|
||||
DefaultCurve = ethcrypto.S256()
|
||||
ErrUnsupportedECDHAlgorithm = fmt.Errorf("ecies: unsupported ECDH algorithm")
|
||||
ErrUnsupportedECIESParameters = fmt.Errorf("ecies: unsupported ECIES parameters")
|
||||
ErrInvalidKeyLen = fmt.Errorf("ecies: invalid key size (> %d) in ECIESParams", maxKeyLen)
|
||||
)
|
||||
|
||||
// KeyLen is limited to prevent overflow of the counter
|
||||
// in concatKDF. While the theoretical limit is much higher,
|
||||
// no known cipher uses keys larger than 512 bytes.
|
||||
const maxKeyLen = 512
|
||||
|
||||
type ECIESParams struct {
|
||||
Hash func() hash.Hash // hash function
|
||||
hashAlgo crypto.Hash
|
||||
@ -115,3 +121,16 @@ func AddParamsForCurve(curve elliptic.Curve, params *ECIESParams) {
|
||||
func ParamsFromCurve(curve elliptic.Curve) (params *ECIESParams) {
|
||||
return paramsFromCurve[curve]
|
||||
}
|
||||
|
||||
func pubkeyParams(key *PublicKey) (*ECIESParams, error) {
|
||||
params := key.Params
|
||||
if params == nil {
|
||||
if params = ParamsFromCurve(key.Curve); params == nil {
|
||||
return nil, ErrUnsupportedECIESParameters
|
||||
}
|
||||
}
|
||||
if params.KeyLen > maxKeyLen {
|
||||
return nil, ErrInvalidKeyLen
|
||||
}
|
||||
return params, nil
|
||||
}
|
||||
|
Reference in New Issue
Block a user