github.com/emmansun/gmsm@v0.29.1/pkcs7/encrypt.go (about)

     1  package pkcs7
     2  
     3  import (
     4  	"crypto/rand"
     5  	"encoding/asn1"
     6  	"errors"
     7  
     8  	"github.com/emmansun/gmsm/pkcs"
     9  )
    10  
    11  type encryptedData struct {
    12  	Version              int
    13  	EncryptedContentInfo encryptedContentInfo
    14  }
    15  
    16  // ErrPSKNotProvided is returned when attempting to encrypt
    17  // using a PSK without actually providing the PSK.
    18  var ErrPSKNotProvided = errors.New("pkcs7: cannot encrypt content: PSK not provided")
    19  
    20  // EncryptUsingPSK creates and returns an encrypted data PKCS7 structure,
    21  // encrypted using caller provided pre-shared secret.
    22  func EncryptUsingPSK(cipher pkcs.Cipher, content []byte, key []byte) ([]byte, error) {
    23  	return encryptUsingPSK(cipher, content, key, []asn1.ObjectIdentifier{OIDData, OIDEncryptedData}, 0)
    24  }
    25  
    26  // EncryptSMUsingPSK creates and returns an encrypted data PKCS7 structure,
    27  // encrypted using caller provided pre-shared secret.
    28  // This method uses China Standard OID
    29  func EncryptSMUsingPSK(cipher pkcs.Cipher, content []byte, key []byte) ([]byte, error) {
    30  	return encryptUsingPSK(cipher, content, key, []asn1.ObjectIdentifier{SM2OIDData, SM2OIDEncryptedData}, 1)
    31  }
    32  
    33  func encryptUsingPSK(cipher pkcs.Cipher, content []byte, key []byte, contentTypes []asn1.ObjectIdentifier, version int) ([]byte, error) {
    34  	var err error
    35  
    36  	if key == nil {
    37  		return nil, ErrPSKNotProvided
    38  	}
    39  
    40  	id, ciphertext, err := cipher.Encrypt(rand.Reader, key, content)
    41  	if err != nil {
    42  		return nil, err
    43  	}
    44  
    45  	// Prepare encrypted-data content
    46  	ed := encryptedData{
    47  		Version:              version,
    48  		EncryptedContentInfo: newEncryptedContent(contentTypes[0], id, marshalEncryptedContent(ciphertext)),
    49  	}
    50  
    51  	innerContent, err := asn1.Marshal(ed)
    52  	if err != nil {
    53  		return nil, err
    54  	}
    55  
    56  	// Prepare outer payload structure
    57  	wrapper := contentInfo{
    58  		ContentType: contentTypes[1],
    59  		Content:     asn1.RawValue{Class: asn1.ClassContextSpecific, Tag: 0, IsCompound: true, Bytes: innerContent},
    60  	}
    61  
    62  	return asn1.Marshal(wrapper)
    63  }