考虑到很多人还在用古老的srand( time(NULL) )和rand(),这在密码学里面是很不安全也很不科学的,推荐OS自己的cryptAPI,其中Windows有API,在Linux下面可以使用OpenSSL的库,先发一个Windows的Cpp封装,支持简单的RAII,随后贴出来Linux下的。
程序里面偷懒了,本来初始化和释放CSP失败应该抛出异常,图省事就写了个printf,请大家多多提意见
WinRandom.h
#ifndef WIN_RANDOM_H_
#define WIN_RANDOM_H_
#include <windows.h>
namespace triod
{
class WinRandom
{
public:
WinRandom();
~WinRandom();
unsigned char random_char();
unsigned short random_short();
unsigned long random_long();
unsigned long set_random_char( unsigned char* memory, unsigned long size );
private:
HCRYPTPROV crypt_prov_;
};
}
#endif
WinRandom.cpp
#include <stdio.h>
#include "winRandom.h"
#pragma comment(lib, "advapi32.lib")
namespace triod
{
WinRandom::WinRandom() : crypt_prov_( NULL )
{
if( !CryptAcquireContext( &crypt_prov_, NULL, NULL, PROV_RSA_FULL, 0) )
{
if( !CryptAcquireContext( &crypt_prov_, NULL, NULL, PROV_RSA_FULL, CRYPT_NEWKEYSET) )
printf("CryptAcquireContext Failed. \n");
}
}
WinRandom::~WinRandom()
{
if( crypt_prov_ )
{
if ( !CryptReleaseContext(crypt_prov_, 0) )
printf( "Failed CryptReleaseContext\n" );
}
}
unsigned char WinRandom::random_char()
{
BYTE data[sizeof(unsigned char)];
unsigned char r = 0;
if( crypt_prov_ )
{
if( CryptGenRandom( crypt_prov_, sizeof(data), data) )
{
memcpy( &r, data, sizeof(data) );
}
}
return r;
}
unsigned short WinRandom::random_short()
{
BYTE data[sizeof(unsigned short)];
unsigned short r = 0;
if( crypt_prov_ )
{
if( CryptGenRandom( crypt_prov_, sizeof(data), data) )
{
memcpy( &r, data, sizeof(data) );
}
}
return r;
}
unsigned long WinRandom::random_long()
{
BYTE data[sizeof(unsigned long)];
unsigned long r = 0;
if( crypt_prov_ )
{
if( CryptGenRandom( crypt_prov_, sizeof(data), data) )
{
memcpy( &r, data, sizeof(data) );
}
}
return r;
}
unsigned long WinRandom::set_random_char( unsigned char* memory, unsigned long size )
{
if( crypt_prov_ )
{
if( !CryptGenRandom( crypt_prov_, size, memory) )
return 0;
}
return size;
}
}
test.cpp
#include "winRandom.h"
#include <stdio.h>
int main()
{
using triod::WinRandom;
WinRandom test;
for ( size_t i = 0; i < 100; ++i )
printf( "%02x ", test.random_char() );
printf( "\n" );
for ( size_t i = 0; i < 100; ++i )
printf( "%04x ", test.random_short() );
printf( "\n" );
for ( size_t i = 0; i < 100; ++i )
printf( "%08x ", test.random_long() );
printf( "\n" );
unsigned char roman[1000];
test.set_random_char( roman, 1000 );
for ( size_t i = 0; i < 1000; ++i )
printf( "%02x ", roman[i] );
}