CryptoSys PKI Pro Manual


Create a CMS enveloped-data object for one or more recipients.

VBA/VB6 Syntax

Public Declare Function CMS_MakeEnvData Lib "diCrPKI.dll" (ByVal strFileOut As String, ByVal strFileIn As String, ByVal strCertList As String, ByVal strKeyString As String, ByVal nCount As Long, ByVal nOptions As Long) As Long

nRet = CMS_MakeEnvData(strFileOut, strFileIn, strCertList, strKeyString, nCount, nOptions) As Long

C/C++ Syntax

long __stdcall CMS_MakeEnvData(const char *szFileOut, const char *szFileIn, const char *szCertList, const char *szKeyString, long nCount, long nOptions);


[in] name of output file to be created.
[in] name of file containing input data.
[in] list of one or more recipient X.509 certificate filenames, separated by semicolons (;). A certificate's representation in base64 or as a PEM string may be used instead of a filename. Alternatively, specify a single PKCS#7 certificate chain file (.p7c/.p7b).

Special cases: Set as "type=@pwri" to create a single recipientInfo of the PasswordRecipientInfo (pwri) type; or set as "type=@kekri,keyid=<string>" to create a single recipientInfo of the KEKRecipientInfo (kekri) type. See Remarks.

[in] (formerly szSeed) Use to pass optional additional user key material (ukm) for KDF where KeyAgreement (kari) type is used. Or use to pass the password for a pwri type or the key encryption key (KEK) for a kekri type. Either pass a plain ASCII string or use the format "#x<hex-digits>" to pass a string of arbitrary octet values. Required for pwri and kekri types.

Examples: "abc" will pass the 3 bytes (0x61, 0x62, 0x63); "#xdeadbeef01" will pass the 5 bytes (0xde, 0xad, 0xbe, 0xef, 0x01).

[in] (formerly nSeedLen) Optional iteration count for KDF in pwri type (default=4096) or tag length for AuthEnvelopedData (in range 12-16, default=16). Otherwise ignored.
[in] option flags: Set as zero (0) to use the defaults rsaEncryption for key transport or ECDH with ANSI-X9.63-KDF using SHA-1 with cms3DESwrap for key agreement; and des-EDE3-CBC for content encryption, and output in binary format.

To set the content encryption algorithm (default is Triple-DES des-EDE3-CBC), add one of the following:
PKI_BC_AES128 to use aes128-CBC for content encryption [minimum recommended]
PKI_BC_AES192 to use aes192-CBC for content encryption
PKI_BC_AES256 to use aes256-CBC for content encryption
PKI_AEAD_AES_128_GCM to use aes128-GCM for content encryption and authentication
PKI_AEAD_AES_192_GCM to use aes192-GCM for content encryption and authentication
PKI_AEAD_AES_256_GCM to use aes256-GCM for content encryption and authentication
PKI_AEAD_CHACHA20_POLY1305 to use AEAD_CHACHA20_POLY1305 for content encryption and authentication

To set the key transport scheme (where applicable), use one of
PKI_KT_RSAES_PKCS (0) to encrypt the key using the RSAES-PKCS1-v1_5 encryption scheme rsaEncryption (default)
PKI_KT_RSAES_OAEP to encrypt the key using the RSAES-OAEP encryption scheme (see RSA signature and encryption schemes).
  --CAUTION: the PKI_KT_RSAES_OAEP flag used here is not equal to the PKI_EME_OAEP flag used in RSA_Encrypt.

To select a hash function for RSAES-OAEP or ECDH KDF or pwri PBKDF2, add one of:
PKI_HASH_SHA1 to use SHA-1 (default).
PKI_HASH_SHA224 to use SHA-224
PKI_HASH_SHA256 to use SHA-256
PKI_HASH_SHA384 to use SHA-384
PKI_HASH_SHA512 to use SHA-512

If you have selected PKI_KT_RSAES_OAEP then, optionally, add
PKI_MGF_MGF1SHA1 to force the MGF hash function to be SHA-1 (default = same as encoding hash function set above)

To set the key derivation function (KDF) for the ECDH key agreement scheme (where applicable), add one of:
PKI_KDF_X963 to use the ANSI-X9.63-KDF key derivation function (default).
PKI_KDF_HKDF to use the HMAC-based Key Derivation Function (HKDF) from RFC 5869

and add one key wrap algorithm for the ECDH key agreement scheme or the kekri key encryption algorithm. Default (0) is to match the key agreement algorithm to the content encryption algorithm:
PKI_KWRAP_3DES to use cms3DESwrap [only valid if Triple DES used for the content encryption algorithm].
PKI_KWRAP_AES128 to use aes128-wrap
PKI_KWRAP_AES192 to use aes192-wrap
PKI_KWRAP_AES256 to use aes256-wrap

Optionally, add any of the bitflags:
PKI_CMS_FORMAT_BASE64 to encode the output with base64 encoding (default output is binary)
PKI_CMS_ALT_ALGID to use specialist alternative encryption algorithm identifier (see Remarks)
PKI_CMS_BIGFILE to speed up the processing of large files (binary file to binary file only)

Returns (VBA/C)

If successful, the return value is the number of successful recipients; otherwise it returns a negative error code.

VBA Wrapper Syntax

Public Function cmsMakeEnvData (szFileOut As String, szFileIn As String, szCertList As String, Optional szKeyString As String = "", Optional nOptions As Long = 0, Optional nCount As Long = 0) As Long

.NET Equivalent

Cms.MakeEnvData Method ( String, String, String, CipherAlgorithm, Cms.EnvDataOptions )
Cms.MakeEnvData Method ( String, String, String, CipherAlgorithm, Cms.KeyEncrAlgorithm, HashAlgorithm, Cms.EnvDataOptions, Kdf.KdfAlg, Kdf.KeyWrapAlg, String, Int32, Cms.ContentEncrAlg )

C++ (STL) Equivalent

static int dipki::Cms::MakeEnvData (const std::string &outputFile, const std::string &inputFile, const std::string &certList, CipherAlg cipherAlg=CipherAlg::Default, KeyEncrAlg keyEncrAlg=KeyEncrAlg::Default, HashAlg hashAlg=HashAlg::Default, EnvDataOptions advOpts=EnvDataOptions::Default_EnvDataOpt, Format format=Format::Default, bool bigFile=false, Kdf::KdfAlg kdfAlg=Kdf::KdfAlg::X963, Kdf::KeyWrapAlg keyWrapAlg=Kdf::KeyWrapAlg::Default, const std::string &keyString="", int count=0)
static int dipki::Cms::MakeEnvData (const std::string &outputFile, const std::string &inputFile, const std::string &schemeType, const std::string &keyString, CipherAlg cipherAlg=CipherAlg::Default, Kdf::KeyWrapAlg keyWrapAlg=Kdf::KeyWrapAlg::Default, EnvDataOptions advOpts=EnvDataOptions::Default_EnvDataOpt, Format format=Format::Default, HashAlg hashAlg=HashAlg::Default, int count=0)

Python Equivalent

static Cms.make_envdata(outputfile, inputfile, certlist, cipheralg=ContentEncrAlg.DEFAULT, keyencralg=KeyEncrAlg.DEFAULT, hashalg=0, opts=EnvDataOpts.DEFAULT, bigfile=False, kdfalg=Kdf.KdfAlg.X963, keywrapalg=0, keyString="", count=0)


The output is a file containing a CMS EnvelopedData or AuthEnvelopedData object which can be sent as part of an S/MIME message or used directly as a binary .p7m file. The supported objects are those described in CMS Content Types. RecipientInfo types can be KeyTransRecipientInfo (ktri), KeyAgreeRecipientInfo (kari), KEKRecipientInfo (kekri) and PasswordRecipientinfo (pwri). If the content encryption algorithm is an authenticated encryption algorithm (AES*-GCM), then the output will be an Authenticated-Enveloped-Data object (AuthEnvelopedData) as specified in [RFC5083] and [RFC5084].

TL;DR. The RecipientInfo type will be set according to the type of public key in the X.509 certificates. If the certificate has an RSA key, then a key-transport RecipientInfo (ktri) will be created (default PKCS#1v1.5 or RSA-OAEP if flag set). If the certificate contains a supported ECC public key, then a key-agreement type (kari) will be used (default ANSI-X9.63-KDF and keywrap to match the content encryption algorithm, HKDF if flag set). You can pass a list of mixed certificates and the appropriate RecipientInfo type will be chosen for each. There are special cases for KEK and password recipientInfo types - see below.

ktri and kari types

By default, the RecipientInfo type is set automatically depending on the public key found in each certificate in szCertList, one for each certificate. If the public key is RSA (rsaEncryption) then the key transport technique (ktri) will be used to create that particular recipientInfo. If the public key is a supported ECC key, then the standard ECDH ephemeral-static key agreement technique (kari) will be used as per [RFC5753] and [RFC8418].

No checks are made on the validity period of the recipients' X.509 certificates or their key usage attributes. A PKCS#7 certificate chain file may be specified as an argument for szCertList. In which case, all certificates in the chain file will be used as recipients.

It is an error if any specified certificate file in szCertList is missing or corrupted. Call PKI_LastError() to find more details of the errors that occurred.

kekri and pwri types

[New in v20.6] RecipientInfo types KEKRecipientInfo (kekri) and PasswordRecipientinfo (pwri) are supported for a single recipient only. For these types no certificates are required and the szCertList argument must include "type=@kekri" or "type=@pwri", respectively, all characters lower case. In addition, for a kekri type, this argument should be of the form "type=@kekri,keyid=<string>" (Note separated by a comma ',') where the value for the keyid attribute is used to set the keyIdentifier field in the KEKIdentifier. This can be a simple ASCII string or can use the format "#x<hex-digits>" to pass a string of arbitrary octet values. If omitted, the default keyIdentifier is "keyid". Optionally add a date field in the KEKIdentifier by adding a date=<iso-date-string>, e.g. "type=@kekri,keyid=ourkeyid,date=2022-07-31T12:01".

The szKeyString argument must include either the key encryption key (KEK) for kekri or the password for pwri. This parameter is expected to be an ASCII string. A binary KEK may be passed by using the format "#x<hex-digits>" to pass a string of arbitrary octet values.


nRet = CMS_MakeEnvData("xscipher_kekri.p7m", "plain.txt", "type=@kekri,keyid=oursharedkey", "#x0123456789ABCDEFF0E1D2C3B4A59687", 0, PKI_BC_AES192 Or PKI_KWRAP_AES128);

Creates an EnvelopedData file with a single recipientInfo of type KEKRecipientInfo (kekri) with a keyid of "oursharedkey" using the 128-bit KEK (0x)0123456789ABCDEFF0E1D2C3B4A59687 wrapped with aes128-wrap. The content is encrypted with AES-192 using a random content encryption key.

nRet = CMS_MakeEnvData("xscipher_pwri.p7m", "plain.txt", "type=@pwri", "This is my password", 6666, PKI_BC_AES256);
Creates an EnvelopedData file with a single recipientInfo of type PasswordRecipientinfo (pwri) using the password "This is my password". The iteration count for the KDF is 6666 (default=4096). The content is encrypted with AES-256 using a random content encryption key.

Other options

Use the PKI_CMS_BIGFILE option flag to handle large files more efficiently. This results in improvements of speed typically of 30% and enables, in theory, unlimited sizes of enveloped files (subject, of course, to your level of boredom in waiting for the output). Binary output only. Not available for authenticated encryption or kekri or pwri recipientInfo types.

Specialist Option: If the PKI_CMS_ALT_ALGID option flag is present, an alternative Content Encryption Algorithm Identifier will be used as follows:

Default Content Encryption Algorithm Identifier with PKI_CMS_ALT_ALGID
des-ede3-cbc (1.2.840.113549.3.7)des_3CBC_pad (

This alternative TeleTrusT algorithm identifier was added for compatibility with certain (superseded?) German Health profiles.


The following example reproduces example 5.1 from [SMIME-EX]. It creates an EnvelopedData CMS object for Bob from the data file excontent.txt using Bob's X.509 certificate BobRSASignByCarl.cer.

Dim nRet As Long
Dim strOutputFile As String
Dim strInputFile As String
Dim strCertFile As String

strOutputFile = "cmsalice2bob.p7m"
strInputFile = "excontent.txt"
strCertFile = "BobRSASignByCarl.cer"
' This should return 1 (indicating one successful recipient)
nRet = CMS_MakeEnvData(strOutputFile, strInputFile, strCertFile, "", 0, 0)
Debug.Print "CMS_MakeEnvData returns " & nRet

Note that the output file will always be different from the smime-example because the content-encryption key, IV and the encrypted-content will be different each time.

The next example does the same except for two recipients: Bob and Carl.

' This should return 2 (indicating two successful recipients)
nRet = CMS_MakeEnvData("cms2bobandcarl.p7m", "excontent.txt", _
    "BobRSASignByCarl.cer;CarlRSASelf.cer", "", 0, 0)
Debug.Print "CMS_MakeEnvData returns " & nRet

The third example is the same as the first, except it uses AES-128 instead of Triple-DES to encrypt the content.

nRet = CMS_MakeEnvData("cms2bob_aes128.p7m", "excontent.txt", _
    "BobRSASignByCarl.cer", "", 0, PKI_BC_AES128)
Debug.Print "CMS_MakeEnvData returns " & nRet

This example shows how to use the PKI_CMS_BIGFILE option.

Dim nRet As Long
Dim strEnvDataFile As String
Dim strInputFile As String
Dim strCheckFile As String
strEnvDataFile = "envbig.p7m"
strInputFile = "bigfile.txt"
Debug.Print "File " & strInputFile & "=" & FileLen(strInputFile) & " bytes"
' Make enveloped-data file: this should return 1 (indicating one successful recipient)
nRet = CMS_MakeEnvData(strEnvDataFile, strInputFile, "bob.cer;", "", 0, PKI_CMS_BIGFILE)
Debug.Print "CMS_MakeEnvData returns " & nRet & " (expected 1 => # recipients)"
' Now decrypt using Bob's private key
Dim strPrivateKey As String
strPrivateKey = rsaReadPrivateKey("bob.p8e", "password")
strCheckFile = strEnvDataFile & ".out.txt"
nRet = CMS_ReadEnvData(strCheckFile, strEnvDataFile, "", strPrivateKey, PKI_CMS_BIGFILE)
Debug.Print "CMS_ReadEnvData returns " & nRet & " (expected 0 => success)"
' Check file length
Debug.Print "File " & strCheckFile & "=" & FileLen(strCheckFile) & " bytes"
File bigfile.txt=10485700 bytes
CMS_MakeEnvData returns 1 (expected 1 => # recipients)
CMS_ReadEnvData returns 0 (expected 0 => success)
File envbig.p7m.out.txt=10485700 bytes

Example (VBA wrapper function)

Dim n As Long
' Create an enveloped CMS object (ktri type) to Bob using Bob's RSA key...
n = cmsMakeEnvData("cms2bob_aes128.p7m", "excontent.txt", "BobRSASignByCarl.cer", "", PKI_BC_AES128 Or PKI_KT_RSAES_OAEP)
' Same but using authenticated encryption and creating an authEnvelopedData object...
n = cmsMakeEnvData("cms2bob_aes128auth.p7m", "excontent.txt", "BobRSASignByCarl.cer", "", PKI_AEAD_AES_128_GCM Or PKI_KT_RSAES_OAEP)
' Create an enveloped CMS object (kari type) to Dana using Dana's ECC key...
n = cmsMakeEnvData("cms2dana_hkdf.p7m", "excontent.txt", "lamps-dana.encrypt.crt", "", PKI_BC_AES256 Or PKI_HASH_SHA256 Or PKI_KDF_HKDF Or PKI_KWRAP_AES256)
' Create an enveloped CMS object (ktri + kari type) to Bob and Dana using respective RSA and ECC keys...
n = cmsMakeEnvData("cms2bob_dana.p7m", "excontent.txt", "BobRSASignByCarl.cer;lamps-dana.encrypt.crt", "", PKI_BC_AES256 Or PKI_KT_RSAES_OAEP Or PKI_HASH_SHA256 Or PKI_KDF_HKDF)
' Create an enveloped CMS object (kekri type) using a previously distributed symmetric key-encryption key (KEK)...
n = cmsMakeEnvData("cms_envdata_kekri.p7m", "excontent.txt", "type=@kekri,keyid=ourcommonkey", "#x0123456789ABCDEFF0E1D2C3B4A59687", PKI_BC_AES256 Or PKI_HASH_SHA256 Or PKI_KWRAP_AES128)
' Create an enveloped CMS object (pwri type) using password-based key management...
n = cmsMakeEnvData("cms_envdata_pwri.p7m", "excontent.txt", "type=@pwri", "password12345", PKI_BC_AES192)

See Also

CMS_MakeEnvDataFromString CMS_MakeEnvDataFromBytes

[Contents] [Index]

[PREV: CMS_MakeDetachedSig...]   [Contents]   [Index]   
   [NEXT: CMS_MakeEnvDataFromBytes...]

Copyright © 2004-23 D.I. Management Services Pty Ltd. All rights reserved. Generated 2023-10-22T11:11:11Z.