auth/vendor/github.com/lestrrat-go/jwx/v2/jwe/internal/concatkdf/concatkdf.go

67 lines
1.4 KiB
Go

package concatkdf
import (
"crypto"
"encoding/binary"
"fmt"
)
type KDF struct {
buf []byte
otherinfo []byte
z []byte
hash crypto.Hash
}
func ndata(src []byte) []byte {
buf := make([]byte, 4+len(src))
binary.BigEndian.PutUint32(buf, uint32(len(src)))
copy(buf[4:], src)
return buf
}
func New(hash crypto.Hash, alg, Z, apu, apv, pubinfo, privinfo []byte) *KDF {
algbuf := ndata(alg)
apubuf := ndata(apu)
apvbuf := ndata(apv)
concat := make([]byte, len(algbuf)+len(apubuf)+len(apvbuf)+len(pubinfo)+len(privinfo))
n := copy(concat, algbuf)
n += copy(concat[n:], apubuf)
n += copy(concat[n:], apvbuf)
n += copy(concat[n:], pubinfo)
copy(concat[n:], privinfo)
return &KDF{
hash: hash,
otherinfo: concat,
z: Z,
}
}
func (k *KDF) Read(out []byte) (int, error) {
var round uint32 = 1
h := k.hash.New()
for len(out) > len(k.buf) {
h.Reset()
if err := binary.Write(h, binary.BigEndian, round); err != nil {
return 0, fmt.Errorf(`failed to write round using kdf: %w`, err)
}
if _, err := h.Write(k.z); err != nil {
return 0, fmt.Errorf(`failed to write z using kdf: %w`, err)
}
if _, err := h.Write(k.otherinfo); err != nil {
return 0, fmt.Errorf(`failed to write other info using kdf: %w`, err)
}
k.buf = append(k.buf, h.Sum(nil)...)
round++
}
n := copy(out, k.buf[:len(out)])
k.buf = k.buf[len(out):]
return n, nil
}