concatkdf.go 1.4 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667
  1. package concatkdf
  2. import (
  3. "crypto"
  4. "encoding/binary"
  5. "github.com/pkg/errors"
  6. )
  7. type KDF struct {
  8. buf []byte
  9. otherinfo []byte
  10. z []byte
  11. hash crypto.Hash
  12. }
  13. func ndata(src []byte) []byte {
  14. buf := make([]byte, 4+len(src))
  15. binary.BigEndian.PutUint32(buf, uint32(len(src)))
  16. copy(buf[4:], src)
  17. return buf
  18. }
  19. func New(hash crypto.Hash, alg, Z, apu, apv, pubinfo, privinfo []byte) *KDF {
  20. algbuf := ndata(alg)
  21. apubuf := ndata(apu)
  22. apvbuf := ndata(apv)
  23. concat := make([]byte, len(algbuf)+len(apubuf)+len(apvbuf)+len(pubinfo)+len(privinfo))
  24. n := copy(concat, algbuf)
  25. n += copy(concat[n:], apubuf)
  26. n += copy(concat[n:], apvbuf)
  27. n += copy(concat[n:], pubinfo)
  28. copy(concat[n:], privinfo)
  29. return &KDF{
  30. hash: hash,
  31. otherinfo: concat,
  32. z: Z,
  33. }
  34. }
  35. func (k *KDF) Read(out []byte) (int, error) {
  36. var round uint32 = 1
  37. h := k.hash.New()
  38. for len(out) > len(k.buf) {
  39. h.Reset()
  40. if err := binary.Write(h, binary.BigEndian, round); err != nil {
  41. return 0, errors.Wrap(err, "failed to write round using kdf")
  42. }
  43. if _, err := h.Write(k.z); err != nil {
  44. return 0, errors.Wrap(err, "failed to write z using kdf")
  45. }
  46. if _, err := h.Write(k.otherinfo); err != nil {
  47. return 0, errors.Wrap(err, "failed to write other info using kdf")
  48. }
  49. k.buf = append(k.buf, h.Sum(nil)...)
  50. round++
  51. }
  52. n := copy(out, k.buf[:len(out)])
  53. k.buf = k.buf[len(out):]
  54. return n, nil
  55. }