我尝试使用CryptGenRandom()调用创建随机数,以避免加密攻击。 我试图运行以下代码来打印rand调用和CryptGenRandom()调用。
HCRYPTPROV hProvider = 0;
const DWORD dwLength = 5;
BYTE pbBuffer[dwLength] = {};
if (!::CryptAcquireContext(&hProvider, 0, 0, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT|CRYPT_SILENT))
return 1;
srand((unsigned)time (0));
for(int i=0; i<10; ++i)
cout<<"rand()::"<<i<<":"<<rand()<<endl;
for (DWORD i = 0; i < dwLength; ++i)
{
if (!::CryptGenRandom(hProvider, dwLength, pbBuffer))
{
::CryptReleaseContext(hProvider, 0);
return 1;
}
std::cout << "windows::"<<i<<"::"<<static_cast<unsigned int>(pbBuffer[0])<< std::endl;
}
if (!::CryptReleaseContext(hProvider, 0))
return 1;
但是rand()
来电的输出是
rand()::0:9754
rand()::1:526
rand()::2:29162
rand()::3:10461
rand()::4:31585
rand()::5:15594
rand()::6:12157
rand()::7:19178
rand()::8:5413
rand()::9:16157
和CryptGenRandom()
来电正在
windows::0::167
windows::1::138
windows::2::197
windows::3::101
windows::4::44
任何人都可以帮我获得使用CryptGenRandom进行rand()调用的相同输出吗? CryptGenRandom()只提供3位数的随机数,这些数字不足以设置我在我的代码中使用的睡眠调用值。
答案 0 :(得分:3)
问题是你在这里使用pBuffer[0]
。
static_cast<unsigned int>(pbBuffer[0])
正如您的代码所示,pBuffer[0]
是一个BYTE
。这就是为什么你没有得到大于255的值。
如果你想要任何可表示的unsigned int
,你会想要这个。
const DWORD dwLength = sizeof(unsigned int);
这就是使用pBuffer
中的所有字节。
*static_cast<unsigned int*>(pbBuffer)
答案 1 :(得分:2)
嗯,它只提供3位数字,因为您只需要一个字节并在执行此操作时将其转换为unsigned int
:static_cast<unsigned int>(pbBuffer[0])
和BYTE
(即{{1} 1}})只能适应0到255之间的值。
您可以稍微改变一下方法:
unsigned char
此函数将在失败时返回unsigned int MyGoodRand()
{
// We make this a static so we don't have
// to initialize it all the time because
// that is expensive.
static HCRYPTPROV hProvider = 0;
if(hProvider == NULL)
{
if(!::CryptAcquireContext(&hProvider, 0, 0, PROV_RSA_FULL,
CRYPT_VERIFYCONTEXT|CRYPT_SILENT))
return 0;
}
unsigned int randval = 0;
if (!::CryptGenRandom(hProvider, sizeof(unsigned int), static_cast<PBYTE>(&randval)))
randval = 0; // Failure!
return randval;
}
,这是一个问题,因为0也是0
的可能结果,并且还会泄漏CryptGenRandom
,因为它仅在函数内部可用且一旦分配,就没有办法释放它。
我们可以对其进行扩充,以相应地返回HCRYPTPROV
或true
,并通过其调用者的引用接受false
,但这不会解决randval
泄漏问题。我们改为将HCRYPTPROV
作为成员class
以及HCRYPTPROV
来生成新数字。
这样的事情:
operator()
现在我们没有泄漏,我们可以轻松生成随机数,并确定操作是否成功可靠。我们可以像这样使用它:
class MYPRNG
{
private:
HCRYPTPROV hProvider;
// declare but not define a private copy constructor to
// prevent copy-construction of this object. If you're
// using C++11 you can use the =delete syntax instead.
MYPRNG(const MYPRNG &o) = delete;
// Same with the default assignment operator.
MYPRNG& operator=(const MYPRNG& o)
public:
MYPRNG()
: hProvider(NULL)
{
if(!::CryptAcquireContext(&hProvider, 0, 0, PROV_RSA_FULL,
CRYPT_VERIFYCONTEXT|CRYPT_SILENT))
hProvider = NULL; // ensure that it's NULL
}
~MYPRNG()
{
if(hProvider)
CryptReleaseContext(hProvider, 0);
}
bool operator()(unsigned int &randval)
{
if(hProvider == NULL)
return false;
if (!::CryptGenRandom(hProvider,
sizeof(unsigned int),
static_cast<PBYTE>(&randval)))
return false;
return true;
}
};