rou*_*bic 5 c encryption cryptography aes cryptoapi
我想使用 Windows CryptoAPI 函数进行 AES 加密。
众所周知,API有很多功能可以创建、散列和更改输入的密钥;它派生出密钥,您就可以处理它。
我的问题是我想知道派生密钥是什么?
#include <Windows.h>
#include <stdio.h>
int main()
{
HCRYPTPROV hProv = 0;
HCRYPTKEY hKey = 0;
HCRYPTHASH hHash = 0;
DWORD dwCount = 5;
BYTE rgData[512] = {0x01, 0x02, 0x03, 0x04, 0x05};
LPWSTR wszPassword = L"pass";
DWORD cbPassword = (wcslen(wszPassword)+1)*sizeof(WCHAR);
if(!CryptAcquireContext(
&hProv,
NULL,
MS_ENH_RSA_AES_PROV,
PROV_RSA_AES,
CRYPT_VERIFYCONTEXT))
{
printf("Error %x during CryptAcquireContext!\n", GetLastError());
goto Cleanup;
}
if(!CryptCreateHash(hProv, CALG_SHA_256, 0, 0, &hHash))
{
printf("Error %x during CryptCreateHash!\n", GetLastError());
goto Cleanup;
}
if(!CryptHashData(hHash, (PBYTE)wszPassword, cbPassword, 0))
{
printf("Error %x during CryptHashData!\n", GetLastError());
goto Cleanup;
}
if (!CryptDeriveKey(hProv, CALG_AES_256, hHash, CRYPT_EXPORTABLE, &hKey))
{
printf("Error %x during CryptDeriveKey!\n", GetLastError());
goto Cleanup;
}
for(DWORD i = 0; i < dwCount; i++)
{
printf("%d ",rgData[i]);
}
printf("\n");
if (!CryptEncrypt(
hKey,
0,
TRUE,
0,
rgData,
&dwCount,
sizeof(rgData)))
{
printf("Error %x during CryptEncrypt!\n", GetLastError());
goto Cleanup;
}
for(DWORD i = 0; i < dwCount; i++)
{
printf("%d ",rgData[i]);
}
printf("\n");
Cleanup:
if(hKey)
{
CryptDestroyKey(hKey);
}
if(hHash)
{
CryptDestroyHash(hHash);
}
if(hProv)
{
CryptReleaseContext(hProv, 0);
}
return 0;
}
Run Code Online (Sandbox Code Playgroud)
编辑:如果密钥派生在软件中,那么软件性的答案可能会更好。所以这是一个更通用的答案,应该是首选。如果软件方法失败,您可以使用此重放方法。如果令牌不允许明文导出,则可能会出现这种情况。
一般来说,这些方法的创建方式使得检索结果秘密即使不是不可能,也是很困难的。不过,密钥的导出方法在API文档的备注部分CryptDeriveKey
有描述。这样您就可以重播基础数据的创建过程。
该 API 没有描述使用 SHA-2 时会发生什么,但我认为它只是使用 SHA-256 结果的最左边位作为密钥。
推导后,您当然可以通过加密/解密或一些数据进行测试。
令n为所需的派生密钥长度(以字节为单位)。派生密钥是完成哈希计算后哈希值的前n 个
CryptDeriveKey
字节。如果哈希值不是 SHA-2 系列的成员,并且所需密钥适用于 3DES 或 AES,则密钥的推导如下:
- 通过重复常量 64 次形成 64 字节缓冲区
0x36
。令k为输入参数 表示的哈希值的长度hBaseData
。将缓冲区的前k字节设置为缓冲区的前k字节与输入参数表示的哈希值进行异或运算的结果hBaseData
。- 通过重复常量 64 次形成 64 字节缓冲区
0x5C
。将缓冲区的前k字节设置为缓冲区的前k字节与输入参数表示的哈希值进行异或运算的结果。hBaseData
- 使用与计算参数表示的哈希值相同的哈希算法对步骤 1 的结果进行哈希处理
hBaseData
。- 使用与计算参数表示的哈希值相同的哈希算法对步骤 2 的结果进行哈希处理
hBaseData
。- 将步骤 3 的结果与步骤 4 的结果连接起来。
- 使用步骤 5 结果的前n 个字节作为派生密钥。