如何导出symetric AES密钥cryptoapi

时间:2014-12-10 08:38:10

标签: c++ encryption aes cryptoapi

我有一些问题。我需要使用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密钥?

UPDATE 例如,我使用下一个代码,可以获得公共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);

    }

1 个答案:

答案 0 :(得分:3)

CryptExportKey有一个限制。 要求以加密形式导出非公钥。导出公共部分或RSA密钥对时,可以使用第二个CryptExportKey参数NULL并以未加密的形式导出密钥。但是,对于必须指定非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向Bob发送她的AES密钥),您必须执行以下步骤:

  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密钥已加密。