github.com/emmansun/gmsm@v0.29.1/pkcs7/decrypt.go (about) 1 package pkcs7 2 3 import ( 4 "bytes" 5 "crypto" 6 "crypto/rand" 7 "encoding/asn1" 8 "errors" 9 "math/big" 10 11 "github.com/emmansun/gmsm/pkcs" 12 "github.com/emmansun/gmsm/sm2" 13 "github.com/emmansun/gmsm/smx509" 14 ) 15 16 // IssuerAndSerial is a structure that holds the issuer name and serial number 17 type IssuerAndSerial struct { 18 RawIssuer []byte 19 SerialNumber *big.Int 20 } 21 22 func newIssuerAndSerial(issuerAndSerial issuerAndSerial) IssuerAndSerial { 23 is := IssuerAndSerial{} 24 if len(issuerAndSerial.IssuerName.FullBytes) > 0 { 25 is.RawIssuer = make([]byte, len(issuerAndSerial.IssuerName.FullBytes)) 26 copy(is.RawIssuer, issuerAndSerial.IssuerName.FullBytes) 27 } 28 if issuerAndSerial.SerialNumber != nil { 29 is.SerialNumber = new(big.Int).Set(issuerAndSerial.SerialNumber) 30 } 31 return is 32 } 33 34 // ErrUnsupportedAlgorithm tells you when our quick dev assumptions have failed 35 var ErrUnsupportedAlgorithm = errors.New("pkcs7: cannot decrypt data: only RSA, SM2, DES, DES-EDE3, AES and SM4 supported") 36 37 // ErrNotEncryptedContent is returned when attempting to Decrypt data that is not encrypted data 38 var ErrNotEncryptedContent = errors.New("pkcs7: content data is NOT a decryptable data type") 39 40 // ErrNotEnvelopedData is returned when attempting to Decrypt data that is not enveloped data 41 var ErrNotEnvelopedData = errors.New("pkcs7: content data is NOT an enveloped data type") 42 43 type decryptable interface { 44 GetRecipient(cert *smx509.Certificate) *recipientInfo 45 GetRecipients() ([]IssuerAndSerial, error) 46 GetEncryptedContentInfo() *encryptedContentInfo 47 } 48 49 // GetRecipients returns the list of recipients for the enveloped data 50 func (p7 *PKCS7) GetRecipients() ([]IssuerAndSerial, error) { 51 decryptableData, ok := p7.raw.(decryptable) 52 if !ok { 53 return nil, ErrNotEnvelopedData 54 } 55 return decryptableData.GetRecipients() 56 } 57 58 // Decrypt decrypts encrypted content info for recipient cert and private key 59 func (p7 *PKCS7) Decrypt(cert *smx509.Certificate, pkey crypto.PrivateKey) ([]byte, error) { 60 return p7.decrypt(cert, pkey, false) 61 } 62 63 // DecryptCFCA decrypts encrypted content info for recipient cert and private key whose SM2 encrypted key is C1C2C3 format 64 // and without 0x4 prefix. 65 func (p7 *PKCS7) DecryptCFCA(cert *smx509.Certificate, pkey crypto.PrivateKey) ([]byte, error) { 66 return p7.decrypt(cert, pkey, true) 67 } 68 69 func (p7 *PKCS7) decrypt(cert *smx509.Certificate, pkey crypto.PrivateKey, isCFCA bool) ([]byte, error) { 70 decryptableData, ok := p7.raw.(decryptable) 71 if !ok { 72 return nil, ErrNotEncryptedContent 73 } 74 recipient := decryptableData.GetRecipient(cert) 75 if recipient == nil { 76 return nil, errors.New("pkcs7: no enveloped recipient for provided certificate") 77 } 78 79 switch pkey := pkey.(type) { 80 case crypto.Decrypter: 81 // Generic case to handle anything that provides the crypto.Decrypter interface. 82 encryptedKey := recipient.EncryptedKey 83 var decrypterOpts crypto.DecrypterOpts 84 if _, ok := pkey.(*sm2.PrivateKey); ok && isCFCA { 85 encryptedKey = make([]byte, len(recipient.EncryptedKey)+1) 86 encryptedKey[0] = 0x04 87 copy(encryptedKey[1:], recipient.EncryptedKey) 88 decrypterOpts = sm2.NewPlainDecrypterOpts(sm2.C1C2C3) 89 } 90 91 contentKey, err := pkey.Decrypt(rand.Reader, encryptedKey, decrypterOpts) 92 if err != nil { 93 return nil, err 94 } 95 return decryptableData.GetEncryptedContentInfo().decrypt(contentKey) 96 } 97 return nil, ErrUnsupportedAlgorithm 98 } 99 100 // DecryptUsingPSK decrypts encrypted data using caller provided 101 // pre-shared secret 102 func (p7 *PKCS7) DecryptUsingPSK(key []byte) ([]byte, error) { 103 data, ok := p7.raw.(encryptedData) 104 if !ok { 105 return nil, ErrNotEncryptedContent 106 } 107 return data.EncryptedContentInfo.decrypt(key) 108 } 109 110 func (eci encryptedContentInfo) getCiphertext() (ciphertext []byte) { 111 // EncryptedContent can either be constructed of multple OCTET STRINGs 112 // or _be_ a tagged OCTET STRING 113 if eci.EncryptedContent.IsCompound { 114 // Complex case to concat all of the children OCTET STRINGs 115 var buf bytes.Buffer 116 cypherbytes := eci.EncryptedContent.Bytes 117 for { 118 var part []byte 119 cypherbytes, _ = asn1.Unmarshal(cypherbytes, &part) 120 buf.Write(part) 121 if cypherbytes == nil { 122 break 123 } 124 } 125 ciphertext = buf.Bytes() 126 } else { 127 // Simple case, the bytes _are_ the cyphertext 128 ciphertext = eci.EncryptedContent.Bytes 129 } 130 return 131 } 132 133 func (eci encryptedContentInfo) decrypt(key []byte) ([]byte, error) { 134 cipher, err := pkcs.GetCipher(eci.ContentEncryptionAlgorithm) 135 if err != nil { 136 return nil, ErrUnsupportedAlgorithm 137 } 138 return cipher.Decrypt(key, &eci.ContentEncryptionAlgorithm.Parameters, eci.getCiphertext()) 139 }