1 package pkcs7
2
3 import (
4 "bytes"
5 "crypto/aes"
6 "crypto/cipher"
7 "crypto/des"
8 "crypto/rand"
9 "crypto/rsa"
10 "crypto/x509"
11 "crypto/x509/pkix"
12 "encoding/asn1"
13 "errors"
14 "fmt"
15 )
16
17 type envelopedData struct {
18 Version int
19 RecipientInfos []recipientInfo `asn1:"set"`
20 EncryptedContentInfo encryptedContentInfo
21 }
22
23 type encryptedData struct {
24 Version int
25 EncryptedContentInfo encryptedContentInfo
26 }
27
28 type recipientInfo struct {
29 Version int
30 IssuerAndSerialNumber issuerAndSerial
31 KeyEncryptionAlgorithm pkix.AlgorithmIdentifier
32 EncryptedKey []byte
33 }
34
35 type encryptedContentInfo struct {
36 ContentType asn1.ObjectIdentifier
37 ContentEncryptionAlgorithm pkix.AlgorithmIdentifier
38 EncryptedContent asn1.RawValue `asn1:"tag:0,optional"`
39 }
40
41 const (
42
43 EncryptionAlgorithmDESCBC = iota
44
45
46
47 EncryptionAlgorithmAES128CBC
48
49
50
51 EncryptionAlgorithmAES256CBC
52
53
54 EncryptionAlgorithmAES128GCM
55
56
57 EncryptionAlgorithmAES256GCM
58 )
59
60
61
62
63 var ContentEncryptionAlgorithm = EncryptionAlgorithmDESCBC
64
65
66
67 var ErrUnsupportedEncryptionAlgorithm = errors.New("pkcs7: cannot encrypt content: only DES-CBC, AES-CBC, and AES-GCM supported")
68
69
70
71 var ErrPSKNotProvided = errors.New("pkcs7: cannot encrypt content: PSK not provided")
72
73 const nonceSize = 12
74
75 type aesGCMParameters struct {
76 Nonce []byte `asn1:"tag:4"`
77 ICVLen int
78 }
79
80 func encryptAESGCM(content []byte, key []byte) ([]byte, *encryptedContentInfo, error) {
81 var keyLen int
82 var algID asn1.ObjectIdentifier
83 switch ContentEncryptionAlgorithm {
84 case EncryptionAlgorithmAES128GCM:
85 keyLen = 16
86 algID = OIDEncryptionAlgorithmAES128GCM
87 case EncryptionAlgorithmAES256GCM:
88 keyLen = 32
89 algID = OIDEncryptionAlgorithmAES256GCM
90 default:
91 return nil, nil, fmt.Errorf("invalid ContentEncryptionAlgorithm in encryptAESGCM: %d", ContentEncryptionAlgorithm)
92 }
93 if key == nil {
94
95 key = make([]byte, keyLen)
96
97 _, err := rand.Read(key)
98 if err != nil {
99 return nil, nil, err
100 }
101 }
102
103
104 nonce := make([]byte, nonceSize)
105
106 _, err := rand.Read(nonce)
107 if err != nil {
108 return nil, nil, err
109 }
110
111
112 block, err := aes.NewCipher(key)
113 if err != nil {
114 return nil, nil, err
115 }
116
117 gcm, err := cipher.NewGCM(block)
118 if err != nil {
119 return nil, nil, err
120 }
121
122 ciphertext := gcm.Seal(nil, nonce, content, nil)
123
124
125 paramSeq := aesGCMParameters{
126 Nonce: nonce,
127 ICVLen: gcm.Overhead(),
128 }
129
130 paramBytes, err := asn1.Marshal(paramSeq)
131 if err != nil {
132 return nil, nil, err
133 }
134
135 eci := encryptedContentInfo{
136 ContentType: OIDData,
137 ContentEncryptionAlgorithm: pkix.AlgorithmIdentifier{
138 Algorithm: algID,
139 Parameters: asn1.RawValue{
140 Tag: asn1.TagSequence,
141 Bytes: paramBytes,
142 },
143 },
144 EncryptedContent: marshalEncryptedContent(ciphertext),
145 }
146
147 return key, &eci, nil
148 }
149
150 func encryptDESCBC(content []byte, key []byte) ([]byte, *encryptedContentInfo, error) {
151 if key == nil {
152
153 key = make([]byte, 8)
154
155 _, err := rand.Read(key)
156 if err != nil {
157 return nil, nil, err
158 }
159 }
160
161
162 iv := make([]byte, des.BlockSize)
163 _, err := rand.Read(iv)
164 if err != nil {
165 return nil, nil, err
166 }
167
168
169 block, err := des.NewCipher(key)
170 if err != nil {
171 return nil, nil, err
172 }
173 mode := cipher.NewCBCEncrypter(block, iv)
174 plaintext, err := pad(content, mode.BlockSize())
175 if err != nil {
176 return nil, nil, err
177 }
178 cyphertext := make([]byte, len(plaintext))
179 mode.CryptBlocks(cyphertext, plaintext)
180
181
182 eci := encryptedContentInfo{
183 ContentType: OIDData,
184 ContentEncryptionAlgorithm: pkix.AlgorithmIdentifier{
185 Algorithm: OIDEncryptionAlgorithmDESCBC,
186 Parameters: asn1.RawValue{Tag: 4, Bytes: iv},
187 },
188 EncryptedContent: marshalEncryptedContent(cyphertext),
189 }
190
191 return key, &eci, nil
192 }
193
194 func encryptAESCBC(content []byte, key []byte) ([]byte, *encryptedContentInfo, error) {
195 var keyLen int
196 var algID asn1.ObjectIdentifier
197 switch ContentEncryptionAlgorithm {
198 case EncryptionAlgorithmAES128CBC:
199 keyLen = 16
200 algID = OIDEncryptionAlgorithmAES128CBC
201 case EncryptionAlgorithmAES256CBC:
202 keyLen = 32
203 algID = OIDEncryptionAlgorithmAES256CBC
204 default:
205 return nil, nil, fmt.Errorf("invalid ContentEncryptionAlgorithm in encryptAESCBC: %d", ContentEncryptionAlgorithm)
206 }
207
208 if key == nil {
209
210 key = make([]byte, keyLen)
211
212 _, err := rand.Read(key)
213 if err != nil {
214 return nil, nil, err
215 }
216 }
217
218
219 iv := make([]byte, aes.BlockSize)
220 _, err := rand.Read(iv)
221 if err != nil {
222 return nil, nil, err
223 }
224
225
226 block, err := aes.NewCipher(key)
227 if err != nil {
228 return nil, nil, err
229 }
230 mode := cipher.NewCBCEncrypter(block, iv)
231 plaintext, err := pad(content, mode.BlockSize())
232 if err != nil {
233 return nil, nil, err
234 }
235 cyphertext := make([]byte, len(plaintext))
236 mode.CryptBlocks(cyphertext, plaintext)
237
238
239 eci := encryptedContentInfo{
240 ContentType: OIDData,
241 ContentEncryptionAlgorithm: pkix.AlgorithmIdentifier{
242 Algorithm: algID,
243 Parameters: asn1.RawValue{Tag: 4, Bytes: iv},
244 },
245 EncryptedContent: marshalEncryptedContent(cyphertext),
246 }
247
248 return key, &eci, nil
249 }
250
251
252
253
254
255
256
257
258
259
260
261
262 func Encrypt(content []byte, recipients []*x509.Certificate) ([]byte, error) {
263 var eci *encryptedContentInfo
264 var key []byte
265 var err error
266
267
268 switch ContentEncryptionAlgorithm {
269 case EncryptionAlgorithmDESCBC:
270 key, eci, err = encryptDESCBC(content, nil)
271 case EncryptionAlgorithmAES128CBC:
272 fallthrough
273 case EncryptionAlgorithmAES256CBC:
274 key, eci, err = encryptAESCBC(content, nil)
275 case EncryptionAlgorithmAES128GCM:
276 fallthrough
277 case EncryptionAlgorithmAES256GCM:
278 key, eci, err = encryptAESGCM(content, nil)
279
280 default:
281 return nil, ErrUnsupportedEncryptionAlgorithm
282 }
283
284 if err != nil {
285 return nil, err
286 }
287
288
289 recipientInfos := make([]recipientInfo, len(recipients))
290 for i, recipient := range recipients {
291 encrypted, err := encryptKey(key, recipient)
292 if err != nil {
293 return nil, err
294 }
295 ias, err := cert2issuerAndSerial(recipient)
296 if err != nil {
297 return nil, err
298 }
299 info := recipientInfo{
300 Version: 0,
301 IssuerAndSerialNumber: ias,
302 KeyEncryptionAlgorithm: pkix.AlgorithmIdentifier{
303 Algorithm: OIDEncryptionAlgorithmRSA,
304 },
305 EncryptedKey: encrypted,
306 }
307 recipientInfos[i] = info
308 }
309
310
311 envelope := envelopedData{
312 EncryptedContentInfo: *eci,
313 Version: 0,
314 RecipientInfos: recipientInfos,
315 }
316 innerContent, err := asn1.Marshal(envelope)
317 if err != nil {
318 return nil, err
319 }
320
321
322 wrapper := contentInfo{
323 ContentType: OIDEnvelopedData,
324 Content: asn1.RawValue{Class: 2, Tag: 0, IsCompound: true, Bytes: innerContent},
325 }
326
327 return asn1.Marshal(wrapper)
328 }
329
330
331
332 func EncryptUsingPSK(content []byte, key []byte) ([]byte, error) {
333 var eci *encryptedContentInfo
334 var err error
335
336 if key == nil {
337 return nil, ErrPSKNotProvided
338 }
339
340
341 switch ContentEncryptionAlgorithm {
342 case EncryptionAlgorithmDESCBC:
343 _, eci, err = encryptDESCBC(content, key)
344
345 case EncryptionAlgorithmAES128GCM:
346 fallthrough
347 case EncryptionAlgorithmAES256GCM:
348 _, eci, err = encryptAESGCM(content, key)
349
350 default:
351 return nil, ErrUnsupportedEncryptionAlgorithm
352 }
353
354 if err != nil {
355 return nil, err
356 }
357
358
359 ed := encryptedData{
360 Version: 0,
361 EncryptedContentInfo: *eci,
362 }
363 innerContent, err := asn1.Marshal(ed)
364 if err != nil {
365 return nil, err
366 }
367
368
369 wrapper := contentInfo{
370 ContentType: OIDEncryptedData,
371 Content: asn1.RawValue{Class: 2, Tag: 0, IsCompound: true, Bytes: innerContent},
372 }
373
374 return asn1.Marshal(wrapper)
375 }
376
377 func marshalEncryptedContent(content []byte) asn1.RawValue {
378 asn1Content, _ := asn1.Marshal(content)
379 return asn1.RawValue{Tag: 0, Class: 2, Bytes: asn1Content, IsCompound: true}
380 }
381
382 func encryptKey(key []byte, recipient *x509.Certificate) ([]byte, error) {
383 if pub := recipient.PublicKey.(*rsa.PublicKey); pub != nil {
384 return rsa.EncryptPKCS1v15(rand.Reader, pub, key)
385 }
386 return nil, ErrUnsupportedAlgorithm
387 }
388
389 func pad(data []byte, blocklen int) ([]byte, error) {
390 if blocklen < 1 {
391 return nil, fmt.Errorf("invalid blocklen %d", blocklen)
392 }
393 padlen := blocklen - (len(data) % blocklen)
394 if padlen == 0 {
395 padlen = blocklen
396 }
397 pad := bytes.Repeat([]byte{byte(padlen)}, padlen)
398 return append(data, pad...), nil
399 }
400
View as plain text