forked from SSLMate/go-pkcs12
/
safebags.go
183 lines (152 loc) · 6.42 KB
/
safebags.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
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
// Copyright 2015, 2018, 2019 Opsmate, Inc. All rights reserved.
// Copyright 2015 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package pkcs12
import (
"crypto/x509"
"crypto/x509/pkix"
"encoding/asn1"
"github.com/pkg/errors"
"io"
"io/ioutil"
)
var (
// see https://tools.ietf.org/html/rfc7292#appendix-D
oidCertTypeX509Certificate = asn1.ObjectIdentifier([]int{1, 2, 840, 113549, 1, 9, 22, 1})
oidCrlTypeX509Crl = asn1.ObjectIdentifier([]int{1, 2, 840, 113549, 1, 9, 23, 1})
oidKeyBag = asn1.ObjectIdentifier([]int{1, 2, 840, 113549, 1, 12, 10, 1, 1})
oidPKCS8ShroundedKeyBag = asn1.ObjectIdentifier([]int{1, 2, 840, 113549, 1, 12, 10, 1, 2})
oidCertBag = asn1.ObjectIdentifier([]int{1, 2, 840, 113549, 1, 12, 10, 1, 3})
oidCrlBag = asn1.ObjectIdentifier([]int{1, 2, 840, 113549, 1, 12, 10, 1, 4})
oidSecretBag = asn1.ObjectIdentifier([]int{1, 2, 840, 113549, 1, 12, 10, 1, 5})
oidSafeContentsBag = asn1.ObjectIdentifier([]int{1, 2, 840, 113549, 1, 12, 10, 1, 6})
)
type certBag struct {
Id asn1.ObjectIdentifier
Data []byte `asn1:"tag:0,explicit"`
}
type crlBag struct {
Id asn1.ObjectIdentifier
Data []byte `asn1:"tag:0,explicit"`
}
type secretBag struct {
Id asn1.ObjectIdentifier
Data []byte `asn1:"tag:0,explicit"`
}
func decodePkcs8ShroudedKeyBag(asn1Data, password []byte) (privateKey interface{}, err error) {
pkinfo := new(encryptedPrivateKeyInfo)
if err = unmarshal(asn1Data, pkinfo); err != nil {
return nil, errors.WithStack(errors.New("pkcs12: error decoding PKCS#8 shrouded key bag: " + err.Error()))
}
pkData, err := pbDecrypt(pkinfo, password)
if err != nil {
return nil, errors.WithStack(errors.New("pkcs12: error decrypting PKCS#8 shrouded key bag: " + err.Error()))
}
ret := new(asn1.RawValue)
if err = unmarshal(pkData, ret); err != nil {
return nil, errors.WithStack(errors.New("pkcs12: error unmarshaling decrypted private key: " + err.Error()))
}
if privateKey, err = x509.ParsePKCS8PrivateKey(pkData); err != nil {
return nil, errors.WithStack(errors.New("pkcs12: error parsing PKCS#8 private key: " + err.Error()))
}
return privateKey, nil
}
func encodePkcs8ShroudedKeyBag(rand io.Reader, privateKey interface{}, password []byte) (asn1Data []byte, err error) {
var pkData []byte
if pkData, err = x509.MarshalPKCS8PrivateKey(privateKey); err != nil {
return nil, errors.WithStack(errors.New("pkcs12: error encoding PKCS#8 private key: " + err.Error()))
}
randomSalt := make([]byte, 8)
if _, err = rand.Read(randomSalt); err != nil {
return nil, errors.WithStack(errors.New("pkcs12: error reading random salt: " + err.Error()))
}
var paramBytes []byte
if paramBytes, err = asn1.Marshal(pbeParams{Salt: randomSalt, Iterations: 2048}); err != nil {
return nil, errors.WithStack(errors.New("pkcs12: error encoding params: " + err.Error()))
}
var pkinfo encryptedPrivateKeyInfo
pkinfo.AlgorithmIdentifier.Algorithm = oidPBEWithSHAAnd3KeyTripleDESCBC
pkinfo.AlgorithmIdentifier.Parameters.FullBytes = paramBytes
if err = pbEncrypt(&pkinfo, pkData, password); err != nil {
return nil, errors.WithStack(errors.New("pkcs12: error encrypting PKCS#8 shrouded key bag: " + err.Error()))
}
if asn1Data, err = asn1.Marshal(pkinfo); err != nil {
return nil, errors.WithStack(errors.New("pkcs12: error encoding PKCS#8 shrouded key bag: " + err.Error()))
}
return asn1Data, nil
}
func decodePkcs8KeyBag(asn1Data []byte) (privateKey interface{}, err error) {
ret := new(asn1.RawValue)
if err = unmarshal(asn1Data, ret); err != nil {
return nil, errors.WithStack(errors.New("pkcs12: error unmarshaling private key: " + err.Error()))
}
if privateKey, err = x509.ParsePKCS8PrivateKey(ret.Bytes); err != nil {
return nil, errors.WithStack(errors.New("pkcs12: error parsing PKCS#8 private key: " + err.Error()))
}
return privateKey, nil
}
func encodePkcs8KeyBag(rand io.Reader, privateKey interface{}) (asn1Data []byte, err error) {
var pkData []byte
if pkData, err = x509.MarshalPKCS8PrivateKey(privateKey); err != nil {
return nil, errors.WithStack(errors.New("pkcs12: error encoding PKCS#8 private key: " + err.Error()))
}
return pkData, nil
}
func decodeCertBag(asn1Data []byte) (x509Certificates []byte, err error) {
bag := new(certBag)
if err := unmarshal(asn1Data, bag); err != nil {
return nil, errors.WithStack(errors.New("pkcs12: error decoding cert bag: " + err.Error()))
}
if !bag.Id.Equal(oidCertTypeX509Certificate) {
return nil, errors.WithStack(NotImplementedError("only X509 certificates are supported"))
}
return bag.Data, nil
}
func encodeCertBag(x509Certificates []byte) (asn1Data []byte, err error) {
var bag certBag
bag.Id = oidCertTypeX509Certificate
bag.Data = x509Certificates
if asn1Data, err = asn1.Marshal(bag); err != nil {
return nil, errors.WithStack(errors.New("pkcs12: error encoding cert bag: " + err.Error()))
}
return asn1Data, nil
}
func decodeCrlBag(asn1Data []byte) (crlData []byte, err error) {
bag := new(crlBag)
if err := unmarshal(asn1Data, bag); err != nil {
return nil, errors.WithStack(errors.New("pkcs12: error decoding crl bag: " + err.Error()))
}
if !bag.Id.Equal(oidCrlTypeX509Crl) {
return nil, errors.WithStack(NotImplementedError("only X509 crls are supported"))
}
return bag.Data, nil
}
func encodeCrlBag(x509Crl *pkix.CertificateList) (asn1Data []byte, err error) {
var bag certBag
bag.Id = oidCrlTypeX509Crl
if bag.Data, err = asn1.Marshal(x509Crl); err != nil {
return nil, errors.WithStack(errors.New("pkcs12: error encoding crl: " + err.Error()))
}
if asn1Data, err = asn1.Marshal(bag); err != nil {
return nil, errors.WithStack(errors.New("pkcs12: error encoding crl bag: " + err.Error()))
}
return asn1Data, nil
}
func decodeSecretBag(asn1Data, password []byte) (secretData []byte, err error) {
ret := new(asn1.RawValue)
if err = unmarshal(asn1Data, ret); err != nil {
return nil, errors.WithStack(errors.New("pkcs12: error unmarshaling secret data: " + err.Error()))
}
ioutil.WriteFile("/tmp/asndump.dat", ret.FullBytes, 0644)
return ret.Bytes, err
}
func encodeSecretBag(secretData []byte) (asn1Data []byte, err error) {
var bag secretBag
bag.Id = oidSecretBag
bag.Data = secretData
if asn1Data, err = asn1.Marshal(bag); err != nil {
return nil, errors.WithStack(errors.New("pkcs12: error encoding secret bag: " + err.Error()))
}
return asn1Data, nil
}