package pkcs7 import ( "crypto/rand" "encoding/asn1" "errors" "github.com/emmansun/gmsm/pkcs" ) type encryptedData struct { Version int EncryptedContentInfo encryptedContentInfo } // ErrPSKNotProvided is returned when attempting to encrypt // using a PSK without actually providing the PSK. var ErrPSKNotProvided = errors.New("pkcs7: cannot encrypt content: PSK not provided") // EncryptUsingPSK creates and returns an encrypted data PKCS7 structure, // encrypted using caller provided pre-shared secret. func EncryptUsingPSK(cipher pkcs.Cipher, content []byte, key []byte) ([]byte, error) { return encryptUsingPSK(cipher, content, key, []asn1.ObjectIdentifier{OIDData, OIDEncryptedData}, 0) } // EncryptSMUsingPSK creates and returns an encrypted data PKCS7 structure, // encrypted using caller provided pre-shared secret. // This method uses China Standard OID func EncryptSMUsingPSK(cipher pkcs.Cipher, content []byte, key []byte) ([]byte, error) { return encryptUsingPSK(cipher, content, key, []asn1.ObjectIdentifier{SM2OIDData, SM2OIDEncryptedData}, 1) } func encryptUsingPSK(cipher pkcs.Cipher, content []byte, key []byte, contentTypes []asn1.ObjectIdentifier, version int) ([]byte, error) { var err error if key == nil { return nil, ErrPSKNotProvided } id, ciphertext, err := cipher.Encrypt(rand.Reader, key, content) if err != nil { return nil, err } // Prepare encrypted-data content ed := encryptedData{ Version: version, EncryptedContentInfo: newEncryptedContent(contentTypes[0], id, marshalEncryptedContent(ciphertext)), } innerContent, err := asn1.Marshal(ed) if err != nil { return nil, err } // Prepare outer payload structure wrapper := contentInfo{ ContentType: contentTypes[1], Content: asn1.RawValue{Class: asn1.ClassContextSpecific, Tag: 0, IsCompound: true, Bytes: innerContent}, } return asn1.Marshal(wrapper) }