/
x509.go
109 lines (95 loc) · 3.23 KB
/
x509.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
package pkcs7
import (
"crypto/x509/pkix"
"encoding/asn1"
"errors"
"fmt"
"github.com/Theo730/gogost/gost3410"
)
type KeyAlgorithm int
const (
UnknownKeyAlgorithm KeyAlgorithm = iota
GOST
)
type GostR3410KeyParameters struct {
KeyParamSet asn1.ObjectIdentifier
DigestParamSet asn1.ObjectIdentifier `asn1:"optional"`
}
func getKeyAlgorithmFromOID(oid asn1.ObjectIdentifier) KeyAlgorithm {
switch {
case oid.Equal(oidSignatureGOSTR3410_2001):
return GOST
case oid.Equal(oidTc26Gost34102012256):
return GOST
case oid.Equal(oidTc26Gost34102012512):
return GOST
case oid.Equal(oidTc26agreementgost341012256):
return GOST
case oid.Equal(oidTc26agreementgost341012512):
return GOST
case oid.Equal(oidTc26signwithdigestgost341012256):
return GOST
case oid.Equal(oidTc26signwithdigestgost341012512):
return GOST
}
return UnknownKeyAlgorithm
}
func getCurve(algo pkix.AlgorithmIdentifier) (curve *gost3410.Curve, err error) {
var keyParams GostR3410KeyParameters
params := algo.Parameters.FullBytes
restBytes, err := asn1.Unmarshal(params, &keyParams)
if err != nil {
return nil, errors.New("x509: failed to parse GOST parameters")
}
if len(restBytes) != 0 {
return nil, errors.New("x509: there is data after GOST parameters ")
}
switch {
case keyParams.KeyParamSet.Equal(oidGostR34102001CryptoProAParamSet):
curve = gost3410.CurveIdGostR34102001CryptoProAParamSet()
case keyParams.KeyParamSet.Equal(oidGostR34102001CryptoProBParamSet):
curve = gost3410.CurveIdGostR34102001CryptoProBParamSet()
case keyParams.KeyParamSet.Equal(oidGostR34102001CryptoProCParamSet):
curve = gost3410.CurveIdGostR34102001CryptoProCParamSet()
case keyParams.KeyParamSet.Equal(oidGostR34102001CryptoProXchAParamSet):
curve = gost3410.CurveIdGostR34102001CryptoProXchAParamSet()
case keyParams.KeyParamSet.Equal(oidGostR34102001CryptoProXchBParamSet):
curve = gost3410.CurveIdGostR34102001CryptoProXchBParamSet()
case keyParams.KeyParamSet.Equal(oidTc26Gost34102012256ParamSetA):
curve = gost3410.CurveIdtc26gost34102012256paramSetA()
case keyParams.KeyParamSet.Equal(oidTc26Gost34102012256ParamSetB):
curve = gost3410.CurveIdtc26gost34102012256paramSetB()
case keyParams.KeyParamSet.Equal(oidTc26Gost34102012256ParamSetC):
curve = gost3410.CurveIdtc26gost34102012256paramSetC()
case keyParams.KeyParamSet.Equal(oidTc26Gost34102012256ParamSetD):
curve = gost3410.CurveIdtc26gost34102012256paramSetD()
default:
return nil, errors.New("x509: unknown GOST curve")
}
return curve, nil
}
type pkcs8 struct {
Version int
Algo pkix.AlgorithmIdentifier
PrivateKey []byte
// options
}
func ParsePKCS8PrivateKey(derBytes []byte) (key *gost3410.PrivateKey, err error) {
var privKey pkcs8
if _, err := asn1.Unmarshal(derBytes, &privKey); err != nil {
return nil, err
}
algo := getKeyAlgorithmFromOID(privKey.Algo.Algorithm)
switch algo {
case GOST:
privRaw := make([]byte,32)
copy(privRaw, privKey.PrivateKey[:32])
curve, err := getCurve(privKey.Algo)
if err != nil {
return nil, err
}
return gost3410.NewPrivateKey(curve, privKey.PrivateKey)
default:
return nil, fmt.Errorf("x509: PKCS#8 unknown algorithm: %v", privKey.Algo.Algorithm)
}
}