...
1
16
17 package josecipher
18
19 import (
20 "crypto"
21 "encoding/binary"
22 "hash"
23 "io"
24 )
25
26 type concatKDF struct {
27 z, info []byte
28 i uint32
29 cache []byte
30 hasher hash.Hash
31 }
32
33
34 func NewConcatKDF(hash crypto.Hash, z, algID, ptyUInfo, ptyVInfo, supPubInfo, supPrivInfo []byte) io.Reader {
35 buffer := make([]byte, uint64(len(algID))+uint64(len(ptyUInfo))+uint64(len(ptyVInfo))+uint64(len(supPubInfo))+uint64(len(supPrivInfo)))
36 n := 0
37 n += copy(buffer, algID)
38 n += copy(buffer[n:], ptyUInfo)
39 n += copy(buffer[n:], ptyVInfo)
40 n += copy(buffer[n:], supPubInfo)
41 copy(buffer[n:], supPrivInfo)
42
43 hasher := hash.New()
44
45 return &concatKDF{
46 z: z,
47 info: buffer,
48 hasher: hasher,
49 cache: []byte{},
50 i: 1,
51 }
52 }
53
54 func (ctx *concatKDF) Read(out []byte) (int, error) {
55 copied := copy(out, ctx.cache)
56 ctx.cache = ctx.cache[copied:]
57
58 for copied < len(out) {
59 ctx.hasher.Reset()
60
61
62 _ = binary.Write(ctx.hasher, binary.BigEndian, ctx.i)
63 _, _ = ctx.hasher.Write(ctx.z)
64 _, _ = ctx.hasher.Write(ctx.info)
65
66 hash := ctx.hasher.Sum(nil)
67 chunkCopied := copy(out[copied:], hash)
68 copied += chunkCopied
69 ctx.cache = hash[chunkCopied:]
70
71 ctx.i++
72 }
73
74 return copied, nil
75 }
76
View as plain text