concat_kdf.go 1.8 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576
  1. /*-
  2. * Copyright 2014 Square Inc.
  3. *
  4. * Licensed under the Apache License, Version 2.0 (the "License");
  5. * you may not use this file except in compliance with the License.
  6. * You may obtain a copy of the License at
  7. *
  8. * http://www.apache.org/licenses/LICENSE-2.0
  9. *
  10. * Unless required by applicable law or agreed to in writing, software
  11. * distributed under the License is distributed on an "AS IS" BASIS,
  12. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. * See the License for the specific language governing permissions and
  14. * limitations under the License.
  15. */
  16. package josecipher
  17. import (
  18. "crypto"
  19. "encoding/binary"
  20. "hash"
  21. "io"
  22. )
  23. type concatKDF struct {
  24. z, info []byte
  25. i uint32
  26. cache []byte
  27. hasher hash.Hash
  28. }
  29. // NewConcatKDF builds a KDF reader based on the given inputs.
  30. func NewConcatKDF(hash crypto.Hash, z, algID, ptyUInfo, ptyVInfo, supPubInfo, supPrivInfo []byte) io.Reader {
  31. buffer := make([]byte, uint64(len(algID))+uint64(len(ptyUInfo))+uint64(len(ptyVInfo))+uint64(len(supPubInfo))+uint64(len(supPrivInfo)))
  32. n := 0
  33. n += copy(buffer, algID)
  34. n += copy(buffer[n:], ptyUInfo)
  35. n += copy(buffer[n:], ptyVInfo)
  36. n += copy(buffer[n:], supPubInfo)
  37. copy(buffer[n:], supPrivInfo)
  38. hasher := hash.New()
  39. return &concatKDF{
  40. z: z,
  41. info: buffer,
  42. hasher: hasher,
  43. cache: []byte{},
  44. i: 1,
  45. }
  46. }
  47. func (ctx *concatKDF) Read(out []byte) (int, error) {
  48. copied := copy(out, ctx.cache)
  49. ctx.cache = ctx.cache[copied:]
  50. for copied < len(out) {
  51. ctx.hasher.Reset()
  52. // Write on a hash.Hash never fails
  53. _ = binary.Write(ctx.hasher, binary.BigEndian, ctx.i)
  54. _, _ = ctx.hasher.Write(ctx.z)
  55. _, _ = ctx.hasher.Write(ctx.info)
  56. hash := ctx.hasher.Sum(nil)
  57. chunkCopied := copy(out[copied:], hash)
  58. copied += chunkCopied
  59. ctx.cache = hash[chunkCopied:]
  60. ctx.i++
  61. }
  62. return copied, nil
  63. }