CryptEncodeObjectEx 函数 (wincrypt.h)

CryptEncodeObjectEx 函数对由 lpszStructType 参数的值指示的类型的结构进行编码。 此函数通过支持使用 CRYPT_ENCODE_ALLOC_FLAG 值的内存分配,显著提高了 CryptEncodeObject 的性能。

语法

BOOL CryptEncodeObjectEx(
  [in]      DWORD              dwCertEncodingType,
  [in]      LPCSTR             lpszStructType,
  [in]      const void         *pvStructInfo,
  [in]      DWORD              dwFlags,
  [in]      PCRYPT_ENCODE_PARA pEncodePara,
  [out]     void               *pvEncoded,
  [in, out] DWORD              *pcbEncoded
);

参数

[in] dwCertEncodingType

用于对对象进行编码的证书编码类型和消息编码类型。 此参数可以是以下一个或多个值的组合。

含义
PKCS_7_ASN_ENCODING
65536 (0x10000)
指定 PKCS 7 消息编码。
X509_ASN_ENCODING
1 (0x1)
指定 X.509 证书编码。

[in] lpszStructType

指向定义结构类型的 OID) (对象标识符 的指针。 如果 lpszStructType 参数的高位字为零,则低序字将指定指定结构的类型的整数标识符。 否则,此参数是指向以 null 结尾的字符串的指针,该字符串包含 OID 的字符串表示形式。

有关对象标识符字符串、其预定义常量和相应结构的详细信息,请参阅 CryptEncodeObject 和 CryptDecodeObject 的常量

[in] pvStructInfo

指向要编码的 结构的指针。 结构必须属于 lpszStructType 指定的类型。

[in] dwFlags

指定编码选项。 此参数可以是零,也可以是以下一个或多个值的组合。

含义
CRYPT_ENCODE_ALLOC_FLAG
32768 (0x8000)
调用的编码函数为编码的字节分配内存。 在 pvEncoded 中返回指向已分配字节的指针。
CRYPT_ENCODE_ENABLE_PUNYCODE_FLAG
131072 (0x20000)
此标志适用于启用 Unicode 字符串值的 Punycode 编码。 有关详细信息,请参阅“备注”。

Windows Server 2008、Windows Vista、Windows Server 2003 和 Windows XP: 不支持此标志。

CRYPT_UNICODE_NAME_ENCODE_DISABLE_CHECK_TYPE_FLAG
1073741824 (0x40000000)
当编码X509_UNICODE_NAME、X509_UNICODE_NAME_VALUE或X509_UNICODE_ANY_STRING时,此标志适用。 如果设置了此标志,则不会检查字符以确定它们是否对指定的值类型有效。
CRYPT_UNICODE_NAME_ENCODE_ENABLE_T61_UNICODE_FLAG
2147483648 (0x80000000)
编码X509_UNICODE_NAME时,此标志适用。 如果设置了此标志,并且所有 Unicode 字符均为 <= 0xFF,则选择CERT_RDN_T61_STRING而不是CERT_RDN_UNICODE_STRING。
CRYPT_UNICODE_NAME_ENCODE_ENABLE_UTF8_UNICODE_FLAG
536870912 (0x20000000)
此标志适用于编码X509_UNICODE_NAME。 设置后,选择CERT_RDN_UTF8_STRING而不是CERT_RDN_UNICODE_STRING。
CRYPT_UNICODE_NAME_ENCODE_FORCE_UTF8_UNICODE_FLAG
268435456 (0x10000000)
此标志适用于编码X509_UNICODE_NAME。 设置后,选择CERT_RDN_UTF8_STRING,而不是为目录字符串类型CERT_RDN_PRINTABLE_STRING。 此外,此标志还支持CRYPT_UNICODE_NAME_ENCODE_ENABLE_UTF8_UNICODE_FLAG。

[in] pEncodePara

指向包含编码信息的 CRYPT_ENCODE_PARA 结构的指针。 此参数可以为 NULL。

如果 pEncodeParapEncodeParapfnAlloc 成员为 NULL,则 LocalAlloc 用于分配,并且必须调用 LocalFree 来释放内存。

如果 pEncodeParapEncodePara 的 pfnAlloc 成员都不为 NULL,则为分配调用 pEncodePara 所指向的 CRYPT_ENCODE_PARA 结构的 pfnAlloc 成员所指向的函数。 必须调用 pEncodeParapfnFree 成员指向的函数以释放内存。

[out] pvEncoded

指向用于接收编码结构的缓冲区的指针。 此缓冲区的大小在 “代码”参数 中指定。 如果指定的缓冲区不够大,无法接收解码的结构,该函数将设置 ERROR_MORE_DATA 代码,并将所需的缓冲区大小(以字节为单位)存储在 由ERROR_MORE_DATA coded 指向的变量中。

此参数可以为 NULL ,用于检索缓冲区的大小,以便进行内存分配。 有关详细信息,请参阅 检索未知长度的数据

如果 dwFlags 包含 CRYPT_ENCODE_ALLOC_FLAG 标志, 则 pvEncoded 不是指向缓冲区的指针,而是指向缓冲区的指针的地址。 由于内存是在函数内分配的,并且指针存储在 pvEncoded 中, 因此 pvEncoded 不能为 NULL

[in, out] pcbEncoded

指向 DWORD 变量的指针,该变量包含 pvEncoded 参数指向的缓冲区的大小(以字节为单位)。 函数返回时, 由码 参数指向的变量包含存储在缓冲区中的已分配编码字节数。

dwFlags 包含 CRYPT_ENCODE_ALLOC_FLAG 标志时, CRYPT_ENCODE_ALLOC_FLAG 是指向已更新的 DWORD 值的指针的地址。

注意 处理缓冲区中返回的数据时,应用程序必须使用返回的数据的实际大小。 实际大小可以略小于输入时指定的缓冲区的大小。 (输入时,缓冲区大小通常指定得足够大,以确保最大输出数据适合 buffer。) 输出时,此参数指向的变量将更新,以反映复制到缓冲区的数据的实际大小。
 

返回值

如果成功,则返回非零值,否则返回零。

有关扩展的错误信息,请调用 GetLastError。 下表显示了当 CryptEncodeObjectEx 失败时,可以从 GetLastError 返回的一些可能的错误代码。

返回代码 说明
CRYPT_E_BAD_ENCODE
编码时遇到错误。
ERROR_FILE_NOT_FOUND
找不到指定的 dwCertEncodingTypelpszStructType 的编码函数。
ERROR_MORE_DATA
如果 pvEncoded 参数指定的缓冲区不够大,无法容纳返回的数据,该函数将设置 ERROR_MORE_DATA 代码,并将所需的缓冲区大小(以字节为单位)存储在 由ERROR_MORE_DATA coded 指向的变量中。
 

如果函数失败, GetLastError 可能会返回 抽象语法表示法 One (ASN.1) 编码/解码错误。 有关这些错误的信息,请参阅 ASN.1 编码/解码返回值

注解

使用首选 CryptEncodeObjectEx 函数对加密对象进行编码时,将包含终止 NULL 字符。 使用首选 CryptDecodeObjectEx 函数进行解码时,不会保留终止 NULL 字符。

CryptEncodeObjectEx 首先查找可安装的扩展编码函数。 如果未找到扩展编码函数,则找到旧的 nonextended、可安装函数。

当无法对对象进行直接 IA5String 编码时,可以通过将 dwFlag 参数设置为 CRYPT_ENCODE_ENABLE_PUNYCODE_FLAG 值来指定 Punycode 编码。 根据 lpszStructType 参数的值所指定的编码结构类型,设置CRYPT_ENCODE_ENABLE_PUNYCODE_FLAG标志会产生不同的效果。

以下列表中的每个常量都有 pvStructInfo 参数指向的关联结构类型。 直接或间接指向的结构具有对 CERT_ALT_NAME_ENTRY 结构的引用。

  • X509_ALTERNATE_NAME
  • szOID_AUTHORITY_INFO_ACCESS
  • X509_AUTHORITY_INFO_ACCESS
  • X509_AUTHORITY_KEY_ID2
  • szOID_AUTHORITY_KEY_IDENTIFIER2
  • szOID_CRL_DIST_POINTS
  • X509_CRL_DIST_POINTS
  • szOID_CROSS_CERT_DIST_POINTS
  • X509_CROSS_CERT_DIST_POINTS
  • szOID_ISSUER_ALT_NAME
  • szOID_ISSUER_ALT_NAME2
  • szOID_ISSUING_DIST_POINT
  • X509_ISSUING_DIST_POINT
  • szOID_NAME_CONSTRAINTS
  • X509_NAME_CONSTRAINTS
  • szOID_NEXT_UPDATE_LOCATION
  • OCSP_REQUEST
  • zOID_SUBJECT_ALT_NAME
  • szOID_SUBJECT_ALT_NAME2
CRYPT_ENCODE_ENABLE_PUNYCODE_FLAG 标志与 CERT_ALT_NAME_ENTRY 结构的 dwAltNameChoice 成员的值一起确定字符串的编码方式。
dwAltNameChoice 效果
CERT_ALT_NAME_DNS_NAME 如果主机名包含 ASCII 字符集外部的 Unicode 字符,则主机名首先在 Punycode 中编码,然后编码为 IA5String 字符串。
CERT_ALT_NAME_RFC822_NAME 如果电子邮件地址的主机名部分包含 ASCII 字符集外部的 Unicode 字符,则电子邮件地址的主机名部分采用 Punycode 编码。 然后,生成的电子邮件地址将编码为 IA5String 字符串。
CERT_ALT_NAME_URL 如果 URI 的服务器主机名包含 ASCII 字符集外部的 Unicode 字符,则 URI 的主机名部分采用 Punycode 编码。 然后,对生成的 URI 进行转义,然后将 URL 编码为 IA5String 字符串。
 

以下列表中的每个常量都有一个由 pvStructInfo 参数指向的关联结构类型。 直接或间接指向的结构具有对 CERT_HASHED_URL 结构的引用。

  • szOID_BIOMETRIC_EXT
  • X509_BIOMETRIC_EXT
  • szOID_LOGOTYPE_EXT
  • X509_LOGOTYPE_EXT
编码 CERT_HASHED_URL 结构值时,如果 URI 的服务器主机名包含 ASCII 字符集外部的 Unicode 字符,并且设置了 CRYPT_ENCODE_ENABLE_PUNYCODE_FLAG ,则 URI 的主机名部分将采用 Punycode 编码。 然后,对生成的 URI 进行转义,然后将 URL 编码为 IA5String 字符串。

以下列表中的每个 X509_UNICODE_NAME 常量都有一个由 pvStructInfo 参数指向的关联结构类型。

  • X509_UNICODE_NAME
如果 CERT_RDN_ATTR 结构的 pszObjId 成员设置为 szOID_RSA_emailAddr 并且 Value 成员中的电子邮件地址包含 ASCII 字符集外部的 Unicode 字符,则电子邮件地址的主机名部分采用 Punycode 编码。 然后,生成的电子邮件地址将编码为 IA5String 字符串。

在所有情况下,主机名的 Punycode 编码都是逐个标签执行的。

示例

以下示例演示如何使用 CryptEncodeObjectEx 初始化和编码 X509_NAME 结构。 有关包含此示例的完整上下文的示例,请参阅 示例 C 程序:ASN.1 编码和解码

#include <windows.h>
#include <stdio.h>
#include <Wincrypt.h>
#pragma comment(lib, "crypt32.lib")


#define MY_TYPE (X509_ASN_ENCODING)

void main()
{

//#define moved

//--------------------------------------------------------------------
//   Declare and initialize local variables.

char *Cert_Sub_Name ="Test User Name";

//--------------------------------------------------------------------
// Initialize a single RDN structure.

CERT_RDN_ATTR rgNameAttr = 
{
   "2.5.4.3",                      // The OID
   CERT_RDN_PRINTABLE_STRING,      // Type of string
   (DWORD)strlen(Cert_Sub_Name)+1, // String length including
                                   //  the terminating null character
   (BYTE *)Cert_Sub_Name           // Pointer to the string 
};
//--------------------------------------------------------------------
// Declare and initialize a structure to include
// the array of RDN structures.

CERT_RDN rgRDN[] = 
{
   1,               // The number of elements in the array
   &rgNameAttr      // Pointer to the array
};

//--------------------------------------------------------------------
//  Declare and initialize a CERT_NAME_INFO 
//  structure that includes a CERT_RND.

CERT_NAME_INFO CertName = 
{
    1,          // The number of elements in the CERT_RND's array
    rgRDN
};

//--------------------------------------------------------------------
//  Declare additional variables.

DWORD cbEncoded;              // Variable to hold the
                              //  length of the encoded string
BYTE *pbEncoded;              // Variable to hold a pointer to the 
                              //  encoded buffer
//--------------------------------------------------------------------
// Call CrypteEncodeObjectEx to get 
// length to allocate for pbEncoded.

if( CryptEncodeObjectEx(
     MY_TYPE,        // The encoding/decoding type
     X509_NAME,    
     &CertName,
     0,                 
     NULL, 
     NULL,
     &cbEncoded))    // Fill in the length needed for
                     // the encoded buffer.
{
     printf("The number of bytes needed is %d \n",cbEncoded);
}
else
{
     printf("The first call to the function failed.\n");
     exit(1);
}

if( pbEncoded = (BYTE*)malloc(cbEncoded))
{
     printf("Memory for pvEncoded has been allocated.\n");
}
else
{
    printf("Memory allocation failed.\n");
    exit(1);
}

if(CryptEncodeObjectEx(
     MY_TYPE,
     X509_NAME,
     &CertName,
     0,
     NULL, 
     pbEncoded,
     &cbEncoded))
{
     printf("The structure has been encoded.\n");
}
else
{
     printf("Encoding failed.");
     exit(1);
}
// Free allocated memory when done.
// ...
if(pbEncoded)
{
    free(pbEncoded);
}


要求

要求
最低受支持的客户端 Windows XP [桌面应用 | UWP 应用]
最低受支持的服务器 Windows Server 2003 [桌面应用 | UWP 应用]
目标平台 Windows
标头 wincrypt.h
Library Crypt32.lib
DLL Crypt32.dll

另请参阅

CryptDecodeObject

CryptDecodeObjectEx

CryptEncodeObject

对象编码和解码函数