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  }