加密法随机数生成器

除了传统的线性同余法(即C语言里的rand())产生伪随机数外,还可以用密码来编写能够生成强伪随机数的伪随机数生成器。密码的机密性是支撑伪随机数生成器不可预测性的基础。原理如下图:


加密法随机数生成器_第1张图片


有关的DES 的 openssl API和数据结构:

            openssl 有关的DES 的API和数据结构
            void DES_string_to_key(const char *str, DES_cblock *key)//根据字符串生成ke
            int DES_set_key_checked(const_DES_cblock *key, DES_key_schedule *schedule);//设置密码表,并进行校验
            void DES_set_key_unchecked(const_DES_cblock *key, DES_key_schedule *schedule);//设置密码表,不需要校验
            void DES_ecb_encrypt(const_DES_cblock *input, DES_cblock *output, DES_key_schedule *ks, int enc);//DES ECB模式加解密API
 
            参数说明:
                input:输入数据,8字节
                output:输出数据,8字节
                ks:密钥
                enc:加密-DES_ENCRYPT,解密-DES_DECRYPT
            
            typedef unsigned char DES_cblock[8];
            typedef unsigned char const_DES_cblock[8];
            typedef struct DES_ks
            {       
                union 
                    {
                        DES_cblock cblock;
                        DES_LONG deslong[2];
                    } ks[16];
            } DES_key_schedule;
 
            sizeof(DES_cblock) = 8字节
            sizeof(const_DES_cblock ) = 8字节
            sizeof(DES_key_schedule) = 128字节


代码:

/*************************************************************************************************
*   1. FILENAME:rand_by_DESencrypt.c
*
*   2.描述: 通过get_seed(seed_text)和get_key_schedule(&key_schedule)分别设置种子(68bit明文)
*           和DES秘钥生成schedule。进而通过函数long long DES_encrypt_rand() 得到DES加密的密文作为
*           long long (64bit)类型的随机数,并且打印到屏幕上。种子在每次程序开始运行时读取种子文件
*           “./seed.txt”,其它情况在每次调用 DES_encrypt_rand()后自加1。如果seek不变,则随机数机
*           会一样。
*
*   3.DATA  : 2017/8/26
*     AUTHOR: keyu
*
*************************************************************************************************/

#include
#include
#include
#include 

char byte2hex_table[16] = {'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'};//hex2bin表

int byte2hex(unsigned char * hex_string,unsigned char *byte_list,unsigned int byte_list_length);
int get_key_schedule(DES_key_schedule * key_schedule);
int get_seed(const_DES_cblock text);
long long DES_encrypt_rand(DES_key_schedule * key_schedule,const_DES_cblock *seed_text);
int read_file( char * block,char * filename);
int hex2byte(char *hex_string,unsigned char *byte_list, unsigned int byte_list_legth);


int main()
{
    int mun = 10;
    long long rand;
    DES_key_schedule  key_schedule;
    const_DES_cblock seed_text;
    get_key_schedule(&key_schedule);
    get_seed(seed_text);

    for(int i = 0; i < mun; i++)//生成并且打印10个随机数
    {
        rand = DES_encrypt_rand(&key_schedule,&seed_text);
        printf("%016llX\n",rand);
    }
    return 1;
}
/*********************************************************************************************
*   1. DES_encrypt_rand()功能:通过key_schedule使用ecd_DES算法加密seed_text得到的64位密
                               文作为long long类型的随机数。
*
*   2.参数:DES_key_schedule * key_schedule ---为DES_key转换成的密码表。 
*           const_DES_cblock * seed_text  -----64位明文
*
*   3.RETURN:返回long long 类型的随机数。
*   
*********************************************************************************************/
long long DES_encrypt_rand(DES_key_schedule * key_schedule,const_DES_cblock * seed_text)

    long long rand;
    DES_cblock output;
    DES_ecb_encrypt(seed_text, &output, key_schedule, DES_ENCRYPT);
    rand = (*((long long *)(output)));
    (*((long long*)(*seed_text)))++;

    return rand;
}
/*********************************************************************************************
1.get_key_schedule()功能:初始化一个DES_key_schedule密码表。注意:并不是DES_key.
                          如果需要改变密码表,只需改变keystring即可。
*********************************************************************************************/
int get_key_schedule(DES_key_schedule * key_schedule)
{
    DES_cblock  key;
    unsigned char *keystring = "keystring is me!";
    DES_string_to_key(keystring, &key);
    DES_set_key_checked(&key, key_schedule);
    return 0;
}
/*******************************************************************************************
1.get_seed()功能:从"seed.txt"文件读取种子(明文)。种子是64位二进制数,而文件里
                存放的是其十六进制的字符串形式。所以文件读出来的字符串需要转化为二进制,
                如"a1ff..ff" -> 10011111.....11111111.
2.参数:const_DES_cblock seed-----8字节大小明文,注意:typedef unsigned char DES_cblock[8];                 
********************************************************************************************/

int get_seed(const_DES_cblock seed)
{
    unsigned char * block = (unsigned char *)(malloc(16+1));
    if( read_file(block,"seed.txt") != 1)
    {
        printf("delete_read() in read_text() fails!\n");
        free(block);
        return 0;
    }
    printf("seed:");
    printf("%s\n",block);
    unsigned char* byte_list = (unsigned char*)(malloc(8));
    if(hex2byte(block,byte_list,8) != 1)
    {
        printf("hex2byte() in read_text() fails!\n");
        free(block);
        free(byte_list);
        return 0;
    }

    *((long long*)seed) = *((long long*)byte_list);

    free(block);
    free(byte_list);
    return 1;
}

/**************************************************************************************
*1.hex2byte()功能:把2×byte_list_legth个字符的十六进制字符串(char *hex_string)转化
*                 为byte_list_legth个字节的二进制数(unsigned char *byte_list)。
***************************************************************************************/
int hex2byte(char *hex_string,unsigned char *byte_list, unsigned int byte_list_legth)
{
    char * temp;
    unsigned int i,j,n;
    if(  strlen(hex_string) != (2*byte_list_legth) )
    {
        printf("HEXstring_length != 2*BYTEstring_length!\n");
        return 0;
    }
    temp = hex_string;
    for( j = 0; j < byte_list_legth; j++)
    {
        sscanf( temp, "%02X", &n ); //n必须为unsigned int(因为%X必须要求是整型,而unsigned是防止负数符号扩展问题)
        byte_list[j] = (unsigned char)n;
        temp += 2;
    }

    return 1;
}
int read_file( char * block,char * filename)
{
    FILE * fp;
    fp  = fopen(filename, "r");
    int i=fread(block,16,1,fp);
    if( i != 1)
    {
        fclose(fp);
        return 0;
    }
    block[16] = 0;
    fclose(fp);
    return 1;
}



结果:

keyu0915@keyu0915:~/CAR/DES$ gcc rand_by_DEScrypt.c -o rand_by_DEScrypt -lcrypto
keyu0915@keyu0915:~/CAR/DES$ ./rand_by_DEScrypt 
seed:EB05AE79F0CE0D2D
5E3673D90DE27224
A717625519A9DD0D
43DD9A1F3FC9402F
A456A23EC3276342
16D05649AD2EAFA3
941E0A924EF66442
62EEA7592181FA1F
5ABA7608EB32D5D2
24EA761E83DF4F02
2FA541DDCE3CB9A8



你可能感兴趣的:(密码学)