cryptExportKey 函数 (wincrypt.h)

重要 此 API 已弃用。 新的和现有的软件应开始使用 加密下一代 API。 Microsoft 可能会在将来的版本中删除此 API。
 
CryptExportKey 函数以安全的方式加密服务提供程序 (CSP) 导出加密密钥或密钥对。

要导出的密钥的句柄传递给函数,函数返回 密钥 BLOB。 此密钥 BLOB 可以通过不安全的传输发送,也可以存储在不安全的存储位置。 此函数可以导出 Schannel 会话密钥、常规 会话密钥公钥公钥/私钥对。 要导出的密钥 BLOB 在目标接收方使用其上的 CryptImportKey 函数将密钥或密钥对导入收件人的 CSP 之前是无用的。

语法

BOOL CryptExportKey(
  [in]      HCRYPTKEY hKey,
  [in]      HCRYPTKEY hExpKey,
  [in]      DWORD     dwBlobType,
  [in]      DWORD     dwFlags,
  [out]     BYTE      *pbData,
  [in, out] DWORD     *pdwDataLen
);

参数

[in] hKey

要导出的密钥的句柄。

[in] hExpKey

目标用户的加密密钥的句柄。 导出的 密钥 BLOB 中的密钥 数据使用此密钥进行加密。 这可确保只有目标用户才能使用密钥 BLOB。 hExpKeyhKey 必须来自同一 CSP。

大多数情况下,这是目标用户的 密钥交换公钥 。 但是,某些 CSP 中的某些协议要求将属于目标用户的会话密钥用于此目的。

如果 dwBlobType 指定的密钥 BLOB 类型为 PUBLICKEYBLOB,则此参数未使用,必须设置为零。

如果 dwBlobType 指定的密钥 BLOB 类型为 PRIVATEKEYBLOB,则这通常是用于加密密钥 BLOB 的会话密钥的句柄。 某些 CSP 允许此参数为零,在这种情况下,应用程序必须手动加密 私钥 BLOB 才能保护它。

若要确定 Microsoft 加密服务提供程序如何响应此参数,请参阅 Microsoft 加密服务提供程序私钥 BLOB 部分。

注意 某些 CSP 可能会因操作而修改此参数。 随后将此密钥用于其他目的的应用程序应调用 CryptDuplicateKey 函数来创建重复的密钥句柄。 当应用程序使用完句柄后,通过调用 CryptDestroyKey 函数释放它。
 

[in] dwBlobType

指定要在 pbData 中导出的密钥 BLOB 的类型。 这必须是加密密钥 存储和 Exchange 中所述的下列常量之一。

含义
OPAQUEKEYBLOB
用于以 Schannel CSP 或任何其他特定于供应商的格式存储会话密钥。 OPAQUEKEYBLOB 不可转让,必须在生成 BLOB 的 CSP 中使用。
PRIVATEKEYBLOB
用于传输 公钥/私钥对
PUBLICKEYBLOB
用于传输公钥。
SIMPLEBLOB
用于传输会话密钥。
PLAINTEXTKEYBLOB
用于导出正在使用的 CSP 支持的任何密钥的 PLAINTEXTKEYBLOB
SYMMETRICWRAPKEYBLOB
用于导出和导入用另一个 对称密钥 包装的对称密钥。 实际的包装密钥采用 IETF RFC 3217 标准中指定的格式。

[in] dwFlags

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

含义
CRYPT_BLOB_VER3
0x00000080
此标志使此函数导出 BLOB 类型的版本 3。
CRYPT_DESTROYKEY
0x00000004
此标志销毁 OPAQUEKEYBLOB 中的原始密钥。 此标志仅在 Schannel CSP 中可用。
CRYPT_OAEP
0x00000040
此标志会导致在导出 SIMPLEB BLOB 时使用 RSA 加密和解密创建 PKCS #1 版本 2 格式设置。
CRYPT_SSL2_FALLBACK
0x00000002
RSA 加密块 填充 的前八个字节必须设置为0x03而不是随机数据。 这可以防止版本回滚攻击,SSL3 规范中对此进行了讨论。 此标志仅适用于 Schannel CSP。
CRYPT_Y_ONLY
0x00000001
未使用此标志。

[out] pbData

指向接收 密钥 BLOB 数据的缓冲区的指针。 此 BLOB 的格式因 dwBlobType 参数中请求的 BLOB 类型而异。 有关 PRIVATEKEYBLOBs、PUBLICKEYBLOBs 和 SIMPLEBLOB 的格式,请参阅 基提供程序密钥 BLOB

如果此参数为 NULL,则将所需的缓冲区大小放置在 pdwDataLen 参数指向的值中。 有关详细信息,请参阅 检索未知长度的数据

[in, out] pdwDataLen

指向 DWORD 值的指针,该值在输入时包含 pbData 参数指向的缓冲区的大小(以字节为单位)。 当函数返回时,此值包含缓冲区中存储的字节数。

注意 处理缓冲区中返回的数据时,应用程序必须使用返回的数据的实际大小。 实际大小可以略小于输入时指定的缓冲区的大小。 在输入时,缓冲区大小通常指定得足够大,以确保最大输出数据适合缓冲区。 输出时,此参数指向的变量将更新,以反映复制到缓冲区的数据的实际大小。
 
若要检索 pbData 缓冲区的所需大小,请为 pbData 传递 NULL。 所需的缓冲区大小将放置在此参数指向的值中。

返回值

如果函数成功,则函数) 返回非零 (TRUE

如果函数失败,它将返回零 (FALSE) 。 有关扩展的错误信息,请调用 GetLastError

以“NTE”开头的错误代码由使用的特定 CSP 生成。 下表显示了一些可能的错误代码。

返回代码 说明
ERROR_INVALID_HANDLE
其中一个参数指定无效的句柄。
ERROR_INVALID_PARAMETER
其中一个参数包含无效的值。 这通常是无效的指针。
ERROR_MORE_DATA
如果 pbData 参数指定的缓冲区不够大,无法容纳返回的数据,该函数将设置ERROR_MORE_DATA代码,并将所需的缓冲区大小(以字节为单位)存储在 pdwDataLen 指向的变量中。
NTE_BAD_DATA
此 CSP 不支持与要导出的公钥一起使用的算法,或者尝试导出使用公钥以外的其他内容加密的会话密钥。
NTE_BAD_FLAGS
dwFlags 参数为非零值。
NTE_BAD_KEY
hKey 和 hExpKey 指定的一个或两个密钥无效。
NTE_BAD_KEY_STATE
您没有导出密钥的权限。 也就是说,创建 hKey 键时,未指定CRYPT_EXPORTABLE标志。
NTE_BAD_PUBLIC_KEY
dwBlobType 指定的密钥 BLOB 类型为 PUBLICKEYBLOB,但 hExpKey 不包含公钥句柄。
NTE_BAD_TYPE
dwBlobType 参数指定未知的 BLOB 类型。
NTE_BAD_UID
找不到创建 hKey 密钥时指定的 CSP 上下文。
NTE_NO_KEY
正在导出会话密钥, hExpKey 参数未指定公钥。

注解

对于使用 PLAINTEXTKEYBLOB 的任何 DES 密钥排列,只能导出完整的密钥大小,包括奇偶校验位。 支持以下密钥大小。

算法 支持的密钥大小
CALG_DES 64 位
CALG_3DES_112 128 位
CALG_3DES 192 位
 

示例

以下示例演示如何以更安全的方式导出加密密钥或密钥对。 此示例假定已获取加密上下文,并且公钥可用于导出。 有关包含使用此函数的完整上下文的示例,请参阅 示例 C 程序:对哈希进行签名和验证哈希签名。 有关使用此函数的另一个示例,请参阅 示例 C 程序:导出会话密钥

#include <windows.h>
#include <stdio.h>
#include <Wincrypt.h>

BOOL GetExportedKey(
    HCRYPTKEY hKey, 
    DWORD dwBlobType,
    LPBYTE *ppbKeyBlob, 
    LPDWORD pdwBlobLen)
{
    DWORD dwBlobLength;
    *ppbKeyBlob = NULL;
    *pdwBlobLen = 0;

    // Export the public key. Here the public key is exported to a 
    // PUBLICKEYBLOB. This BLOB can be written to a file and
    // sent to another user.

    if(CryptExportKey(   
        hKey,    
        NULL,    
        dwBlobType,
        0,    
        NULL, 
        &dwBlobLength)) 
    {
        printf("Size of the BLOB for the public key determined. \n");
    }
    else
    {
        printf("Error computing BLOB length.\n");
        return FALSE;
    }

    // Allocate memory for the pbKeyBlob.
    if(*ppbKeyBlob = (LPBYTE)malloc(dwBlobLength)) 
    {
        printf("Memory has been allocated for the BLOB. \n");
    }
    else
    {
        printf("Out of memory. \n");
        return FALSE;
    }

    // Do the actual exporting into the key BLOB.
    if(CryptExportKey(   
        hKey, 
        NULL,    
        dwBlobType,    
        0,    
        *ppbKeyBlob,    
        &dwBlobLength))
    {
        printf("Contents have been written to the BLOB. \n");
        *pdwBlobLen = dwBlobLength;
    }
    else
    {
        printf("Error exporting key.\n");
        free(*ppbKeyBlob);
        *ppbKeyBlob = NULL;

        return FALSE;
    }

    return TRUE;
}

要求

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

另请参阅

CryptImportKey

密钥生成和交换函数