ecies: overhaul concatKDF

- Eliminate overflow error case
- Simplify and inline incCounter
- Preallocate k
This commit is contained in:
Luke Champine 2020-03-31 13:13:55 -04:00 committed by GitHub
parent 5b70f574fd
commit 830d1382f1
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23

View file

@ -138,54 +138,26 @@ func (prv *PrivateKey) GenerateShared(pub *PublicKey, skLen, macLen int) (sk []b
} }
var ( var (
ErrKeyDataTooLong = fmt.Errorf("ecies: can't supply requested key data")
ErrSharedTooLong = fmt.Errorf("ecies: shared secret is too long") ErrSharedTooLong = fmt.Errorf("ecies: shared secret is too long")
ErrInvalidMessage = fmt.Errorf("ecies: invalid message") ErrInvalidMessage = fmt.Errorf("ecies: invalid message")
) )
func incCounter(ctr []byte) {
if ctr[3]++; ctr[3] != 0 {
return
}
if ctr[2]++; ctr[2] != 0 {
return
}
if ctr[1]++; ctr[1] != 0 {
return
}
if ctr[0]++; ctr[0] != 0 {
return
}
}
// NIST SP 800-56 Concatenation Key Derivation Function (see section 5.8.1). // NIST SP 800-56 Concatenation Key Derivation Function (see section 5.8.1).
func concatKDF(hash hash.Hash, z, s1 []byte, kdLen int) (k []byte, err error) { func concatKDF(hash hash.Hash, z, s1 []byte, kdLen int) []byte {
if s1 == nil {
s1 = make([]byte, 0)
}
// reps is the maximum number of iterations of the
// counter hashing loop. This is capped to 32 bits to
// prevent overflow of the counter.
reps := (int64(kdLen) + 7) * 8 / int64(hash.Size()*8)
if reps > int64(^uint32(0)) {
return nil, ErrKeyDataTooLong
}
counter := []byte{0, 0, 0, 1} counter := []byte{0, 0, 0, 1}
k = make([]byte, 0) k := make([]byte, 0, kdLen+hash.Size())
for len(k) < kdLen {
for i := int64(0); i <= reps; i++ { hash.Reset()
hash.Write(counter) hash.Write(counter)
hash.Write(z) hash.Write(z)
hash.Write(s1) hash.Write(s1)
k = append(k, hash.Sum(nil)...) k = k[:len(k)+hash.Size()]
hash.Reset() hash.Sum(k[:len(k)-hash.Size()])
incCounter(counter) // increment counter
binary.BigEndian.PutUint32(counter, binary.BigEndian.Uint32(counter)+1)
} }
return k[:kdLen]
k = k[:kdLen]
return
} }
// messageTag computes the MAC of a message (called the tag) as per // messageTag computes the MAC of a message (called the tag) as per
@ -263,10 +235,7 @@ func Encrypt(rand io.Reader, pub *PublicKey, m, s1, s2 []byte) (ct []byte, err e
if err != nil { if err != nil {
return return
} }
K, err := concatKDF(hash, z, s1, params.KeyLen+params.KeyLen) K := concatKDF(hash, z, s1, params.KeyLen+params.KeyLen)
if err != nil {
return
}
Ke := K[:params.KeyLen] Ke := K[:params.KeyLen]
Km := K[params.KeyLen:] Km := K[params.KeyLen:]
hash.Write(Km) hash.Write(Km)
@ -341,11 +310,7 @@ func (prv *PrivateKey) Decrypt(c, s1, s2 []byte) (m []byte, err error) {
return return
} }
K, err := concatKDF(hash, z, s1, params.KeyLen+params.KeyLen) K := concatKDF(hash, z, s1, params.KeyLen+params.KeyLen)
if err != nil {
return
}
Ke := K[:params.KeyLen] Ke := K[:params.KeyLen]
Km := K[params.KeyLen:] Km := K[params.KeyLen:]
hash.Write(Km) hash.Write(Km)