├── AES ├── AES example.txt ├── AES.h ├── example.cpp └── readme.md ├── DAA ├── DAA example.txt ├── DAA.h ├── DES.h ├── example.cpp └── readme.md ├── DES ├── DES example.txt ├── DES.h ├── example.cpp └── readme.md ├── Diffie-Hellman ├── DH.py ├── example.py └── readme.md ├── Elgamel ├── Elgamel.py ├── example.py └── readme.md ├── HMAC ├── HMAC example.txt ├── HMAC.h ├── MD5.h ├── SHA512.h ├── example.cpp └── readme.md ├── HashCenter ├── HashCenter.h ├── MD5.h ├── SHA512.h ├── example.cpp └── readme.md ├── LICENSE ├── MD5 ├── MD5 example.txt ├── MD5.h ├── example.cpp └── readme.md ├── Pattern ├── AES.h ├── DES.h ├── Pattern.h ├── example.cpp └── readme.md ├── README.md ├── RSA ├── RSA.py ├── example.py └── readme.md ├── SHA512 ├── SHA512 example.txt ├── SHA512.h ├── example.cpp └── readme.md └── Tradition ├── Tradition.h ├── example.cpp └── readme.md /AES/AES example.txt: -------------------------------------------------------------------------------- 1 | 以下均为明文和密文在内存中的十六进制形式 2 | 明文:0123456789abcdeffedcba9876543210 3 | 密钥:0f1571c947d9e8590cb7add6af7f6798 4 | 密文:ff0b844a0853bf7c6934ab4364148fb9 5 | -------------------------------------------------------------------------------- /AES/example.cpp: -------------------------------------------------------------------------------- 1 | #include "AES.h" 2 | #include 3 | #include 4 | 5 | using namespace std; 6 | 7 | int main(void) 8 | { 9 | string plain="0123456789abcdeffedcba9876543210"; 10 | string key="0f1571c947d9e8590cb7add6af7f6798"; 11 | string enpt; 12 | 13 | AES aes=AES(); 14 | aes.key(key,"0x"); 15 | 16 | enpt=aes.encrypt(plain,"0x","0x"); 17 | cout<<"encrypt result: "< 1. key方法的第一个参数为32位十六进制或者128位二进制密钥。 11 | > 2. 第二个参数的"0x"表示密钥为十六进制,"0b"表示密钥为二进制。 12 | 13 | string key="0f1571c947d9e8590cb7add6af7f6798"; 14 | aes.key(key,"0x"); 15 | 16 | 17 | ## 4. 使用encrypt方法进行AES加密 18 | > 1. encrypt方法的第一个参数为32位十六进制或者128位二进制明文。 19 | > 2. 第二个参数的"0x"表示输入明文为十六进制,"0b"表示输入的明文为二进制。 20 | > 3. 第三个参数的"0x"表示加密后的密文以十六进制返回,"0b"表示密文以二进制返回。 21 | 22 | string plain="0123456789abcdeffedcba9876543210"; 23 | string enpt=aes.encrypt(plain,"0x","0x"); 24 | 25 | 26 | ## 5. 使用decrypt方法进行AES解密 27 | > 1. decrypt方法的第一个参数为32位十六进制或者128位二进制密文。 28 | > 2. 第二个参数的"0x"表示输入密文为十六进制,"0b"表示输入的密文为二进制。 29 | > 3. 第三个参数的"0x"表示解密后的明文以十六进制返回,"0b"表示明文以二进制返回。 30 | 31 | string enpt="0123456789abcdeffedcba9876543210"; 32 | string plain=aes.decrypt(enpt,"0x","0x"); 33 | 34 | 35 | ## 附注: 36 | > 1. example.cpp中提供了一个使用AES模块加密和解密的完整示例。AES example.txt中提供了一个AES加密的"明文-密文-密钥"实例。 37 | > 2. 本模块的明文/密文/密钥输入必须是32位长的十六进制或者128位长的二进制,其他如字符串需要首先转化为十六进制或者二进制再输入。 38 | > 3. 若需要进行任意长度的字符串加密,请右转至本库的Pattern模块: 39 | 该模块整合了DES,AES两种分组密码,支持任意长度的字符串输入,并且支持以ECB, CBC, CFB, OFB, CTR五种工作模式进行加密和解密。 40 | -------------------------------------------------------------------------------- /DAA/DAA example.txt: -------------------------------------------------------------------------------- 1 | 原消息:"abc" 2 | 原消息在内存中的十六进制格式(也是本DAA算法的输入):616263 3 | 原始密钥:"abcdefgh" 4 | 原始密钥的十六进制格式(也是本DAA算法的输入):616263646566768 5 | DAA消息认证码结果:fcfbce44f212da7e 6 | -------------------------------------------------------------------------------- /DAA/DAA.h: -------------------------------------------------------------------------------- 1 | /***************************************************************** 2 | *Module Name: DAA 3 | *Module Date: 2018-12-03 4 | *Module Auth: pzh 5 | *AEScription: Simple DAA module for get DAA Mac 6 | *****************************************************************/ 7 | 8 | #include "DES.h" 9 | 10 | using namespace std; 11 | 12 | class DAA 13 | { 14 | public: 15 | string getDac(string input,string key,string inmode,string outmode);//DAA: 该方法实现基于分组密码DES的MAC——DAA数据认证算法 16 | 17 | private: 18 | string hexToBinary(string input); //hexToBinary: 十六进制输入转换为二进制 19 | string binToHexto(string input); //binToHexto: 二进制输入转换为十六进制 20 | string XOR(string a,string b); //XOR: 对两个等长二进制字符串进行异或运算 21 | }; 22 | 23 | 24 | /********************* public functions *************************/ 25 | 26 | /*1. 27 | *getDac: 该方法实现基于分组密码DES的MAC——DAA数据认证算法 28 | *Param: input--输入16位十六进制原始消息,key--输入16位十六进制原始密钥,长度需要调用者进行判断 29 | *Return: output--十六进制DAA消息提取结果 30 | */ 31 | string DAA::getDac(string input,string key,string inmode,string outmode) 32 | { 33 | //1. 将十六进制的原始消息和密钥转化为二进制形式 34 | input=(inmode=="0x")?hexToBinary(input):input; 35 | key=(inmode=="0x")?hexToBinary(key):key; 36 | 37 | //2. 判断当前的原始消息长度是否为64的整数倍,若不是则首先将原始消息使用0在右侧填充至长度为64的整数倍 38 | while(input.size()%64!=0) 39 | { 40 | input.push_back('0'); 41 | } 42 | 43 | //3. 将填充后的消息以64位作为一个分组进行划分 44 | int partsize=input.size()/64; 45 | string inputlis[partsize]; 46 | for(int i=0;i dic; //十六进制数到二进制数的转换表 81 | dic['0']="0000"; dic['1']="0001"; dic['2']="0010"; dic['3']="0011"; dic['4']="0100"; dic['5']="0101"; dic['6']="0110"; dic['7']="0111"; dic['8']="1000"; dic['9']="1001"; dic['A']="1010"; dic['B']="1011"; dic['C']="1100"; dic['D']="1101"; dic['E']="1110"; dic['F']="1111";dic['a']="1010"; dic['b']="1011"; dic['c']="1100"; dic['d']="1101"; dic['e']="1110"; dic['f']="1111"; 82 | 83 | string output; 84 | for(int i=0;i redic; //二进制数到十六进制数的转换表 99 | redic["0000"]="0"; redic["0001"]="1"; redic["0010"]="2"; redic["0011"]="3"; redic["0100"]="4"; redic["0101"]="5"; redic["0110"]="6"; redic["0111"]="7"; redic["1000"]="8"; redic["1001"]="9"; redic["1010"]="a"; redic["1011"]="b"; redic["1100"]="c"; redic["1101"]="d"; redic["1110"]="e"; redic["1111"]="f"; 100 | 101 | string output; 102 | for(int i=0;i 9 | #include 10 | #include 11 | #include 12 | #include 13 | 14 | using namespace std; 15 | 16 | class DES 17 | { 18 | public: 19 | DES(); //DES: 默认构造函数 20 | void key(string key, string mode); //key: 设定密钥 21 | string encrypt(string input, string inmode, string outmode); //encrypt: DES加密 22 | string decrypt(string input, string inmode, string outmode); //decrypt: DES解密 23 | string getkey(string mode); //getkey:获取当前密钥 24 | private: 25 | 26 | int __plain[64], __enpt[64], __key[64]; //plain, enpt, key: 最近的明文和密文,密钥 27 | bool __flag; 28 | 29 | string hexToBinary(string input); //hexToBinary: 十六进制输入转换为二进制 30 | string binToHexto(string input); //binToHexto: 二进制输入转换为十六进制 31 | void ipSub(const int input[64], int output[64]); //ipSub: IP置换 32 | void eSub(const int input[32], int output[48]); //eSub: E扩展置换 33 | void shiftBinary(int lis[56], int num); //shiftBinary: 循环左移 34 | void keySub(int roll_no, const int input[64],int output[48]); //keySub: 密钥置换 35 | void sSub(const int input[48], int output[32]); //sSub: S盒代替 36 | void pSub(const int input[32], int output[32]); //pSub: P盒代替 37 | void ipReSub(const int input[64], int output[64]); //ipReSub: IP逆置换 38 | void roleDES(const int leftinput[32],const int rightinput[32],int leftoutput[32],int rightoutput[32],int rolekey[48]); //roleDES:单轮DES加密 39 | void _DES(int input[64],int output[64],int key[64]); //_DES: 底层DES加密实现 40 | void _deDES(int input[64],int output[64],int key[64]); //_deDES: 底层DES解密实现 41 | }; 42 | 43 | /********************* public functions *************************/ 44 | 45 | /*0. 46 | *DES: 类默认初始化函数 47 | */ 48 | DES::DES() 49 | { 50 | __flag=false; 51 | } 52 | 53 | /*1. 54 | *key: 该方法设定DES加密密钥 55 | *Param: input--无前缀十六进制或者二进制输入, mode--'0b'指示二进制输入,'0x'指示十六进制输入 56 | */ 57 | void DES::key(string key, string mode) 58 | { 59 | __flag=true; 60 | if(mode=="0x") 61 | key=hexToBinary(key); 62 | for(int i=0;i dic; //十六进制数到二进制数的转换表 149 | dic['0']="0000"; dic['1']="0001"; dic['2']="0010"; dic['3']="0011"; dic['4']="0100"; dic['5']="0101"; dic['6']="0110"; dic['7']="0111"; dic['8']="1000"; dic['9']="1001"; dic['A']="1010"; dic['B']="1011"; dic['C']="1100"; dic['D']="1101"; dic['E']="1110"; dic['F']="1111";dic['a']="1010"; dic['b']="1011"; dic['c']="1100"; dic['d']="1101"; dic['e']="1110"; dic['f']="1111"; 150 | 151 | string output; 152 | for(int i=0;i redic; //二进制数到十六进制数的转换表 167 | redic["0000"]="0"; redic["0001"]="1"; redic["0010"]="2"; redic["0011"]="3"; redic["0100"]="4"; redic["0101"]="5"; redic["0110"]="6"; redic["0111"]="7"; redic["1000"]="8"; redic["1001"]="9"; redic["1010"]="a"; redic["1011"]="b"; redic["1100"]="c"; redic["1101"]="d"; redic["1110"]="e"; redic["1111"]="f"; 168 | 169 | string output; 170 | for(int i=0;i=0;k--) 324 | { 325 | output[i*4+k]=res%2; 326 | res/=2; 327 | } 328 | } 329 | return; 330 | } 331 | 332 | /*8. 333 | *pSub: 该方法进行P盒置换 334 | *Param: input--32位S盒代替后的结果输入,output--32位P盒置换结果输出 335 | */ 336 | void DES::pSub(const int input[32],int output[32]) 337 | { 338 | //首先制作P盒 339 | int P_box[32]={16,7,20,21,29,12,28,17,1,15,23,26,5,18,31,10,2,8,24,14,32,27,3,9,19,13,30,6,22,11,4,25}; 340 | //然后使用P盒对32位输入进行P盒置换,得到32位输出 341 | for(int i=0;i<32;i++) 342 | { 343 | output[i]=input[P_box[i]-1]; 344 | } 345 | return; 346 | } 347 | 348 | /*9. 349 | *ipReSub: 该方法进行IP逆置换 350 | *Param: input--32位输入,output--32位IP逆置换结果输出 351 | */ 352 | void DES::ipReSub(const int input[64],int output[64]) 353 | { 354 | //首先生成IP置换表 355 | int REIP_lis[64]={40,8,48,16,56,24,64,32,39,7,47,15,55,23,63,31,38,6,46,14,54,22,62,30,37,5,45,13,53,21,61,29,36,4,44,12,52,20,60,28,35,3,43,11,51,19,59,27,34,2,42,10,50,18,58,26,33,1,41,9,49,17,57,25}; 356 | //然后根据IP逆置换表进行IP逆置换 357 | for(int i=0;i<64;i++) 358 | { 359 | output[i]=input[REIP_lis[i]-1]; 360 | } 361 | return; 362 | } 363 | 364 | /*10. 365 | *roleDES: 该方法进行单轮DES加密 366 | *Param: leftinput--32位左半部分原文输入,rightinput--32位右半部分原文输入,leftoutput--32位左半部分原文输出,rightoutput--32位右半部分原文输出,key--当前轮的48位密钥 367 | */ 368 | void DES::roleDES(const int leftinput[32],const int rightinput[32],int leftoutput[32],int rightoutput[32],int rolekey[48]) 369 | { 370 | //首先计算左半部分输出,左半部分输出就是右半部分输入 371 | for(int i=0;i<32;i++) 372 | { 373 | leftoutput[i]=rightinput[i]; 374 | } 375 | //然后计算右半部分输出,这部分按照如下几个步骤完成 376 | //1.对原始的32位右半部分输入作E扩展置换,扩展为48位 377 | int rightinput_2[48]; 378 | eSub(rightinput,rightinput_2); 379 | //2.将48位的E扩展置换结果rightinput_2与当前轮的密钥进行异或操作 380 | int rightinput_3[48]; 381 | for(int i=0;i<48;i++) 382 | { 383 | rightinput_3[i]=rightinput_2[i]^rolekey[i]; 384 | } 385 | //3.将异或结果依次进行S盒代替以及P盒置换 386 | int rightinput_4[32]; 387 | sSub(rightinput_3,rightinput_4); //问题在此 388 | int rightinput_5[32]; 389 | pSub(rightinput_4,rightinput_5); 390 | //4.将两轮代替以及置换后的结果再和左半部分输入leftinput进行异或操作 391 | int rightinput_6[32]; 392 | for(int i=0;i<32;i++) 393 | { 394 | rightinput_6[i]=rightinput_5[i]^leftinput[i]; 395 | } 396 | //5.rightinput_6就是最终的右半部分输出结果 397 | for(int i=0;i<32;i++) 398 | { 399 | rightoutput[i]=rightinput_6[i]; 400 | } 401 | } 402 | 403 | /*11. 404 | *DES:该方法进行DES加密 405 | *Param:input--64位明文输入,output--64位密文输出,key--64位DES加密原始密钥(其中56位有效,其余位数作为奇偶校验位) 406 | */ 407 | void DES::_DES(int input[64],int output[64],int key[64]) 408 | { 409 | //1.将原始明文进行IP置换 410 | int input_2[64]; 411 | ipSub(input,input_2); 412 | //2.将原始明文分拆为左右两部分,进行16轮的DES单轮加密,最后再将得到的左右两部分合并 413 | int leftinput[32],rightinput[32],leftoutput[32],rightoutput[32],rolekey[48]; 414 | for(int i=0;i<64;i++) 415 | { 416 | if(i>=0&&i<32) 417 | leftinput[i]=input_2[i]; 418 | else 419 | rightinput[i-32]=input_2[i]; 420 | } 421 | for(int i=1;i<=16;i++) 422 | { 423 | //首先生成当前轮的密钥 424 | keySub(i,key,rolekey); 425 | //利用当前轮密钥进行加密 426 | roleDES(leftinput,rightinput,leftoutput,rightoutput,rolekey); 427 | //然后令leftinput=leftoutput,rightinput=rightoutput,准备进行下一轮迭代 428 | for(int i=0;i<32;i++) 429 | { 430 | leftinput[i]=leftoutput[i]; 431 | rightinput[i]=rightoutput[i]; 432 | } 433 | } 434 | //最后一轮得到的leftoutput和rightoutput即为得到的密文 435 | //3.对得到的两个32位密文互换位置后合并,然后进行IP逆置换,即得到最终加密的密文结果output 436 | int tempres[64]; 437 | for(int i=0;i<64;i++) 438 | { 439 | if(i>=0&&i<32) 440 | tempres[i]=rightoutput[i]; 441 | else 442 | tempres[i]=leftoutput[i-32]; 443 | } 444 | ipReSub(tempres,output); 445 | return; 446 | } 447 | 448 | /*12. 449 | *deDES: 该方法进行DES解密 450 | *Param: input--64位密文输入,output--64位明文输出,key--64位DES加密原始密钥 451 | */ 452 | void DES::_deDES(int input[64],int output[64],int key[64]) 453 | { 454 | //1.将原始明文进行IP置换 455 | int input_2[64]; 456 | ipSub(input,input_2); 457 | //2.将原始明文分拆为左右两部分,进行16轮的DES单轮加密,最后再将得到的左右两部分合并 458 | int leftinput[32],rightinput[32],leftoutput[32],rightoutput[32],rolekey[48]; 459 | for(int i=0;i<64;i++) 460 | { 461 | if(i>=0&&i<32) 462 | leftinput[i]=input_2[i]; 463 | else 464 | rightinput[i-32]=input_2[i]; 465 | } 466 | for(int i=16;i>=1;i--) 467 | { 468 | //首先生成当前轮的密钥 469 | keySub(i,key,rolekey); //DES解密时需要反向使用密钥 470 | //利用当前轮密钥进行加密 471 | roleDES(leftinput,rightinput,leftoutput,rightoutput,rolekey); 472 | //然后令leftinput=leftoutput,rightinput=rightoutput,准备进行下一轮迭代 473 | for(int i=0;i<32;i++) 474 | { 475 | leftinput[i]=leftoutput[i]; 476 | rightinput[i]=rightoutput[i]; 477 | } 478 | } 479 | //最后一轮得到的leftoutput和rightoutput即为得到的密文 480 | //3.对得到的两个32位密文互换位置后合并,然后进行IP逆置换,即得到最终加密的密文结果output 481 | int tempres[64]; 482 | for(int i=0;i<64;i++) 483 | { 484 | if(i>=0&&i<32) 485 | tempres[i]=rightoutput[i]; 486 | else 487 | tempres[i]=leftoutput[i-32]; 488 | } 489 | ipReSub(tempres,output); 490 | return; 491 | } 492 | -------------------------------------------------------------------------------- /DAA/example.cpp: -------------------------------------------------------------------------------- 1 | #include "DAA.h" 2 | 3 | using namespace std; 4 | 5 | int main(void) 6 | { 7 | string plain="616263"; 8 | string key="6162636465666768"; 9 | string enpt; 10 | 11 | DAA daa=DAA(); 12 | enpt=daa.getDac(plain,key,"0x","0x"); 13 | 14 | cout<<"DAA result: "< 1. getDac方法的第一个参数为十六进制或者二进制原始消息。 11 | > 2. 第二个参数为十六进制或者二进制密钥 12 | > 3. 第三个参数的"0x"表示输入的原始消息为十六进制,"0b"表示输入的原始消息为二进制。 13 | > 4. 第四个参数的"0x"表示消息认证码结果以十六进制返回,"0b"表示消息认证码结果以二进制返回。 14 | 15 | string plain="616263"; 16 | string key="6162636465666768"; 17 | enpt=daa.getDac(plain,key,"0x","0x"); 18 | 19 | 20 | ## 附注: 21 | > 1. example.cpp中提供了一个使用DAA获得消息认证码的完整示例。DAA example.txt中提供了一个DAA的"原消息-密钥-DAA消息认证码"实例。 22 | > 2. 本模块的明文输入必须是长度不限的十六进制或者二进制,密钥受DES加密算法限制,必须为64位二进制或者16位十六进制密钥,其他如字符串需要首先转化为十六进制或者二进制再输入。 23 | > 3. 若需要直接获得字符串的消息认证码,请左转至本库的macCenter模块: 24 | 该模块整合了HMAC(md5,sha512),DAA消息认证码,支持任意长度的字符串作为输入。 25 | 26 | -------------------------------------------------------------------------------- /DES/DES example.txt: -------------------------------------------------------------------------------- 1 | 以下均为明文和密文在内存中的十六进制形式 2 | 明文:02468aceeca86420 3 | 密钥:0f1571c947d9e859 4 | 密文:da02ce3a89ecac3b 5 | -------------------------------------------------------------------------------- /DES/DES.h: -------------------------------------------------------------------------------- 1 | /***************************************************************** 2 | *Module Name: DES 3 | *Module Date: 2018-11-28 4 | *Module Auth: pzh 5 | *Description: Simple DES module for single DES-64 encrypt 6 | *****************************************************************/ 7 | 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | 14 | using namespace std; 15 | 16 | class DES 17 | { 18 | public: 19 | DES(); //DES: 默认构造函数 20 | void key(string key, string mode); //key: 设定密钥 21 | string encrypt(string input, string inmode, string outmode); //encrypt: DES加密 22 | string decrypt(string input, string inmode, string outmode); //decrypt: DES解密 23 | string getkey(string mode); //getkey:获取当前密钥 24 | private: 25 | 26 | int __plain[64], __enpt[64], __key[64]; //plain, enpt, key: 最近的明文和密文,密钥 27 | bool __flag; 28 | 29 | string hexToBinary(string input); //hexToBinary: 十六进制输入转换为二进制 30 | string binToHexto(string input); //binToHexto: 二进制输入转换为十六进制 31 | void ipSub(const int input[64], int output[64]); //ipSub: IP置换 32 | void eSub(const int input[32], int output[48]); //eSub: E扩展置换 33 | void shiftBinary(int lis[56], int num); //shiftBinary: 循环左移 34 | void keySub(int roll_no, const int input[64],int output[48]); //keySub: 密钥置换 35 | void sSub(const int input[48], int output[32]); //sSub: S盒代替 36 | void pSub(const int input[32], int output[32]); //pSub: P盒代替 37 | void ipReSub(const int input[64], int output[64]); //ipReSub: IP逆置换 38 | void roleDES(const int leftinput[32],const int rightinput[32],int leftoutput[32],int rightoutput[32],int rolekey[48]); //roleDES:单轮DES加密 39 | void _DES(int input[64],int output[64],int key[64]); //_DES: 底层DES加密实现 40 | void _deDES(int input[64],int output[64],int key[64]); //_deDES: 底层DES解密实现 41 | }; 42 | 43 | /********************* public functions *************************/ 44 | 45 | /*0. 46 | *DES: 类默认初始化函数 47 | */ 48 | DES::DES() 49 | { 50 | __flag=false; 51 | } 52 | 53 | /*1. 54 | *key: 该方法设定DES加密密钥 55 | *Param: input--无前缀十六进制或者二进制输入, mode--'0b'指示二进制输入,'0x'指示十六进制输入 56 | */ 57 | void DES::key(string key, string mode) 58 | { 59 | __flag=true; 60 | if(mode=="0x") 61 | key=hexToBinary(key); 62 | for(int i=0;i dic; //十六进制数到二进制数的转换表 149 | dic['0']="0000"; dic['1']="0001"; dic['2']="0010"; dic['3']="0011"; dic['4']="0100"; dic['5']="0101"; dic['6']="0110"; dic['7']="0111"; dic['8']="1000"; dic['9']="1001"; dic['A']="1010"; dic['B']="1011"; dic['C']="1100"; dic['D']="1101"; dic['E']="1110"; dic['F']="1111";dic['a']="1010"; dic['b']="1011"; dic['c']="1100"; dic['d']="1101"; dic['e']="1110"; dic['f']="1111"; 150 | 151 | string output; 152 | for(int i=0;i redic; //二进制数到十六进制数的转换表 167 | redic["0000"]="0"; redic["0001"]="1"; redic["0010"]="2"; redic["0011"]="3"; redic["0100"]="4"; redic["0101"]="5"; redic["0110"]="6"; redic["0111"]="7"; redic["1000"]="8"; redic["1001"]="9"; redic["1010"]="a"; redic["1011"]="b"; redic["1100"]="c"; redic["1101"]="d"; redic["1110"]="e"; redic["1111"]="f"; 168 | 169 | string output; 170 | for(int i=0;i=0;k--) 324 | { 325 | output[i*4+k]=res%2; 326 | res/=2; 327 | } 328 | } 329 | return; 330 | } 331 | 332 | /*8. 333 | *pSub: 该方法进行P盒置换 334 | *Param: input--32位S盒代替后的结果输入,output--32位P盒置换结果输出 335 | */ 336 | void DES::pSub(const int input[32],int output[32]) 337 | { 338 | //首先制作P盒 339 | int P_box[32]={16,7,20,21,29,12,28,17,1,15,23,26,5,18,31,10,2,8,24,14,32,27,3,9,19,13,30,6,22,11,4,25}; 340 | //然后使用P盒对32位输入进行P盒置换,得到32位输出 341 | for(int i=0;i<32;i++) 342 | { 343 | output[i]=input[P_box[i]-1]; 344 | } 345 | return; 346 | } 347 | 348 | /*9. 349 | *ipReSub: 该方法进行IP逆置换 350 | *Param: input--32位输入,output--32位IP逆置换结果输出 351 | */ 352 | void DES::ipReSub(const int input[64],int output[64]) 353 | { 354 | //首先生成IP置换表 355 | int REIP_lis[64]={40,8,48,16,56,24,64,32,39,7,47,15,55,23,63,31,38,6,46,14,54,22,62,30,37,5,45,13,53,21,61,29,36,4,44,12,52,20,60,28,35,3,43,11,51,19,59,27,34,2,42,10,50,18,58,26,33,1,41,9,49,17,57,25}; 356 | //然后根据IP逆置换表进行IP逆置换 357 | for(int i=0;i<64;i++) 358 | { 359 | output[i]=input[REIP_lis[i]-1]; 360 | } 361 | return; 362 | } 363 | 364 | /*10. 365 | *roleDES: 该方法进行单轮DES加密 366 | *Param: leftinput--32位左半部分原文输入,rightinput--32位右半部分原文输入,leftoutput--32位左半部分原文输出,rightoutput--32位右半部分原文输出,key--当前轮的48位密钥 367 | */ 368 | void DES::roleDES(const int leftinput[32],const int rightinput[32],int leftoutput[32],int rightoutput[32],int rolekey[48]) 369 | { 370 | //首先计算左半部分输出,左半部分输出就是右半部分输入 371 | for(int i=0;i<32;i++) 372 | { 373 | leftoutput[i]=rightinput[i]; 374 | } 375 | //然后计算右半部分输出,这部分按照如下几个步骤完成 376 | //1.对原始的32位右半部分输入作E扩展置换,扩展为48位 377 | int rightinput_2[48]; 378 | eSub(rightinput,rightinput_2); 379 | //2.将48位的E扩展置换结果rightinput_2与当前轮的密钥进行异或操作 380 | int rightinput_3[48]; 381 | for(int i=0;i<48;i++) 382 | { 383 | rightinput_3[i]=rightinput_2[i]^rolekey[i]; 384 | } 385 | //3.将异或结果依次进行S盒代替以及P盒置换 386 | int rightinput_4[32]; 387 | sSub(rightinput_3,rightinput_4); //问题在此 388 | int rightinput_5[32]; 389 | pSub(rightinput_4,rightinput_5); 390 | //4.将两轮代替以及置换后的结果再和左半部分输入leftinput进行异或操作 391 | int rightinput_6[32]; 392 | for(int i=0;i<32;i++) 393 | { 394 | rightinput_6[i]=rightinput_5[i]^leftinput[i]; 395 | } 396 | //5.rightinput_6就是最终的右半部分输出结果 397 | for(int i=0;i<32;i++) 398 | { 399 | rightoutput[i]=rightinput_6[i]; 400 | } 401 | } 402 | 403 | /*11. 404 | *DES:该方法进行DES加密 405 | *Param:input--64位明文输入,output--64位密文输出,key--64位DES加密原始密钥(其中56位有效,其余位数作为奇偶校验位) 406 | */ 407 | void DES::_DES(int input[64],int output[64],int key[64]) 408 | { 409 | //1.将原始明文进行IP置换 410 | int input_2[64]; 411 | ipSub(input,input_2); 412 | //2.将原始明文分拆为左右两部分,进行16轮的DES单轮加密,最后再将得到的左右两部分合并 413 | int leftinput[32],rightinput[32],leftoutput[32],rightoutput[32],rolekey[48]; 414 | for(int i=0;i<64;i++) 415 | { 416 | if(i>=0&&i<32) 417 | leftinput[i]=input_2[i]; 418 | else 419 | rightinput[i-32]=input_2[i]; 420 | } 421 | for(int i=1;i<=16;i++) 422 | { 423 | //首先生成当前轮的密钥 424 | keySub(i,key,rolekey); 425 | //利用当前轮密钥进行加密 426 | roleDES(leftinput,rightinput,leftoutput,rightoutput,rolekey); 427 | //然后令leftinput=leftoutput,rightinput=rightoutput,准备进行下一轮迭代 428 | for(int i=0;i<32;i++) 429 | { 430 | leftinput[i]=leftoutput[i]; 431 | rightinput[i]=rightoutput[i]; 432 | } 433 | } 434 | //最后一轮得到的leftoutput和rightoutput即为得到的密文 435 | //3.对得到的两个32位密文互换位置后合并,然后进行IP逆置换,即得到最终加密的密文结果output 436 | int tempres[64]; 437 | for(int i=0;i<64;i++) 438 | { 439 | if(i>=0&&i<32) 440 | tempres[i]=rightoutput[i]; 441 | else 442 | tempres[i]=leftoutput[i-32]; 443 | } 444 | ipReSub(tempres,output); 445 | return; 446 | } 447 | 448 | /*12. 449 | *deDES: 该方法进行DES解密 450 | *Param: input--64位密文输入,output--64位明文输出,key--64位DES加密原始密钥 451 | */ 452 | void DES::_deDES(int input[64],int output[64],int key[64]) 453 | { 454 | //1.将原始明文进行IP置换 455 | int input_2[64]; 456 | ipSub(input,input_2); 457 | //2.将原始明文分拆为左右两部分,进行16轮的DES单轮加密,最后再将得到的左右两部分合并 458 | int leftinput[32],rightinput[32],leftoutput[32],rightoutput[32],rolekey[48]; 459 | for(int i=0;i<64;i++) 460 | { 461 | if(i>=0&&i<32) 462 | leftinput[i]=input_2[i]; 463 | else 464 | rightinput[i-32]=input_2[i]; 465 | } 466 | for(int i=16;i>=1;i--) 467 | { 468 | //首先生成当前轮的密钥 469 | keySub(i,key,rolekey); //DES解密时需要反向使用密钥 470 | //利用当前轮密钥进行加密 471 | roleDES(leftinput,rightinput,leftoutput,rightoutput,rolekey); 472 | //然后令leftinput=leftoutput,rightinput=rightoutput,准备进行下一轮迭代 473 | for(int i=0;i<32;i++) 474 | { 475 | leftinput[i]=leftoutput[i]; 476 | rightinput[i]=rightoutput[i]; 477 | } 478 | } 479 | //最后一轮得到的leftoutput和rightoutput即为得到的密文 480 | //3.对得到的两个32位密文互换位置后合并,然后进行IP逆置换,即得到最终加密的密文结果output 481 | int tempres[64]; 482 | for(int i=0;i<64;i++) 483 | { 484 | if(i>=0&&i<32) 485 | tempres[i]=rightoutput[i]; 486 | else 487 | tempres[i]=leftoutput[i-32]; 488 | } 489 | ipReSub(tempres,output); 490 | return; 491 | } 492 | -------------------------------------------------------------------------------- /DES/example.cpp: -------------------------------------------------------------------------------- 1 | #include "DES.h" 2 | #include 3 | #include 4 | 5 | using namespace std; 6 | 7 | int main(void) 8 | { 9 | string plain="02468aceeca86420"; 10 | string key="0f1571c947d9e859"; 11 | string enpt; 12 | 13 | DES des=DES(); 14 | des.key(key,"0x"); 15 | 16 | enpt=des.encrypt(plain,"0x","0x"); 17 | cout<<"encrypt result: "< 1. key方法的第一个参数为16位十六进制或者64位二进制密钥。 11 | > 2. 第二个参数的"0x"表示密钥为十六进制,"0b"表示密钥为二进制。 12 | 13 | string key="0f1571c947d9e859"; 14 | des.key(key,"0x"); 15 | 16 | 17 | ## 4. 使用encrypt方法进行DES加密。 18 | > 1. encrypt方法的第一个参数为16位十六进制或者64位二进制明文。 19 | > 2. 第二个参数的"0x"表示输入明文为十六进制,"0b"表示输入的明文为二进制。 20 | > 3. 第三个参数的"0x"表示加密后的密文以十六进制返回,"0b"表示密文以二进制返回。 21 | 22 | string plain="02468aceeca86420"; 23 | string enpt=des.encrypt(plain,"0x","0x"); 24 | 25 | 26 | ## 5. 使用decrypt方法进行DES解密。 27 | > 1. decrypt方法的第一个参数为16位十六进制或者64位二进制密文。 28 | > 2. 第二个参数的"0x"表示输入密文为十六进制,"0b"表示输入的密文为二进制。 29 | > 3. 第三个参数的"0x"表示解密后的明文以十六进制返回,"0b"表示明文以二进制返回。 30 | 31 | string enpt="02468aceeca86420"; 32 | string plain=des.decrypt(enpt,"0x","0x"); 33 | 34 | 35 | ## 附注: 36 | > 1. example.cpp中提供了一个使用DES模块加密和解密的完整示例。DES example.txt中提供了一个DES加密的"明文-密文-密钥"实例。 37 | > 2. 本模块的明文/密文/密钥输入必须是16位长的十六进制或者64位长的二进制,其他如字符串需要首先转化为十六进制或者二进制再输入。 38 | > 3. 若需要进行任意长度的字符串加密,请右转至本库的Pattern模块: 39 | 该模块整合了DES,AES两种分组密码,支持任意长度的字符串输入,并且支持以ECB, CBC, CFB, OFB, CTR五种工作模式进行加密和解密。 40 | -------------------------------------------------------------------------------- /Diffie-Hellman/DH.py: -------------------------------------------------------------------------------- 1 | import math 2 | import random 3 | 4 | class DeffieHellman: 5 | def __init__(self): 6 | self.q=0 #公开参数:所选择的素数 7 | self.a=0 #公开参数:本原根 8 | self.Y=0 #公开参数:公钥Y 9 | self.__X=0 #私密参数:私钥X 10 | 11 | 12 | # private function 13 | def __fastExpMod(self, b, e, m): 14 | ''' 15 | : __fastExpMod: 快速幂取模算法 16 | : Param: b,e,m--对应于幂取模运算式b^e mod m中对应参数 17 | : Return: 幂取模运算式b^e mod m的计算结果 18 | ''' 19 | result = 1 20 | while e != 0: 21 | if (e&1) == 1: 22 | result = (result * b) % m 23 | e >>= 1 24 | b = (b*b) % m 25 | return result 26 | 27 | def __primeArray(self,r): 28 | ''' 29 | : __primeArray:该方法生成范围在[0,r]内的素数表 30 | : Param: r--素数表上界 31 | : Return: 范围在[0,r]内的素数表 32 | ''' 33 | prime=[0 for i in range(r+1)] 34 | lis=[] 35 | for i in range(2,r+1): 36 | if prime[i]==0: 37 | lis.append(i) 38 | for j in lis: 39 | if i*j>r: 40 | break 41 | prime[i*j]=1 42 | if i%j==0: 43 | break 44 | return lis 45 | 46 | def __primeGenerate(self,limits): 47 | ''' 48 | : __primeGenerate: 该方法从生成的素数表中随机筛选一个素数 49 | : Param: limits--随机筛选素数的素数表上界 50 | : Return: p--随机筛选的在上界内的素数 51 | ''' 52 | a= self.__primeArray(limits) #生成一定范围内的素数表 53 | p = random.choice(a) #随机从素数表中筛选出一个素数 54 | return p 55 | 56 | def __getPrimitive(self,p): 57 | ''' 58 | : __getPrimitive: 该方法计算给定的素数的随机的一个本原根 59 | : Param: p--给定的素数 60 | : Return: res--给定的素数的一个随机筛选出的本原根 61 | ''' 62 | testset=set([i for i in range(1,p)]) 63 | res=[] 64 | for i in range(1,p): 65 | tempset=[] 66 | for k in range(1,p): 67 | tempset.append(self.__fastExpMod(i,k,p)) 68 | if set(tempset)==testset: 69 | res.append(i) 70 | return random.choice(res) 71 | 72 | # public functions 73 | def generateArg(self): 74 | ''' 75 | : generateArg: 随机生成共享参数——素数q和素数q的本原根a 76 | : Param: 无 77 | : Return: 密钥交换共享参数(q,a)——素数q和素数q的一个本原根a 78 | ''' 79 | #1. 首先随机选定一个素数q,并且计算出该素数的本原根a 80 | self.q=self.__primeGenerate(1000) 81 | self.a=self.__getPrimitive(self.q) 82 | return (self.q, self.a) 83 | 84 | def generateKey(self,q,a): 85 | ''' 86 | : generateKey: 根据密钥双方的共享参数q和a,随机生成自己的私钥X,并计算出自己的公钥Y 87 | : Param: q, a--密钥交换双方的共享参数q和a 88 | : Return: X--密钥交换中自己一方的公钥 89 | ''' 90 | #1. 随机选择一个小于q的随机数X作为密钥交换中自己一方的私钥 91 | self.q=q 92 | self.a=a 93 | self.__X=random.randint(0,self.q-1) 94 | #2. 根据私钥X,共享参数a和q,计算出Y作为密钥交换中自己一方的公钥 95 | self.Y=self.__fastExpMod(self.a,self.__X,self.q) 96 | return self.Y 97 | 98 | def publish(self): 99 | ''' 100 | : publish: 公开自己一方的素数q,本原根a,以及公钥Y 101 | : Param: 无 102 | : Return: 素数q,本原根a,以及公钥Y 103 | ''' 104 | return (self.q,self.a,self.Y) 105 | 106 | def getKey(self,Y): 107 | ''' 108 | : getKey: 计算真实的共享密钥key 109 | : Param: 密钥交换中另一方的公钥Y 110 | : Return: 共享密钥key 111 | ''' 112 | key=self.__fastExpMod(Y,self.__X,self.q) 113 | return key 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | -------------------------------------------------------------------------------- /Diffie-Hellman/example.py: -------------------------------------------------------------------------------- 1 | import DH 2 | 3 | if __name__ == "__main__": 4 | # 1. 初始化密钥交换的双方A和B 5 | A = DH.DeffieHellman() 6 | B = DH.DeffieHellman() 7 | 8 | # 2. 密钥交换双方的其中一方A生成共享参数——素数q及其本原根a 9 | q, a = A.generateArg() 10 | 11 | # 3. 密钥交换的双方A,B利用上述素数q和本原根a生成各自的公钥和私钥,并共享A,B各自的公钥Ya,Yb 12 | Ya = A.generateKey(q,a) 13 | Yb = B.generateKey(q,a) 14 | 15 | # 4. 输出双方的共享参数q, a,以及双方各自的公钥Ya,Yb 16 | (qa, aa, Ya) = A.publish() 17 | (qb, ab, Yb) = B.publish() 18 | print("A的公开参数q = ",qa) 19 | print("A的公开参数a = ",aa) 20 | print("A的公钥Ya = ",Ya) 21 | print("B的公开参数q = ",qb) 22 | print("B的公开参数a = ",ab) 23 | print("B的公钥Yb = ",Yb) 24 | 25 | # 5. A根据公钥Yb计算出共享密钥并输出 26 | keya=A.getKey(Yb) 27 | print("A计算出的共享密钥为: ",keya) 28 | 29 | # 6. B根据公钥Ya计算出共享密钥并输出 30 | keyb=B.getKey(Ya) 31 | print("B计算出的共享密钥为: ",keyb) -------------------------------------------------------------------------------- /Diffie-Hellman/readme.md: -------------------------------------------------------------------------------- 1 | # Diffie-Hellman密钥交换模块 2 | 3 | ## 1. 引用头文件"DH.py" 4 | import DH 5 | 6 | ## 2. 创建两个DeffieHellman对象A和B,作为密钥交换的两方 7 | A = DH.DeffieHellman() 8 | B = DH.DeffieHellman() 9 | 10 | ## 3. 由其中的一方A调用generateArg成员方法,生成Diffie-Hellman密钥交换的共享参数——素数q及其本原根a 11 | > 1. generateArg成员方法返回生成的DH密钥交换的公共参数(q,a) 12 | 13 | q, a = A.generateArg() 14 | 15 | 16 | ## 4. 密钥交换的双方A和B,共享上述素数q和本原根a,根据共享参数q和a,调用generateKey成员方法生成各自的公钥和私钥,并共享A,B各自的公钥Ya,Yb 17 | > 1. generateKey成员方法的两个参数依次为共享参数——素数q和本原根a 18 | > 2. 返回值为生成的公钥 19 | 20 | Ya = A.generateKey(q,a) 21 | Yb = B.generateKey(q,a) 22 | 23 | ## 5. 双方根据对方的公钥,调用getKey成员方法计算出共享密钥并输出 24 | > 1. getKey成员方法的唯一参数是密钥交换中另一方的公钥 25 | > 2. 返回值为共享的真实密钥 26 | 27 | keya=A.getKey(Yb) 28 | keyb=B.getKey(Ya) 29 | 30 | ## 附注: 31 | > 1. example.py中提供了一个使用DH密钥交换模块的示例程序。 32 | 33 | 34 | -------------------------------------------------------------------------------- /Elgamel/Elgamel.py: -------------------------------------------------------------------------------- 1 | import math 2 | import random 3 | 4 | class Elgamel: 5 | def __init__(self): 6 | self.q=0 #公开参数:所选择的素数 7 | self.a=0 #公开参数:本原根 8 | self.Y=0 #公开参数:公钥Y 9 | self.__X=0 #私密参数:私钥X 10 | self.__key=0 #私密参数:密钥key 11 | self.__plain=0 #私密参数:明文 12 | self.__crpt=(0,0) #私密参数:密文 13 | 14 | def __fastExpMod(self, b, e, m): 15 | ''' 16 | : __fastExpMod: 快速幂取模算法 17 | : Param: b,e,m--对应于幂取模运算式b^e mod m中对应参数 18 | : Return: 幂取模运算式b^e mod m的计算结果 19 | ''' 20 | result = 1 21 | while e != 0: 22 | if (e&1) == 1: 23 | result = (result * b) % m 24 | e >>= 1 25 | b = (b*b) % m 26 | return result 27 | 28 | def __primeArray(self,r): 29 | ''' 30 | : __primeArray: 该方法生成范围在[0,r]内的素数表 31 | : Param: r--素数表上界 32 | : Return: 范围在[0,r]内的素数表 33 | ''' 34 | prime=[0 for i in range(r+1)] 35 | lis=[] 36 | for i in range(2,r+1): 37 | if prime[i]==0: 38 | lis.append(i) 39 | for j in lis: 40 | if i*j>r: 41 | break 42 | prime[i*j]=1 43 | if i%j==0: 44 | break 45 | return lis 46 | 47 | def __primeGenerate(self,limits): 48 | ''' 49 | : __primeGenerate: 该方法从生成的素数表中随机筛选一个素数 50 | : Param: limits--随机筛选素数的素数表上界 51 | : Return: p--随机筛选的在上界内的素数 52 | ''' 53 | a= self.__primeArray(limits) #生成一定范围内的素数表 54 | p = random.choice(a) #随机从素数表中筛选出一个素数 55 | return p 56 | 57 | def __getPrimitive(self,p): 58 | ''' 59 | : __getPrimitive: 该方法计算给定的素数的随机的一个本原根 60 | : Param: p--给定的素数 61 | : Return: res--给定的素数的一个随机筛选出的本原根 62 | ''' 63 | testset=set([i for i in range(1,p)]) 64 | res=[] 65 | for i in range(1,p): 66 | tempset=[] 67 | for k in range(1,p): 68 | tempset.append(self.__fastExpMod(i,k,p)) 69 | if set(tempset)==testset: 70 | res.append(i) 71 | return random.choice(res) 72 | 73 | def __ext_euclid(self,a, b): 74 | ''' 75 | : __ext_euclid: 扩展欧几里得算法 76 | ''' 77 | a1 = max(a, b) 78 | b1 = min(a, b) 79 | return self.__ext_algorithm(a1, b1) 80 | 81 | def __ext_algorithm(self,a, b): 82 | ''' 83 | : __ext_algorithm: 扩展欧几里得算法 84 | ''' 85 | if b == 0: 86 | return (1, 0, a) 87 | x2, y2, gcd = self.__ext_euclid(b, a % b) 88 | tmp = x2 89 | x1 = y2 90 | y1 = tmp - int(a/b)*y2 91 | return (x1, y1, gcd) 92 | 93 | def sendClient(self,q,a,Y): 94 | ''' 95 | : sendClient: 发送方A初始化 96 | : Param: 接收方B的公开参数——素数q,本原根a,公钥Y 97 | : Return: 无 98 | : Comment: 本方法为发送方,作用为初始化发送方A——设置从接收方获得的基本公开参数q,a,Y 99 | ''' 100 | #1. 发送方设置基本公共参数 101 | self.q=q 102 | self.a=a 103 | self.Y=Y 104 | return 105 | 106 | def receiveClient(self): 107 | ''' 108 | : receiveClient: 接收方B初始化 109 | : Param: 无 110 | : Return: 公开参数(q,a,Y) 111 | : Comment: 本方法为接收方操作,作用为初始化接收方B——选定素数q以及本原根a,并选定私钥X,从而计算出收发双方共享公钥Y,并返回公开参数(q,a,Y)给发送方 112 | ''' 113 | #1. 密钥接收方首先随机选定一个素数q,并且计算出该素数的本原根a 114 | self.q=self.__primeGenerate(1000) 115 | self.a=self.__getPrimitive(self.q) 116 | #2. 密钥发送方随机选择一个小于q的随机数X作为私钥 117 | self.__X=random.randint(0,self.q-1) 118 | #3. 密钥发送方计算出Ya作为公钥 119 | self.Y=self.__fastExpMod(self.a,self.__X,self.q) 120 | return (self.q,self.a,self.Y) 121 | 122 | def publish(self): 123 | ''' 124 | : publish: 发送方A/接收方B公开公开参数——素数q,本原根a,以及公钥Y 125 | : Param: 无 126 | : Return: 素数q,本原根a,以及公钥Y 127 | ''' 128 | return (self.q,self.a,self.Y) 129 | 130 | def encrypt(self,plain): 131 | ''' 132 | : encrypt: 发送方A加密信息 133 | : Param: plain--明文信息 134 | : Return: 加密后的密文对 135 | : Comment: 本方法为发送方操作 136 | ''' 137 | #1. 随机选定整数k 1. 首先使用Elgamel类的默认初始化函数初始化Elgamel 8 | > 2. 使用类的receiveClient方法将对象设置为接收方对象,receiveClient方法将生成Elgamel体系中的共享参数q, a, Y,并根据这些共享参数将对象设置为接收方对象: 9 | >> 参数列表:空; 返回值:(q, a, Y),即生成的Elgamel密码体系中的由收发双方共享的参数 10 | > 3. 使用类的sendClient方法将对象设置为发送方对象,sendClient方法根据接收方设定的共享参数将对象设置为发送方对象。 11 | >> 参数列表: 3个参数依次为q, a, Y,这些参数由接收方调用的receiveClient方法返回; 返回值:空 12 | 13 | A = El.Elgamel() 14 | B = El.Elgamel() 15 | 16 | q, a, Y = B.receiveClient() 17 | A.sendClient(q,a,Y) 18 | 19 | ## 3. 使用encrypt方法进行Elgamel加密 20 | > 1. encrypt方法的参数为不大于共享参数q的十进制整数明文M 21 | > 2. 返回值为加密后的密文对(C1, C2),其中C1, C2均为十进制整数 22 | 23 | crpt = A.encrypt(plain) 24 | 25 | 26 | ## 4. 使用decipher方法进行Elgamel解密 27 | > 1. decrypt方法的参数为Elgamel密文对(C1, C2) 28 | > 2. 返回值为解密后的十进制整数明文和加密密钥key的元组(M, key) 29 | 30 | plain = B.decipher(crpt) 31 | print("明文 = ", plain[0]) 32 | print("密钥 = ", plain[1]) 33 | 34 | ## 附注: 35 | > 1. example.py中提供了一个使用DES模块加密和解密的完整示例。 36 | 37 | -------------------------------------------------------------------------------- /HMAC/HMAC example.txt: -------------------------------------------------------------------------------- 1 | 输入:616263 2 | 密钥:616263 3 | SHA-512 HMAC结果:1a97e05c35e6727690dfdf2e8079b34fefabf15236abc9170dccdcf5623e4c5ce72a446842bd7607186c9e3f21c0a0edf6ab6c5ec8304a1f969c20c1455e9b7c 4 | -------------------------------------------------------------------------------- /HMAC/HMAC.h: -------------------------------------------------------------------------------- 1 | /***************************************************************** 2 | *Module Name: HMAC(SHA512) 3 | *Module Date: 2018-12-01 4 | *Module Auth: pzh 5 | *Description: Simple HMAC module using SHA-512 hashing 6 | *****************************************************************/ 7 | 8 | #include "SHA512.h" 9 | #include "MD5.h" 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | 19 | using namespace std; 20 | 21 | class HMAC 22 | { 23 | public: 24 | string getMac(string input,string key,string mode,string informat,string outformat); //getMac: 获得基于SHA-512或者MD5 Hash函数的HMAC消息认证码 25 | 26 | private: 27 | string hexToBinary(string input); //hexToBinary: 十六进制输入转换为二进制 28 | string binToHexto(string input); //binToHexto: 二进制输入转换为十六进制 29 | string XOR(string a,string b); //XOR:对两个等长二进制字符串进行异或运算 30 | }; 31 | 32 | 33 | 34 | /********************* public functions *************************/ 35 | 36 | /*1. 37 | *getMac: 使用SHA-512 Hash函数实现的HMAC消息认证码 38 | *Param: input--原始十六进制消息输入,output--原始十六进制密钥输入 39 | *Return: output--十六进制HMAC消息认证码 40 | */ 41 | string HMAC::getMac(string input,string key,string mode,string informat,string outformat) 42 | { 43 | SHA512 sha512; 44 | MD5 md5; 45 | 46 | //1.将输入的原始信息input和原始密钥key由十六进制序列转化为二进制序列 47 | input=(informat=="0x")?hexToBinary(input):input; 48 | key=(informat=="0x")?hexToBinary(key):key; 49 | 50 | //2.密钥长度变换: 51 | //若原始密钥key长度大于SHA-512分组长度1024位,则将key作为输入送入SHA-512 Hash算法,得到的512位Hash结果再在左侧进行添0,得到的1024位结果作为新的密钥值;若原始密钥key的长度小于1024,则直接在右侧(教材有误)进行添0,得到的1024结果作为新的密钥值 52 | if(key.size()>1024) 53 | key=(mode=="sha512")?sha512.hash(key,"0b","0b"):md5.hash(key,"0b","0b"); 54 | string fill(1024-key.size(),'0'); 55 | key=key+fill; 56 | 57 | //3.生成1024位常量ipad,opad 58 | string ipad,opad; 59 | for(int i=0;i<1024/8;i++) 60 | { 61 | ipad+="00110110"; 62 | opad+="01011100"; 63 | } 64 | 65 | //4.计算tempres=H[(K^ipad)||M] 66 | string tempres=XOR(key,ipad)+input; 67 | tempres=(mode=="sha512")?sha512.hash(tempres,"0b","0b"):md5.hash(tempres,"0b","0b"); 68 | 69 | //5.计算res=H[(K^opad)||tempres],res即为最终的SHA-512 HMAC消息认证码 70 | string res=XOR(key,opad)+tempres; 71 | res=(mode=="sha512")?sha512.hash(res,"0b","0b"):md5.hash(res,"0b","0b"); 72 | res=(outformat=="0x")?binToHexto(res):res; 73 | 74 | return res; 75 | } 76 | 77 | 78 | 79 | /********************* private functions ************************/ 80 | 81 | /*1. 82 | *hexToBinary: 该方法将十六进制字符串转化为二进制字符串(均不含前缀) 83 | *Param: input--无前缀十六进制输入 84 | *Return:output--无前缀二进制输出 85 | */ 86 | string HMAC::hexToBinary(string input) 87 | { 88 | map dic; //十六进制数到二进制数的转换表 89 | dic['0']="0000"; dic['1']="0001"; dic['2']="0010"; dic['3']="0011"; dic['4']="0100"; dic['5']="0101"; dic['6']="0110"; dic['7']="0111"; dic['8']="1000"; dic['9']="1001"; dic['A']="1010"; dic['B']="1011"; dic['C']="1100"; dic['D']="1101"; dic['E']="1110"; dic['F']="1111";dic['a']="1010"; dic['b']="1011"; dic['c']="1100"; dic['d']="1101"; dic['e']="1110"; dic['f']="1111"; 90 | 91 | string output; 92 | for(int i=0;i redic; //二进制数到十六进制数的转换表 107 | redic["0000"]="0"; redic["0001"]="1"; redic["0010"]="2"; redic["0011"]="3"; redic["0100"]="4"; redic["0101"]="5"; redic["0110"]="6"; redic["0111"]="7"; redic["1000"]="8"; redic["1001"]="9"; redic["1010"]="a"; redic["1011"]="b"; redic["1100"]="c"; redic["1101"]="d"; redic["1110"]="e"; redic["1111"]="f"; 108 | 109 | string output; 110 | for(int i=0;i 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | 17 | using namespace std; 18 | 19 | class MD5 20 | { 21 | public: 22 | MD5(); //DES: 默认构造函数 23 | string hash(string input, string inmode, string outmode); //hash: 进行MD5 Hash,返回MD5 Hash结果 24 | private: 25 | 26 | unsigned int __plain, __enpt; //__plain: 原始消息; __enpt: MD5 Hash结果 27 | 28 | string hexToBinary(string input); //hexToBinary: 十六进制输入转换为二进制 29 | string binToHexto(string input); //binToHexto: 二进制输入转换为十六进制 30 | void print(unsigned int input); //print: 将unsigned int类型以32位二进制的形式输出 31 | string convert(unsigned int input); //convert: 将unsigned int类型以32位二进制的形式字符串转化 32 | string fillString(string input); //fillString: 对原始输入的二进制序列进行填充,填充到长度size符合size%512==448,然后附加一个64位的填充前长度值序列 33 | void initDepart(string input,vector &output); //initDepart: 该方法将N*512位的二进制字符串拆分为若干512位的字符串数组 34 | void departString(string input,unsigned int output[16]); //departString: 将512位的二进制序列输入拆分为16个32位二进制的unsigned int类型x序列 35 | unsigned int cycleLeftShift(unsigned int a,unsigned int b); //cycleLeftShift: 实现循环左移 36 | unsigned int F(unsigned int x,unsigned int y,unsigned int z); //F: 非线性函数F 37 | unsigned int G(unsigned int x,unsigned int y,unsigned int z); //G: 非线性函数G 38 | unsigned int H(unsigned int x,unsigned int y,unsigned int z); //H: 非线性函数H 39 | unsigned int I(unsigned int x,unsigned int y,unsigned int z); //I: 非线性函数I 40 | unsigned int FF(unsigned int &a,unsigned int b,unsigned int c ,unsigned int d ,unsigned int Mj,unsigned int s,unsigned int ti); //FF: 复合操作函数FF 41 | unsigned int GG(unsigned int &a,unsigned int b,unsigned int c ,unsigned int d ,unsigned int Mj,unsigned int s,unsigned int ti); //GG: 复合操作函数GG 42 | unsigned int HH(unsigned int &a,unsigned int b,unsigned int c ,unsigned int d ,unsigned int Mj,unsigned int s,unsigned int ti); //HH: 复合操作函数HH 43 | unsigned int II(unsigned int &a,unsigned int b,unsigned int c ,unsigned int d ,unsigned int Mj,unsigned int s,unsigned int ti); //HH: 复合操作函数II 44 | string _MD5(string user_input); //_MD5:MD5 Hash底层实现函数 45 | }; 46 | 47 | /********************* public functions *************************/ 48 | 49 | /*0. 50 | *MD5: 类默认初始化函数 51 | */ 52 | MD5::MD5() 53 | { 54 | } 55 | 56 | /*2. 57 | *hash: 该方法进行MD5 Hash,返回MD5 Hash结果 58 | *Param: input--无前缀十六进制或者二进制原始信息输入, inmode--'0b'指示以二进制形式输入,'0x'指示以十六进制形式输入,outmode--'0b'指示以二进制形式输出,'0x'指示以十六进制形式输出 59 | *Return: 无前缀十六进制或者二进制Hash结果输出 60 | */ 61 | string MD5::hash(string input, string inmode, string outmode) 62 | { 63 | input=(inmode=="0x")?hexToBinary(input):input; 64 | string res=_MD5(input); 65 | res=(outmode=="0x")?binToHexto(res):res; 66 | 67 | return res; 68 | } 69 | 70 | 71 | /********************* private functions ************************/ 72 | 73 | /*1. 74 | *hexToBinary: 该方法将十六进制字符串转化为二进制字符串(均不含前缀) 75 | *Param: input--无前缀十六进制输入 76 | *Return:output--无前缀二进制输出 77 | */ 78 | string MD5::hexToBinary(string input) 79 | { 80 | map dic; //十六进制数到二进制数的转换表 81 | dic['0']="0000"; dic['1']="0001"; dic['2']="0010"; dic['3']="0011"; dic['4']="0100"; dic['5']="0101"; dic['6']="0110"; dic['7']="0111"; dic['8']="1000"; dic['9']="1001"; dic['A']="1010"; dic['B']="1011"; dic['C']="1100"; dic['D']="1101"; dic['E']="1110"; dic['F']="1111";dic['a']="1010"; dic['b']="1011"; dic['c']="1100"; dic['d']="1101"; dic['e']="1110"; dic['f']="1111"; 82 | 83 | string output; 84 | for(int i=0;i redic; //二进制数到十六进制数的转换表 99 | redic["0000"]="0"; redic["0001"]="1"; redic["0010"]="2"; redic["0011"]="3"; redic["0100"]="4"; redic["0101"]="5"; redic["0110"]="6"; redic["0111"]="7"; redic["1000"]="8"; redic["1001"]="9"; redic["1010"]="a"; redic["1011"]="b"; redic["1100"]="c"; redic["1101"]="d"; redic["1110"]="e"; redic["1111"]="f"; 100 | 101 | string output; 102 | for(int i=0;i=0;i--) 122 | { 123 | cout<<((input>>i)&1); 124 | } 125 | } 126 | 127 | /*4. 128 | *convert: 该方法将unsigned int类型以32位二进制的形式字符串转化 129 | *Param: input--需要输出的unsigned int类型数字 130 | */ 131 | string MD5::convert(unsigned int input) 132 | { 133 | //这里使用的算法非常经典,通过不断移位来输出每一个二进制位,需要特别注意该种方法,移位的执行效率是非常之高的 134 | string res; 135 | for(int i=31;i>=0;i--) 136 | { 137 | res.push_back(((input>>i)&1)+'0'); 138 | } 139 | return res; 140 | } 141 | 142 | /*5. 143 | *fillString: 该方法对原始输入的二进制序列进行填充,填充到长度size符合size%512==448,然后附加一个64位的填充前长度值序列 144 | *Param: input--输入二进制序列。返回值:string类型--填充后的二进制序列 145 | */ 146 | string MD5::fillString(string input) 147 | { 148 | //1.首先判断是否需要进行填充,需要填充的情况下进行填充 149 | int osize=input.size(); 150 | if(osize%512!=448) 151 | { 152 | //1.1对于需要填充的情况,第一次填充1,后续每一次填充0,迭代操作直到长度size符合要求为止 153 | input.push_back('1'); 154 | while(input.size()%512!=448) 155 | { 156 | input.push_back('0'); 157 | } 158 | } 159 | //2.在符合条件的序列后添加一个64位二进制序列表示输入二进制序列在填充前的长度值 160 | string nums="0000000000000000000000000000000000000000000000000000000000000000"; 161 | //2.1首先将原输入字符串长度转化为16进制字符串 162 | char temp_str[10000]; 163 | sprintf(temp_str,"%x",osize); 164 | string temp(temp_str); 165 | temp=hexToBinary(temp_str); 166 | for(int i=0;i &output) 179 | { 180 | int size=(input.size()+1)/512; 181 | for(int i=0;i=0;k--) 205 | { 206 | for(int m=0;m<8;m++) 207 | { 208 | temp.push_back(input[i*32+k*8+m]); 209 | } 210 | } 211 | //然后将字符串转化为unsigned int类型 212 | output[i]=strtoul(temp.c_str(),0,2); //string转unsigned int常使用内置strtoul来进行快速实现,当然也可以自行实现 213 | } 214 | return; 215 | } 216 | 217 | /*8. 218 | *cycleLeftShift: 实现循环左移 219 | *Param: a--待移位数,b--移位数 220 | *Return: 移位结果 221 | */ 222 | unsigned int MD5::cycleLeftShift(unsigned int a,unsigned int b) 223 | { 224 | unsigned int res=a<>(32-b); //再将a进行右移32-b位得到a的前b位,即结果2,最后再将结果1和结果2进行或操作进行合并 226 | return res; 227 | } 228 | 229 | /*9. 230 | *4个非线性函数F,G,H,I的实现 231 | */ 232 | //非线性函数F 233 | unsigned int MD5::F(unsigned int x,unsigned int y,unsigned int z) 234 | { 235 | return (x&y)|((~x)&z); 236 | } 237 | 238 | //非线性函数G 239 | unsigned int MD5::G(unsigned int x,unsigned int y,unsigned int z) 240 | { 241 | return (x&z)|(y&(~z)); 242 | } 243 | 244 | //非线性函数H 245 | unsigned int MD5::H(unsigned int x,unsigned int y,unsigned int z) 246 | { 247 | return x^y^z; 248 | } 249 | 250 | //非线性函数I 251 | unsigned int MD5::I(unsigned int x,unsigned int y,unsigned int z) 252 | { 253 | return y^(x|(~z)); 254 | } 255 | 256 | /*10. 257 | *4个复合操作函数FF,GG,HH,II的实现 258 | *Comment: 需要特别注意,MD5使用复合操作函数的过程中,会改变各个参数的值后作为下一次使用复合函数的输入,因此输入参数a需要使用引用形式,且其中的移位为循环左移位 259 | */ 260 | //复合操作函数FF 261 | unsigned int MD5::FF(unsigned int &a,unsigned int b,unsigned int c ,unsigned int d ,unsigned int Mj,unsigned int s,unsigned int ti) 262 | { 263 | a = b + cycleLeftShift( (a + F(b,c,d) + Mj + ti), s); 264 | } 265 | 266 | //复合操作函数GG 267 | unsigned int MD5::GG(unsigned int &a,unsigned int b,unsigned int c ,unsigned int d ,unsigned int Mj,unsigned int s,unsigned int ti) 268 | { 269 | a = b + cycleLeftShift( (a + G(b,c,d) + Mj + ti), s); 270 | } 271 | 272 | //复合操作函数HH 273 | unsigned int MD5::HH(unsigned int &a,unsigned int b,unsigned int c ,unsigned int d ,unsigned int Mj,unsigned int s,unsigned int ti) 274 | { 275 | a = b + cycleLeftShift( (a + H(b,c,d) + Mj + ti), s); 276 | } 277 | 278 | //复合操作函数II 279 | unsigned int MD5::II(unsigned int &a,unsigned int b,unsigned int c ,unsigned int d ,unsigned int Mj,unsigned int s,unsigned int ti) 280 | { 281 | a = b + cycleLeftShift( (a + I(b,c,d) + Mj + ti), s); 282 | } 283 | 284 | /*11. 285 | *MD5: 该方法用户输入字符串进行MD5核心算法 286 | *Param: user_input--用户字符串输入 287 | *Return: 128位MD5算法结果输出 288 | *Comment: 本处需要严格注意MD5加密过程中所需要使用的参数值 289 | */ 290 | string MD5::_MD5(string user_input) 291 | { 292 | //MD-5加密参量 293 | unsigned int x[16]={}; 294 | unsigned int A=0x67452301; 295 | unsigned int B=0xefcdab89; 296 | unsigned int C=0x98badcfe; 297 | unsigned int D=0x10325476; 298 | //首先将用户输入的字符串进行填充,并以512为一组进行分组 299 | user_input=fillString(user_input); 300 | vector lis; 301 | initDepart(user_input,lis); 302 | //cout<=0;m--) 409 | { 410 | user_output.push_back(((A>>(k*8+m))&1)+'0'); 411 | } 412 | } 413 | for(int k=0;k<4;k++) 414 | { 415 | for(int m=7;m>=0;m--) 416 | { 417 | user_output.push_back(((B>>(k*8+m))&1)+'0'); 418 | } 419 | } 420 | for(int k=0;k<4;k++) 421 | { 422 | for(int m=7;m>=0;m--) 423 | { 424 | user_output.push_back(((C>>(k*8+m))&1)+'0'); 425 | } 426 | } 427 | for(int k=0;k<4;k++) 428 | { 429 | for(int m=7;m>=0;m--) 430 | { 431 | user_output.push_back(((D>>(k*8+m))&1)+'0'); 432 | } 433 | } 434 | return user_output; 435 | } -------------------------------------------------------------------------------- /HMAC/SHA512.h: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | using namespace std; 11 | 12 | class SHA512 13 | { 14 | public: 15 | SHA512(); //SHA512: 默认构造函数 16 | string hash(string input, string inmode, string outmode); //hash: 进行SHA512 Hash,返回SHA512 Hash结果 17 | private: 18 | 19 | unsigned int __plain, __enpt; //__plain: 原始消息; __enpt: SHA512 Hash结果 20 | 21 | string hexToBinary(string input); //hexToBinary: 十六进制输入转换为二进制 22 | string binToHexto(string input); //binToHexto: 二进制输入转换为十六进制 23 | void print(unsigned long long int input); //print: 将unsigned int类型以32位二进制的形式输出 24 | string convert(unsigned long long int input); //convert: 将unsigned int类型以32位二进制的形式字符串转化 25 | string fillString(string input); //fillString: 该方法对原始输入的二进制序列进行填充 26 | 27 | void initDepart(string input,vector &output); //initDepart: 该方法将N*1024位的二进制字符串拆分为若干1024位的字符串数组 28 | 29 | // SHA-512在轮函数F中使用的4个复合操作函数 30 | unsigned long long int cycleRightShift(unsigned long long int a,unsigned long long int b); //cycleRightShift:实现循环右移 31 | unsigned long long int Ch(unsigned long long int e,unsigned long long int f,unsigned long long int g); //Ch: 复合操作函数Ch 32 | unsigned long long int Maj(unsigned long long int a,unsigned long long int b,unsigned long long int c); //Maj: 复合操作函数Maj 33 | unsigned long long int Sigma0(unsigned long long int a); //Sigma0: 复合操作函数Sigma0 34 | unsigned long long int Sigma1(unsigned long long int e); //Sigma1: 复合操作函数Sigma1 35 | 36 | void F(unsigned long long int &a,unsigned long long int &b,unsigned long long int &c,unsigned long long int &d,unsigned long long int &e,unsigned long long int &f,unsigned long long int &g,unsigned long long int &h,unsigned long long int Wi,unsigned long long int Ki); //F: SHA-512的单轮函数F 37 | 38 | // SHA-512的在消息扩展中所使用的2个复合操作函数 39 | unsigned long long int Theta0(unsigned long long int x); //Theta0: 复合操作函数Theta0 40 | unsigned long long int Theta1(unsigned long long int x); //Theta1: 复合操作函数Theta1 41 | 42 | void FExtended(string input,unsigned long long int output[80]);//FExtended:该方法为轮函数进行消息扩展操作 43 | string _SHA512(string input); //_SHA512: SHA-512 Hash算法底层实现方法 44 | }; 45 | 46 | 47 | /**********************************public functions********************************************/ 48 | 49 | /*0. 50 | *SHA512: 类默认初始化函数 51 | */ 52 | SHA512::SHA512() 53 | { 54 | } 55 | 56 | /*2. 57 | *hash: 该方法进行SHA512 Hash,返回SHA512 Hash结果 58 | *Param: input--无前缀十六进制或者二进制原始信息输入, inmode--'0b'指示以二进制形式输入,'0x'指示以十六进制形式输入,outmode--'0b'指示以二进制形式输出,'0x'指示以十六进制形式输出 59 | *Return: 无前缀十六进制或者二进制Hash结果输出 60 | */ 61 | string SHA512::hash(string input, string inmode, string outmode) 62 | { 63 | input=(inmode=="0b")?binToHexto(input):input; 64 | string res=_SHA512(input); 65 | res=(outmode=="0b")?hexToBinary(res):res; 66 | 67 | return res; 68 | } 69 | 70 | 71 | /**********************************private functions*******************************************/ 72 | 73 | /*1. 74 | *hexToBinary: 该方法将十六进制字符串转化为二进制字符串(均不含前缀) 75 | *Param: input--无前缀十六进制输入 76 | *Return: output--无前缀二进制输出 77 | */ 78 | string SHA512::hexToBinary(string input) 79 | { 80 | map dic; //十六进制数到二进制数的转换表 81 | dic['0']="0000"; dic['1']="0001"; dic['2']="0010"; dic['3']="0011"; dic['4']="0100"; dic['5']="0101"; dic['6']="0110"; dic['7']="0111"; dic['8']="1000"; dic['9']="1001"; dic['A']="1010"; dic['B']="1011"; dic['C']="1100"; dic['D']="1101"; dic['E']="1110"; dic['F']="1111";dic['a']="1010"; dic['b']="1011"; dic['c']="1100"; dic['d']="1101"; dic['e']="1110"; dic['f']="1111"; 82 | 83 | string output; 84 | for(int i=0;i redic; //二进制数到十六进制数的转换表 99 | redic["0000"]="0"; redic["0001"]="1"; redic["0010"]="2"; redic["0011"]="3"; redic["0100"]="4"; redic["0101"]="5"; redic["0110"]="6"; redic["0111"]="7"; redic["1000"]="8"; redic["1001"]="9"; redic["1010"]="a"; redic["1011"]="b"; redic["1100"]="c"; redic["1101"]="d"; redic["1110"]="e"; redic["1111"]="f"; 100 | 101 | string output; 102 | for(int i=0;i=0;i--) 122 | { 123 | cout<<((input>>i)&1); 124 | } 125 | } 126 | 127 | /*4. 128 | *convert: 该方法将unsigned long long int类型以64位二进制的形式字符串转化 129 | *Param: input--需要输出的unsigned long long int类型数字 130 | *Return:二进制字符串化的输入值input 131 | */ 132 | string SHA512::convert(unsigned long long int input) 133 | { 134 | //这里使用的算法非常经典,通过不断移位来输出每一个二进制位,需要特别注意该种方法,移位的执行效率是非常之高的 135 | string res; 136 | for(int i=63;i>=0;i--) 137 | { 138 | res.push_back(((input>>i)&1)+'0'); 139 | } 140 | return res; 141 | } 142 | 143 | /*5. 144 | *fillString:该方法对原始输入的二进制序列进行填充,填充到长度size符合size%1024==896,然后附加一个128位的填充前长度值序列 145 | *Param:input--输入二进制序列。返回值:string类型--填充后的二进制序列 146 | */ 147 | string SHA512::fillString(string input) 148 | { 149 | //1.首先判断是否需要进行填充,需要填充的情况下进行填充 150 | int osize=input.size(); 151 | if(osize%1024!=896) 152 | { 153 | //1.1对于需要填充的情况,第一次填充1,后续每一次填充0,迭代操作直到长度size符合要求为止 154 | input.push_back('1'); 155 | while(input.size()%1024!=896) 156 | { 157 | input.push_back('0'); 158 | } 159 | } 160 | //2.在符合条件的序列后添加一个128位二进制序列表示输入二进制序列在填充前的长度值 161 | string nums(128,'0'); 162 | //2.1首先将原输入字符串长度转化为16进制字符串 163 | char temp_str[10000]; 164 | sprintf(temp_str,"%x",osize); 165 | string temp(temp_str); 166 | temp=hexToBinary(temp_str); 167 | int m=128-temp.size(); 168 | for(int i=0;i &output) 181 | { 182 | int size=input.size()/1024; 183 | for(int i=0;i>b; //先将a进行右移b位得到结果1 203 | res|=a<<(64-b); //再将a进行左移64-b位得到a的后b位,即结果2,最后再将结果1和结果2进行或操作进行合并 204 | return res; 205 | } 206 | 207 | /*8. 208 | *SHA-512的4个复合操作函数 209 | */ 210 | //复合操作函数Ch 211 | unsigned long long int SHA512::Ch(unsigned long long int e,unsigned long long int f,unsigned long long int g) 212 | { 213 | return (e&f)^((~e)&g); 214 | } 215 | 216 | //复合操作函数Maj 217 | unsigned long long int SHA512::Maj(unsigned long long int a,unsigned long long int b,unsigned long long int c) 218 | { 219 | return (a&b)^(a&c)^(b&c); 220 | } 221 | 222 | //复合操作函数Sigma0 223 | unsigned long long int SHA512::Sigma0(unsigned long long int a) 224 | { 225 | return cycleRightShift(a,28)^cycleRightShift(a,34)^cycleRightShift(a,39); 226 | } 227 | 228 | //复合操作函数Sigma1 229 | unsigned long long int SHA512::Sigma1(unsigned long long int e) 230 | { 231 | return cycleRightShift(e,14)^cycleRightShift(e,18)^cycleRightShift(e,41); 232 | } 233 | 234 | /*9. 235 | *F: SHA-512的单轮函数F 236 | *Param: a,b,c,d,e,f,g,h--Hash变量,Wi--64位消息扩展得到的子消息,Ki--轮常量 237 | */ 238 | void SHA512::F(unsigned long long int &a,unsigned long long int &b,unsigned long long int &c,unsigned long long int &d,unsigned long long int &e,unsigned long long int &f,unsigned long long int &g,unsigned long long int &h,unsigned long long int Wi,unsigned long long int Ki) 239 | { 240 | unsigned long long int T1=h+Ch(e,f,g)+Sigma1(e)+Wi+Ki; 241 | unsigned long long int T2=Sigma0(a)+Maj(a,b,c); 242 | h=g; 243 | g=f; 244 | f=e; 245 | e=d+T1; 246 | d=c; 247 | c=b; 248 | b=a; 249 | a=T1+T2; 250 | return; 251 | } 252 | 253 | /*10. 254 | *SHA-512的轮常数 255 | */ 256 | const unsigned long long int Ki[80]= {//80个常数 257 | 0x428a2f98d728ae22ULL, 0x7137449123ef65cdULL, 0xb5c0fbcfec4d3b2fULL, 258 | 0xe9b5dba58189dbbcULL, 0x3956c25bf348b538ULL, 0x59f111f1b605d019ULL, 259 | 0x923f82a4af194f9bULL, 0xab1c5ed5da6d8118ULL, 0xd807aa98a3030242ULL, 260 | 0x12835b0145706fbeULL, 0x243185be4ee4b28cULL, 0x550c7dc3d5ffb4e2ULL, 261 | 0x72be5d74f27b896fULL, 0x80deb1fe3b1696b1ULL, 0x9bdc06a725c71235ULL, 262 | 0xc19bf174cf692694ULL, 0xe49b69c19ef14ad2ULL, 0xefbe4786384f25e3ULL, 263 | 0x0fc19dc68b8cd5b5ULL, 0x240ca1cc77ac9c65ULL, 0x2de92c6f592b0275ULL, 264 | 0x4a7484aa6ea6e483ULL, 0x5cb0a9dcbd41fbd4ULL, 0x76f988da831153b5ULL, 265 | 0x983e5152ee66dfabULL, 0xa831c66d2db43210ULL, 0xb00327c898fb213fULL, 266 | 0xbf597fc7beef0ee4ULL, 0xc6e00bf33da88fc2ULL, 0xd5a79147930aa725ULL, 267 | 0x06ca6351e003826fULL, 0x142929670a0e6e70ULL, 0x27b70a8546d22ffcULL, 268 | 0x2e1b21385c26c926ULL, 0x4d2c6dfc5ac42aedULL, 0x53380d139d95b3dfULL, 269 | 0x650a73548baf63deULL, 0x766a0abb3c77b2a8ULL, 0x81c2c92e47edaee6ULL, 270 | 0x92722c851482353bULL, 0xa2bfe8a14cf10364ULL, 0xa81a664bbc423001ULL, 271 | 0xc24b8b70d0f89791ULL, 0xc76c51a30654be30ULL, 0xd192e819d6ef5218ULL, 272 | 0xd69906245565a910ULL, 0xf40e35855771202aULL, 0x106aa07032bbd1b8ULL, 273 | 0x19a4c116b8d2d0c8ULL, 0x1e376c085141ab53ULL, 0x2748774cdf8eeb99ULL, 274 | 0x34b0bcb5e19b48a8ULL, 0x391c0cb3c5c95a63ULL, 0x4ed8aa4ae3418acbULL, 275 | 0x5b9cca4f7763e373ULL, 0x682e6ff3d6b2b8a3ULL, 0x748f82ee5defb2fcULL, 276 | 0x78a5636f43172f60ULL, 0x84c87814a1f0ab72ULL, 0x8cc702081a6439ecULL, 277 | 0x90befffa23631e28ULL, 0xa4506cebde82bde9ULL, 0xbef9a3f7b2c67915ULL, 278 | 0xc67178f2e372532bULL, 0xca273eceea26619cULL, 0xd186b8c721c0c207ULL, 279 | 0xeada7dd6cde0eb1eULL, 0xf57d4f7fee6ed178ULL, 0x06f067aa72176fbaULL, 280 | 0x0a637dc5a2c898a6ULL, 0x113f9804bef90daeULL, 0x1b710b35131c471bULL, 281 | 0x28db77f523047d84ULL, 0x32caab7b40c72493ULL, 0x3c9ebe0a15c9bebcULL, 282 | 0x431d67c49c100d4cULL, 0x4cc5d4becb3e42b6ULL, 0x597f299cfc657e2aULL, 283 | 0x5fcb6fab3ad6faecULL, 0x6c44198c4a475817ULL, 284 | }; 285 | 286 | /*11. 287 | *SHA-512的在消息扩展中所使用的2个复合操作函数 288 | */ 289 | //复合操作函数Theta0 290 | unsigned long long int SHA512::Theta0(unsigned long long int x) 291 | { 292 | return cycleRightShift(x,1)^cycleRightShift(x,8)^(x>>7); 293 | } 294 | 295 | //复合操作函数Theta1 296 | unsigned long long int SHA512::Theta1(unsigned long long int x) 297 | { 298 | return cycleRightShift(x,19)^cycleRightShift(x,61)^(x>>6); 299 | } 300 | 301 | /*12. 302 | *FExtended: 该方法为轮函数进行消息扩展操作,具体而言,该方法将1024位的二进制序列输入拆分为80个64位二进制的unsigned long long int类型x序列 303 | *Param: input--1024位输入二进制序列,output--16个64位输出二进制序列(即Wi) 304 | *Comment: 需要特别注意,在分拆时需要特别注意大端和小端的问题,为了方便,首先对字符串作变换,然后再将字符串转化为unsigned long long int类型 305 | */ 306 | void SHA512::FExtended(string input,unsigned long long int output[80]) 307 | { 308 | //前16个消息扩展结果Wi即为原1024位消息的16个64位分段 309 | for(int i=0;i<16;i++) 310 | { 311 | string temp; 312 | //首先将字符串作倒装变换 313 | for(int k=0;k<64;k++) 314 | { 315 | temp.push_back(input[i*64+k]); 316 | } 317 | //然后将字符串转化为unsigned long long int类型 318 | output[i]=strtoull(temp.c_str(),0,2); //string转unsigned long long int常使用内置strtoul来进行快速实现,当然也可以自行实现 319 | } 320 | //后续的消息扩展结果Wi使用固定的公式进行递推扩展 321 | for(int i=16;i<80;i++) 322 | { 323 | output[i]=Theta1(output[i-2])+output[i-7]+Theta0(output[i-15])+output[i-16]; 324 | } 325 | return; 326 | } 327 | 328 | /*13. 329 | *_SHA512: 该方法对输入的字符串序列进行SHA-512算法,并返回Hash结果 330 | *Param: input--十六进制输入 331 | *Return: 十六进制SHA-512 Hash结果输出 332 | */ 333 | string SHA512::_SHA512(string input) 334 | { 335 | //1.首先将输入消息input进行消息扩展操作 336 | input=fillString(hexToBinary(input)); //注意首先要将输入的十六进制转化为二进制 337 | vector lis; 338 | initDepart(input,lis); 339 | //2.初始化a,b,c,d,e,f,g,h总共8个轮变量 340 | unsigned long long int a=0x6a09e667f3bcc908ULL,b=0xbb67ae8584caa73bULL,c=0x3c6ef372fe94f82bULL,d=0xa54ff53a5f1d36f1ULL,e=0x510e527fade682d1ULL,f=0x9b05688c2b3e6c1fULL,g=0x1f83d9abfb41bd6bULL,h=0x5be0cd19137e2179ULL; 341 | for(int i=0;i 3 | #include 4 | 5 | using namespace std; 6 | 7 | int main(void) 8 | { 9 | string plain="616263"; 10 | string key="616263"; 11 | string result; 12 | 13 | HMAC hmac=HMAC(); 14 | 15 | result=hmac.getMac(plain,key,"sha512","0x","0x"); 16 | cout<<"sha512 mac result: "< 1. 第一个参数为任意长度的原始十六进制或者二进制消息。 11 | > 2. 第二个参数为任意长度的原始十六进制或者二进制密钥。 12 | > 3. 第三个参数指定生成消息认证码(mac)使用的hash函数,"sha512"指定使用sha512 hash函数,"md5"指定使用md5 hash函数。 13 | > 4. 第四个参数指定输入格式,"0x"表示输入的原始消息为十六进制,"0b"表示输入的原始消息为二进制。 14 | > 5. 第五个参数指定输出格式,"0x"表示生成的消息认证码以十六进制返回,"0b"表示结果以二进制返回。 15 | 16 | string plain="616263"; 17 | string key="616263"; 18 | string result; 19 | 20 | //获取sha512 消息认证码 21 | result=hmac.getMac(plain,key,"sha512","0x","0x"); 22 | cout<<"sha512 mac result: "< 1. example.cpp中提供了一个使用HMAC生成消息认证码(mac)操作的完整示例。HMAC example.txt中提供了一个sha512和md5生成的消息认证码的实例。 31 | > 2. 本模块的原始消息/密钥输入必须是长度不限的十六进制或者二进制,其他如字符串需要首先转化为十六进制或者二进制再输入。 32 | -------------------------------------------------------------------------------- /HashCenter/HashCenter.h: -------------------------------------------------------------------------------- 1 | #include "SHA512.h" 2 | #include "MD5.h" 3 | 4 | using namespace std; 5 | 6 | class HashCenter 7 | { 8 | public: 9 | //public functions 10 | HashCenter(string hashmode); 11 | void reset(string hashmode); 12 | string gethash(string infor, string outmode); 13 | 14 | private: 15 | //private functions 16 | string __convert(string input); 17 | string __hexToBinary(string input); 18 | 19 | //private variables 20 | MD5 __md5; SHA512 __sha512; 21 | string __hashmode; 22 | }; 23 | 24 | /************************** public functions ***************************/ 25 | /*1. 26 | *HashCenter: HashCenter类的默认构造函数 27 | *Param: hashmode--指定hash函数,其值为"SHA512"或者"MD5" 28 | *Return: None 29 | */ 30 | HashCenter::HashCenter(string hashmode) 31 | { 32 | __hashmode=hashmode; 33 | } 34 | 35 | /*2. 36 | *reset: 重新指定hash函数 37 | *Param: hashmode--新的指定hash函数种类,其值为"SHA512"或者"MD5" 38 | *Return: None 39 | */ 40 | void HashCenter::reset(string hashmode) 41 | { 42 | __hashmode=hashmode; 43 | } 44 | 45 | /*3. 46 | *gethash: 获取输入的原始消息的hash值 47 | *Param: infor--需要计算hash值的原始消息;outmode--输出格式,"0x"指定hash结果以十六进制格式输出,"0b"指定hash结果以二进制格式输出 48 | *Return: 原始消息的hash值 49 | */ 50 | string HashCenter::gethash(string infor, string outmode) 51 | { 52 | infor=__convert(infor); 53 | if(__hashmode=="MD5") 54 | return __md5.hash(infor,"0b",outmode); 55 | else 56 | return __sha512.hash(infor,"0b",outmode); 57 | } 58 | 59 | /************************** private functions **************************/ 60 | 61 | /*1. 62 | *__convert: 将用户输入的字符串转化为在内存中的二进制形式 63 | *Param: input--用户输入的,字符串形式的明文,密文或者密钥 64 | *Return: 明文,密文或者密钥在内存中的二进制形式 65 | */ 66 | string HashCenter::__convert(string input) 67 | { 68 | //1. 将用户输入转化为十六进制ASCII码 69 | string res; 70 | char buff[10]; 71 | for(int i=0;i dic; //十六进制数到二进制数的转换表 90 | dic['0']="0000"; dic['1']="0001"; dic['2']="0010"; dic['3']="0011"; dic['4']="0100"; dic['5']="0101"; dic['6']="0110"; dic['7']="0111"; dic['8']="1000"; dic['9']="1001"; dic['A']="1010"; dic['B']="1011"; dic['C']="1100"; dic['D']="1101"; dic['E']="1110"; dic['F']="1111";dic['a']="1010"; dic['b']="1011"; dic['c']="1100"; dic['d']="1101"; dic['e']="1110"; dic['f']="1111"; 91 | 92 | string output; 93 | for(int i=0;i 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | 17 | using namespace std; 18 | 19 | class MD5 20 | { 21 | public: 22 | MD5(); //DES: 默认构造函数 23 | string hash(string input, string inmode, string outmode); //hash: 进行MD5 Hash,返回MD5 Hash结果 24 | private: 25 | 26 | unsigned int __plain, __enpt; //__plain: 原始消息; __enpt: MD5 Hash结果 27 | 28 | string hexToBinary(string input); //hexToBinary: 十六进制输入转换为二进制 29 | string binToHexto(string input); //binToHexto: 二进制输入转换为十六进制 30 | void print(unsigned int input); //print: 将unsigned int类型以32位二进制的形式输出 31 | string convert(unsigned int input); //convert: 将unsigned int类型以32位二进制的形式字符串转化 32 | string fillString(string input); //fillString: 对原始输入的二进制序列进行填充,填充到长度size符合size%512==448,然后附加一个64位的填充前长度值序列 33 | void initDepart(string input,vector &output); //initDepart: 该方法将N*512位的二进制字符串拆分为若干512位的字符串数组 34 | void departString(string input,unsigned int output[16]); //departString: 将512位的二进制序列输入拆分为16个32位二进制的unsigned int类型x序列 35 | unsigned int cycleLeftShift(unsigned int a,unsigned int b); //cycleLeftShift: 实现循环左移 36 | unsigned int F(unsigned int x,unsigned int y,unsigned int z); //F: 非线性函数F 37 | unsigned int G(unsigned int x,unsigned int y,unsigned int z); //G: 非线性函数G 38 | unsigned int H(unsigned int x,unsigned int y,unsigned int z); //H: 非线性函数H 39 | unsigned int I(unsigned int x,unsigned int y,unsigned int z); //I: 非线性函数I 40 | unsigned int FF(unsigned int &a,unsigned int b,unsigned int c ,unsigned int d ,unsigned int Mj,unsigned int s,unsigned int ti); //FF: 复合操作函数FF 41 | unsigned int GG(unsigned int &a,unsigned int b,unsigned int c ,unsigned int d ,unsigned int Mj,unsigned int s,unsigned int ti); //GG: 复合操作函数GG 42 | unsigned int HH(unsigned int &a,unsigned int b,unsigned int c ,unsigned int d ,unsigned int Mj,unsigned int s,unsigned int ti); //HH: 复合操作函数HH 43 | unsigned int II(unsigned int &a,unsigned int b,unsigned int c ,unsigned int d ,unsigned int Mj,unsigned int s,unsigned int ti); //HH: 复合操作函数II 44 | string _MD5(string user_input); //_MD5:MD5 Hash底层实现函数 45 | }; 46 | 47 | /********************* public functions *************************/ 48 | 49 | /*0. 50 | *MD5: 类默认初始化函数 51 | */ 52 | MD5::MD5() 53 | { 54 | } 55 | 56 | /*2. 57 | *hash: 该方法进行MD5 Hash,返回MD5 Hash结果 58 | *Param: input--无前缀十六进制或者二进制原始信息输入, inmode--'0b'指示以二进制形式输入,'0x'指示以十六进制形式输入,outmode--'0b'指示以二进制形式输出,'0x'指示以十六进制形式输出 59 | *Return: 无前缀十六进制或者二进制Hash结果输出 60 | */ 61 | string MD5::hash(string input, string inmode, string outmode) 62 | { 63 | input=(inmode=="0x")?hexToBinary(input):input; 64 | string res=_MD5(input); 65 | res=(outmode=="0x")?binToHexto(res):res; 66 | 67 | return res; 68 | } 69 | 70 | 71 | /********************* private functions ************************/ 72 | 73 | /*1. 74 | *hexToBinary: 该方法将十六进制字符串转化为二进制字符串(均不含前缀) 75 | *Param: input--无前缀十六进制输入 76 | *Return:output--无前缀二进制输出 77 | */ 78 | string MD5::hexToBinary(string input) 79 | { 80 | map dic; //十六进制数到二进制数的转换表 81 | dic['0']="0000"; dic['1']="0001"; dic['2']="0010"; dic['3']="0011"; dic['4']="0100"; dic['5']="0101"; dic['6']="0110"; dic['7']="0111"; dic['8']="1000"; dic['9']="1001"; dic['A']="1010"; dic['B']="1011"; dic['C']="1100"; dic['D']="1101"; dic['E']="1110"; dic['F']="1111";dic['a']="1010"; dic['b']="1011"; dic['c']="1100"; dic['d']="1101"; dic['e']="1110"; dic['f']="1111"; 82 | 83 | string output; 84 | for(int i=0;i redic; //二进制数到十六进制数的转换表 99 | redic["0000"]="0"; redic["0001"]="1"; redic["0010"]="2"; redic["0011"]="3"; redic["0100"]="4"; redic["0101"]="5"; redic["0110"]="6"; redic["0111"]="7"; redic["1000"]="8"; redic["1001"]="9"; redic["1010"]="a"; redic["1011"]="b"; redic["1100"]="c"; redic["1101"]="d"; redic["1110"]="e"; redic["1111"]="f"; 100 | 101 | string output; 102 | for(int i=0;i=0;i--) 122 | { 123 | cout<<((input>>i)&1); 124 | } 125 | } 126 | 127 | /*4. 128 | *convert: 该方法将unsigned int类型以32位二进制的形式字符串转化 129 | *Param: input--需要输出的unsigned int类型数字 130 | */ 131 | string MD5::convert(unsigned int input) 132 | { 133 | //这里使用的算法非常经典,通过不断移位来输出每一个二进制位,需要特别注意该种方法,移位的执行效率是非常之高的 134 | string res; 135 | for(int i=31;i>=0;i--) 136 | { 137 | res.push_back(((input>>i)&1)+'0'); 138 | } 139 | return res; 140 | } 141 | 142 | /*5. 143 | *fillString: 该方法对原始输入的二进制序列进行填充,填充到长度size符合size%512==448,然后附加一个64位的填充前长度值序列 144 | *Param: input--输入二进制序列。返回值:string类型--填充后的二进制序列 145 | */ 146 | string MD5::fillString(string input) 147 | { 148 | //1.首先判断是否需要进行填充,需要填充的情况下进行填充 149 | int osize=input.size(); 150 | if(osize%512!=448) 151 | { 152 | //1.1对于需要填充的情况,第一次填充1,后续每一次填充0,迭代操作直到长度size符合要求为止 153 | input.push_back('1'); 154 | while(input.size()%512!=448) 155 | { 156 | input.push_back('0'); 157 | } 158 | } 159 | //2.在符合条件的序列后添加一个64位二进制序列表示输入二进制序列在填充前的长度值 160 | string nums="0000000000000000000000000000000000000000000000000000000000000000"; 161 | //2.1首先将原输入字符串长度转化为16进制字符串 162 | char temp_str[10000]; 163 | sprintf(temp_str,"%x",osize); 164 | string temp(temp_str); 165 | temp=hexToBinary(temp_str); 166 | for(int i=0;i &output) 179 | { 180 | int size=(input.size()+1)/512; 181 | for(int i=0;i=0;k--) 205 | { 206 | for(int m=0;m<8;m++) 207 | { 208 | temp.push_back(input[i*32+k*8+m]); 209 | } 210 | } 211 | //然后将字符串转化为unsigned int类型 212 | output[i]=strtoul(temp.c_str(),0,2); //string转unsigned int常使用内置strtoul来进行快速实现,当然也可以自行实现 213 | } 214 | return; 215 | } 216 | 217 | /*8. 218 | *cycleLeftShift: 实现循环左移 219 | *Param: a--待移位数,b--移位数 220 | *Return: 移位结果 221 | */ 222 | unsigned int MD5::cycleLeftShift(unsigned int a,unsigned int b) 223 | { 224 | unsigned int res=a<>(32-b); //再将a进行右移32-b位得到a的前b位,即结果2,最后再将结果1和结果2进行或操作进行合并 226 | return res; 227 | } 228 | 229 | /*9. 230 | *4个非线性函数F,G,H,I的实现 231 | */ 232 | //非线性函数F 233 | unsigned int MD5::F(unsigned int x,unsigned int y,unsigned int z) 234 | { 235 | return (x&y)|((~x)&z); 236 | } 237 | 238 | //非线性函数G 239 | unsigned int MD5::G(unsigned int x,unsigned int y,unsigned int z) 240 | { 241 | return (x&z)|(y&(~z)); 242 | } 243 | 244 | //非线性函数H 245 | unsigned int MD5::H(unsigned int x,unsigned int y,unsigned int z) 246 | { 247 | return x^y^z; 248 | } 249 | 250 | //非线性函数I 251 | unsigned int MD5::I(unsigned int x,unsigned int y,unsigned int z) 252 | { 253 | return y^(x|(~z)); 254 | } 255 | 256 | /*10. 257 | *4个复合操作函数FF,GG,HH,II的实现 258 | *Comment: 需要特别注意,MD5使用复合操作函数的过程中,会改变各个参数的值后作为下一次使用复合函数的输入,因此输入参数a需要使用引用形式,且其中的移位为循环左移位 259 | */ 260 | //复合操作函数FF 261 | unsigned int MD5::FF(unsigned int &a,unsigned int b,unsigned int c ,unsigned int d ,unsigned int Mj,unsigned int s,unsigned int ti) 262 | { 263 | a = b + cycleLeftShift( (a + F(b,c,d) + Mj + ti), s); 264 | } 265 | 266 | //复合操作函数GG 267 | unsigned int MD5::GG(unsigned int &a,unsigned int b,unsigned int c ,unsigned int d ,unsigned int Mj,unsigned int s,unsigned int ti) 268 | { 269 | a = b + cycleLeftShift( (a + G(b,c,d) + Mj + ti), s); 270 | } 271 | 272 | //复合操作函数HH 273 | unsigned int MD5::HH(unsigned int &a,unsigned int b,unsigned int c ,unsigned int d ,unsigned int Mj,unsigned int s,unsigned int ti) 274 | { 275 | a = b + cycleLeftShift( (a + H(b,c,d) + Mj + ti), s); 276 | } 277 | 278 | //复合操作函数II 279 | unsigned int MD5::II(unsigned int &a,unsigned int b,unsigned int c ,unsigned int d ,unsigned int Mj,unsigned int s,unsigned int ti) 280 | { 281 | a = b + cycleLeftShift( (a + I(b,c,d) + Mj + ti), s); 282 | } 283 | 284 | /*11. 285 | *MD5: 该方法用户输入字符串进行MD5核心算法 286 | *Param: user_input--用户字符串输入 287 | *Return: 128位MD5算法结果输出 288 | *Comment: 本处需要严格注意MD5加密过程中所需要使用的参数值 289 | */ 290 | string MD5::_MD5(string user_input) 291 | { 292 | //MD-5加密参量 293 | unsigned int x[16]={}; 294 | unsigned int A=0x67452301; 295 | unsigned int B=0xefcdab89; 296 | unsigned int C=0x98badcfe; 297 | unsigned int D=0x10325476; 298 | //首先将用户输入的字符串进行填充,并以512为一组进行分组 299 | user_input=fillString(user_input); 300 | vector lis; 301 | initDepart(user_input,lis); 302 | //cout<=0;m--) 409 | { 410 | user_output.push_back(((A>>(k*8+m))&1)+'0'); 411 | } 412 | } 413 | for(int k=0;k<4;k++) 414 | { 415 | for(int m=7;m>=0;m--) 416 | { 417 | user_output.push_back(((B>>(k*8+m))&1)+'0'); 418 | } 419 | } 420 | for(int k=0;k<4;k++) 421 | { 422 | for(int m=7;m>=0;m--) 423 | { 424 | user_output.push_back(((C>>(k*8+m))&1)+'0'); 425 | } 426 | } 427 | for(int k=0;k<4;k++) 428 | { 429 | for(int m=7;m>=0;m--) 430 | { 431 | user_output.push_back(((D>>(k*8+m))&1)+'0'); 432 | } 433 | } 434 | return user_output; 435 | } -------------------------------------------------------------------------------- /HashCenter/SHA512.h: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | using namespace std; 11 | 12 | class SHA512 13 | { 14 | public: 15 | SHA512(); //SHA512: 默认构造函数 16 | string hash(string input, string inmode, string outmode); //hash: 进行SHA512 Hash,返回SHA512 Hash结果 17 | private: 18 | 19 | unsigned int __plain, __enpt; //__plain: 原始消息; __enpt: SHA512 Hash结果 20 | 21 | string hexToBinary(string input); //hexToBinary: 十六进制输入转换为二进制 22 | string binToHexto(string input); //binToHexto: 二进制输入转换为十六进制 23 | void print(unsigned long long int input); //print: 将unsigned int类型以32位二进制的形式输出 24 | string convert(unsigned long long int input); //convert: 将unsigned int类型以32位二进制的形式字符串转化 25 | string fillString(string input); //fillString: 该方法对原始输入的二进制序列进行填充 26 | 27 | void initDepart(string input,vector &output); //initDepart: 该方法将N*1024位的二进制字符串拆分为若干1024位的字符串数组 28 | 29 | // SHA-512在轮函数F中使用的4个复合操作函数 30 | unsigned long long int cycleRightShift(unsigned long long int a,unsigned long long int b); //cycleRightShift:实现循环右移 31 | unsigned long long int Ch(unsigned long long int e,unsigned long long int f,unsigned long long int g); //Ch: 复合操作函数Ch 32 | unsigned long long int Maj(unsigned long long int a,unsigned long long int b,unsigned long long int c); //Maj: 复合操作函数Maj 33 | unsigned long long int Sigma0(unsigned long long int a); //Sigma0: 复合操作函数Sigma0 34 | unsigned long long int Sigma1(unsigned long long int e); //Sigma1: 复合操作函数Sigma1 35 | 36 | void F(unsigned long long int &a,unsigned long long int &b,unsigned long long int &c,unsigned long long int &d,unsigned long long int &e,unsigned long long int &f,unsigned long long int &g,unsigned long long int &h,unsigned long long int Wi,unsigned long long int Ki); //F: SHA-512的单轮函数F 37 | 38 | // SHA-512的在消息扩展中所使用的2个复合操作函数 39 | unsigned long long int Theta0(unsigned long long int x); //Theta0: 复合操作函数Theta0 40 | unsigned long long int Theta1(unsigned long long int x); //Theta1: 复合操作函数Theta1 41 | 42 | void FExtended(string input,unsigned long long int output[80]);//FExtended:该方法为轮函数进行消息扩展操作 43 | string _SHA512(string input); //_SHA512: SHA-512 Hash算法底层实现方法 44 | }; 45 | 46 | 47 | /**********************************public functions********************************************/ 48 | 49 | /*0. 50 | *SHA512: 类默认初始化函数 51 | */ 52 | SHA512::SHA512() 53 | { 54 | } 55 | 56 | /*2. 57 | *hash: 该方法进行SHA512 Hash,返回SHA512 Hash结果 58 | *Param: input--无前缀十六进制或者二进制原始信息输入, inmode--'0b'指示以二进制形式输入,'0x'指示以十六进制形式输入,outmode--'0b'指示以二进制形式输出,'0x'指示以十六进制形式输出 59 | *Return: 无前缀十六进制或者二进制Hash结果输出 60 | */ 61 | string SHA512::hash(string input, string inmode, string outmode) 62 | { 63 | input=(inmode=="0b")?binToHexto(input):input; 64 | string res=_SHA512(input); 65 | res=(outmode=="0b")?hexToBinary(res):res; 66 | 67 | return res; 68 | } 69 | 70 | 71 | /**********************************private functions*******************************************/ 72 | 73 | /*1. 74 | *hexToBinary: 该方法将十六进制字符串转化为二进制字符串(均不含前缀) 75 | *Param: input--无前缀十六进制输入 76 | *Return: output--无前缀二进制输出 77 | */ 78 | string SHA512::hexToBinary(string input) 79 | { 80 | map dic; //十六进制数到二进制数的转换表 81 | dic['0']="0000"; dic['1']="0001"; dic['2']="0010"; dic['3']="0011"; dic['4']="0100"; dic['5']="0101"; dic['6']="0110"; dic['7']="0111"; dic['8']="1000"; dic['9']="1001"; dic['A']="1010"; dic['B']="1011"; dic['C']="1100"; dic['D']="1101"; dic['E']="1110"; dic['F']="1111";dic['a']="1010"; dic['b']="1011"; dic['c']="1100"; dic['d']="1101"; dic['e']="1110"; dic['f']="1111"; 82 | 83 | string output; 84 | for(int i=0;i redic; //二进制数到十六进制数的转换表 99 | redic["0000"]="0"; redic["0001"]="1"; redic["0010"]="2"; redic["0011"]="3"; redic["0100"]="4"; redic["0101"]="5"; redic["0110"]="6"; redic["0111"]="7"; redic["1000"]="8"; redic["1001"]="9"; redic["1010"]="a"; redic["1011"]="b"; redic["1100"]="c"; redic["1101"]="d"; redic["1110"]="e"; redic["1111"]="f"; 100 | 101 | string output; 102 | for(int i=0;i=0;i--) 122 | { 123 | cout<<((input>>i)&1); 124 | } 125 | } 126 | 127 | /*4. 128 | *convert: 该方法将unsigned long long int类型以64位二进制的形式字符串转化 129 | *Param: input--需要输出的unsigned long long int类型数字 130 | *Return:二进制字符串化的输入值input 131 | */ 132 | string SHA512::convert(unsigned long long int input) 133 | { 134 | //这里使用的算法非常经典,通过不断移位来输出每一个二进制位,需要特别注意该种方法,移位的执行效率是非常之高的 135 | string res; 136 | for(int i=63;i>=0;i--) 137 | { 138 | res.push_back(((input>>i)&1)+'0'); 139 | } 140 | return res; 141 | } 142 | 143 | /*5. 144 | *fillString:该方法对原始输入的二进制序列进行填充,填充到长度size符合size%1024==896,然后附加一个128位的填充前长度值序列 145 | *Param:input--输入二进制序列。返回值:string类型--填充后的二进制序列 146 | */ 147 | string SHA512::fillString(string input) 148 | { 149 | //1.首先判断是否需要进行填充,需要填充的情况下进行填充 150 | int osize=input.size(); 151 | if(osize%1024!=896) 152 | { 153 | //1.1对于需要填充的情况,第一次填充1,后续每一次填充0,迭代操作直到长度size符合要求为止 154 | input.push_back('1'); 155 | while(input.size()%1024!=896) 156 | { 157 | input.push_back('0'); 158 | } 159 | } 160 | //2.在符合条件的序列后添加一个128位二进制序列表示输入二进制序列在填充前的长度值 161 | string nums(128,'0'); 162 | //2.1首先将原输入字符串长度转化为16进制字符串 163 | char temp_str[10000]; 164 | sprintf(temp_str,"%x",osize); 165 | string temp(temp_str); 166 | temp=hexToBinary(temp_str); 167 | int m=128-temp.size(); 168 | for(int i=0;i &output) 181 | { 182 | int size=input.size()/1024; 183 | for(int i=0;i>b; //先将a进行右移b位得到结果1 203 | res|=a<<(64-b); //再将a进行左移64-b位得到a的后b位,即结果2,最后再将结果1和结果2进行或操作进行合并 204 | return res; 205 | } 206 | 207 | /*8. 208 | *SHA-512的4个复合操作函数 209 | */ 210 | //复合操作函数Ch 211 | unsigned long long int SHA512::Ch(unsigned long long int e,unsigned long long int f,unsigned long long int g) 212 | { 213 | return (e&f)^((~e)&g); 214 | } 215 | 216 | //复合操作函数Maj 217 | unsigned long long int SHA512::Maj(unsigned long long int a,unsigned long long int b,unsigned long long int c) 218 | { 219 | return (a&b)^(a&c)^(b&c); 220 | } 221 | 222 | //复合操作函数Sigma0 223 | unsigned long long int SHA512::Sigma0(unsigned long long int a) 224 | { 225 | return cycleRightShift(a,28)^cycleRightShift(a,34)^cycleRightShift(a,39); 226 | } 227 | 228 | //复合操作函数Sigma1 229 | unsigned long long int SHA512::Sigma1(unsigned long long int e) 230 | { 231 | return cycleRightShift(e,14)^cycleRightShift(e,18)^cycleRightShift(e,41); 232 | } 233 | 234 | /*9. 235 | *F: SHA-512的单轮函数F 236 | *Param: a,b,c,d,e,f,g,h--Hash变量,Wi--64位消息扩展得到的子消息,Ki--轮常量 237 | */ 238 | void SHA512::F(unsigned long long int &a,unsigned long long int &b,unsigned long long int &c,unsigned long long int &d,unsigned long long int &e,unsigned long long int &f,unsigned long long int &g,unsigned long long int &h,unsigned long long int Wi,unsigned long long int Ki) 239 | { 240 | unsigned long long int T1=h+Ch(e,f,g)+Sigma1(e)+Wi+Ki; 241 | unsigned long long int T2=Sigma0(a)+Maj(a,b,c); 242 | h=g; 243 | g=f; 244 | f=e; 245 | e=d+T1; 246 | d=c; 247 | c=b; 248 | b=a; 249 | a=T1+T2; 250 | return; 251 | } 252 | 253 | /*10. 254 | *SHA-512的轮常数 255 | */ 256 | const unsigned long long int Ki[80]= {//80个常数 257 | 0x428a2f98d728ae22ULL, 0x7137449123ef65cdULL, 0xb5c0fbcfec4d3b2fULL, 258 | 0xe9b5dba58189dbbcULL, 0x3956c25bf348b538ULL, 0x59f111f1b605d019ULL, 259 | 0x923f82a4af194f9bULL, 0xab1c5ed5da6d8118ULL, 0xd807aa98a3030242ULL, 260 | 0x12835b0145706fbeULL, 0x243185be4ee4b28cULL, 0x550c7dc3d5ffb4e2ULL, 261 | 0x72be5d74f27b896fULL, 0x80deb1fe3b1696b1ULL, 0x9bdc06a725c71235ULL, 262 | 0xc19bf174cf692694ULL, 0xe49b69c19ef14ad2ULL, 0xefbe4786384f25e3ULL, 263 | 0x0fc19dc68b8cd5b5ULL, 0x240ca1cc77ac9c65ULL, 0x2de92c6f592b0275ULL, 264 | 0x4a7484aa6ea6e483ULL, 0x5cb0a9dcbd41fbd4ULL, 0x76f988da831153b5ULL, 265 | 0x983e5152ee66dfabULL, 0xa831c66d2db43210ULL, 0xb00327c898fb213fULL, 266 | 0xbf597fc7beef0ee4ULL, 0xc6e00bf33da88fc2ULL, 0xd5a79147930aa725ULL, 267 | 0x06ca6351e003826fULL, 0x142929670a0e6e70ULL, 0x27b70a8546d22ffcULL, 268 | 0x2e1b21385c26c926ULL, 0x4d2c6dfc5ac42aedULL, 0x53380d139d95b3dfULL, 269 | 0x650a73548baf63deULL, 0x766a0abb3c77b2a8ULL, 0x81c2c92e47edaee6ULL, 270 | 0x92722c851482353bULL, 0xa2bfe8a14cf10364ULL, 0xa81a664bbc423001ULL, 271 | 0xc24b8b70d0f89791ULL, 0xc76c51a30654be30ULL, 0xd192e819d6ef5218ULL, 272 | 0xd69906245565a910ULL, 0xf40e35855771202aULL, 0x106aa07032bbd1b8ULL, 273 | 0x19a4c116b8d2d0c8ULL, 0x1e376c085141ab53ULL, 0x2748774cdf8eeb99ULL, 274 | 0x34b0bcb5e19b48a8ULL, 0x391c0cb3c5c95a63ULL, 0x4ed8aa4ae3418acbULL, 275 | 0x5b9cca4f7763e373ULL, 0x682e6ff3d6b2b8a3ULL, 0x748f82ee5defb2fcULL, 276 | 0x78a5636f43172f60ULL, 0x84c87814a1f0ab72ULL, 0x8cc702081a6439ecULL, 277 | 0x90befffa23631e28ULL, 0xa4506cebde82bde9ULL, 0xbef9a3f7b2c67915ULL, 278 | 0xc67178f2e372532bULL, 0xca273eceea26619cULL, 0xd186b8c721c0c207ULL, 279 | 0xeada7dd6cde0eb1eULL, 0xf57d4f7fee6ed178ULL, 0x06f067aa72176fbaULL, 280 | 0x0a637dc5a2c898a6ULL, 0x113f9804bef90daeULL, 0x1b710b35131c471bULL, 281 | 0x28db77f523047d84ULL, 0x32caab7b40c72493ULL, 0x3c9ebe0a15c9bebcULL, 282 | 0x431d67c49c100d4cULL, 0x4cc5d4becb3e42b6ULL, 0x597f299cfc657e2aULL, 283 | 0x5fcb6fab3ad6faecULL, 0x6c44198c4a475817ULL, 284 | }; 285 | 286 | /*11. 287 | *SHA-512的在消息扩展中所使用的2个复合操作函数 288 | */ 289 | //复合操作函数Theta0 290 | unsigned long long int SHA512::Theta0(unsigned long long int x) 291 | { 292 | return cycleRightShift(x,1)^cycleRightShift(x,8)^(x>>7); 293 | } 294 | 295 | //复合操作函数Theta1 296 | unsigned long long int SHA512::Theta1(unsigned long long int x) 297 | { 298 | return cycleRightShift(x,19)^cycleRightShift(x,61)^(x>>6); 299 | } 300 | 301 | /*12. 302 | *FExtended: 该方法为轮函数进行消息扩展操作,具体而言,该方法将1024位的二进制序列输入拆分为80个64位二进制的unsigned long long int类型x序列 303 | *Param: input--1024位输入二进制序列,output--16个64位输出二进制序列(即Wi) 304 | *Comment: 需要特别注意,在分拆时需要特别注意大端和小端的问题,为了方便,首先对字符串作变换,然后再将字符串转化为unsigned long long int类型 305 | */ 306 | void SHA512::FExtended(string input,unsigned long long int output[80]) 307 | { 308 | //前16个消息扩展结果Wi即为原1024位消息的16个64位分段 309 | for(int i=0;i<16;i++) 310 | { 311 | string temp; 312 | //首先将字符串作倒装变换 313 | for(int k=0;k<64;k++) 314 | { 315 | temp.push_back(input[i*64+k]); 316 | } 317 | //然后将字符串转化为unsigned long long int类型 318 | output[i]=strtoull(temp.c_str(),0,2); //string转unsigned long long int常使用内置strtoul来进行快速实现,当然也可以自行实现 319 | } 320 | //后续的消息扩展结果Wi使用固定的公式进行递推扩展 321 | for(int i=16;i<80;i++) 322 | { 323 | output[i]=Theta1(output[i-2])+output[i-7]+Theta0(output[i-15])+output[i-16]; 324 | } 325 | return; 326 | } 327 | 328 | /*13. 329 | *_SHA512: 该方法对输入的字符串序列进行SHA-512算法,并返回Hash结果 330 | *Param: input--十六进制输入 331 | *Return: 十六进制SHA-512 Hash结果输出 332 | */ 333 | string SHA512::_SHA512(string input) 334 | { 335 | //1.首先将输入消息input进行消息扩展操作 336 | input=fillString(hexToBinary(input)); //注意首先要将输入的十六进制转化为二进制 337 | vector lis; 338 | initDepart(input,lis); 339 | //2.初始化a,b,c,d,e,f,g,h总共8个轮变量 340 | unsigned long long int a=0x6a09e667f3bcc908ULL,b=0xbb67ae8584caa73bULL,c=0x3c6ef372fe94f82bULL,d=0xa54ff53a5f1d36f1ULL,e=0x510e527fade682d1ULL,f=0x9b05688c2b3e6c1fULL,g=0x1f83d9abfb41bd6bULL,h=0x5be0cd19137e2179ULL; 341 | for(int i=0;i 1. HashCenter类的构造函数接受一个参数。 8 | > 2. 该参数用于指定hash函数,值为"MD5"指定MD5作为hash函数,值为"SHA512"指定SHA512作为hash函数。 9 | 10 | HashCenter hashcenter("MD5"); 11 | 12 | ## 3. 利用创建的HashCenter对象进行Hash操作 13 | > 1. 使用gethash成员函数获得输入原始消息的hash值 14 | > 2. 该成员函数的第一个参数为原始消息 15 | > 3. 该成员函数的第二个参数用于指定输出格式,"0x"指定输出的hash结果为十六进制,"0b"指定输出的hash结果为二进制 16 | 17 | string infor="abcdefgh"; 18 | string md5_result=hashcenter.gethash(infor,"0x"); 19 | 20 | ## 4. 改变HashCenter对象所使用的hash函数 21 | > 1. 使用reset重新设置所使用的hash函数 22 | > 2. 该成员函数的唯一参数为重新设置的hash函数种类,值为"MD5"指定MD5作为hash函数,值为"SHA512"指定SHA512作为hash函数。 23 | 24 | hashcenter.reset("SHA512"); 25 | string sha512_result=hashcenter.gethash(infor,"0x"); 26 | 27 | ## 附注: 28 | > 1. example.cpp中提供了一个使用HashCenter模块的具体示例程序。 29 | 30 | 31 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "[]" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright [yyyy] [name of copyright owner] 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | -------------------------------------------------------------------------------- /MD5/MD5 example.txt: -------------------------------------------------------------------------------- 1 | 原文:"abc" 2 | 内存中的十六进制格式(也是本MD5算法的输入):6a6b6c6d6e 3 | MD5消息提取结果:603f52d844017e83ca267751fee5b61b 4 | -------------------------------------------------------------------------------- /MD5/MD5.h: -------------------------------------------------------------------------------- 1 | /***************************************************************** 2 | *Module Name: MD5 3 | *Module Date: 2018-11-28 4 | *Module Auth: pzh 5 | *Description: Simple MD5 module for single MD5 hashing 6 | *****************************************************************/ 7 | 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | 17 | using namespace std; 18 | 19 | class MD5 20 | { 21 | public: 22 | MD5(); //DES: 默认构造函数 23 | string hash(string input, string inmode, string outmode); //hash: 进行MD5 Hash,返回MD5 Hash结果 24 | private: 25 | 26 | unsigned int __plain, __enpt; //__plain: 原始消息; __enpt: MD5 Hash结果 27 | 28 | string hexToBinary(string input); //hexToBinary: 十六进制输入转换为二进制 29 | string binToHexto(string input); //binToHexto: 二进制输入转换为十六进制 30 | void print(unsigned int input); //print: 将unsigned int类型以32位二进制的形式输出 31 | string convert(unsigned int input); //convert: 将unsigned int类型以32位二进制的形式字符串转化 32 | string fillString(string input); //fillString: 对原始输入的二进制序列进行填充,填充到长度size符合size%512==448,然后附加一个64位的填充前长度值序列 33 | void initDepart(string input,vector &output); //initDepart: 该方法将N*512位的二进制字符串拆分为若干512位的字符串数组 34 | void departString(string input,unsigned int output[16]); //departString: 将512位的二进制序列输入拆分为16个32位二进制的unsigned int类型x序列 35 | unsigned int cycleLeftShift(unsigned int a,unsigned int b); //cycleLeftShift: 实现循环左移 36 | unsigned int F(unsigned int x,unsigned int y,unsigned int z); //F: 非线性函数F 37 | unsigned int G(unsigned int x,unsigned int y,unsigned int z); //G: 非线性函数G 38 | unsigned int H(unsigned int x,unsigned int y,unsigned int z); //H: 非线性函数H 39 | unsigned int I(unsigned int x,unsigned int y,unsigned int z); //I: 非线性函数I 40 | unsigned int FF(unsigned int &a,unsigned int b,unsigned int c ,unsigned int d ,unsigned int Mj,unsigned int s,unsigned int ti); //FF: 复合操作函数FF 41 | unsigned int GG(unsigned int &a,unsigned int b,unsigned int c ,unsigned int d ,unsigned int Mj,unsigned int s,unsigned int ti); //GG: 复合操作函数GG 42 | unsigned int HH(unsigned int &a,unsigned int b,unsigned int c ,unsigned int d ,unsigned int Mj,unsigned int s,unsigned int ti); //HH: 复合操作函数HH 43 | unsigned int II(unsigned int &a,unsigned int b,unsigned int c ,unsigned int d ,unsigned int Mj,unsigned int s,unsigned int ti); //HH: 复合操作函数II 44 | string _MD5(string user_input); //_MD5:MD5 Hash底层实现函数 45 | }; 46 | 47 | /********************* public functions *************************/ 48 | 49 | /*0. 50 | *MD5: 类默认初始化函数 51 | */ 52 | MD5::MD5() 53 | { 54 | } 55 | 56 | /*2. 57 | *hash: 该方法进行MD5 Hash,返回MD5 Hash结果 58 | *Param: input--无前缀十六进制或者二进制原始信息输入, inmode--'0b'指示以二进制形式输入,'0x'指示以十六进制形式输入,outmode--'0b'指示以二进制形式输出,'0x'指示以十六进制形式输出 59 | *Return: 无前缀十六进制或者二进制Hash结果输出 60 | */ 61 | string MD5::hash(string input, string inmode, string outmode) 62 | { 63 | input=(inmode=="0x")?hexToBinary(input):input; 64 | string res=_MD5(input); 65 | res=(outmode=="0x")?binToHexto(res):res; 66 | 67 | return res; 68 | } 69 | 70 | 71 | /********************* private functions ************************/ 72 | 73 | /*1. 74 | *hexToBinary: 该方法将十六进制字符串转化为二进制字符串(均不含前缀) 75 | *Param: input--无前缀十六进制输入 76 | *Return:output--无前缀二进制输出 77 | */ 78 | string MD5::hexToBinary(string input) 79 | { 80 | map dic; //十六进制数到二进制数的转换表 81 | dic['0']="0000"; dic['1']="0001"; dic['2']="0010"; dic['3']="0011"; dic['4']="0100"; dic['5']="0101"; dic['6']="0110"; dic['7']="0111"; dic['8']="1000"; dic['9']="1001"; dic['A']="1010"; dic['B']="1011"; dic['C']="1100"; dic['D']="1101"; dic['E']="1110"; dic['F']="1111";dic['a']="1010"; dic['b']="1011"; dic['c']="1100"; dic['d']="1101"; dic['e']="1110"; dic['f']="1111"; 82 | 83 | string output; 84 | for(int i=0;i redic; //二进制数到十六进制数的转换表 99 | redic["0000"]="0"; redic["0001"]="1"; redic["0010"]="2"; redic["0011"]="3"; redic["0100"]="4"; redic["0101"]="5"; redic["0110"]="6"; redic["0111"]="7"; redic["1000"]="8"; redic["1001"]="9"; redic["1010"]="a"; redic["1011"]="b"; redic["1100"]="c"; redic["1101"]="d"; redic["1110"]="e"; redic["1111"]="f"; 100 | 101 | string output; 102 | for(int i=0;i=0;i--) 122 | { 123 | cout<<((input>>i)&1); 124 | } 125 | } 126 | 127 | /*4. 128 | *convert: 该方法将unsigned int类型以32位二进制的形式字符串转化 129 | *Param: input--需要输出的unsigned int类型数字 130 | */ 131 | string MD5::convert(unsigned int input) 132 | { 133 | //这里使用的算法非常经典,通过不断移位来输出每一个二进制位,需要特别注意该种方法,移位的执行效率是非常之高的 134 | string res; 135 | for(int i=31;i>=0;i--) 136 | { 137 | res.push_back(((input>>i)&1)+'0'); 138 | } 139 | return res; 140 | } 141 | 142 | /*5. 143 | *fillString: 该方法对原始输入的二进制序列进行填充,填充到长度size符合size%512==448,然后附加一个64位的填充前长度值序列 144 | *Param: input--输入二进制序列。返回值:string类型--填充后的二进制序列 145 | */ 146 | string MD5::fillString(string input) 147 | { 148 | //1.首先判断是否需要进行填充,需要填充的情况下进行填充 149 | int osize=input.size(); 150 | if(osize%512!=448) 151 | { 152 | //1.1对于需要填充的情况,第一次填充1,后续每一次填充0,迭代操作直到长度size符合要求为止 153 | input.push_back('1'); 154 | while(input.size()%512!=448) 155 | { 156 | input.push_back('0'); 157 | } 158 | } 159 | //2.在符合条件的序列后添加一个64位二进制序列表示输入二进制序列在填充前的长度值 160 | string nums="0000000000000000000000000000000000000000000000000000000000000000"; 161 | //2.1首先将原输入字符串长度转化为16进制字符串 162 | char temp_str[10000]; 163 | sprintf(temp_str,"%x",osize); 164 | string temp(temp_str); 165 | temp=hexToBinary(temp_str); 166 | for(int i=0;i &output) 179 | { 180 | int size=(input.size()+1)/512; 181 | for(int i=0;i=0;k--) 205 | { 206 | for(int m=0;m<8;m++) 207 | { 208 | temp.push_back(input[i*32+k*8+m]); 209 | } 210 | } 211 | //然后将字符串转化为unsigned int类型 212 | output[i]=strtoul(temp.c_str(),0,2); //string转unsigned int常使用内置strtoul来进行快速实现,当然也可以自行实现 213 | } 214 | return; 215 | } 216 | 217 | /*8. 218 | *cycleLeftShift: 实现循环左移 219 | *Param: a--待移位数,b--移位数 220 | *Return: 移位结果 221 | */ 222 | unsigned int MD5::cycleLeftShift(unsigned int a,unsigned int b) 223 | { 224 | unsigned int res=a<>(32-b); //再将a进行右移32-b位得到a的前b位,即结果2,最后再将结果1和结果2进行或操作进行合并 226 | return res; 227 | } 228 | 229 | /*9. 230 | *4个非线性函数F,G,H,I的实现 231 | */ 232 | //非线性函数F 233 | unsigned int MD5::F(unsigned int x,unsigned int y,unsigned int z) 234 | { 235 | return (x&y)|((~x)&z); 236 | } 237 | 238 | //非线性函数G 239 | unsigned int MD5::G(unsigned int x,unsigned int y,unsigned int z) 240 | { 241 | return (x&z)|(y&(~z)); 242 | } 243 | 244 | //非线性函数H 245 | unsigned int MD5::H(unsigned int x,unsigned int y,unsigned int z) 246 | { 247 | return x^y^z; 248 | } 249 | 250 | //非线性函数I 251 | unsigned int MD5::I(unsigned int x,unsigned int y,unsigned int z) 252 | { 253 | return y^(x|(~z)); 254 | } 255 | 256 | /*10. 257 | *4个复合操作函数FF,GG,HH,II的实现 258 | *Comment: 需要特别注意,MD5使用复合操作函数的过程中,会改变各个参数的值后作为下一次使用复合函数的输入,因此输入参数a需要使用引用形式,且其中的移位为循环左移位 259 | */ 260 | //复合操作函数FF 261 | unsigned int MD5::FF(unsigned int &a,unsigned int b,unsigned int c ,unsigned int d ,unsigned int Mj,unsigned int s,unsigned int ti) 262 | { 263 | a = b + cycleLeftShift( (a + F(b,c,d) + Mj + ti), s); 264 | } 265 | 266 | //复合操作函数GG 267 | unsigned int MD5::GG(unsigned int &a,unsigned int b,unsigned int c ,unsigned int d ,unsigned int Mj,unsigned int s,unsigned int ti) 268 | { 269 | a = b + cycleLeftShift( (a + G(b,c,d) + Mj + ti), s); 270 | } 271 | 272 | //复合操作函数HH 273 | unsigned int MD5::HH(unsigned int &a,unsigned int b,unsigned int c ,unsigned int d ,unsigned int Mj,unsigned int s,unsigned int ti) 274 | { 275 | a = b + cycleLeftShift( (a + H(b,c,d) + Mj + ti), s); 276 | } 277 | 278 | //复合操作函数II 279 | unsigned int MD5::II(unsigned int &a,unsigned int b,unsigned int c ,unsigned int d ,unsigned int Mj,unsigned int s,unsigned int ti) 280 | { 281 | a = b + cycleLeftShift( (a + I(b,c,d) + Mj + ti), s); 282 | } 283 | 284 | /*11. 285 | *MD5: 该方法用户输入字符串进行MD5核心算法 286 | *Param: user_input--用户字符串输入 287 | *Return: 128位MD5算法结果输出 288 | *Comment: 本处需要严格注意MD5加密过程中所需要使用的参数值 289 | */ 290 | string MD5::_MD5(string user_input) 291 | { 292 | //MD-5加密参量 293 | unsigned int x[16]={}; 294 | unsigned int A=0x67452301; 295 | unsigned int B=0xefcdab89; 296 | unsigned int C=0x98badcfe; 297 | unsigned int D=0x10325476; 298 | //首先将用户输入的字符串进行填充,并以512为一组进行分组 299 | user_input=fillString(user_input); 300 | vector lis; 301 | initDepart(user_input,lis); 302 | //cout<=0;m--) 409 | { 410 | user_output.push_back(((A>>(k*8+m))&1)+'0'); 411 | } 412 | } 413 | for(int k=0;k<4;k++) 414 | { 415 | for(int m=7;m>=0;m--) 416 | { 417 | user_output.push_back(((B>>(k*8+m))&1)+'0'); 418 | } 419 | } 420 | for(int k=0;k<4;k++) 421 | { 422 | for(int m=7;m>=0;m--) 423 | { 424 | user_output.push_back(((C>>(k*8+m))&1)+'0'); 425 | } 426 | } 427 | for(int k=0;k<4;k++) 428 | { 429 | for(int m=7;m>=0;m--) 430 | { 431 | user_output.push_back(((D>>(k*8+m))&1)+'0'); 432 | } 433 | } 434 | return user_output; 435 | } -------------------------------------------------------------------------------- /MD5/example.cpp: -------------------------------------------------------------------------------- 1 | #include "MD5.h" 2 | #include 3 | #include 4 | 5 | using namespace std; 6 | 7 | int main(void) 8 | { 9 | string plain="6a6b6c6d6e"; 10 | string enpt; 11 | 12 | MD5 md5=MD5(); 13 | 14 | enpt=md5.hash(plain,"0x","0x"); 15 | cout<<"hash result: "< 1. key方法的第一个参数为十六进制或者二进制密钥。 11 | > 2. 第二个参数的"0x"表示输入的原始消息为十六进制,"0b"表示输入的原始消息为二进制。 12 | > 3. 第三个参数的"0x"表示hash结果以十六进制返回,"0b"表示hash结果以二进制返回。 13 | 14 | string plain="6a6b6c6d6e";; 15 | string result=md5.hash(plain,"0x","0x"); 16 | 17 | 18 | ## 附注: 19 | > 1. example.cpp中提供了一个使用MD5进行Hash操作的完整示例。MD5 example.txt中提供了一个MD5的"原消息-Hash结果"实例。 20 | > 2. 本模块的明文/密文/密钥输入必须是长度不限的十六进制或者二进制,其他如字符串需要首先转化为十六进制或者二进制再输入。 21 | > 3. 若需要直接进行字符串的Hash操作,请左转至本库的HashCenter模块: 22 | 该模块整合了MD5, SHA512两种Hash函数,支持任意长度的字符串输入。 23 | -------------------------------------------------------------------------------- /Pattern/DES.h: -------------------------------------------------------------------------------- 1 | /***************************************************************** 2 | *Module Name: DES 3 | *Module Date: 2018-11-28 4 | *Module Auth: pzh 5 | *Description: Simple DES module for single DES-64 encrypt 6 | *****************************************************************/ 7 | 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | 14 | using namespace std; 15 | 16 | class DES 17 | { 18 | public: 19 | DES(); //DES: 默认构造函数 20 | void key(string key, string mode); //key: 设定密钥 21 | string encrypt(string input, string inmode, string outmode); //encrypt: DES加密 22 | string decrypt(string input, string inmode, string outmode); //decrypt: DES解密 23 | string getkey(string mode); //getkey:获取当前密钥 24 | private: 25 | 26 | int __plain[64], __enpt[64], __key[64]; //plain, enpt, key: 最近的明文和密文,密钥 27 | bool __flag; 28 | 29 | string hexToBinary(string input); //hexToBinary: 十六进制输入转换为二进制 30 | string binToHexto(string input); //binToHexto: 二进制输入转换为十六进制 31 | void ipSub(const int input[64], int output[64]); //ipSub: IP置换 32 | void eSub(const int input[32], int output[48]); //eSub: E扩展置换 33 | void shiftBinary(int lis[56], int num); //shiftBinary: 循环左移 34 | void keySub(int roll_no, const int input[64],int output[48]); //keySub: 密钥置换 35 | void sSub(const int input[48], int output[32]); //sSub: S盒代替 36 | void pSub(const int input[32], int output[32]); //pSub: P盒代替 37 | void ipReSub(const int input[64], int output[64]); //ipReSub: IP逆置换 38 | void roleDES(const int leftinput[32],const int rightinput[32],int leftoutput[32],int rightoutput[32],int rolekey[48]); //roleDES:单轮DES加密 39 | void _DES(int input[64],int output[64],int key[64]); //_DES: 底层DES加密实现 40 | void _deDES(int input[64],int output[64],int key[64]); //_deDES: 底层DES解密实现 41 | }; 42 | 43 | /********************* public functions *************************/ 44 | 45 | /*0. 46 | *DES: 类默认初始化函数 47 | */ 48 | DES::DES() 49 | { 50 | __flag=false; 51 | } 52 | 53 | /*1. 54 | *key: 该方法设定DES加密密钥 55 | *Param: input--无前缀十六进制或者二进制输入, mode--'0b'指示二进制输入,'0x'指示十六进制输入 56 | */ 57 | void DES::key(string key, string mode) 58 | { 59 | __flag=true; 60 | if(mode=="0x") 61 | key=hexToBinary(key); 62 | for(int i=0;i dic; //十六进制数到二进制数的转换表 149 | dic['0']="0000"; dic['1']="0001"; dic['2']="0010"; dic['3']="0011"; dic['4']="0100"; dic['5']="0101"; dic['6']="0110"; dic['7']="0111"; dic['8']="1000"; dic['9']="1001"; dic['A']="1010"; dic['B']="1011"; dic['C']="1100"; dic['D']="1101"; dic['E']="1110"; dic['F']="1111";dic['a']="1010"; dic['b']="1011"; dic['c']="1100"; dic['d']="1101"; dic['e']="1110"; dic['f']="1111"; 150 | 151 | string output; 152 | for(int i=0;i redic; //二进制数到十六进制数的转换表 167 | redic["0000"]="0"; redic["0001"]="1"; redic["0010"]="2"; redic["0011"]="3"; redic["0100"]="4"; redic["0101"]="5"; redic["0110"]="6"; redic["0111"]="7"; redic["1000"]="8"; redic["1001"]="9"; redic["1010"]="a"; redic["1011"]="b"; redic["1100"]="c"; redic["1101"]="d"; redic["1110"]="e"; redic["1111"]="f"; 168 | 169 | string output; 170 | for(int i=0;i=0;k--) 324 | { 325 | output[i*4+k]=res%2; 326 | res/=2; 327 | } 328 | } 329 | return; 330 | } 331 | 332 | /*8. 333 | *pSub: 该方法进行P盒置换 334 | *Param: input--32位S盒代替后的结果输入,output--32位P盒置换结果输出 335 | */ 336 | void DES::pSub(const int input[32],int output[32]) 337 | { 338 | //首先制作P盒 339 | int P_box[32]={16,7,20,21,29,12,28,17,1,15,23,26,5,18,31,10,2,8,24,14,32,27,3,9,19,13,30,6,22,11,4,25}; 340 | //然后使用P盒对32位输入进行P盒置换,得到32位输出 341 | for(int i=0;i<32;i++) 342 | { 343 | output[i]=input[P_box[i]-1]; 344 | } 345 | return; 346 | } 347 | 348 | /*9. 349 | *ipReSub: 该方法进行IP逆置换 350 | *Param: input--32位输入,output--32位IP逆置换结果输出 351 | */ 352 | void DES::ipReSub(const int input[64],int output[64]) 353 | { 354 | //首先生成IP置换表 355 | int REIP_lis[64]={40,8,48,16,56,24,64,32,39,7,47,15,55,23,63,31,38,6,46,14,54,22,62,30,37,5,45,13,53,21,61,29,36,4,44,12,52,20,60,28,35,3,43,11,51,19,59,27,34,2,42,10,50,18,58,26,33,1,41,9,49,17,57,25}; 356 | //然后根据IP逆置换表进行IP逆置换 357 | for(int i=0;i<64;i++) 358 | { 359 | output[i]=input[REIP_lis[i]-1]; 360 | } 361 | return; 362 | } 363 | 364 | /*10. 365 | *roleDES: 该方法进行单轮DES加密 366 | *Param: leftinput--32位左半部分原文输入,rightinput--32位右半部分原文输入,leftoutput--32位左半部分原文输出,rightoutput--32位右半部分原文输出,key--当前轮的48位密钥 367 | */ 368 | void DES::roleDES(const int leftinput[32],const int rightinput[32],int leftoutput[32],int rightoutput[32],int rolekey[48]) 369 | { 370 | //首先计算左半部分输出,左半部分输出就是右半部分输入 371 | for(int i=0;i<32;i++) 372 | { 373 | leftoutput[i]=rightinput[i]; 374 | } 375 | //然后计算右半部分输出,这部分按照如下几个步骤完成 376 | //1.对原始的32位右半部分输入作E扩展置换,扩展为48位 377 | int rightinput_2[48]; 378 | eSub(rightinput,rightinput_2); 379 | //2.将48位的E扩展置换结果rightinput_2与当前轮的密钥进行异或操作 380 | int rightinput_3[48]; 381 | for(int i=0;i<48;i++) 382 | { 383 | rightinput_3[i]=rightinput_2[i]^rolekey[i]; 384 | } 385 | //3.将异或结果依次进行S盒代替以及P盒置换 386 | int rightinput_4[32]; 387 | sSub(rightinput_3,rightinput_4); //问题在此 388 | int rightinput_5[32]; 389 | pSub(rightinput_4,rightinput_5); 390 | //4.将两轮代替以及置换后的结果再和左半部分输入leftinput进行异或操作 391 | int rightinput_6[32]; 392 | for(int i=0;i<32;i++) 393 | { 394 | rightinput_6[i]=rightinput_5[i]^leftinput[i]; 395 | } 396 | //5.rightinput_6就是最终的右半部分输出结果 397 | for(int i=0;i<32;i++) 398 | { 399 | rightoutput[i]=rightinput_6[i]; 400 | } 401 | } 402 | 403 | /*11. 404 | *DES:该方法进行DES加密 405 | *Param:input--64位明文输入,output--64位密文输出,key--64位DES加密原始密钥(其中56位有效,其余位数作为奇偶校验位) 406 | */ 407 | void DES::_DES(int input[64],int output[64],int key[64]) 408 | { 409 | //1.将原始明文进行IP置换 410 | int input_2[64]; 411 | ipSub(input,input_2); 412 | //2.将原始明文分拆为左右两部分,进行16轮的DES单轮加密,最后再将得到的左右两部分合并 413 | int leftinput[32],rightinput[32],leftoutput[32],rightoutput[32],rolekey[48]; 414 | for(int i=0;i<64;i++) 415 | { 416 | if(i>=0&&i<32) 417 | leftinput[i]=input_2[i]; 418 | else 419 | rightinput[i-32]=input_2[i]; 420 | } 421 | for(int i=1;i<=16;i++) 422 | { 423 | //首先生成当前轮的密钥 424 | keySub(i,key,rolekey); 425 | //利用当前轮密钥进行加密 426 | roleDES(leftinput,rightinput,leftoutput,rightoutput,rolekey); 427 | //然后令leftinput=leftoutput,rightinput=rightoutput,准备进行下一轮迭代 428 | for(int i=0;i<32;i++) 429 | { 430 | leftinput[i]=leftoutput[i]; 431 | rightinput[i]=rightoutput[i]; 432 | } 433 | } 434 | //最后一轮得到的leftoutput和rightoutput即为得到的密文 435 | //3.对得到的两个32位密文互换位置后合并,然后进行IP逆置换,即得到最终加密的密文结果output 436 | int tempres[64]; 437 | for(int i=0;i<64;i++) 438 | { 439 | if(i>=0&&i<32) 440 | tempres[i]=rightoutput[i]; 441 | else 442 | tempres[i]=leftoutput[i-32]; 443 | } 444 | ipReSub(tempres,output); 445 | return; 446 | } 447 | 448 | /*12. 449 | *deDES: 该方法进行DES解密 450 | *Param: input--64位密文输入,output--64位明文输出,key--64位DES加密原始密钥 451 | */ 452 | void DES::_deDES(int input[64],int output[64],int key[64]) 453 | { 454 | //1.将原始明文进行IP置换 455 | int input_2[64]; 456 | ipSub(input,input_2); 457 | //2.将原始明文分拆为左右两部分,进行16轮的DES单轮加密,最后再将得到的左右两部分合并 458 | int leftinput[32],rightinput[32],leftoutput[32],rightoutput[32],rolekey[48]; 459 | for(int i=0;i<64;i++) 460 | { 461 | if(i>=0&&i<32) 462 | leftinput[i]=input_2[i]; 463 | else 464 | rightinput[i-32]=input_2[i]; 465 | } 466 | for(int i=16;i>=1;i--) 467 | { 468 | //首先生成当前轮的密钥 469 | keySub(i,key,rolekey); //DES解密时需要反向使用密钥 470 | //利用当前轮密钥进行加密 471 | roleDES(leftinput,rightinput,leftoutput,rightoutput,rolekey); 472 | //然后令leftinput=leftoutput,rightinput=rightoutput,准备进行下一轮迭代 473 | for(int i=0;i<32;i++) 474 | { 475 | leftinput[i]=leftoutput[i]; 476 | rightinput[i]=rightoutput[i]; 477 | } 478 | } 479 | //最后一轮得到的leftoutput和rightoutput即为得到的密文 480 | //3.对得到的两个32位密文互换位置后合并,然后进行IP逆置换,即得到最终加密的密文结果output 481 | int tempres[64]; 482 | for(int i=0;i<64;i++) 483 | { 484 | if(i>=0&&i<32) 485 | tempres[i]=rightoutput[i]; 486 | else 487 | tempres[i]=leftoutput[i-32]; 488 | } 489 | ipReSub(tempres,output); 490 | return; 491 | } 492 | -------------------------------------------------------------------------------- /Pattern/example.cpp: -------------------------------------------------------------------------------- 1 | #include "Pattern.h" 2 | 3 | using namespace std; 4 | 5 | int main(void) 6 | { 7 | string plain="abcdefghabcdefghabcdefghabcdefghabcdefghabcdefghabcdefghabcdefghabcdefghabcdefghabcdefghabcdefghab"; 8 | string key="abcdefghabcdefgh"; //aes使用32位十六进制密钥,每个字母对应两位二进制 9 | string vec="abcdefghabcdefgh"; 10 | string crpt0, crpt1, crpt2, crpt3, crpt4; 11 | cout<<"明文="< 1. 初始化一个Pattern对象需要提供两个参数,这两个参数分别指定分组密码种类和加密模式。 8 | > 2. 第一个参数指定分组密码种类,其值为"AES"或者"DES",分别指定DES和AES加密。 9 | > 3. 第二个参数指定分组密码的加密模式,其值为"ECB","CBC","CFB","OFB","CTR",分别指定对应的分组加密模式。 10 | 11 | Pattern pat0=Pattern("AES","CTR"); //初始化pat0为使用AES分组密码和CTR加密模式的Pattern对象 12 | 13 | 14 | ## 3. 改变一个已经创建的Pattern对象的加密模式 15 | > 1. 使用reset成员方法来改变加密模式。 16 | > 2. 同构造函数相同,第一个参数指定分组密码种类,其值为"AES"或者"DES",分别指定DES和AES加密。 17 | > 3. 同构造函数相同,第二个参数指定分组密码的加密模式,其值为"ECB","CBC","CFB","OFB","CTR",分别指定对应的分组加密模式。 18 | 19 | pat0.reset("DES","ECB"); //将pat0对象修改为使用AES分组密码和ECB加密模式的Pattern对象 20 | 21 | ## 4. 使用Pattern对象进行加密 22 | > 1. 使用encrypt成员方法来进行字符串加密。 23 | > 2. 第一个参数为明文字符串,长度不限。 24 | > 3. 第二个参数为密钥字符串,若为DES加密,则该密钥字符串的长度必须为8;若为AES加密,则该密钥字符串的长度必须为16。 25 | > 4. 第三个参数为偏移向量字符串,若为DES加密,则该偏移向量的长度必须为8;若为AES加密,则该偏移向量的长度必须为16;特别地,当使用ECB加密时,由于ECB加密中不使用偏移向量,因此该参数取值可以为任意字符串。 26 | > 5. 第四个参数为输出格式指定,取值为"0x"时指定输出密文格式为十六进制;取值为"0b"时指定输出密文格式为二进制。 27 | 28 | string plain="abcdefghabcdefghabcdefghabcdefghabcdefghabcdefghabcdefghabcdefghabcdefghabcdefghabcdefghabcdefghab"; 29 | string key="abcdefghabcdefgh"; //aes使用32位十六进制密钥,每个字母对应两位二进制 30 | string vec="abcdefghabcdefgh"; 31 | 32 | string crpt0=pat0.encrypt(plain, key, vec, "0x"); 33 | cout<<"ECB加密得到的密文="< 1. 使用decrypt成员方法来进行字符串加密。 38 | > 2. 第一个参数为密文字符串,长度不限。 39 | > 3. 第二个参数为密钥字符串,若为DES解密,则该密钥字符串的长度必须为8;若为AES解密,则该密钥字符串的长度必须为16。 40 | > 4. 第三个参数为偏移向量字符串,若为DES解密,则该偏移向量的长度必须为8;若为AES解密,则该偏移向量的长度必须为16;特别地,当使用ECB解密时,由于ECB解密中不使用偏移向量,因此该参数取值可以为任意字符串。 41 | > 5. 第四个参数为输出格式指定,取值为"0x"时指定输出明文格式为十六进制;取值为"0b"时指定输出明文格式为二进制。 42 | 43 | string result=pat0.decrypt(crpt0, key, vec, "0x"); 44 | cout<<"ECB解密得到的密文="< 1. example.cpp中提供了一个使用该Pattern集成分组加密模块的示例。 48 | 49 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # CrptoLib 2 | 中山大学信息安全基础课程实验作业/Experimental homework of information-security-basic course in SYSU. 3 | 4 | CrptoLib是一个较为简单的实验性质的加密算法库,包含《密码编码学与网络安全》书中主要加密方案,例如DES,AES,MD5,SHA-512等常见加密方案的手写实现。 5 | 6 | ### 目录 7 | #### 1. AES:AES分组加密模块 8 | #### 2. DES:DES分组加密模块 9 | #### 3. MD5:MD5 Hash函数实现 10 | #### 4. SHA512:SHA512 Hash函数实现 11 | #### 5. RSA:RSA公钥加密模块 12 | #### 6. Diffie-Hellman:Diffie-Hellman密钥交换模块 13 | #### 7. Elgamel:Elgamel密钥交换模块 14 | #### 8. DAA:DAA消息认证码(MAC)模块 (附注: DAA标准因安全性问题已经于2003年后废止,不推荐使用) 15 | #### 9. HMAC:基于MD5和SHA512 Hash函数的消息认证码(MAC)模块 16 | #### 10. Pattern:分组加密集成模块,集成了AES, DES分组加密算法,并支持CBC, ECB, CTR, OCF, CFB五种分组密码的加密模式 17 | #### 11. HashCenter:Hash函数集成模块,集成了MD5, SHA512 Hash函数,并支持文件输入 18 | #### 12. Tradition:传统密码集成模块,集成了Caesar密码,仿射密码和Vigenere密码 19 | 20 | -------------------------------------------------------------------------------- /RSA/RSA.py: -------------------------------------------------------------------------------- 1 | import math 2 | import random 3 | 4 | import os 5 | 6 | class RSA: 7 | 8 | # public function members 9 | def __init__(self): 10 | ''' 11 | : __init: RSA类的初始化,生成并初始化公钥和私钥参数n, e, d 12 | ''' 13 | self.__p, self.__q, self.__n, self.__f, self.__e, self.__d = [0 for i in range(6)] 14 | self.__n, self.__e, self.__d=self.__keyGenerate() 15 | return 16 | 17 | def generatePubKey(self): 18 | ''' 19 | : generatePubKey: 返回RSA公钥(n, e) 20 | : Return: RSA公钥(n, e) 21 | ''' 22 | return (self.__n, self.__e) 23 | 24 | def generatePrivKey(self): 25 | ''' 26 | : generatePrivKey: 返回RSA私钥(n, d) 27 | : Return: RSA私钥(n, d) 28 | ''' 29 | return (self.__n, self.__d) 30 | 31 | def encrypt(self, plain): 32 | ''' 33 | : encrypt: 进行RSA加密 34 | : Param: plain--明文 35 | : Return: RSA加密密文结果 36 | ''' 37 | return self.__RSA(plain, (self.__n, self.__e)) 38 | 39 | def decrypt(self, crpt): 40 | ''' 41 | : decrypt: 进行RSA解密 42 | : Param: crpt--密文 43 | : Return: RSA解密明文结果 44 | ''' 45 | return self.__deRSA(crpt, (self.__n, self.__d)) 46 | 47 | 48 | #private functions members 49 | def __fastExpMod(self, b, e, m): 50 | ''' 51 | : __fastExpMod: 快速幂取模算法 52 | : Param: b,e,m--对应于幂取模运算式b^e mod m中对应参数 53 | : Return: 幂取模运算式b^e mod m的计算结果 54 | ''' 55 | result = 1 56 | while e != 0: 57 | if (e&1) == 1: 58 | result = (result * b) % m 59 | e >>= 1 60 | b = (b*b) % m 61 | return result 62 | 63 | def __primeArray(self, r): 64 | ''' 65 | : __primeArray:该方法生成范围在[0,r]内的素数表 66 | : Param: r--素数表上界 67 | : Return: 范围在[0,r]内的素数表 68 | ''' 69 | prime=[0 for i in range(r+1)] 70 | lis=[] 71 | for i in range(2,r+1): 72 | if prime[i]==0: 73 | lis.append(i) 74 | for j in lis: 75 | if i*j>r: 76 | break 77 | prime[i*j]=1 78 | if i%j==0: 79 | break 80 | return lis 81 | 82 | def __prime(self, n, test_divisor): 83 | ''' 84 | : __prime: 判断是否为素数 85 | ''' 86 | if math.sqrt(n) < test_divisor: 87 | return True #为素数时返回True 88 | if n % test_divisor==0: 89 | return False #不为素数时返回Fasle 90 | else: 91 | return self.__prime(n, test_divisor+1) 92 | 93 | def __findCoPrime(self, s): 94 | ''' 95 | : __findCoPrime: 筛选出符合条件的数e满足gcd(e,(p-1,q-1))==1 96 | : Param: s--(p-1)*(q-1) 97 | : Return: 符合条件的值e 98 | : comment: 因为两个随机数互质的概率为0.6,因此只需要随机选取一个数e,然后测试是否满足gcd(e,(p-1,q-1))==1即可 99 | ''' 100 | while True: 101 | e = random.choice(range(10000)) 102 | x = self.__gcd(e,s) 103 | if x==1: 104 | break 105 | return e 106 | 107 | def __gcd(self, a,b): 108 | ''' 109 | : __gcd: 求两个数的最大公约数 110 | : Param: a,b--数a,数b 111 | : Return: 数a,b的最大公约数 112 | ''' 113 | if b==0: 114 | return a 115 | else: 116 | return self.__gcd(b, a%b) 117 | 118 | def __inV(self, a,b): 119 | ''' 120 | : __inV:扩展欧几里得算法求解乘法逆元 121 | ''' 122 | if b == 0: 123 | return (1,0,a) 124 | (x, y, r) = self.__inV(b,a%b) 125 | temp = x 126 | x = y 127 | y = temp - int(a / b) * y 128 | return (x,y,r) 129 | 130 | def __searchD(self, e,s): 131 | ''' 132 | : __searchD: 筛选出符合条件的参数d的值 133 | : Param: e--RSA加密参数e,s--(p-1)*(q-1) 134 | ''' 135 | x=0 136 | y=0 137 | r=0 138 | (x,y,r)=self.__inV(e,s) 139 | d=(x+s)%s 140 | return d 141 | 142 | def __keyGenerate(self): 143 | ''' 144 | : __keyGenerate: 生成RSA加密的关键变量n,e,d 145 | : Return: (n,e,d)的三元组 146 | ''' 147 | a= self.__primeArray(10000) #生成素数表 148 | #print("范围在[0,10000]的素数表为:",a) 149 | p = random.choice(a) #随机从素数表中筛选出p 150 | q = random.choice(a) #随机从素数表中筛选出q 151 | #print("随机筛选出的素数p,q分别为:",p,q) 152 | n=p*q 153 | s=(p-1)*(q-1) 154 | e = self.__findCoPrime(s) 155 | #print("根据gcd(e,(p-1)*(q-1))==1得到e的值为: e=", e) 156 | d = self.__searchD(e,s) 157 | #print("根据(e*d)%((p-1)*(q-1))==1得到d的值为: d=", d) 158 | #print("公钥为: n=",n," e=",e) 159 | #print("私钥为: n=",n," d=",d) 160 | res=(n,e,d) 161 | return res 162 | 163 | def __RSA(self, plain, ned): 164 | ''' 165 | : __RSA:进行RSA加密 166 | : Param: plain--明文,ned--公钥 167 | : Return: 密文 168 | ''' 169 | crpt = self.__fastExpMod(plain,ned[1],ned[0]) 170 | return crpt 171 | 172 | def __deRSA(self, crpt, ned): 173 | ''' 174 | : __deRSA: 进行RSA解密 175 | : Param: crpt--明文,ned--私钥 176 | : Return: 明文 177 | ''' 178 | plain = self.__fastExpMod(crpt,ned[1],ned[0]) 179 | return plain 180 | 181 | 182 | 183 | 184 | 185 | 186 | 187 | 188 | 189 | -------------------------------------------------------------------------------- /RSA/example.py: -------------------------------------------------------------------------------- 1 | import RSA 2 | 3 | if __name__ == "__main__": 4 | rsa = RSA.RSA() 5 | pubkey = rsa.generatePubKey() 6 | privkey = rsa.generatePrivKey() 7 | 8 | plain = int(input("请输入要进行RSA加密的明文: ")) 9 | 10 | print('RSA公钥为: ', pubkey) 11 | crpt = rsa.encrypt(plain) 12 | print('使用RSA公钥加密的结果为: ',crpt) 13 | 14 | print('RSA私钥为: ', privkey) 15 | plain = rsa.decrypt(crpt) 16 | print('使用RSA私钥解密的结果为: ',plain) -------------------------------------------------------------------------------- /RSA/readme.md: -------------------------------------------------------------------------------- 1 | # RSA模块 2 | 3 | ## 1. 引用头文件"RSA.py" 4 | import RSA 5 | 6 | ## 2. 创建一个RSA对象 7 | rsa = RSA.RSA() 8 | 9 | ## 3. 分别使用generatePubKey和generatePrivKey成员方法生成RSA加密的公钥(n,e)和私钥(n,d) 10 | > 1. generatePubKey成员方法返回生成的公钥(n,e) 11 | > 2. generatePrivKey成员方法返回生成的私钥(n,d) 12 | 13 | pubkey = rsa.generatePubKey() #生成公钥pubkey=(n,e) 14 | privkey = rsa.generatePrivKey() #生成私钥privkey=(n,d) 15 | 16 | 17 | ## 4. 使用encrypt成员方法进行RSA加密 18 | > 1. encrypt成员方法的唯一参数为十进制的明文输入 19 | > 2. 返回值为RSA加密结果 20 | 21 | crpt = rsa.encrypt(plain) 22 | 23 | ## 5. 使用decrypt成员方法进行RSA解密 24 | > 1. decrypt成员方法的唯一参数为十进制的密文输入 25 | > 2. 返回值为RSA解密结果 26 | 27 | plain = rsa.decrypt(crpt) 28 | 29 | ## 附注: 30 | > 1. example.py中提供了一个使用RSA模块进行加密和解密的完整示例。 31 | 32 | -------------------------------------------------------------------------------- /SHA512/SHA512 example.txt: -------------------------------------------------------------------------------- 1 | 原始字符串:abcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabc 2 | 作为输入的内存中的字符串对应信息(本算法输入):616263616263616263616263616263616263616263616263616263616263616263616263616263616263616263616263616263616263616263616263616263616263616263616263616263616263616263616263616263616263616263616263616263616263616263616263616263616263616263616263616263616263616263616263616263616263616263616263616263616263616263616263616263616263616263616263616263616263616263616263616263616263616263616263616263616263616263616263616263616263616263616263616263616263616263616263616263616263616263616263616263616263616263616263616263616263616263616263616263616263616263616263616263616263616263616263616263616263616263616263616263616263616263616263616263616263616263616263616263616263616263616263616263616263616263616263616263616263616263616263616263616263616263616263616263616263616263616263616263616263616263616263616263616263616263616263616263616263616263616263616263616263616263616263616263616263616263616263616263616263616263616263616263616263616263616263616263616263616263616263616263616263616263616263616263616263616263616263616263616263616263616263616263616263616263616263616263616263616263616263616263616263616263616263616263616263616263616263616263616263616263616263616263616263616263616263616263616263616263616263 3 | SHA-512 Hash结果:2eaf1488268ded7ca13be2eb17eb2549801ffadd5f75bbcba461b37476318430bd8549a5755129ce6f6698c7506870a32fd00043b74e307ba811496bc6ae5996 4 | -------------------------------------------------------------------------------- /SHA512/SHA512.h: -------------------------------------------------------------------------------- 1 | /***************************************************************** 2 | *Module Name: SHA512 3 | *Module Date: 2018-11-28 4 | *Module Auth: pzh 5 | *AEScription: SHA hashing module 6 | *****************************************************************/ 7 | 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | 17 | using namespace std; 18 | 19 | class SHA512 20 | { 21 | public: 22 | SHA512(); //SHA512: 默认构造函数 23 | string hash(string input, string inmode, string outmode); //hash: 进行SHA512 Hash,返回SHA512 Hash结果 24 | private: 25 | 26 | unsigned int __plain, __enpt; //__plain: 原始消息; __enpt: SHA512 Hash结果 27 | 28 | string hexToBinary(string input); //hexToBinary: 十六进制输入转换为二进制 29 | string binToHexto(string input); //binToHexto: 二进制输入转换为十六进制 30 | void print(unsigned long long int input); //print: 将unsigned int类型以32位二进制的形式输出 31 | string convert(unsigned long long int input); //convert: 将unsigned int类型以32位二进制的形式字符串转化 32 | string fillString(string input); //fillString: 该方法对原始输入的二进制序列进行填充 33 | 34 | void initDepart(string input,vector &output); //initDepart: 该方法将N*1024位的二进制字符串拆分为若干1024位的字符串数组 35 | 36 | // SHA-512在轮函数F中使用的4个复合操作函数 37 | unsigned long long int cycleRightShift(unsigned long long int a,unsigned long long int b); //cycleRightShift:实现循环右移 38 | unsigned long long int Ch(unsigned long long int e,unsigned long long int f,unsigned long long int g); //Ch: 复合操作函数Ch 39 | unsigned long long int Maj(unsigned long long int a,unsigned long long int b,unsigned long long int c); //Maj: 复合操作函数Maj 40 | unsigned long long int Sigma0(unsigned long long int a); //Sigma0: 复合操作函数Sigma0 41 | unsigned long long int Sigma1(unsigned long long int e); //Sigma1: 复合操作函数Sigma1 42 | 43 | void F(unsigned long long int &a,unsigned long long int &b,unsigned long long int &c,unsigned long long int &d,unsigned long long int &e,unsigned long long int &f,unsigned long long int &g,unsigned long long int &h,unsigned long long int Wi,unsigned long long int Ki); //F: SHA-512的单轮函数F 44 | 45 | // SHA-512的在消息扩展中所使用的2个复合操作函数 46 | unsigned long long int Theta0(unsigned long long int x); //Theta0: 复合操作函数Theta0 47 | unsigned long long int Theta1(unsigned long long int x); //Theta1: 复合操作函数Theta1 48 | 49 | void FExtended(string input,unsigned long long int output[80]);//FExtended:该方法为轮函数进行消息扩展操作 50 | string _SHA512(string input); //_SHA512: SHA-512 Hash算法底层实现方法 51 | }; 52 | 53 | 54 | /**********************************public functions********************************************/ 55 | 56 | /*0. 57 | *SHA512: 类默认初始化函数 58 | */ 59 | SHA512::SHA512() 60 | { 61 | } 62 | 63 | /*2. 64 | *hash: 该方法进行SHA512 Hash,返回SHA512 Hash结果 65 | *Param: input--无前缀十六进制或者二进制原始信息输入, inmode--'0b'指示以二进制形式输入,'0x'指示以十六进制形式输入,outmode--'0b'指示以二进制形式输出,'0x'指示以十六进制形式输出 66 | *Return: 无前缀十六进制或者二进制Hash结果输出 67 | */ 68 | string SHA512::hash(string input, string inmode, string outmode) 69 | { 70 | input=(inmode=="0b")?binToHexto(input):input; 71 | string res=_SHA512(input); 72 | res=(outmode=="0b")?hexToBinary(res):res; 73 | 74 | return res; 75 | } 76 | 77 | 78 | /**********************************private functions*******************************************/ 79 | 80 | /*1. 81 | *hexToBinary: 该方法将十六进制字符串转化为二进制字符串(均不含前缀) 82 | *Param: input--无前缀十六进制输入 83 | *Return: output--无前缀二进制输出 84 | */ 85 | string SHA512::hexToBinary(string input) 86 | { 87 | map dic; //十六进制数到二进制数的转换表 88 | dic['0']="0000"; dic['1']="0001"; dic['2']="0010"; dic['3']="0011"; dic['4']="0100"; dic['5']="0101"; dic['6']="0110"; dic['7']="0111"; dic['8']="1000"; dic['9']="1001"; dic['A']="1010"; dic['B']="1011"; dic['C']="1100"; dic['D']="1101"; dic['E']="1110"; dic['F']="1111";dic['a']="1010"; dic['b']="1011"; dic['c']="1100"; dic['d']="1101"; dic['e']="1110"; dic['f']="1111"; 89 | 90 | string output; 91 | for(int i=0;i redic; //二进制数到十六进制数的转换表 106 | redic["0000"]="0"; redic["0001"]="1"; redic["0010"]="2"; redic["0011"]="3"; redic["0100"]="4"; redic["0101"]="5"; redic["0110"]="6"; redic["0111"]="7"; redic["1000"]="8"; redic["1001"]="9"; redic["1010"]="a"; redic["1011"]="b"; redic["1100"]="c"; redic["1101"]="d"; redic["1110"]="e"; redic["1111"]="f"; 107 | 108 | string output; 109 | for(int i=0;i=0;i--) 129 | { 130 | cout<<((input>>i)&1); 131 | } 132 | } 133 | 134 | /*4. 135 | *convert: 该方法将unsigned long long int类型以64位二进制的形式字符串转化 136 | *Param: input--需要输出的unsigned long long int类型数字 137 | *Return:二进制字符串化的输入值input 138 | */ 139 | string SHA512::convert(unsigned long long int input) 140 | { 141 | //这里使用的算法非常经典,通过不断移位来输出每一个二进制位,需要特别注意该种方法,移位的执行效率是非常之高的 142 | string res; 143 | for(int i=63;i>=0;i--) 144 | { 145 | res.push_back(((input>>i)&1)+'0'); 146 | } 147 | return res; 148 | } 149 | 150 | /*5. 151 | *fillString:该方法对原始输入的二进制序列进行填充,填充到长度size符合size%1024==896,然后附加一个128位的填充前长度值序列 152 | *Param:input--输入二进制序列。返回值:string类型--填充后的二进制序列 153 | */ 154 | string SHA512::fillString(string input) 155 | { 156 | //1.首先判断是否需要进行填充,需要填充的情况下进行填充 157 | int osize=input.size(); 158 | if(osize%1024!=896) 159 | { 160 | //1.1对于需要填充的情况,第一次填充1,后续每一次填充0,迭代操作直到长度size符合要求为止 161 | input.push_back('1'); 162 | while(input.size()%1024!=896) 163 | { 164 | input.push_back('0'); 165 | } 166 | } 167 | //2.在符合条件的序列后添加一个128位二进制序列表示输入二进制序列在填充前的长度值 168 | string nums(128,'0'); 169 | //2.1首先将原输入字符串长度转化为16进制字符串 170 | char temp_str[10000]; 171 | sprintf(temp_str,"%x",osize); 172 | string temp(temp_str); 173 | temp=hexToBinary(temp_str); 174 | int m=128-temp.size(); 175 | for(int i=0;i &output) 188 | { 189 | int size=input.size()/1024; 190 | for(int i=0;i>b; //先将a进行右移b位得到结果1 210 | res|=a<<(64-b); //再将a进行左移64-b位得到a的后b位,即结果2,最后再将结果1和结果2进行或操作进行合并 211 | return res; 212 | } 213 | 214 | /*8. 215 | *SHA-512的4个复合操作函数 216 | */ 217 | //复合操作函数Ch 218 | unsigned long long int SHA512::Ch(unsigned long long int e,unsigned long long int f,unsigned long long int g) 219 | { 220 | return (e&f)^((~e)&g); 221 | } 222 | 223 | //复合操作函数Maj 224 | unsigned long long int SHA512::Maj(unsigned long long int a,unsigned long long int b,unsigned long long int c) 225 | { 226 | return (a&b)^(a&c)^(b&c); 227 | } 228 | 229 | //复合操作函数Sigma0 230 | unsigned long long int SHA512::Sigma0(unsigned long long int a) 231 | { 232 | return cycleRightShift(a,28)^cycleRightShift(a,34)^cycleRightShift(a,39); 233 | } 234 | 235 | //复合操作函数Sigma1 236 | unsigned long long int SHA512::Sigma1(unsigned long long int e) 237 | { 238 | return cycleRightShift(e,14)^cycleRightShift(e,18)^cycleRightShift(e,41); 239 | } 240 | 241 | /*9. 242 | *F: SHA-512的单轮函数F 243 | *Param: a,b,c,d,e,f,g,h--Hash变量,Wi--64位消息扩展得到的子消息,Ki--轮常量 244 | */ 245 | void SHA512::F(unsigned long long int &a,unsigned long long int &b,unsigned long long int &c,unsigned long long int &d,unsigned long long int &e,unsigned long long int &f,unsigned long long int &g,unsigned long long int &h,unsigned long long int Wi,unsigned long long int Ki) 246 | { 247 | unsigned long long int T1=h+Ch(e,f,g)+Sigma1(e)+Wi+Ki; 248 | unsigned long long int T2=Sigma0(a)+Maj(a,b,c); 249 | h=g; 250 | g=f; 251 | f=e; 252 | e=d+T1; 253 | d=c; 254 | c=b; 255 | b=a; 256 | a=T1+T2; 257 | return; 258 | } 259 | 260 | /*10. 261 | *SHA-512的轮常数 262 | */ 263 | const unsigned long long int Ki[80]= {//80个常数 264 | 0x428a2f98d728ae22ULL, 0x7137449123ef65cdULL, 0xb5c0fbcfec4d3b2fULL, 265 | 0xe9b5dba58189dbbcULL, 0x3956c25bf348b538ULL, 0x59f111f1b605d019ULL, 266 | 0x923f82a4af194f9bULL, 0xab1c5ed5da6d8118ULL, 0xd807aa98a3030242ULL, 267 | 0x12835b0145706fbeULL, 0x243185be4ee4b28cULL, 0x550c7dc3d5ffb4e2ULL, 268 | 0x72be5d74f27b896fULL, 0x80deb1fe3b1696b1ULL, 0x9bdc06a725c71235ULL, 269 | 0xc19bf174cf692694ULL, 0xe49b69c19ef14ad2ULL, 0xefbe4786384f25e3ULL, 270 | 0x0fc19dc68b8cd5b5ULL, 0x240ca1cc77ac9c65ULL, 0x2de92c6f592b0275ULL, 271 | 0x4a7484aa6ea6e483ULL, 0x5cb0a9dcbd41fbd4ULL, 0x76f988da831153b5ULL, 272 | 0x983e5152ee66dfabULL, 0xa831c66d2db43210ULL, 0xb00327c898fb213fULL, 273 | 0xbf597fc7beef0ee4ULL, 0xc6e00bf33da88fc2ULL, 0xd5a79147930aa725ULL, 274 | 0x06ca6351e003826fULL, 0x142929670a0e6e70ULL, 0x27b70a8546d22ffcULL, 275 | 0x2e1b21385c26c926ULL, 0x4d2c6dfc5ac42aedULL, 0x53380d139d95b3dfULL, 276 | 0x650a73548baf63deULL, 0x766a0abb3c77b2a8ULL, 0x81c2c92e47edaee6ULL, 277 | 0x92722c851482353bULL, 0xa2bfe8a14cf10364ULL, 0xa81a664bbc423001ULL, 278 | 0xc24b8b70d0f89791ULL, 0xc76c51a30654be30ULL, 0xd192e819d6ef5218ULL, 279 | 0xd69906245565a910ULL, 0xf40e35855771202aULL, 0x106aa07032bbd1b8ULL, 280 | 0x19a4c116b8d2d0c8ULL, 0x1e376c085141ab53ULL, 0x2748774cdf8eeb99ULL, 281 | 0x34b0bcb5e19b48a8ULL, 0x391c0cb3c5c95a63ULL, 0x4ed8aa4ae3418acbULL, 282 | 0x5b9cca4f7763e373ULL, 0x682e6ff3d6b2b8a3ULL, 0x748f82ee5defb2fcULL, 283 | 0x78a5636f43172f60ULL, 0x84c87814a1f0ab72ULL, 0x8cc702081a6439ecULL, 284 | 0x90befffa23631e28ULL, 0xa4506cebde82bde9ULL, 0xbef9a3f7b2c67915ULL, 285 | 0xc67178f2e372532bULL, 0xca273eceea26619cULL, 0xd186b8c721c0c207ULL, 286 | 0xeada7dd6cde0eb1eULL, 0xf57d4f7fee6ed178ULL, 0x06f067aa72176fbaULL, 287 | 0x0a637dc5a2c898a6ULL, 0x113f9804bef90daeULL, 0x1b710b35131c471bULL, 288 | 0x28db77f523047d84ULL, 0x32caab7b40c72493ULL, 0x3c9ebe0a15c9bebcULL, 289 | 0x431d67c49c100d4cULL, 0x4cc5d4becb3e42b6ULL, 0x597f299cfc657e2aULL, 290 | 0x5fcb6fab3ad6faecULL, 0x6c44198c4a475817ULL, 291 | }; 292 | 293 | /*11. 294 | *SHA-512的在消息扩展中所使用的2个复合操作函数 295 | */ 296 | //复合操作函数Theta0 297 | unsigned long long int SHA512::Theta0(unsigned long long int x) 298 | { 299 | return cycleRightShift(x,1)^cycleRightShift(x,8)^(x>>7); 300 | } 301 | 302 | //复合操作函数Theta1 303 | unsigned long long int SHA512::Theta1(unsigned long long int x) 304 | { 305 | return cycleRightShift(x,19)^cycleRightShift(x,61)^(x>>6); 306 | } 307 | 308 | /*12. 309 | *FExtended: 该方法为轮函数进行消息扩展操作,具体而言,该方法将1024位的二进制序列输入拆分为80个64位二进制的unsigned long long int类型x序列 310 | *Param: input--1024位输入二进制序列,output--16个64位输出二进制序列(即Wi) 311 | *Comment: 需要特别注意,在分拆时需要特别注意大端和小端的问题,为了方便,首先对字符串作变换,然后再将字符串转化为unsigned long long int类型 312 | */ 313 | void SHA512::FExtended(string input,unsigned long long int output[80]) 314 | { 315 | //前16个消息扩展结果Wi即为原1024位消息的16个64位分段 316 | for(int i=0;i<16;i++) 317 | { 318 | string temp; 319 | //首先将字符串作倒装变换 320 | for(int k=0;k<64;k++) 321 | { 322 | temp.push_back(input[i*64+k]); 323 | } 324 | //然后将字符串转化为unsigned long long int类型 325 | output[i]=strtoull(temp.c_str(),0,2); //string转unsigned long long int常使用内置strtoul来进行快速实现,当然也可以自行实现 326 | } 327 | //后续的消息扩展结果Wi使用固定的公式进行递推扩展 328 | for(int i=16;i<80;i++) 329 | { 330 | output[i]=Theta1(output[i-2])+output[i-7]+Theta0(output[i-15])+output[i-16]; 331 | } 332 | return; 333 | } 334 | 335 | /*13. 336 | *_SHA512: 该方法对输入的字符串序列进行SHA-512算法,并返回Hash结果 337 | *Param: input--十六进制输入 338 | *Return: 十六进制SHA-512 Hash结果输出 339 | */ 340 | string SHA512::_SHA512(string input) 341 | { 342 | //1.首先将输入消息input进行消息扩展操作 343 | input=fillString(hexToBinary(input)); //注意首先要将输入的十六进制转化为二进制 344 | vector lis; 345 | initDepart(input,lis); 346 | //2.初始化a,b,c,d,e,f,g,h总共8个轮变量 347 | unsigned long long int a=0x6a09e667f3bcc908ULL,b=0xbb67ae8584caa73bULL,c=0x3c6ef372fe94f82bULL,d=0xa54ff53a5f1d36f1ULL,e=0x510e527fade682d1ULL,f=0x9b05688c2b3e6c1fULL,g=0x1f83d9abfb41bd6bULL,h=0x5be0cd19137e2179ULL; 348 | for(int i=0;i 3 | #include 4 | 5 | using namespace std; 6 | 7 | int main(void) 8 | { 9 | string plain="616263616263616263616263616263616263616263616263616263616263616263616263616263616263616263616263616263616263616263616263616263616263616263616263616263616263616263616263616263616263616263616263616263616263616263616263616263616263616263616263616263616263616263616263616263616263616263616263616263616263616263616263616263616263616263616263616263616263616263616263616263616263616263616263616263616263616263616263616263616263616263616263616263616263616263616263616263616263616263616263616263616263616263616263616263616263616263616263616263616263616263616263616263616263616263616263616263616263616263616263616263616263616263616263616263616263616263616263616263616263616263616263616263616263616263616263616263616263616263616263616263616263616263616263616263616263616263616263616263616263616263616263616263616263616263616263616263616263616263616263616263616263616263616263616263616263616263616263616263616263616263616263616263616263616263616263616263616263616263616263616263616263616263616263616263616263616263616263616263616263616263616263616263616263616263616263616263616263616263616263616263616263616263616263616263616263616263616263616263616263616263616263616263616263616263616263616263616263616263616263"; 10 | string enpt; 11 | 12 | SHA512 sha512=SHA512(); 13 | 14 | enpt=sha512.hash(plain,"0x","0x"); 15 | cout<<"hash result: "< 1. key方法的第一个参数为十六进制或者二进制密钥。 11 | > 2. 第二个参数的"0x"表示输入的原始消息为十六进制,"0b"表示输入的原始消息为二进制。 12 | > 3. 第三个参数的"0x"表示hash结果以十六进制返回,"0b"表示hash结果以二进制返回。 13 | 14 | string plain="6a6b6c6d6e";; 15 | string result=sha512.hash(plain,"0x","0x"); 16 | 17 | 18 | ## 附注: 19 | > 1. example.cpp中提供了一个使用SHA512进行Hash操作的完整示例。SHA512 example.txt中提供了一个SHA512的"原消息-Hash结果"实例。 20 | > 2. 本模块的明文/密文/密钥输入必须是长度不限的十六进制或者二进制,其他如字符串需要首先转化为十六进制或者二进制再输入。 21 | > 3. 若需要直接进行字符串的Hash操作,请左转至本库的HashCenter模块: 22 | 该模块整合了MD5, SHA512两种Hash函数,支持任意长度的字符串作为输入。 23 | -------------------------------------------------------------------------------- /Tradition/Tradition.h: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | using namespace std; 5 | 6 | class Tradition 7 | { 8 | public: 9 | Tradition(); 10 | string caesar_encrypt(string plain, int key); 11 | string caesar_decrypt(string crpt, int key); 12 | string corr_encrypt(string plain, int a, int b); 13 | string corr_decrypt(string crpt, int a, int b); 14 | string vigenere_encrypt(string plain, string key); 15 | string vigenere_decrypt(string crpt, string key); 16 | 17 | private: 18 | int __inV(int a, int b, int &x, int &y); 19 | }; 20 | 21 | /********************* public functions *************************/ 22 | 23 | /*0. 24 | *Tradition: 默认构造函数 25 | *Param: None 26 | *Return: None 27 | */ 28 | Tradition::Tradition() 29 | { 30 | } 31 | 32 | /*1. 33 | *caesar_encrypt: Caesar加密算法 34 | *Param: plain--明文;key--密钥 35 | *Return: 密文 36 | */ 37 | string Tradition::caesar_encrypt(string plain,int key) 38 | { 39 | string crpt=plain; //加密后的密文 40 | string errorcrpt; //错误密文输出 41 | if(key<0||key>=26) 42 | return errorcrpt; 43 | for(int i=0;i='a'&&plain[i]<='z') 46 | { 47 | crpt[i]='a'+(plain[i]-'a'+key)%26; 48 | } 49 | else if(plain[i]>='A'&&plain[i]<='Z') 50 | { 51 | crpt[i]='A'+(plain[i]-'A'+key)%26; 52 | } 53 | else 54 | return errorcrpt; 55 | } 56 | return crpt; 57 | } 58 | 59 | /*2. 60 | *caesar_decrypt: Caesar解密算法 61 | *Param: crpt--密文;key--密钥 62 | *Return: 明文 63 | */ 64 | string Tradition::caesar_decrypt(string crpt,int key) 65 | { 66 | string plain=crpt; //加密后的密文 67 | string errorplain; //错误明文输出 68 | if(key<0||key>=26) 69 | return errorplain; 70 | for(int i=0;i='a'&&crpt[i]<='z') 73 | { 74 | plain[i]='a'+(crpt[i]-'a'-key+26)%26; //注意crpt[i]-'a'-key的值可能为负数,因此首先需要加上26转化为正数 75 | } 76 | else if(plain[i]>='A'&&plain[i]<='Z') 77 | { 78 | plain[i]='A'+(crpt[i]-'A'-key+26)%26; 79 | } 80 | else 81 | return errorplain; 82 | } 83 | return plain; 84 | } 85 | 86 | /*3. 87 | *corr_encrypt: 仿射密码加密 88 | *Param: plain--明文;a,b--密钥(a,b),其中加密规则为crpt = (a*plain + b) mod 26 89 | *Return: 密文 90 | */ 91 | string Tradition::corr_encrypt(string plain,int a,int b) 92 | { 93 | string crpt=plain; //加密后的密文 94 | string errorcrpt; //错误密文输出 95 | if(a%2==0||a%13==0) 96 | return errorcrpt; 97 | for(int i=0;i='a'&&plain[i]<='z') 100 | { 101 | crpt[i]='a'+((plain[i]-'a')*a+b)%26; 102 | } 103 | else if(plain[i]>='A'&&plain[i]<='Z') 104 | { 105 | crpt[i]='A'+((plain[i]-'A')*a+b)%26; 106 | } 107 | else 108 | return errorcrpt; 109 | } 110 | return crpt; 111 | } 112 | 113 | /*4. 114 | *corr_decrypt: 仿射密码解密 115 | *Param: crpt--密文;a,b--密钥(a,b) 116 | *Return: 明文 117 | */ 118 | string Tradition::corr_decrypt(string crpy,int a,int b) 119 | { 120 | string plain=crpy; //解密后的明文 121 | string errorplain; //错误明文输出 122 | if(a%2==0||a%13==0) 123 | return errorplain; 124 | int x,y; 125 | //先求解密钥a相对于26的乘法逆元x 126 | __inV(a,26,x,y); 127 | x=(x+26)%26; 128 | //cout<<"乘法逆元为:"<='a'&&crpy[i]<='z') 133 | { 134 | plain[i]='a'+(x*((crpy[i]-'a')-b%26+26))%26; //详细说明:此处需要特别注意-b%26+26的部分,因为(crpy[i]-'a')的值的范围在0到25之间,而b的值是任意的,b%26便得到了0到25之间范围的数字,这时(crpy[i]-'a')-b%26有可能为负数(最大负值不小于-26),因此需要加上26转化为正数 135 | } 136 | else if(crpy[i]>='A'&&crpy[i]<='Z') 137 | { 138 | plain[i]='A'+(x*((crpy[i]-'A')-b%26+26))%26; 139 | } 140 | else 141 | return errorplain; 142 | } 143 | return plain; 144 | } 145 | 146 | /*5. 147 | *vigenere_encrypt: Vigenere密码加密 148 | *Param: plain--明文;key--密钥 149 | *Return: 密文 150 | */ 151 | string Tradition::vigenere_encrypt(string plain,string key) 152 | { 153 | string crpt=plain; //加密后的密文 154 | string errorcrpt; 155 | for(int i=0;i='a'&&key[i%key.size()]<='z')?'a':'A'); 158 | if(plain[i]>='a'&&plain[i]<='z') 159 | { 160 | crpt[i]='a'+(plain[i]-'a'+tempkey)%26; 161 | } 162 | else if(plain[i]>='A'&&plain[i]<='Z') 163 | { 164 | crpt[i]='A'+(plain[i]-'A'+tempkey)%26; 165 | } 166 | else 167 | return errorcrpt; 168 | } 169 | return crpt; 170 | } 171 | 172 | /*5. 173 | *vigenere_decrypt: Vigenere密码解密 174 | *Param: crpt--密文;key--密钥 175 | *Return: 明文 176 | */ 177 | string Tradition::vigenere_decrypt(string crpt,string key) 178 | { 179 | string plain=crpt; //解密后的明文 180 | string errorplain; //错误明文输出 181 | for(int i=0;i='a'&&key[i%key.size()]<='z')?'a':'A'); 184 | if(crpt[i]>='a'&&crpt[i]<='z') 185 | { 186 | plain[i]='a'+(crpt[i]-'a'-tempkey+26)%26; //注意crpt[i]-'a'-key的值可能为负数,因此首先需要加上26转化为正数 187 | } 188 | else if(plain[i]>='A'&&plain[i]<='Z') 189 | { 190 | plain[i]='A'+(crpt[i]-'A'-tempkey+26)%26; 191 | } 192 | else 193 | return errorplain; 194 | } 195 | return plain; 196 | } 197 | 198 | /********************* private functions *************************/ 199 | 200 | /*1. 201 | *__inV:扩展欧几里得算法求解乘法逆元 202 | */ 203 | int Tradition::__inV(int a, int b, int &x, int &y) 204 | { 205 | if (b==0) 206 | { 207 | x=1; 208 | y=0; 209 | return a; 210 | } 211 | int gcd=__inV(b,a%b,x,y); 212 | int tmp=x; 213 | x=y; 214 | y=tmp-(a/b)*y; 215 | return gcd; 216 | } -------------------------------------------------------------------------------- /Tradition/example.cpp: -------------------------------------------------------------------------------- 1 | #include "Tradition.h" 2 | #include 3 | #include 4 | 5 | using namespace std; 6 | 7 | int main(void) 8 | { 9 | Tradition trad; 10 | 11 | //Caesar 12 | string plain="abcdefghijklmnopqrstuvwxyz"; 13 | string crpt; 14 | int key=3; 15 | 16 | crpt=trad.caesar_encrypt(plain,key); 17 | cout<<"Caesar encrypt = "< 1. Tradition类的对象可以进行默认初始化,即在初始化的时候无需提供任何的参数。 8 | > 2. Tradition类包含Caesar,仿射,Vigenere三种经典密码的加密和解密实现,根据这三种加密算法的定义,其的明文和密文字符串中均要求仅含26个英文字母。 9 | 10 | Tradition trad; 11 | 12 | ## 3. 进行Caesar加密和解密 13 | > 1. 使用caesar_encrypt成员函数进行加密,第一个参数为任意长度的明文字符串,第二个参数为一个整数密钥,返回加密得到的密文字符串。 14 | > 2. 使用caesar_decrypt成员函数进行解密,第一个参数为任意长度的密文字符串,第二个参数为一个整数密钥,返回解密得到的明文字符串。 15 | 16 | //Caesar 17 | string plain="abcdefghijklmnopqrstuvwxyz"; 18 | string crpt; 19 | int key=3; 20 | 21 | crpt=trad.caesar_encrypt(plain,key); 22 | cout<<"Caesar encrypt = "<