-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathhmac_drbg.go
113 lines (92 loc) · 2.41 KB
/
hmac_drbg.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
package crypto
import (
"crypto/hmac"
"crypto/sha256"
"errors"
)
// HmacDRBG ...
type HmacDRBG struct {
k []byte
v []byte
reseedCounter int
}
var (
reseedInterval = 10000
// Key = 0x00 00...00
initK = []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}
// V = 0x01 01...01
initV = []byte{0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01}
)
// NewHmacDRBG ...
func NewHmacDRBG(entropy, nonce, pers []byte) *HmacDRBG {
// seed = entropy || nonce || personalization
seed := append(append(entropy, nonce...), pers...)
k := initK
v := initV
h := &HmacDRBG{
k: k,
v: v,
reseedCounter: 0,
}
h.update(seed)
h.reseedCounter = 1
return h
}
// Reseed ...
func (h *HmacDRBG) Reseed(entropy []byte, input []byte) error {
seed := append(entropy, input...)
h.update(seed)
h.reseedCounter = 1
return nil
}
// Generate ...
func (h *HmacDRBG) Generate(byteLength int32, input []byte) ([]byte, error) {
if h.reseedCounter > reseedInterval {
return nil, errors.New("Reseed is reqired")
}
if len(input) > 0 {
h.update(input)
}
temp := make([]byte, 0, byteLength)
for i := int32(0); i < byteLength; i += int32(32) {
mac := hmac.New(sha256.New, h.k)
mac.Write(h.v)
h.v = mac.Sum(nil)
temp = append(temp, h.v...)
}
result := make([]byte, byteLength)
copy(result, temp[:byteLength])
h.update(input)
h.reseedCounter++
return result, nil
}
func (h *HmacDRBG) update(input []byte) {
// K = HMAC(K, V || 0x00 || input)
var data = make([]byte, 0, len(h.v)+len(input)+1)
data = append(data, h.v...)
data = append(data, 0x00)
data = append(data, input...)
mac := hmac.New(sha256.New, h.k)
mac.Write(data)
h.k = mac.Sum(nil)
// V = HMAC(K, V)
mac = hmac.New(sha256.New, h.k)
mac.Write(h.v)
h.v = mac.Sum(nil)
if len(input) == 0 {
return
}
// K = HMAC(K, V || 0x01 || input)
data = make([]byte, 0, len(h.v)+len(input)+1)
data = append(data, h.v...)
data = append(data, 0x01)
data = append(data, input...)
mac = hmac.New(sha256.New, h.k)
mac.Write(data)
h.k = mac.Sum(nil)
// V = HMAC(K, V)
mac = hmac.New(sha256.New, h.k)
mac.Write(h.v)
h.v = mac.Sum(nil)
return
}