1// Package pkcs7 implements parsing and generation of some PKCS#7 structures. 2package pkcs7 3 4import ( 5 "bytes" 6 "crypto" 7 "crypto/aes" 8 "crypto/cipher" 9 "crypto/des" 10 "crypto/hmac" 11 "crypto/rand" 12 "crypto/rsa" 13 "crypto/x509" 14 "crypto/x509/pkix" 15 "encoding/asn1" 16 "errors" 17 "fmt" 18 "math/big" 19 "sort" 20 "time" 21 22 _ "crypto/sha1" // for crypto.SHA1 23) 24 25// PKCS7 Represents a PKCS7 structure 26type PKCS7 struct { 27 Content []byte 28 Certificates []*x509.Certificate 29 CRLs []pkix.CertificateList 30 Signers []signerInfo 31 raw interface{} 32} 33 34type contentInfo struct { 35 ContentType asn1.ObjectIdentifier 36 Content asn1.RawValue `asn1:"explicit,optional,tag:0"` 37} 38 39// ErrUnsupportedContentType is returned when a PKCS7 content is not supported. 40// Currently only Data (1.2.840.113549.1.7.1), Signed Data (1.2.840.113549.1.7.2), 41// and Enveloped Data are supported (1.2.840.113549.1.7.3) 42var ErrUnsupportedContentType = errors.New("pkcs7: cannot parse data: unimplemented content type") 43 44type unsignedData []byte 45 46var ( 47 oidData = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 7, 1} 48 oidSignedData = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 7, 2} 49 oidEnvelopedData = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 7, 3} 50 oidSignedAndEnvelopedData = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 7, 4} 51 oidDigestedData = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 7, 5} 52 oidEncryptedData = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 7, 6} 53 oidAttributeContentType = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 9, 3} 54 oidAttributeMessageDigest = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 9, 4} 55 oidAttributeSigningTime = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 9, 5} 56) 57 58type signedData struct { 59 Version int `asn1:"default:1"` 60 DigestAlgorithmIdentifiers []pkix.AlgorithmIdentifier `asn1:"set"` 61 ContentInfo contentInfo 62 Certificates rawCertificates `asn1:"optional,tag:0"` 63 CRLs []pkix.CertificateList `asn1:"optional,tag:1"` 64 SignerInfos []signerInfo `asn1:"set"` 65} 66 67type rawCertificates struct { 68 Raw asn1.RawContent 69} 70 71type envelopedData struct { 72 Version int 73 RecipientInfos []recipientInfo `asn1:"set"` 74 EncryptedContentInfo encryptedContentInfo 75} 76 77type recipientInfo struct { 78 Version int 79 IssuerAndSerialNumber issuerAndSerial 80 KeyEncryptionAlgorithm pkix.AlgorithmIdentifier 81 EncryptedKey []byte 82} 83 84type encryptedContentInfo struct { 85 ContentType asn1.ObjectIdentifier 86 ContentEncryptionAlgorithm pkix.AlgorithmIdentifier 87 EncryptedContent asn1.RawValue `asn1:"tag:0,optional"` 88} 89 90type attribute struct { 91 Type asn1.ObjectIdentifier 92 Value asn1.RawValue `asn1:"set"` 93} 94 95type issuerAndSerial struct { 96 IssuerName asn1.RawValue 97 SerialNumber *big.Int 98} 99 100// MessageDigestMismatchError is returned when the signer data digest does not 101// match the computed digest for the contained content 102type MessageDigestMismatchError struct { 103 ExpectedDigest []byte 104 ActualDigest []byte 105} 106 107func (err *MessageDigestMismatchError) Error() string { 108 return fmt.Sprintf("pkcs7: Message digest mismatch\n\tExpected: %X\n\tActual : %X", err.ExpectedDigest, err.ActualDigest) 109} 110 111type signerInfo struct { 112 Version int `asn1:"default:1"` 113 IssuerAndSerialNumber issuerAndSerial 114 DigestAlgorithm pkix.AlgorithmIdentifier 115 AuthenticatedAttributes []attribute `asn1:"optional,tag:0"` 116 DigestEncryptionAlgorithm pkix.AlgorithmIdentifier 117 EncryptedDigest []byte 118 UnauthenticatedAttributes []attribute `asn1:"optional,tag:1"` 119} 120 121// Parse decodes a DER encoded PKCS7 package 122func Parse(data []byte) (p7 *PKCS7, err error) { 123 if len(data) == 0 { 124 return nil, errors.New("pkcs7: input data is empty") 125 } 126 var info contentInfo 127 der, err := ber2der(data) 128 if err != nil { 129 return nil, err 130 } 131 rest, err := asn1.Unmarshal(der, &info) 132 if len(rest) > 0 { 133 err = asn1.SyntaxError{Msg: "trailing data"} 134 return 135 } 136 if err != nil { 137 return 138 } 139 140 // fmt.Printf("--> Content Type: %s", info.ContentType) 141 switch { 142 case info.ContentType.Equal(oidSignedData): 143 return parseSignedData(info.Content.Bytes) 144 case info.ContentType.Equal(oidEnvelopedData): 145 return parseEnvelopedData(info.Content.Bytes) 146 } 147 return nil, ErrUnsupportedContentType 148} 149 150func parseSignedData(data []byte) (*PKCS7, error) { 151 var sd signedData 152 asn1.Unmarshal(data, &sd) 153 certs, err := sd.Certificates.Parse() 154 if err != nil { 155 return nil, err 156 } 157 // fmt.Printf("--> Signed Data Version %d\n", sd.Version) 158 159 var compound asn1.RawValue 160 var content unsignedData 161 162 // The Content.Bytes maybe empty on PKI responses. 163 if len(sd.ContentInfo.Content.Bytes) > 0 { 164 if _, err := asn1.Unmarshal(sd.ContentInfo.Content.Bytes, &compound); err != nil { 165 return nil, err 166 } 167 } 168 // Compound octet string 169 if compound.IsCompound { 170 if _, err = asn1.Unmarshal(compound.Bytes, &content); err != nil { 171 return nil, err 172 } 173 } else { 174 // assuming this is tag 04 175 content = compound.Bytes 176 } 177 return &PKCS7{ 178 Content: content, 179 Certificates: certs, 180 CRLs: sd.CRLs, 181 Signers: sd.SignerInfos, 182 raw: sd}, nil 183} 184 185func (raw rawCertificates) Parse() ([]*x509.Certificate, error) { 186 if len(raw.Raw) == 0 { 187 return nil, nil 188 } 189 190 var val asn1.RawValue 191 if _, err := asn1.Unmarshal(raw.Raw, &val); err != nil { 192 return nil, err 193 } 194 195 return x509.ParseCertificates(val.Bytes) 196} 197 198func parseEnvelopedData(data []byte) (*PKCS7, error) { 199 var ed envelopedData 200 if _, err := asn1.Unmarshal(data, &ed); err != nil { 201 return nil, err 202 } 203 return &PKCS7{ 204 raw: ed, 205 }, nil 206} 207 208// Verify checks the signatures of a PKCS7 object 209// WARNING: Verify does not check signing time or verify certificate chains at 210// this time. 211func (p7 *PKCS7) Verify() (err error) { 212 if len(p7.Signers) == 0 { 213 return errors.New("pkcs7: Message has no signers") 214 } 215 for _, signer := range p7.Signers { 216 if err := verifySignature(p7, signer); err != nil { 217 return err 218 } 219 } 220 return nil 221} 222 223func verifySignature(p7 *PKCS7, signer signerInfo) error { 224 signedData := p7.Content 225 hash, err := getHashForOID(signer.DigestAlgorithm.Algorithm) 226 if err != nil { 227 return err 228 } 229 if len(signer.AuthenticatedAttributes) > 0 { 230 // TODO(fullsailor): First check the content type match 231 var digest []byte 232 err := unmarshalAttribute(signer.AuthenticatedAttributes, oidAttributeMessageDigest, &digest) 233 if err != nil { 234 return err 235 } 236 h := hash.New() 237 h.Write(p7.Content) 238 computed := h.Sum(nil) 239 if !hmac.Equal(digest, computed) { 240 return &MessageDigestMismatchError{ 241 ExpectedDigest: digest, 242 ActualDigest: computed, 243 } 244 } 245 // TODO(fullsailor): Optionally verify certificate chain 246 // TODO(fullsailor): Optionally verify signingTime against certificate NotAfter/NotBefore 247 signedData, err = marshalAttributes(signer.AuthenticatedAttributes) 248 if err != nil { 249 return err 250 } 251 } 252 cert := getCertFromCertsByIssuerAndSerial(p7.Certificates, signer.IssuerAndSerialNumber) 253 if cert == nil { 254 return errors.New("pkcs7: No certificate for signer") 255 } 256 257 algo := getSignatureAlgorithmFromAI(signer.DigestEncryptionAlgorithm) 258 if algo == x509.UnknownSignatureAlgorithm { 259 // I'm not sure what the spec here is, and the openssl sources were not 260 // helpful. But, this is what App Store receipts appear to do. 261 // The DigestEncryptionAlgorithm is just "rsaEncryption (PKCS #1)" 262 // But we're expecting a digest + encryption algorithm. So... we're going 263 // to determine an algorithm based on the DigestAlgorithm and this 264 // encryption algorithm. 265 if signer.DigestEncryptionAlgorithm.Algorithm.Equal(oidEncryptionAlgorithmRSA) { 266 algo = getRSASignatureAlgorithmForDigestAlgorithm(hash) 267 } 268 } 269 return cert.CheckSignature(algo, signedData, signer.EncryptedDigest) 270} 271 272func marshalAttributes(attrs []attribute) ([]byte, error) { 273 encodedAttributes, err := asn1.Marshal(struct { 274 A []attribute `asn1:"set"` 275 }{A: attrs}) 276 if err != nil { 277 return nil, err 278 } 279 280 // Remove the leading sequence octets 281 var raw asn1.RawValue 282 asn1.Unmarshal(encodedAttributes, &raw) 283 return raw.Bytes, nil 284} 285 286var ( 287 oidDigestAlgorithmSHA1 = asn1.ObjectIdentifier{1, 3, 14, 3, 2, 26} 288 oidEncryptionAlgorithmRSA = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 1, 1} 289) 290 291func getCertFromCertsByIssuerAndSerial(certs []*x509.Certificate, ias issuerAndSerial) *x509.Certificate { 292 for _, cert := range certs { 293 if isCertMatchForIssuerAndSerial(cert, ias) { 294 return cert 295 } 296 } 297 return nil 298} 299 300func getHashForOID(oid asn1.ObjectIdentifier) (crypto.Hash, error) { 301 switch { 302 case oid.Equal(oidDigestAlgorithmSHA1): 303 return crypto.SHA1, nil 304 case oid.Equal(oidSHA256): 305 return crypto.SHA256, nil 306 } 307 return crypto.Hash(0), ErrUnsupportedAlgorithm 308} 309 310func getRSASignatureAlgorithmForDigestAlgorithm(hash crypto.Hash) x509.SignatureAlgorithm { 311 for _, details := range signatureAlgorithmDetails { 312 if details.pubKeyAlgo == x509.RSA && details.hash == hash { 313 return details.algo 314 } 315 } 316 return x509.UnknownSignatureAlgorithm 317} 318 319// GetOnlySigner returns an x509.Certificate for the first signer of the signed 320// data payload. If there are more or less than one signer, nil is returned 321func (p7 *PKCS7) GetOnlySigner() *x509.Certificate { 322 if len(p7.Signers) != 1 { 323 return nil 324 } 325 signer := p7.Signers[0] 326 return getCertFromCertsByIssuerAndSerial(p7.Certificates, signer.IssuerAndSerialNumber) 327} 328 329// ErrUnsupportedAlgorithm tells you when our quick dev assumptions have failed 330var ErrUnsupportedAlgorithm = errors.New("pkcs7: cannot decrypt data: only RSA, DES, DES-EDE3, AES-256-CBC and AES-128-GCM supported") 331 332// ErrNotEncryptedContent is returned when attempting to Decrypt data that is not encrypted data 333var ErrNotEncryptedContent = errors.New("pkcs7: content data is a decryptable data type") 334 335// Decrypt decrypts encrypted content info for recipient cert and private key 336func (p7 *PKCS7) Decrypt(cert *x509.Certificate, pk crypto.PrivateKey) ([]byte, error) { 337 data, ok := p7.raw.(envelopedData) 338 if !ok { 339 return nil, ErrNotEncryptedContent 340 } 341 recipient := selectRecipientForCertificate(data.RecipientInfos, cert) 342 if recipient.EncryptedKey == nil { 343 return nil, errors.New("pkcs7: no enveloped recipient for provided certificate") 344 } 345 if priv := pk.(*rsa.PrivateKey); priv != nil { 346 var contentKey []byte 347 contentKey, err := rsa.DecryptPKCS1v15(rand.Reader, priv, recipient.EncryptedKey) 348 if err != nil { 349 return nil, err 350 } 351 return data.EncryptedContentInfo.decrypt(contentKey) 352 } 353 fmt.Printf("Unsupported Private Key: %v\n", pk) 354 return nil, ErrUnsupportedAlgorithm 355} 356 357var oidEncryptionAlgorithmDESCBC = asn1.ObjectIdentifier{1, 3, 14, 3, 2, 7} 358var oidEncryptionAlgorithmDESEDE3CBC = asn1.ObjectIdentifier{1, 2, 840, 113549, 3, 7} 359var oidEncryptionAlgorithmAES256CBC = asn1.ObjectIdentifier{2, 16, 840, 1, 101, 3, 4, 1, 42} 360var oidEncryptionAlgorithmAES128GCM = asn1.ObjectIdentifier{2, 16, 840, 1, 101, 3, 4, 1, 6} 361var oidEncryptionAlgorithmAES128CBC = asn1.ObjectIdentifier{2, 16, 840, 1, 101, 3, 4, 1, 2} 362 363func (eci encryptedContentInfo) decrypt(key []byte) ([]byte, error) { 364 alg := eci.ContentEncryptionAlgorithm.Algorithm 365 if !alg.Equal(oidEncryptionAlgorithmDESCBC) && 366 !alg.Equal(oidEncryptionAlgorithmDESEDE3CBC) && 367 !alg.Equal(oidEncryptionAlgorithmAES256CBC) && 368 !alg.Equal(oidEncryptionAlgorithmAES128CBC) && 369 !alg.Equal(oidEncryptionAlgorithmAES128GCM) { 370 fmt.Printf("Unsupported Content Encryption Algorithm: %s\n", alg) 371 return nil, ErrUnsupportedAlgorithm 372 } 373 374 // EncryptedContent can either be constructed of multple OCTET STRINGs 375 // or _be_ a tagged OCTET STRING 376 var cyphertext []byte 377 if eci.EncryptedContent.IsCompound { 378 // Complex case to concat all of the children OCTET STRINGs 379 var buf bytes.Buffer 380 cypherbytes := eci.EncryptedContent.Bytes 381 for { 382 var part []byte 383 cypherbytes, _ = asn1.Unmarshal(cypherbytes, &part) 384 buf.Write(part) 385 if cypherbytes == nil { 386 break 387 } 388 } 389 cyphertext = buf.Bytes() 390 } else { 391 // Simple case, the bytes _are_ the cyphertext 392 cyphertext = eci.EncryptedContent.Bytes 393 } 394 395 var block cipher.Block 396 var err error 397 398 switch { 399 case alg.Equal(oidEncryptionAlgorithmDESCBC): 400 block, err = des.NewCipher(key) 401 case alg.Equal(oidEncryptionAlgorithmDESEDE3CBC): 402 block, err = des.NewTripleDESCipher(key) 403 case alg.Equal(oidEncryptionAlgorithmAES256CBC): 404 fallthrough 405 case alg.Equal(oidEncryptionAlgorithmAES128GCM), alg.Equal(oidEncryptionAlgorithmAES128CBC): 406 block, err = aes.NewCipher(key) 407 } 408 409 if err != nil { 410 return nil, err 411 } 412 413 if alg.Equal(oidEncryptionAlgorithmAES128GCM) { 414 params := aesGCMParameters{} 415 paramBytes := eci.ContentEncryptionAlgorithm.Parameters.Bytes 416 417 _, err := asn1.Unmarshal(paramBytes, ¶ms) 418 if err != nil { 419 return nil, err 420 } 421 422 gcm, err := cipher.NewGCM(block) 423 if err != nil { 424 return nil, err 425 } 426 427 if len(params.Nonce) != gcm.NonceSize() { 428 return nil, errors.New("pkcs7: encryption algorithm parameters are incorrect") 429 } 430 if params.ICVLen != gcm.Overhead() { 431 return nil, errors.New("pkcs7: encryption algorithm parameters are incorrect") 432 } 433 434 plaintext, err := gcm.Open(nil, params.Nonce, cyphertext, nil) 435 if err != nil { 436 return nil, err 437 } 438 439 return plaintext, nil 440 } 441 442 iv := eci.ContentEncryptionAlgorithm.Parameters.Bytes 443 if len(iv) != block.BlockSize() { 444 return nil, errors.New("pkcs7: encryption algorithm parameters are malformed") 445 } 446 mode := cipher.NewCBCDecrypter(block, iv) 447 plaintext := make([]byte, len(cyphertext)) 448 mode.CryptBlocks(plaintext, cyphertext) 449 if plaintext, err = unpad(plaintext, mode.BlockSize()); err != nil { 450 return nil, err 451 } 452 return plaintext, nil 453} 454 455func selectRecipientForCertificate(recipients []recipientInfo, cert *x509.Certificate) recipientInfo { 456 for _, recp := range recipients { 457 if isCertMatchForIssuerAndSerial(cert, recp.IssuerAndSerialNumber) { 458 return recp 459 } 460 } 461 return recipientInfo{} 462} 463 464func isCertMatchForIssuerAndSerial(cert *x509.Certificate, ias issuerAndSerial) bool { 465 return cert.SerialNumber.Cmp(ias.SerialNumber) == 0 && bytes.Compare(cert.RawIssuer, ias.IssuerName.FullBytes) == 0 466} 467 468func pad(data []byte, blocklen int) ([]byte, error) { 469 if blocklen < 1 { 470 return nil, fmt.Errorf("invalid blocklen %d", blocklen) 471 } 472 padlen := blocklen - (len(data) % blocklen) 473 if padlen == 0 { 474 padlen = blocklen 475 } 476 pad := bytes.Repeat([]byte{byte(padlen)}, padlen) 477 return append(data, pad...), nil 478} 479 480func unpad(data []byte, blocklen int) ([]byte, error) { 481 if blocklen < 1 { 482 return nil, fmt.Errorf("invalid blocklen %d", blocklen) 483 } 484 if len(data)%blocklen != 0 || len(data) == 0 { 485 return nil, fmt.Errorf("invalid data len %d", len(data)) 486 } 487 488 // the last byte is the length of padding 489 padlen := int(data[len(data)-1]) 490 491 // check padding integrity, all bytes should be the same 492 pad := data[len(data)-padlen:] 493 for _, padbyte := range pad { 494 if padbyte != byte(padlen) { 495 return nil, errors.New("invalid padding") 496 } 497 } 498 499 return data[:len(data)-padlen], nil 500} 501 502func unmarshalAttribute(attrs []attribute, attributeType asn1.ObjectIdentifier, out interface{}) error { 503 for _, attr := range attrs { 504 if attr.Type.Equal(attributeType) { 505 _, err := asn1.Unmarshal(attr.Value.Bytes, out) 506 return err 507 } 508 } 509 return errors.New("pkcs7: attribute type not in attributes") 510} 511 512// UnmarshalSignedAttribute decodes a single attribute from the signer info 513func (p7 *PKCS7) UnmarshalSignedAttribute(attributeType asn1.ObjectIdentifier, out interface{}) error { 514 sd, ok := p7.raw.(signedData) 515 if !ok { 516 return errors.New("pkcs7: payload is not signedData content") 517 } 518 if len(sd.SignerInfos) < 1 { 519 return errors.New("pkcs7: payload has no signers") 520 } 521 attributes := sd.SignerInfos[0].AuthenticatedAttributes 522 return unmarshalAttribute(attributes, attributeType, out) 523} 524 525// SignedData is an opaque data structure for creating signed data payloads 526type SignedData struct { 527 sd signedData 528 certs []*x509.Certificate 529 messageDigest []byte 530} 531 532// Attribute represents a key value pair attribute. Value must be marshalable byte 533// `encoding/asn1` 534type Attribute struct { 535 Type asn1.ObjectIdentifier 536 Value interface{} 537} 538 539// SignerInfoConfig are optional values to include when adding a signer 540type SignerInfoConfig struct { 541 ExtraSignedAttributes []Attribute 542} 543 544// NewSignedData initializes a SignedData with content 545func NewSignedData(data []byte) (*SignedData, error) { 546 content, err := asn1.Marshal(data) 547 if err != nil { 548 return nil, err 549 } 550 ci := contentInfo{ 551 ContentType: oidData, 552 Content: asn1.RawValue{Class: 2, Tag: 0, Bytes: content, IsCompound: true}, 553 } 554 digAlg := pkix.AlgorithmIdentifier{ 555 Algorithm: oidDigestAlgorithmSHA1, 556 } 557 h := crypto.SHA1.New() 558 h.Write(data) 559 md := h.Sum(nil) 560 sd := signedData{ 561 ContentInfo: ci, 562 Version: 1, 563 DigestAlgorithmIdentifiers: []pkix.AlgorithmIdentifier{digAlg}, 564 } 565 return &SignedData{sd: sd, messageDigest: md}, nil 566} 567 568type attributes struct { 569 types []asn1.ObjectIdentifier 570 values []interface{} 571} 572 573// Add adds the attribute, maintaining insertion order 574func (attrs *attributes) Add(attrType asn1.ObjectIdentifier, value interface{}) { 575 attrs.types = append(attrs.types, attrType) 576 attrs.values = append(attrs.values, value) 577} 578 579type sortableAttribute struct { 580 SortKey []byte 581 Attribute attribute 582} 583 584type attributeSet []sortableAttribute 585 586func (sa attributeSet) Len() int { 587 return len(sa) 588} 589 590func (sa attributeSet) Less(i, j int) bool { 591 return bytes.Compare(sa[i].SortKey, sa[j].SortKey) < 0 592} 593 594func (sa attributeSet) Swap(i, j int) { 595 sa[i], sa[j] = sa[j], sa[i] 596} 597 598func (sa attributeSet) Attributes() []attribute { 599 attrs := make([]attribute, len(sa)) 600 for i, attr := range sa { 601 attrs[i] = attr.Attribute 602 } 603 return attrs 604} 605 606func (attrs *attributes) ForMarshaling() ([]attribute, error) { 607 sortables := make(attributeSet, len(attrs.types)) 608 for i := range sortables { 609 attrType := attrs.types[i] 610 attrValue := attrs.values[i] 611 asn1Value, err := asn1.Marshal(attrValue) 612 if err != nil { 613 return nil, err 614 } 615 attr := attribute{ 616 Type: attrType, 617 Value: asn1.RawValue{Tag: 17, IsCompound: true, Bytes: asn1Value}, // 17 == SET tag 618 } 619 encoded, err := asn1.Marshal(attr) 620 if err != nil { 621 return nil, err 622 } 623 sortables[i] = sortableAttribute{ 624 SortKey: encoded, 625 Attribute: attr, 626 } 627 } 628 sort.Sort(sortables) 629 return sortables.Attributes(), nil 630} 631 632// AddSigner signs attributes about the content and adds certificate to payload 633func (sd *SignedData) AddSigner(cert *x509.Certificate, pkey crypto.PrivateKey, config SignerInfoConfig) error { 634 attrs := &attributes{} 635 attrs.Add(oidAttributeContentType, sd.sd.ContentInfo.ContentType) 636 attrs.Add(oidAttributeMessageDigest, sd.messageDigest) 637 attrs.Add(oidAttributeSigningTime, time.Now()) 638 for _, attr := range config.ExtraSignedAttributes { 639 attrs.Add(attr.Type, attr.Value) 640 } 641 finalAttrs, err := attrs.ForMarshaling() 642 if err != nil { 643 return err 644 } 645 signature, err := signAttributes(finalAttrs, pkey, crypto.SHA1) 646 if err != nil { 647 return err 648 } 649 650 ias, err := cert2issuerAndSerial(cert) 651 if err != nil { 652 return err 653 } 654 655 signer := signerInfo{ 656 AuthenticatedAttributes: finalAttrs, 657 DigestAlgorithm: pkix.AlgorithmIdentifier{Algorithm: oidDigestAlgorithmSHA1}, 658 DigestEncryptionAlgorithm: pkix.AlgorithmIdentifier{Algorithm: oidSignatureSHA1WithRSA}, 659 IssuerAndSerialNumber: ias, 660 EncryptedDigest: signature, 661 Version: 1, 662 } 663 // create signature of signed attributes 664 sd.certs = append(sd.certs, cert) 665 sd.sd.SignerInfos = append(sd.sd.SignerInfos, signer) 666 return nil 667} 668 669// AddCertificate adds the certificate to the payload. Useful for parent certificates 670func (sd *SignedData) AddCertificate(cert *x509.Certificate) { 671 sd.certs = append(sd.certs, cert) 672} 673 674// Detach removes content from the signed data struct to make it a detached signature. 675// This must be called right before Finish() 676func (sd *SignedData) Detach() { 677 sd.sd.ContentInfo = contentInfo{ContentType: oidData} 678} 679 680// Finish marshals the content and its signers 681func (sd *SignedData) Finish() ([]byte, error) { 682 sd.sd.Certificates = marshalCertificates(sd.certs) 683 inner, err := asn1.Marshal(sd.sd) 684 if err != nil { 685 return nil, err 686 } 687 outer := contentInfo{ 688 ContentType: oidSignedData, 689 Content: asn1.RawValue{Class: 2, Tag: 0, Bytes: inner, IsCompound: true}, 690 } 691 return asn1.Marshal(outer) 692} 693 694func cert2issuerAndSerial(cert *x509.Certificate) (issuerAndSerial, error) { 695 var ias issuerAndSerial 696 // The issuer RDNSequence has to match exactly the sequence in the certificate 697 // We cannot use cert.Issuer.ToRDNSequence() here since it mangles the sequence 698 ias.IssuerName = asn1.RawValue{FullBytes: cert.RawIssuer} 699 ias.SerialNumber = cert.SerialNumber 700 701 return ias, nil 702} 703 704// signs the DER encoded form of the attributes with the private key 705func signAttributes(attrs []attribute, pkey crypto.PrivateKey, hash crypto.Hash) ([]byte, error) { 706 attrBytes, err := marshalAttributes(attrs) 707 if err != nil { 708 return nil, err 709 } 710 h := hash.New() 711 h.Write(attrBytes) 712 hashed := h.Sum(nil) 713 switch priv := pkey.(type) { 714 case *rsa.PrivateKey: 715 return rsa.SignPKCS1v15(rand.Reader, priv, crypto.SHA1, hashed) 716 } 717 return nil, ErrUnsupportedAlgorithm 718} 719 720// concats and wraps the certificates in the RawValue structure 721func marshalCertificates(certs []*x509.Certificate) rawCertificates { 722 var buf bytes.Buffer 723 for _, cert := range certs { 724 buf.Write(cert.Raw) 725 } 726 rawCerts, _ := marshalCertificateBytes(buf.Bytes()) 727 return rawCerts 728} 729 730// Even though, the tag & length are stripped out during marshalling the 731// RawContent, we have to encode it into the RawContent. If its missing, 732// then `asn1.Marshal()` will strip out the certificate wrapper instead. 733func marshalCertificateBytes(certs []byte) (rawCertificates, error) { 734 var val = asn1.RawValue{Bytes: certs, Class: 2, Tag: 0, IsCompound: true} 735 b, err := asn1.Marshal(val) 736 if err != nil { 737 return rawCertificates{}, err 738 } 739 return rawCertificates{Raw: b}, nil 740} 741 742// DegenerateCertificate creates a signed data structure containing only the 743// provided certificate or certificate chain. 744func DegenerateCertificate(cert []byte) ([]byte, error) { 745 rawCert, err := marshalCertificateBytes(cert) 746 if err != nil { 747 return nil, err 748 } 749 emptyContent := contentInfo{ContentType: oidData} 750 sd := signedData{ 751 Version: 1, 752 ContentInfo: emptyContent, 753 Certificates: rawCert, 754 CRLs: []pkix.CertificateList{}, 755 } 756 content, err := asn1.Marshal(sd) 757 if err != nil { 758 return nil, err 759 } 760 signedContent := contentInfo{ 761 ContentType: oidSignedData, 762 Content: asn1.RawValue{Class: 2, Tag: 0, Bytes: content, IsCompound: true}, 763 } 764 return asn1.Marshal(signedContent) 765} 766 767const ( 768 EncryptionAlgorithmDESCBC = iota 769 EncryptionAlgorithmAES128GCM 770) 771 772// ContentEncryptionAlgorithm determines the algorithm used to encrypt the 773// plaintext message. Change the value of this variable to change which 774// algorithm is used in the Encrypt() function. 775var ContentEncryptionAlgorithm = EncryptionAlgorithmDESCBC 776 777// ErrUnsupportedEncryptionAlgorithm is returned when attempting to encrypt 778// content with an unsupported algorithm. 779var ErrUnsupportedEncryptionAlgorithm = errors.New("pkcs7: cannot encrypt content: only DES-CBC and AES-128-GCM supported") 780 781const nonceSize = 12 782 783type aesGCMParameters struct { 784 Nonce []byte `asn1:"tag:4"` 785 ICVLen int 786} 787 788func encryptAES128GCM(content []byte) ([]byte, *encryptedContentInfo, error) { 789 // Create AES key and nonce 790 key := make([]byte, 16) 791 nonce := make([]byte, nonceSize) 792 793 _, err := rand.Read(key) 794 if err != nil { 795 return nil, nil, err 796 } 797 798 _, err = rand.Read(nonce) 799 if err != nil { 800 return nil, nil, err 801 } 802 803 // Encrypt content 804 block, err := aes.NewCipher(key) 805 if err != nil { 806 return nil, nil, err 807 } 808 809 gcm, err := cipher.NewGCM(block) 810 if err != nil { 811 return nil, nil, err 812 } 813 814 ciphertext := gcm.Seal(nil, nonce, content, nil) 815 816 // Prepare ASN.1 Encrypted Content Info 817 paramSeq := aesGCMParameters{ 818 Nonce: nonce, 819 ICVLen: gcm.Overhead(), 820 } 821 822 paramBytes, err := asn1.Marshal(paramSeq) 823 if err != nil { 824 return nil, nil, err 825 } 826 827 eci := encryptedContentInfo{ 828 ContentType: oidData, 829 ContentEncryptionAlgorithm: pkix.AlgorithmIdentifier{ 830 Algorithm: oidEncryptionAlgorithmAES128GCM, 831 Parameters: asn1.RawValue{ 832 Tag: asn1.TagSequence, 833 Bytes: paramBytes, 834 }, 835 }, 836 EncryptedContent: marshalEncryptedContent(ciphertext), 837 } 838 839 return key, &eci, nil 840} 841 842func encryptDESCBC(content []byte) ([]byte, *encryptedContentInfo, error) { 843 // Create DES key & CBC IV 844 key := make([]byte, 8) 845 iv := make([]byte, des.BlockSize) 846 _, err := rand.Read(key) 847 if err != nil { 848 return nil, nil, err 849 } 850 _, err = rand.Read(iv) 851 if err != nil { 852 return nil, nil, err 853 } 854 855 // Encrypt padded content 856 block, err := des.NewCipher(key) 857 if err != nil { 858 return nil, nil, err 859 } 860 mode := cipher.NewCBCEncrypter(block, iv) 861 plaintext, err := pad(content, mode.BlockSize()) 862 cyphertext := make([]byte, len(plaintext)) 863 mode.CryptBlocks(cyphertext, plaintext) 864 865 // Prepare ASN.1 Encrypted Content Info 866 eci := encryptedContentInfo{ 867 ContentType: oidData, 868 ContentEncryptionAlgorithm: pkix.AlgorithmIdentifier{ 869 Algorithm: oidEncryptionAlgorithmDESCBC, 870 Parameters: asn1.RawValue{Tag: 4, Bytes: iv}, 871 }, 872 EncryptedContent: marshalEncryptedContent(cyphertext), 873 } 874 875 return key, &eci, nil 876} 877 878// Encrypt creates and returns an envelope data PKCS7 structure with encrypted 879// recipient keys for each recipient public key. 880// 881// The algorithm used to perform encryption is determined by the current value 882// of the global ContentEncryptionAlgorithm package variable. By default, the 883// value is EncryptionAlgorithmDESCBC. To use a different algorithm, change the 884// value before calling Encrypt(). For example: 885// 886// ContentEncryptionAlgorithm = EncryptionAlgorithmAES128GCM 887// 888// TODO(fullsailor): Add support for encrypting content with other algorithms 889func Encrypt(content []byte, recipients []*x509.Certificate) ([]byte, error) { 890 var eci *encryptedContentInfo 891 var key []byte 892 var err error 893 894 // Apply chosen symmetric encryption method 895 switch ContentEncryptionAlgorithm { 896 case EncryptionAlgorithmDESCBC: 897 key, eci, err = encryptDESCBC(content) 898 899 case EncryptionAlgorithmAES128GCM: 900 key, eci, err = encryptAES128GCM(content) 901 902 default: 903 return nil, ErrUnsupportedEncryptionAlgorithm 904 } 905 906 if err != nil { 907 return nil, err 908 } 909 910 // Prepare each recipient's encrypted cipher key 911 recipientInfos := make([]recipientInfo, len(recipients)) 912 for i, recipient := range recipients { 913 encrypted, err := encryptKey(key, recipient) 914 if err != nil { 915 return nil, err 916 } 917 ias, err := cert2issuerAndSerial(recipient) 918 if err != nil { 919 return nil, err 920 } 921 info := recipientInfo{ 922 Version: 0, 923 IssuerAndSerialNumber: ias, 924 KeyEncryptionAlgorithm: pkix.AlgorithmIdentifier{ 925 Algorithm: oidEncryptionAlgorithmRSA, 926 }, 927 EncryptedKey: encrypted, 928 } 929 recipientInfos[i] = info 930 } 931 932 // Prepare envelope content 933 envelope := envelopedData{ 934 EncryptedContentInfo: *eci, 935 Version: 0, 936 RecipientInfos: recipientInfos, 937 } 938 innerContent, err := asn1.Marshal(envelope) 939 if err != nil { 940 return nil, err 941 } 942 943 // Prepare outer payload structure 944 wrapper := contentInfo{ 945 ContentType: oidEnvelopedData, 946 Content: asn1.RawValue{Class: 2, Tag: 0, IsCompound: true, Bytes: innerContent}, 947 } 948 949 return asn1.Marshal(wrapper) 950} 951 952func marshalEncryptedContent(content []byte) asn1.RawValue { 953 asn1Content, _ := asn1.Marshal(content) 954 return asn1.RawValue{Tag: 0, Class: 2, Bytes: asn1Content, IsCompound: true} 955} 956 957func encryptKey(key []byte, recipient *x509.Certificate) ([]byte, error) { 958 if pub := recipient.PublicKey.(*rsa.PublicKey); pub != nil { 959 return rsa.EncryptPKCS1v15(rand.Reader, pub, key) 960 } 961 return nil, ErrUnsupportedAlgorithm 962} 963