【问题标题】:How export symetric AES key cryptoapi如何导出对称 AES 密钥 cryptoapi
【发布时间】:2015-02-08 09:07:05
【问题描述】:

我有一些问题。我需要使用 CryptoAPI 生成和导出对称密钥。

     if(CryptAcquireContext(&hCryptProv_AES, NULL, MS_ENH_RSA_AES_PROV, PROV_RSA_AES,  0))
    {
        _tprintf(
            TEXT("A cryptographic provider has been acquired. \n"));
    }
    else
    {
            DWORD d = GetLastError();
            std::cout<<"";
            return -1;
    }

    if (!CryptGenKey(hCryptProv_AES,CALG_AES_256,CRYPT_EXPORTABLE,&hSessionKey_AES))
        {
            DWORD d = GetLastError();
            std::cout<<"";
            return -1;
        }
    else 
    {
        std::cout<<"OK";
    }

    // Export key
   BYTE keybuf[ 1024 ], buffer[ 1024 ];
   DWORD i, keylen = sizeof( buffer );

    struct ekb
   {
       PUBLICKEYSTRUC  hdr;
       ALG_ID                 algId;
       BYTE                    key[1];
   } *encKey = (struct ekb *)buffer;

    bool bbb = CryptExportKey(hSessionKey_AES, NULL, SIMPLEBLOB, 0, (BYTE *)encKey, &keylen);
    DWORD f = GetLastError();

但不能使用 AES 密钥。 我该如何解决这个问题,请帮助。如何获取 AES 密钥??

更新 例如,我使用下一个代码并且可以获得公共 RSA 密钥。

char * base_txt = "Test text";
    char * enc_text = "";


     if(CryptAcquireContext(&hCryptProv_RSA, NULL, MS_ENHANCED_PROV , PROV_RSA_FULL,  0))
    {
        _tprintf(
            TEXT("A cryptographic provider has been acquired. \n"));
    }
    else
    {
            DWORD d = GetLastError();
            std::cout<<"";
            return -1;
    }

    if (!CryptGenKey(hCryptProv_RSA,AT_KEYEXCHANGE,1024<<16,&hSessionKey))
        {
            DWORD d = GetLastError();
            std::cout<<"";
            return -1;
        }

    RSAPubKey1024 key; 
    DWORD dwLen=sizeof(RSAPubKey1024);



    // Export key
    bool bb = CryptExportKey(hSessionKey,NULL,PUBLICKEYBLOB,0,(BYTE *)&key,&dwLen);

更新 2 导出后我导入密钥并尝试加密和解密

HCRYPTPROV hCryptProv_AES22;
    if (CryptAcquireContext(&hCryptProv_AES22, NULL, MS_ENH_RSA_AES_PROV, PROV_RSA_AES, 0))
    {
        printf("A cryptographic provider has been acquired.\r\n");
    }
    else
    {
        DWORD d = GetLastError();
        return -1;
    }
    int iii =  CryptImportKey(hCryptProv_AES22,(BYTE *)&exportKey_AES,keylen,NULL,NULL,&hSessionKey_AES2);

    if(CryptSetKeyParam(hSessionKey_AES2,KP_IV, exportKey_AES, 0))
    {
        BYTE encryptedMessage[1024];
        const char * message = "Decryption Works -- using multiple blocks";
        BYTE messageLen = (BYTE)strlen(message);
        memcpy(encryptedMessage, message, messageLen);
        DWORD encryptedMessageLen = messageLen;
        CryptEncrypt(hSessionKey_AES2, NULL, TRUE, 0, encryptedMessage, &encryptedMessageLen, sizeof(encryptedMessage));    
        CryptDecrypt(hSessionKey_AES2,NULL,TRUE,0,encryptedMessage, &encryptedMessageLen);

    }

【问题讨论】:

  • 为什么你认为你不能赌AES密钥? CryptExportKey 是否返回 FALSE?如果是,GetLastError 给出的错误代码是什么?
  • 返回 FALSE && 错误代码 f = 2148073485

标签: c++ encryption aes cryptoapi


【解决方案1】:

CryptExportKey 有一个限制。它要求以加密形式导出非公钥。导出公共部分或 RSA 密钥对时,可以设置第二个CryptExportKey 参数NULL 并以未加密的形式导出密钥。但是,您不能对 必须 指定非空 hExpKey 参数的对称密钥执行相同操作。 如果您指定hExpKey 参数,您的代码可以工作,请参见示例:

#include <Windows.h>
#include <cstdio>

int main(int argc, char *argv[])
{
    // Create AES key
    HCRYPTPROV hCryptProv_AES;
    if (CryptAcquireContext(&hCryptProv_AES, NULL, MS_ENH_RSA_AES_PROV, PROV_RSA_AES, 0))
    {
        printf("A cryptographic provider has been acquired.\r\n");
    }
    else
    {
        DWORD d = GetLastError();
        return -1;
    }
    HCRYPTKEY hSessionKey_AES;
    if (!CryptGenKey(hCryptProv_AES, CALG_AES_256, CRYPT_EXPORTABLE, &hSessionKey_AES))
    {
        DWORD d = GetLastError();
        return -1;
    }
    // Create RSA key to encrypt AES one
    HCRYPTKEY hSessionKey;
    if (!CryptGenKey(hCryptProv_AES, AT_KEYEXCHANGE, 1024 << 16, &hSessionKey))
    {
        DWORD d = GetLastError();
        return -1;
    }
    // Export key
    DWORD keylen;
    BOOL ok = CryptExportKey(hSessionKey_AES, hSessionKey, SIMPLEBLOB, 0, NULL, &keylen);
    if (ok == FALSE)
    {
        DWORD d = GetLastError();
        return -1;
    }
    BYTE *encKey = (BYTE *)malloc(keylen);
    ok = CryptExportKey(hSessionKey_AES, hSessionKey, SIMPLEBLOB, 0, encKey, &keylen);
    if (ok == FALSE)
    {
        DWORD d = GetLastError();
        return -1;
    }
    else
        printf("A cryptographic key export succeeded.\r\n");
    return 0;
}

如果您想进行密钥交换(假设您希望 Alice 将她的 AES 密钥发送给 Bob),您必须执行以下步骤:

  1. Bob 生成 RSA 密钥并将其公共部分发送给 Alice。看,鲍勃开始了,而不是爱丽丝!
  2. Bob 将他的密钥公开部分发送给 Alice。
  3. Alice 生成 AES 密钥。
  4. Alice 使用 Bob 的公钥加密 AES 密钥。
  5. Alice 将 AES 密钥发送给 Bob。
  6. Bob 使用他的私钥解密 AES 密钥(即使用 CryptImportKey 导入它)。导入密钥时,将hPubKey参数设置为非NULL值,实际上是设置为Bob的密钥句柄,否则导入将失败,因为AES密钥已加密。

【讨论】:

  • 好的,但是我想导入的地方只需要使用 int iii = CryptImportKey(hCryptProv_AES,(BYTE *)&exportKey_AES,keylen,NULL,NULL,&new_session_key); ?
  • 我添加了解释如何交换答案的密钥。
猜你喜欢
  • 2015-06-17
  • 1970-01-01
  • 1970-01-01
  • 2016-10-09
  • 1970-01-01
  • 1970-01-01
  • 2011-09-26
  • 2018-01-09
  • 1970-01-01
相关资源
最近更新 更多