抱歉,我不能为此使用单独的类,我尝试构建以下代码并在循环中从外侧调用时获得相同的输出。
unsigned int crypt_rand()
{
HCRYPTPROV hProvider = 0;
const DWORD dwLength = sizeof(unsigned int);
unsigned int pbBuffer[dwLength] = {};
if (!::CryptAcquireContext(&hProvider, 0, 0, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT | CRYPT_SILENT))
return 1;
if (!::CryptGenRandom(hProvider, sizeof(unsigned int), reinterpret_cast<PBYTE>(&pbBuffer)))
{
::CryptReleaseContext(hProvider, 0);
return 1;
}
if (!::CryptReleaseContext(hProvider, 0))
return 1;
return (unsigned int)pbBuffer;
}
如果我从循环调用此函数每次都获得相同的输出。这是我在这个方法中可以像输入一样给出的任何东西。你能帮我解决这个问题吗?
for (DWORD i = 0; i < 5; ++i)
{
rand_no = crypt_rand();
std::cout << "windows::"<<i<<"::"<<rand_no<< std::endl;
}
输出
windows::0::4519964
windows::1::4519964
windows::2::4519964
windows::3::4519964
windows::4::4519964
答案 0 :(得分:4)
使用强制转换(reinterpret_cast
和return
语句中的一个)隐藏了一些重要的编译器错误,这些错误可以让您首先正确编写此代码。
尽可能避免使用强制转换,而是修改类型。
CryptGenRandom
期待
BYTE *pbBuffer
参数。传递一个指向BYTE
数组的指针,而不是其他任何东西(你传递一个指向int
数组的指针。)
在您的退货声明中,您要将地址转换为unsigned int
。您需要获取BYTE
数组并将其包含的值转换为int(您可以在线找到该示例,或者您可以通过坐换和添加自己创建一个)。你现在正在做的可能是一遍又一遍地输出相同的地址(或部分地址)。
澄清一下,将数组定义为
BYTE pbBuffer[dwLength] = {};
并将您的功能称为
::CryptGenRandom(hProvider, dwLength, pbBuffer)
避免使用强制转换,尤其是C样式转换,并阅读有关数组的内容。在C ++中,当传递给函数时,数组会衰减到指向数组第一个元素的指针。如果您有一个BYTE
数组,它将衰减为BYTE*
,即函数的预期类型。
答案 1 :(得分:0)
问题出在return (unsigned int)pbBuffer;
这里你只是每次都得到pbBUffer的地址。如果pbBuffer是一个数组,函数crypt_rand返回unsigned int那么它应该是返回时数组的元素。
您需要在编译期间启用警告。这些可能的错误必须作为警告。
答案 2 :(得分:0)
你想要一个无符号整数的随机数吗? 只需将BYTE缓冲区的内容强制转换为unsigned int
即可怎么样:
unsigned int crypt_rand()
{
HCRYPTPROV hProvider = 0;
const DWORD dwLength = sizeof(unsigned int);
BYTE buffer[dwLength];
if (!::CryptAcquireContext(&hProvider, 0, 0, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT | CRYPT_SILENT))
return 1;
if (!::CryptGenRandom(hProvider, sizeof(buffer), &buffer))
{
::CryptReleaseContext(hProvider, 0);
return 1;
}
if (!::CryptReleaseContext(hProvider, 0))
return 1;
return *(unsigned int*)buffer;
}