1
2
3
4
5 package hkdf
6
7 import (
8 "crypto/internal/fips140"
9 "crypto/internal/fips140/hmac"
10 )
11
12 func Extract[H fips140.Hash](h func() H, secret, salt []byte) []byte {
13 if len(secret) < 112/8 {
14 fips140.RecordNonApproved()
15 }
16 if salt == nil {
17 salt = make([]byte, h().Size())
18 }
19 extractor := hmac.New(h, salt)
20 hmac.MarkAsUsedInKDF(extractor)
21 extractor.Write(secret)
22
23 return extractor.Sum(nil)
24 }
25
26 func Expand[H fips140.Hash](h func() H, pseudorandomKey []byte, info string, keyLen int) []byte {
27 out := make([]byte, 0, keyLen)
28 expander := hmac.New(h, pseudorandomKey)
29 hmac.MarkAsUsedInKDF(expander)
30 var counter uint8
31 var buf []byte
32
33 for len(out) < keyLen {
34 counter++
35 if counter == 0 {
36 panic("hkdf: counter overflow")
37 }
38 if counter > 1 {
39 expander.Reset()
40 }
41 expander.Write(buf)
42 expander.Write([]byte(info))
43 expander.Write([]byte{counter})
44 buf = expander.Sum(buf[:0])
45 remain := keyLen - len(out)
46 remain = min(remain, len(buf))
47 out = append(out, buf[:remain]...)
48 }
49
50 return out
51 }
52
53 func Key[H fips140.Hash](h func() H, secret, salt []byte, info string, keyLen int) []byte {
54 prk := Extract(h, secret, salt)
55 return Expand(h, prk, info, keyLen)
56 }
57
View as plain text