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