加密法隨機數生成器
阿新 • • 發佈:2019-01-10
除了傳統的線性同餘法(即C語言裡的rand())產生偽隨機數外,還可以用密碼來編寫能夠生成強偽隨機數的偽隨機數生成器。密碼的機密性是支撐偽隨機數生成器不可預測性的基礎。原理如下圖:
有關的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<stdio.h> #include<stdlib.h> #include<string.h> #include <openssl/des.h> 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; }
結果:
[email protected]:~/CAR/DES$ gcc rand_by_DEScrypt.c -o rand_by_DEScrypt -lcrypto [email protected]:~/CAR/DES$ ./rand_by_DEScrypt seed:EB05AE79F0CE0D2D 5E3673D90DE27224 A717625519A9DD0D 43DD9A1F3FC9402F A456A23EC3276342 16D05649AD2EAFA3 941E0A924EF66442 62EEA7592181FA1F 5ABA7608EB32D5D2 24EA761E83DF4F02 2FA541DDCE3CB9A8