Skip to content

Instantly share code, notes, and snippets.

@taylortrimble
Created April 1, 2018 00:34
Show Gist options
  • Save taylortrimble/0b8edc68d242e7f1f5b0aff45faab56f to your computer and use it in GitHub Desktop.
Save taylortrimble/0b8edc68d242e7f1f5b0aff45faab56f to your computer and use it in GitHub Desktop.
An implementation of the NIST concat KDF from SP 800-56A rev 2
package ecies
import (
"encoding/binary"
"hash"
"io"
)
type nistConcatKDF struct {
hash hash.Hash
sharedSecret []byte
otherInfo []byte
counter uint32
cache []byte
}
func newNISTConcatKDF(hash func() hash.Hash, sharedSecret, otherInfo []byte) io.Reader {
return &nistConcatKDF{hash: hash(), sharedSecret: sharedSecret, otherInfo: otherInfo, counter: 1}
}
func (kdf *nistConcatKDF) Read(p []byte) (int, error) {
// Check whether enough data can be generated
need := len(p)
// Read from the cache, if enough data is present
n := copy(p, kdf.cache)
p = p[n:]
// Fill the buffer
for len(p) > 0 {
kdf.hash.Reset()
binary.Write(kdf.hash, binary.BigEndian, kdf.counter)
kdf.hash.Write(kdf.sharedSecret)
kdf.hash.Write(kdf.otherInfo)
kdf.counter++
// Copy the new batch into p
kdf.cache = kdf.hash.Sum(nil)
n = copy(p, kdf.cache)
p = p[n:]
}
// Save leftovers for next run
kdf.cache = kdf.cache[n:]
return need, nil
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment