考虑到很多人还在用古老的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
#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;
}
}
#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] );
}
#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] );
}