-
Notifications
You must be signed in to change notification settings - Fork 56
/
kdf_pbkdf2.go
141 lines (126 loc) · 4.11 KB
/
kdf_pbkdf2.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
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
package pkcs8
//
// Reference https://datatracker.ietf.org/doc/html/rfc8018#section-5.2
//
import (
"crypto/sha1"
"crypto/sha256"
"crypto/sha512"
"crypto/x509/pkix"
"encoding/asn1"
"errors"
"hash"
"github.com/emmansun/gmsm/sm3"
"golang.org/x/crypto/pbkdf2"
)
// http://gmssl.org/docs/oid.html
var (
oidPKCS5PBKDF2 = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 5, 12}
oidHMACWithSHA1 = asn1.ObjectIdentifier{1, 2, 840, 113549, 2, 7}
oidHMACWithSHA224 = asn1.ObjectIdentifier{1, 2, 840, 113549, 2, 8}
oidHMACWithSHA256 = asn1.ObjectIdentifier{1, 2, 840, 113549, 2, 9}
oidHMACWithSHA384 = asn1.ObjectIdentifier{1, 2, 840, 113549, 2, 10}
oidHMACWithSHA512 = asn1.ObjectIdentifier{1, 2, 840, 113549, 2, 11}
oidHMACWithSHA512_224 = asn1.ObjectIdentifier{1, 2, 840, 113549, 2, 12}
oidHMACWithSHA512_256 = asn1.ObjectIdentifier{1, 2, 840, 113549, 2, 13}
oidHMACWithSM3 = asn1.ObjectIdentifier{1, 2, 156, 10197, 1, 401, 2}
)
func init() {
RegisterKDF(oidPKCS5PBKDF2, func() KDFParameters {
return new(pbkdf2Params)
})
}
func newHashFromPRF(ai pkix.AlgorithmIdentifier) (func() hash.Hash, error) {
switch {
case len(ai.Algorithm) == 0 || ai.Algorithm.Equal(oidHMACWithSHA1):
return sha1.New, nil
case ai.Algorithm.Equal(oidHMACWithSHA224):
return sha256.New224, nil
case ai.Algorithm.Equal(oidHMACWithSHA256):
return sha256.New, nil
case ai.Algorithm.Equal(oidHMACWithSHA384):
return sha512.New384, nil
case ai.Algorithm.Equal(oidHMACWithSHA512):
return sha512.New, nil
case ai.Algorithm.Equal(oidHMACWithSHA512_224):
return sha512.New512_224, nil
case ai.Algorithm.Equal(oidHMACWithSHA512_256):
return sha512.New512_256, nil
case ai.Algorithm.Equal(oidHMACWithSM3):
return sm3.New, nil
default:
return nil, errors.New("pkcs8: unsupported hash function")
}
}
func newPRFParamFromHash(h Hash) (pkix.AlgorithmIdentifier, error) {
switch h {
case SHA1:
return pkix.AlgorithmIdentifier{
Algorithm: oidHMACWithSHA1,
Parameters: asn1.RawValue{Tag: asn1.TagNull}}, nil
case SHA224:
return pkix.AlgorithmIdentifier{
Algorithm: oidHMACWithSHA224,
Parameters: asn1.RawValue{Tag: asn1.TagNull}}, nil
case SHA256:
return pkix.AlgorithmIdentifier{
Algorithm: oidHMACWithSHA256,
Parameters: asn1.RawValue{Tag: asn1.TagNull}}, nil
case SHA384:
return pkix.AlgorithmIdentifier{
Algorithm: oidHMACWithSHA384,
Parameters: asn1.RawValue{Tag: asn1.TagNull}}, nil
case SHA512:
return pkix.AlgorithmIdentifier{
Algorithm: oidHMACWithSHA512,
Parameters: asn1.RawValue{Tag: asn1.TagNull}}, nil
case SHA512_224:
return pkix.AlgorithmIdentifier{
Algorithm: oidHMACWithSHA512_224,
Parameters: asn1.RawValue{Tag: asn1.TagNull}}, nil
case SHA512_256:
return pkix.AlgorithmIdentifier{
Algorithm: oidHMACWithSHA512_256,
Parameters: asn1.RawValue{Tag: asn1.TagNull}}, nil
case SM3:
return pkix.AlgorithmIdentifier{
Algorithm: oidHMACWithSM3,
Parameters: asn1.RawValue{Tag: asn1.TagNull}}, nil
}
return pkix.AlgorithmIdentifier{}, errors.New("pkcs8: unsupported hash function")
}
type pbkdf2Params struct {
Salt []byte
IterationCount int
KeyLen int `asn1:"optional"`
PRF pkix.AlgorithmIdentifier `asn1:"optional"`
}
func (p pbkdf2Params) DeriveKey(password []byte, size int) (key []byte, err error) {
h, err := newHashFromPRF(p.PRF)
if err != nil {
return nil, err
}
return pbkdf2.Key(password, p.Salt, p.IterationCount, size, h), nil
}
// PBKDF2Opts contains options for the PBKDF2 key derivation function.
type PBKDF2Opts struct {
SaltSize int
IterationCount int
HMACHash Hash
}
func (p PBKDF2Opts) DeriveKey(password, salt []byte, size int) (
key []byte, params KDFParameters, err error) {
key = pbkdf2.Key(password, salt, p.IterationCount, size, p.HMACHash.New)
prfParam, err := newPRFParamFromHash(p.HMACHash)
if err != nil {
return nil, nil, err
}
params = pbkdf2Params{salt, p.IterationCount, size, prfParam}
return key, params, nil
}
func (p PBKDF2Opts) GetSaltSize() int {
return p.SaltSize
}
func (p PBKDF2Opts) OID() asn1.ObjectIdentifier {
return oidPKCS5PBKDF2
}