-
Notifications
You must be signed in to change notification settings - Fork 21
/
key_pkcs8.go
144 lines (112 loc) · 3.38 KB
/
key_pkcs8.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
142
143
144
package sm2
import (
"errors"
"encoding/asn1"
"crypto/x509/pkix"
"github.com/deatil/go-cryptobin/gm/sm2/sm2curve"
)
var (
oidSM2 = asn1.ObjectIdentifier{1, 2, 840, 10045, 2, 1}
oidPublicKeySM2 = asn1.ObjectIdentifier{1, 2, 156, 10197, 1, 301}
)
// pkcs8 info
type pkcs8 struct {
Version int
Algo pkix.AlgorithmIdentifier
PrivateKey []byte
Attributes []asn1.RawValue `asn1:"optional,tag:0"`
}
// pkcs8 attribute info
type pkcs8Attribute struct {
Id asn1.ObjectIdentifier
Values []asn1.RawValue `asn1:"set"`
}
// pkixPublicKey reflects a PKIX public key structure. See SubjectPublicKeyInfo
// in RFC 3280.
type pkixPublicKey struct {
Algo pkix.AlgorithmIdentifier
BitString asn1.BitString
}
func ParsePrivateKey(der []byte) (*PrivateKey, error) {
var privKey pkcs8
if _, err := asn1.Unmarshal(der, &privKey); err != nil {
return nil, err
}
if !privKey.Algo.Algorithm.Equal(oidSM2) &&
!privKey.Algo.Algorithm.Equal(oidPublicKeySM2) {
err := errors.New("sm2: unknown private key algorithm")
return nil, err
}
bytes := privKey.Algo.Parameters.FullBytes
namedCurveOID := new(asn1.ObjectIdentifier)
if _, err := asn1.Unmarshal(bytes, namedCurveOID); err != nil {
namedCurveOID = nil
}
return parseSM2PrivateKey(namedCurveOID, privKey.PrivateKey)
}
func MarshalPrivateKey(key *PrivateKey) ([]byte, error) {
var r pkcs8
var algo pkix.AlgorithmIdentifier
if key.Curve != P256() {
return nil, errors.New("sm2: unsupported SM2 curve")
}
oidBytes, err := asn1.Marshal(oidPublicKeySM2)
if err != nil {
return nil, errors.New("sm2: failed to marshal algo param: " + err.Error())
}
algo.Algorithm = oidSM2
algo.Parameters.Class = 0
algo.Parameters.Tag = 6
algo.Parameters.IsCompound = false
algo.Parameters.FullBytes = oidBytes
oid, ok := oidFromNamedCurve(key.Curve)
if !ok {
return nil, errors.New("sm2: unknown curve")
}
r.Version = 0
r.Algo = algo
r.PrivateKey, err = marshalSM2PrivateKeyWithOID(key, oid)
if err != nil {
return nil, err
}
return asn1.Marshal(r)
}
func ParsePublicKey(der []byte) (*PublicKey, error) {
var pubkey pkixPublicKey
if _, err := asn1.Unmarshal(der, &pubkey); err != nil {
return nil, err
}
if !pubkey.Algo.Algorithm.Equal(oidSM2) &&
!pubkey.Algo.Algorithm.Equal(oidPublicKeySM2) {
return nil, errors.New("sm2: not sm2 curve")
}
c := P256()
x, y := sm2curve.Unmarshal(c, pubkey.BitString.Bytes)
pub := PublicKey{
Curve: c,
X: x,
Y: y,
}
return &pub, nil
}
func MarshalPublicKey(key *PublicKey) ([]byte, error) {
var r pkixPublicKey
var algo pkix.AlgorithmIdentifier
if key.Curve != P256() {
return nil, errors.New("sm2: unsupported SM2 curve")
}
oidBytes, err := asn1.Marshal(oidPublicKeySM2)
if err != nil {
return nil, errors.New("sm2: failed to marshal algo param: " + err.Error())
}
algo.Algorithm = oidSM2
algo.Parameters.Class = 0
algo.Parameters.Tag = 6
algo.Parameters.IsCompound = false
algo.Parameters.FullBytes = oidBytes
r.Algo = algo
r.BitString = asn1.BitString{
Bytes: sm2curve.Marshal(key.Curve, key.X, key.Y),
}
return asn1.Marshal(r)
}