Left: | ||
Right: |
OLD | NEW |
---|---|
(Empty) | |
1 // Copyright 2013 The Go Authors. All rights reserved. | |
2 // Use of this source code is governed by a BSD-style | |
3 // license that can be found in the LICENSE file. | |
4 | |
5 // Package hkdf implements the HMAC-based Extract-and-Expand Key Derivation | |
6 // Function (HKDF) as defined in Internet Engineering Task Force, Request for | |
7 // Comments 5869. | |
8 // | |
9 // An HKDF is a cryptographic key derivation function (KDF) with the goal of | |
10 // expanding some limited size input keying material into one or more | |
11 // cryptographically strong secret keys. | |
12 // | |
13 // RFC 5869: https://tools.ietf.org/html/rfc5869 | |
14 package hkdf | |
15 | |
16 import ( | |
17 "crypto/hmac" | |
18 "errors" | |
19 "fmt" | |
20 "hash" | |
21 "io" | |
22 ) | |
23 | |
24 type hkdf struct { | |
25 hash func() hash.Hash | |
26 size int | |
27 | |
28 prk []byte | |
29 info []byte | |
30 counter byte | |
31 | |
32 prev []byte | |
33 cache []byte | |
34 } | |
35 | |
36 func (f *hkdf) Read(p []byte) (n int, err error) { | |
37 need := len(p) | |
38 remains := len(f.cache) + int(255-f.counter+1)*f.size | |
39 if remains < need { | |
40 return 0, errors.New(fmt.Sprintf("entropy limit reached %d < %d" , remains, need)) | |
41 } | |
42 | |
43 for len(f.cache) < need { | |
44 input := append(f.prev, append(f.info, f.counter)...) | |
agl1
2013/03/12 15:12:15
this is better written as two, non-nested appends.
| |
45 | |
46 expander := hmac.New(f.hash, f.prk) | |
agl1
2013/03/12 15:12:15
the HMAC from New can be passed in and Reset() rat
| |
47 expander.Write(input) | |
48 output := expander.Sum(nil) | |
agl1
2013/03/12 15:12:15
in the case where the full hash result fits in p,
| |
49 | |
50 f.cache = append(f.cache, output...) | |
51 f.prev = output | |
52 f.counter++ | |
53 } | |
54 | |
55 copy(p, f.cache[:need]) | |
56 f.cache = f.cache[need:] | |
57 | |
58 return need, nil | |
59 } | |
60 | |
61 // New returns a new HKDF using the given hash, the master keying material to ex pand | |
62 // and optional salt and info fields. | |
63 func New(hash func() hash.Hash, master []byte, salt []byte, info []byte) io.Read er { | |
agl1
2013/03/12 15:12:15
argument names should either be commonly used, or
| |
64 extractor := hmac.New(hash, salt) | |
agl1
2013/03/12 15:12:15
If a salt is not provided, hash.Size() zero bytes
| |
65 extractor.Write(master) | |
66 | |
67 return &hkdf{hash, hash().Size(), extractor.Sum(nil), info, 1, []byte{}, []byte{}} | |
agl1
2013/03/12 15:12:15
s/[]byte{}/nil/
| |
68 } | |
OLD | NEW |