├── PGP └── PGP.py ├── README.md ├── RSA ├── 47-1密码学中的数学原理之再谈碰撞.pptx ├── 47-2密码学中的数学原理之Montgomery算法.pptx ├── CRT.cpp ├── GeneratePara.cpp ├── Mont.cpp ├── RSA_Utils.h ├── Readme.md ├── main.cpp ├── modRepeat.cpp └── mont最新解释.ppt ├── RainbowTable ├── FileDivision.cpp ├── Rainbow_Table_Gen.cpp ├── Rainbow_Table_head.hpp ├── Readme.md ├── avl_tree.cpp ├── main.cpp └── md5Cracker.cpp ├── Report.pdf └── SPN ├── DifferentialAttack.cpp ├── LinearAttack.cpp ├── RandTest.cpp ├── SPN.cpp ├── SPN_Plus.cpp ├── Utils.h └── main.cpp /PGP/PGP.py: -------------------------------------------------------------------------------- 1 | from Crypto.PublicKey import ECC, RSA 2 | from Crypto.Signature import DSS 3 | from Crypto.Hash import SHA256 4 | from Crypto.Cipher import DES, PKCS1_OAEP 5 | from Crypto.Util.Padding import pad, unpad 6 | import Crypto.Random 7 | import zlib 8 | 9 | # return: (private_key, public_key) 10 | def generate_ECC_key(): 11 | private_key = ECC.generate(curve='P-256') 12 | return private_key, private_key.public_key() 13 | 14 | 15 | # return: (private_key, public_key) 16 | def generate_RSA_key(): 17 | private_key = RSA.generate(1024) 18 | return private_key, private_key.publickey() 19 | 20 | 21 | def generate_DES_key(): 22 | key = Crypto.Random.get_random_bytes(8) 23 | return key 24 | 25 | 26 | def sign(data, key): 27 | h = SHA256.new(data) 28 | signer = DSS.new(key, 'fips-186-3') 29 | signature = signer.sign(h) 30 | return signature 31 | 32 | 33 | # return True if data is authentic 34 | def verify(data, signature, key): 35 | h = SHA256.new(data) 36 | verifier = DSS.new(key, 'fips-186-3') 37 | try: 38 | verifier.verify(h, signature) 39 | return True 40 | except ValueError: 41 | return False 42 | 43 | 44 | def DES_encrypt(data, key): 45 | cipher = DES.new(key, DES.MODE_ECB) 46 | cipher_text = cipher.encrypt(pad(data, 32)) 47 | return cipher_text 48 | 49 | 50 | def DES_decrypt(data, key): 51 | cipher = DES.new(key, DES.MODE_ECB) 52 | data_dec = cipher.decrypt(data) 53 | plain_text = unpad(data_dec, 32) 54 | return plain_text 55 | 56 | 57 | def RSA_encrypt(data, key): 58 | cipher = PKCS1_OAEP.new(key) 59 | cipher_text = cipher.encrypt(data) 60 | return cipher_text 61 | 62 | 63 | def RSA_decrypt(data, key): 64 | cipher = PKCS1_OAEP.new(key) 65 | plain_text = cipher.decrypt(data) 66 | return plain_text 67 | 68 | 69 | def Zip(data): 70 | return zlib.compress(data,7) 71 | 72 | 73 | def UnZip(data): 74 | return zlib.decompress(data) 75 | 76 | 77 | def PGP_send(data, alice_pri_key, bob_pub_key): 78 | data += sign(data, alice_pri_key) 79 | des_key = generate_DES_key() 80 | data = DES_encrypt(data, des_key) 81 | des_key_enc = RSA_encrypt(des_key, bob_pub_key) # 加密后的DES密钥 82 | data += des_key_enc 83 | data = Zip(data) 84 | return data 85 | 86 | 87 | def PGP_recieve(data, alice_pub_key, bob_pri_key): 88 | data = UnZip(data) 89 | data, des_key_enc = data[:-128], data[-128:] 90 | des_key = RSA_decrypt(des_key_enc, bob_pri_key) 91 | data = DES_decrypt(data, des_key) 92 | data, signature = data[:-64], data[-64:] 93 | assert verify(data, signature, alice_pub_key) 94 | return data 95 | 96 | 97 | if __name__ == '__main__': 98 | alice_pri_key, alice_pub_key = generate_ECC_key() 99 | bob_pri_key, bob_pub_key = generate_RSA_key() 100 | data = b'Test Test Test Test Test Test Test Test Test Test Test Test Test Test Test Test !!!!!' 101 | data = PGP_send(data, alice_pri_key, bob_pub_key) 102 | data = PGP_recieve(data, alice_pub_key, bob_pri_key) 103 | print(data) 104 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # 华中科技大学密码学课程设计2019 2 | 3 | 文档说明:report.pdf 4 | -------------------------------------------------------------------------------- /RSA/47-1密码学中的数学原理之再谈碰撞.pptx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Billy1900/cryptography-course-project/7b182300889d400a6f258e1fb3488fb35eaac0d5/RSA/47-1密码学中的数学原理之再谈碰撞.pptx -------------------------------------------------------------------------------- /RSA/47-2密码学中的数学原理之Montgomery算法.pptx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Billy1900/cryptography-course-project/7b182300889d400a6f258e1fb3488fb35eaac0d5/RSA/47-2密码学中的数学原理之Montgomery算法.pptx -------------------------------------------------------------------------------- /RSA/CRT.cpp: -------------------------------------------------------------------------------- 1 | #include "RSA_Utils.h" 2 | 3 | //x=y^pow (mod(p*q)) 4 | void CRT(BIGNUM *Result,const BIGNUM *y, const BIGNUM *p, const BIGNUM *q,const BIGNUM *Pow){ 5 | BIGNUM *Cp = BN_new(); 6 | BIGNUM *Cq = BN_new(); 7 | BIGNUM *c1 = BN_new(); 8 | BIGNUM *c2 = BN_new(); 9 | BIGNUM *Pow1 = BN_new(); 10 | BIGNUM *Pow2 = BN_new(); 11 | BIGNUM *x11 = BN_new(); 12 | BIGNUM *x12 = BN_new(); 13 | BIGNUM *x21 = BN_new(); 14 | BIGNUM *x22 = BN_new(); 15 | BIGNUM *p_CutOne = BN_new(); 16 | BIGNUM *q_CutOne = BN_new(); 17 | BIGNUM *Mod = BN_new(); 18 | 19 | BN_CTX *ctx = BN_CTX_new(); 20 | 21 | BN_mul(Mod, p, q, ctx);//mod=n=p*q 22 | 23 | BN_sub(p_CutOne, p, BN_value_one());//p-1 24 | BN_sub(q_CutOne, q, BN_value_one());//q-1 25 | 26 | BN_nnmod(Pow1, Pow, p_CutOne, ctx);//计算Pow与p-1的模,小于0就加上p-1,存在Pow1中; 27 | BN_nnmod(Pow2, Pow, q_CutOne, ctx); 28 | 29 | ModRepeatSquare(Cp, y, p, Pow1);//Cp=y^Pow1(mod p) 30 | ModRepeatSquare(Cq, y, q, Pow2);//Cq=y^Pow2(mod q) 31 | 32 | BN_mod_inverse(c1,q,p,ctx);//模逆,((c*q)%p==1) 33 | BN_mod_inverse(c2,p,q,ctx); 34 | 35 | BN_mul(x11, Cp, c1, ctx);//x11=Cp*c1 36 | BN_mul(x12, x11, q, ctx);//x12=x11*q 37 | BN_mul(x21, Cq, c2, ctx);//x21=Cq*c2 38 | BN_mul(x22, x21, p, ctx);//x22=x21*p 39 | 40 | BN_mod_add(Result, x12, x22, Mod, ctx);//x=(x12+x22)mod Mod 41 | 42 | BN_CTX_free(ctx); 43 | 44 | BN_free(q_CutOne); 45 | BN_free(p_CutOne); 46 | BN_free(x22); 47 | BN_free(x21); 48 | BN_free(x12); 49 | BN_free(x11); 50 | BN_free(Pow2); 51 | BN_free(Pow1); 52 | BN_free(c2); 53 | BN_free(c1); 54 | BN_free(Cq); 55 | BN_free(Cp); 56 | } 57 | 58 | void CRT_Encrypt(const char *Plain,BIGNUM *Cipher,const BIGNUM *p,const BIGNUM *q,const BIGNUM *e){ 59 | BIGNUM *Plain_temp = BN_new(); 60 | 61 | BN_bin2bn((unsigned char*)Plain, strlen(Plain), Plain_temp); 62 | CRT(Cipher,Plain_temp,p,q,e); 63 | 64 | printf("Cipher:\n"); 65 | printf("%s\n",BN_bn2hex(Cipher)); 66 | 67 | BN_free(Plain_temp); 68 | } 69 | 70 | void CRT_Decrypt(const BIGNUM *Cipher,const BIGNUM *p,const BIGNUM *q,const BIGNUM *d){ 71 | BIGNUM *Plain_temp = BN_new(); 72 | 73 | CRT(Plain_temp,Cipher,p,q,d); 74 | 75 | printf("Plain:\n"); 76 | printf("%s\n",BN_bn2hex(Plain_temp)); 77 | 78 | BN_free(Plain_temp); 79 | } 80 | -------------------------------------------------------------------------------- /RSA/GeneratePara.cpp: -------------------------------------------------------------------------------- 1 | #include "RSA_Utils.h" 2 | 3 | void RSA_Parameter(BIGNUM *p, BIGNUM *q, BIGNUM *n, BIGNUM *d, BIGNUM *e){ 4 | 5 | BIGNUM *p_Cutone = BN_new(); 6 | BIGNUM *q_Cutone = BN_new(); 7 | BIGNUM *exp = BN_new(); 8 | BIGNUM *GCD = BN_new(); 9 | BN_CTX *ctx = BN_CTX_new(); 10 | 11 | //generate p,q 12 | do{ 13 | BN_generate_prime(p, 512, NULL, NULL, NULL, NULL, NULL); 14 | }while (!BN_is_prime(p,NULL,NULL,NULL,NULL)); 15 | do{ 16 | BN_generate_prime(q, 512, NULL, NULL, NULL, NULL, NULL); 17 | }while (!BN_is_prime(q,NULL,NULL,NULL,NULL)); 18 | 19 | BN_mul(n,p,q,ctx);//n=p*q 20 | BN_sub(p_Cutone,p,BN_value_one()); //p_Cutone = p - 1 21 | BN_sub(q_Cutone,q,BN_value_one());//q_Cutone = q - 1 22 | BN_mul(exp,p_Cutone,q_Cutone,ctx);//exp = p_Cutone * q_Cutone 23 | 24 | do{ 25 | BN_rand_range(e,exp); 26 | BN_gcd(GCD,e,exp,ctx); 27 | }while (BN_cmp(GCD,BN_value_one()));// e 28 | while (!BN_mod_inverse(d,e,exp,ctx));//d 29 | 30 | printf("private key:\n"); 31 | //printf("p:%s\n",BN_bn2hex(p)); 32 | //printf("q:%s\n",BN_bn2hex(q)); 33 | printf("N:%s\n",BN_bn2hex(n)); 34 | printf("d:%s\n",BN_bn2hex(d)); 35 | printf("Public key:\n"); 36 | printf("N:%s\n",BN_bn2hex(n)); 37 | printf("e:%s\n",BN_bn2hex(e)); 38 | 39 | BN_CTX_free(ctx); 40 | BN_free(GCD); 41 | BN_free(q_Cutone); 42 | BN_free(p_Cutone); 43 | BN_free(exp); 44 | } 45 | -------------------------------------------------------------------------------- /RSA/Mont.cpp: -------------------------------------------------------------------------------- 1 | #include "RSA_Utils.h" 2 | 3 | void Montgomerie(BIGNUM *Result, const BIGNUM *Base, const BIGNUM *Pow, const BIGNUM *Mod){ 4 | BIGNUM *Res = BN_new(); 5 | BIGNUM *Two = BN_new(); 6 | BIGNUM *Zero = BN_new(); 7 | BIGNUM *Cup = BN_new(); 8 | BIGNUM *Pow_backup = BN_new(); 9 | BN_CTX *ctx = BN_CTX_new(); 10 | 11 | BN_one(Result); 12 | BN_set_word(Zero, 0); 13 | BN_set_word(Two, 2); 14 | BN_copy(Res, Base); 15 | BN_copy(Pow_backup, Pow); 16 | // 17 | while (BN_cmp(Pow_backup, Zero) == 1)//大于0循环 18 | { 19 | BN_mod(Cup, Pow_backup, Two, ctx);//计算Pow_backup与2的模,存入Cup(取余) 20 | 21 | if (BN_is_zero(Cup)) { 22 | BN_mod_sqr(Res, Res, Mod, ctx);//Res=Res^2(mod Mod) 23 | 24 | BN_div(Pow_backup, NULL, Pow_backup, Two, ctx);//Pow_backup=Pow_backup/2 25 | 26 | } 27 | else { 28 | BN_mod_mul(Result, Result, Res, Mod, ctx);//Result=Result*Res(mod Mod) 29 | 30 | BN_sub(Pow_backup, Pow_backup, BN_value_one());//Pow_backup=Pow_backup-1 31 | } 32 | } 33 | 34 | BN_CTX_free(ctx); 35 | BN_free(Pow_backup); 36 | BN_free(Cup); 37 | BN_free(Zero); 38 | BN_free(Two); 39 | BN_free(Res); 40 | } 41 | 42 | void Mont_Encrypt(const char* plain,BIGNUM *Cipher,const BIGNUM *n, const BIGNUM *e){ 43 | BIGNUM *Plain_temp = BN_new(); 44 | BN_bin2bn((unsigned char*)plain,strlen(plain),Plain_temp); 45 | Montgomerie(Cipher,Plain_temp,e,n); 46 | 47 | printf("Cipher:\n"); 48 | printf("%s\n",BN_bn2hex(Cipher)); 49 | 50 | BN_free(Plain_temp); 51 | } 52 | 53 | void Mont_Decrypt(const BIGNUM *Cipher, const BIGNUM *n, const BIGNUM *d){ 54 | BIGNUM *Plain_temp = BN_new(); 55 | 56 | Montgomerie(Plain_temp,Cipher,d,n); 57 | 58 | printf("Plain:\n"); 59 | printf("%s\n",BN_bn2hex(Plain_temp)); 60 | 61 | BN_free(Plain_temp); 62 | } 63 | -------------------------------------------------------------------------------- /RSA/RSA_Utils.h: -------------------------------------------------------------------------------- 1 | 2 | #ifndef RSA_RSA_UTILS_H 3 | #define RSA_RSA_UTILS_H 4 | 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | void RSA_Parameter(BIGNUM *p, BIGNUM *q, BIGNUM *n, BIGNUM *d, BIGNUM *e); 11 | 12 | void ModRepeatSquare(BIGNUM *Result,const BIGNUM *b,const BIGNUM *Mod,const BIGNUM *Pow); 13 | void ModRepeat_Encrypt(BIGNUM *n,BIGNUM *e,const char *Plain,BIGNUM *Cipher); 14 | void ModRepeat_Decryption(BIGNUM *n,BIGNUM *d,BIGNUM *Cipher); 15 | 16 | void CRT(BIGNUM *x,const BIGNUM *y, const BIGNUM *p, const BIGNUM *q,const BIGNUM *Pow); 17 | void CRT_Encrypt(const char *Plain,BIGNUM *Cipher,const BIGNUM *p,const BIGNUM *q,const BIGNUM *e); 18 | void CRT_Decrypt(const BIGNUM *Cipher,const BIGNUM *p,const BIGNUM *q,const BIGNUM *d); 19 | 20 | void Montgomerie(BIGNUM *Result, const BIGNUM *Base, const BIGNUM *Pow, const BIGNUM *Mod); 21 | void Mont_Encrypt(const char* plain,BIGNUM *Cipher,const BIGNUM *n, const BIGNUM *e); 22 | void Mont_Decrypt(const BIGNUM *Cipher, const BIGNUM *n, const BIGNUM *d); 23 | 24 | #endif //RSA_RSA_UTILS_H 25 | -------------------------------------------------------------------------------- /RSA/Readme.md: -------------------------------------------------------------------------------- 1 | This is a small project on **RSA**, by using **Montgomerie, CRT, Mod Repeatation** algorithm. 2 | 3 | 4 | This file can be compiled on Linux 5 | 6 | Dependencies: openssl 1.1.0 7 | 8 | command line: add Parameter when you compile it, such as
 gcc \ -o \ -lcrypto -lssl
9 | -------------------------------------------------------------------------------- /RSA/main.cpp: -------------------------------------------------------------------------------- 1 | #include "RSA_Utils.h" 2 | 3 | int main(){ 4 | BIGNUM *p=BN_new(); 5 | BIGNUM *q=BN_new(); 6 | BIGNUM *n=BN_new(); 7 | BIGNUM *d=BN_new(); 8 | BIGNUM *e=BN_new(); 9 | BIGNUM *Cipher = BN_new(); 10 | const char* Plain = "1100"; 11 | 12 | clock_t start,end; 13 | start = clock(); 14 | 15 | //generate parameter 16 | RSA_Parameter(p,q,n,d,e); 17 | 18 | //Modrepeat 19 | // ModRepeat_Encrypt(n,e,Plain,Cipher); 20 | // ModRepeat_Decryption(n,d,Cipher); 21 | 22 | //CRT 23 | //CRT_Encrypt(Plain,Cipher,p,q,e); 24 | //CRT_Decrypt(Cipher,p,q,d); 25 | 26 | //Mont 27 | //Mont_Encrypt(Plain,Cipher,n,e); 28 | //Mont_Decrypt(Cipher,n,d); 29 | 30 | 31 | end = clock(); 32 | printf("the time is:%g ms\n",double(end-start)); 33 | } 34 | -------------------------------------------------------------------------------- /RSA/modRepeat.cpp: -------------------------------------------------------------------------------- 1 | #include "RSA_Utils.h" 2 | 3 | void ModRepeatSquare(BIGNUM *Result,const BIGNUM *b,const BIGNUM *Mod,const BIGNUM *Pow){ 4 | BIGNUM *DivRes = BN_new(); 5 | BIGNUM *Cup_b = BN_new(); 6 | BIGNUM *Cup_Pow = BN_new(); 7 | BIGNUM *a = BN_new(); 8 | BIGNUM *a_new = BN_new(); 9 | BIGNUM *b_sqr = BN_new(); 10 | BIGNUM *Rem = BN_new(); 11 | BIGNUM *Two = BN_new(); 12 | 13 | BN_CTX *ctx = BN_CTX_new(); 14 | BN_copy(Cup_b,b); 15 | BN_copy(Cup_Pow,Pow); 16 | 17 | BN_set_word(a_new,1); 18 | BN_set_word(Two,2); 19 | //(b^pow)mod(mod)=result 20 | //将Pow转换为二进制的算法:位上为1是an=an-1*bn,bn=bn-1*bn-1;位上为0时是an=an-1,bn=bn-1*bn-1 21 | do { 22 | BN_div(DivRes, Rem, Cup_Pow, Two, ctx);//计算Cup_Pow与Two的商,值储存在DivRes中,余数储存在rem中。 23 | if (BN_is_one(Rem)) 24 | BN_mod_mul(a, a_new, Cup_b, Mod, ctx);//计算a_new与Cup_b的积,再模mod,值储存在a中。 25 | else BN_copy(a, a_new); 26 | 27 | BN_mod_sqr(b_sqr, Cup_b, Mod, ctx);//计算Cup_b^2,再模mod,值储存在b_sqr中; 28 | 29 | 30 | BN_copy(a_new, a); 31 | BN_copy(Cup_Pow, DivRes); 32 | BN_copy(Cup_b, b_sqr); 33 | 34 | } while (!BN_is_zero(DivRes));//余数为0跳出循环 35 | 36 | BN_copy(Result,a); 37 | 38 | BN_CTX_free(ctx); 39 | BN_free(Two); 40 | BN_free(Rem); 41 | BN_free(b_sqr); 42 | BN_free(a_new); 43 | BN_free(a); 44 | BN_free(Cup_Pow); 45 | BN_free(Cup_b); 46 | BN_free(DivRes); 47 | } 48 | 49 | void ModRepeat_Encrypt(BIGNUM *n,BIGNUM *e,const char *Plain,BIGNUM *Cipher){ 50 | BIGNUM *Plain_temp = BN_new(); 51 | 52 | BN_bin2bn((unsigned char*)Plain, strlen(Plain), Plain_temp); 53 | ModRepeatSquare(Cipher, Plain_temp, n, e); 54 | 55 | printf("Cipher:\n"); 56 | printf("%s\n",BN_bn2hex(Cipher)); 57 | 58 | BN_free(Plain_temp); 59 | } 60 | 61 | void ModRepeat_Decryption(BIGNUM *n,BIGNUM *d,BIGNUM *Cipher){ 62 | BIGNUM *Plain_temp = BN_new(); 63 | 64 | ModRepeatSquare(Plain_temp,Cipher,n,d); 65 | 66 | printf("Plain:\n"); 67 | printf("%s\n",BN_bn2hex(Plain_temp)); 68 | 69 | BN_free(Plain_temp); 70 | } 71 | -------------------------------------------------------------------------------- /RSA/mont最新解释.ppt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Billy1900/cryptography-course-project/7b182300889d400a6f258e1fb3488fb35eaac0d5/RSA/mont最新解释.ppt -------------------------------------------------------------------------------- /RainbowTable/FileDivision.cpp: -------------------------------------------------------------------------------- 1 | #include "Rainbow_Table_head.hpp" 2 | 3 | bool openRainbowTableFile(char *filename, Tree_Node_ptr &T){ 4 | // 先打开彩虹表文件 5 | FILE *fo = fopen(filename, "r"); 6 | if (fo == NULL) { 7 | printf("file can not open!\n"); 8 | return false; 9 | } 10 | printf("file is loading.....\n"); 11 | while (true){ 12 | bool taller = 0; 13 | unsigned char * head= (unsigned char*)malloc(sizeof(unsigned char) * stringlength); 14 | unsigned char * tail= (unsigned char*)malloc(sizeof(unsigned char) * stringlength); 15 | // 当读到文件尾时,跳出循环 16 | if (fgets((char *)head, stringlength+1, fo) == NULL) 17 | break; 18 | getc(fo); 19 | fgets((char *)tail, stringlength+1, fo); 20 | getc(fo); 21 | Tree_insert_AVL(T, head, tail, taller); 22 | } 23 | printf("file extract succeed!"); 24 | return true; 25 | } 26 | -------------------------------------------------------------------------------- /RainbowTable/Rainbow_Table_Gen.cpp: -------------------------------------------------------------------------------- 1 | #include "Rainbow_Table_head.hpp" 2 | 3 | unsigned char* formatConvert(char *raw){ 4 | /* 5 | 将输入的字符串形式的 MD5 码转换成数字 6 | */ 7 | unsigned char *converted = (unsigned char*)malloc(sizeof(unsigned char) * 16); 8 | for (int i=0; i<16; i++) { 9 | int a = 0,b = 0; 10 | if (raw[2*i] >= '0' && raw[2*i] <= '9') 11 | a = raw[2*i] - '0'; 12 | else if (raw[2*i] >= 'a' && raw[2*i] <= 'f') 13 | a = raw[2*i] - 'a' + 10; 14 | 15 | if (raw[2*i + 1] >= '0' && raw[2*i + 1] <= '9') 16 | b = raw[2*i + 1] - '0'; 17 | else if (raw[2*i + 1] >= 'a' && raw[2*i + 1] <= 'f') 18 | b = raw[2*i + 1] - 'a' + 10; 19 | converted[i] = (unsigned char)((a << 4) + b); 20 | } 21 | return converted; 22 | } 23 | 24 | unsigned char *Red(unsigned char* md5_cr, int round, int lenth,unsigned char* pre_str){ 25 | /* 26 | 约简函数,将 MD5 按照一定规则转换到 Z36 域中 27 | pre_str 是之前的字符串,释放其空间 28 | */ 29 | if (pre_str != NULL) { 30 | free(pre_str); 31 | } 32 | unsigned char *Reduced = (unsigned char*)malloc(sizeof(char) * (lenth+1)); 33 | for (int i = 0; i < lenth; i++){ 34 | Reduced[i] = (md5_cr[(round + i*2) % 16] + round) % 36;// 随机选择md5中的若干位,映射到Z36中 35 | if (Reduced[i] >= 0 && Reduced[i] <= 9) 36 | Reduced[i] += '0'; 37 | else if (Reduced[i] >= 10 && Reduced[i] <=36) 38 | Reduced[i] = Reduced[i] - 10 + 'a'; 39 | } 40 | Reduced[lenth] = '\0'; 41 | return Reduced; 42 | } 43 | 44 | bool insert_node_to_write(Tree_Node_ptr &head, Tree_Node_ptr &tail, Tree_Node_ptr ¤t){ 45 | // 仅仅构成一个单向链表, head 指向链表首节点, tail 指向链表尾节点 46 | if (current == NULL) { 47 | return false; 48 | } 49 | if (head == NULL && tail == NULL) { 50 | // 当是空链时插入一个节点 51 | head = current; 52 | tail = current; 53 | return true; 54 | } 55 | tail->right = current; 56 | tail = current; 57 | return true; 58 | } 59 | 60 | void rainbow_table_gen(int length, int chainLength){ 61 | int count = 0; 62 | int writeTime = 0; 63 | 64 | Tree_Node_ptr head_total = NULL; 65 | if (openRainbowTableFile(rainbow_table_filename, head_total)) 66 | printf("文件读取完成!\n"); 67 | else printf("正在新建文件.....\n"); 68 | 69 | int index[stringlength] = {0,2,35,14,0,0,0}; 70 | int loop_level; // 指示当前循环的层数 71 | 72 | // 当生成的链数少于 chainNum 时不进行文件写操作 73 | count = 0; 74 | Tree_Node_ptr head_to_write = NULL, tail_to_write = NULL; 75 | // 一个多重循环, 循环层数为待生成的字符串长度。用于遍历生成首节点 76 | do { 77 | // 每次都从最里层循环开始 78 | loop_level = stringlength-1; 79 | // 生成单个字符, 共生成 stringlength 长度的字符串 80 | unsigned char *head_str = (unsigned char *)malloc(sizeof(char) * (length+1)); 81 | for (int i = 0; i < stringlength; i++) { 82 | head_str[i] = index[i]; 83 | if (head_str[i] >= 0 && head_str[i] <= 9) 84 | head_str[i] += '0'; 85 | else if (head_str[i] >= 10 && head_str[i] <=36) 86 | head_str[i] = head_str[i] - 10 + 'a'; 87 | } 88 | head_str[length] = '\0'; 89 | // 计算生成彩虹链中的最后一个节点 90 | unsigned char *node_str = (unsigned char *)malloc(sizeof(char) * (length+1)); 91 | memcpy(node_str, head_str, sizeof(char) * (length+1)); 92 | for (int round = 0; round < chainLength; round++) { 93 | unsigned char mdStr[16] = {0}; 94 | MD5(node_str, length, mdStr); 95 | node_str = Red(mdStr, round, length, node_str); 96 | } 97 | // 尝试将这一条链(首节点和尾节点)插入总的树中 98 | bool taller = 0; 99 | if (Tree_insert_AVL(head_total, head_str, node_str, taller)){ 100 | // 若成功插入, 则把这一条链插入到待写入的链表中 101 | Tree_Node_ptr node_to_write= (Tree_Node_ptr)malloc(sizeof(Tree_Node)); 102 | node_to_write->head = head_str; 103 | node_to_write->value = node_str; 104 | node_to_write->left = NULL; 105 | node_to_write->right = NULL; 106 | //printf("%s %s\n",head_str, node_str); 107 | insert_node_to_write(head_to_write, tail_to_write, node_to_write); 108 | count ++; // 计数器增加 109 | } 110 | // 计数器达到 1000 时, 写文件 111 | if (count == chainNumToWrite){ 112 | //Tree_preOrder_traverse(head_to_write); 113 | printf("!!写文件%d\n",++writeTime); 114 | FILE *fp = fopen(rainbow_table_filename, "a"); 115 | Tree_Node_ptr writing = head_to_write, temp; 116 | while (writing != NULL) { 117 | // 读取节点信息, 写入文件后释放空间 118 | fputs((char *)writing->head, fp); 119 | fputs(" ", fp); 120 | fputs((char *)writing->value, fp); 121 | fputs("\n", fp); 122 | temp = writing->right; 123 | free(writing); 124 | writing = temp; 125 | } 126 | // 待写入的链表清空 127 | head_to_write = tail_to_write = NULL; 128 | // 计数器清空 129 | count = 0; 130 | fclose(fp); 131 | } 132 | // 循环控制 133 | while (loop_level > 0 && (++index[loop_level] > charLimit)) { 134 | index[loop_level] = 0; 135 | loop_level --; 136 | } 137 | } while (loop_level > 0); 138 | } 139 | -------------------------------------------------------------------------------- /RainbowTable/Rainbow_Table_head.hpp: -------------------------------------------------------------------------------- 1 | #ifndef Rainbow_Table_Gen_hpp 2 | #define Rainbow_Table_Gen_hpp 3 | 4 | #include "openssl/md5.h" 5 | #include "stdio.h" 6 | #include "time.h" 7 | #include "stdlib.h" 8 | #include "string.h" 9 | 10 | #define random(x) (rand()%x) 11 | #define chainNumToWrite 1000 12 | #define nodeInChain 1000 13 | #define stringlength 7 14 | #define charLimit 35 15 | #define LH +1 16 | #define EH 0 17 | #define RH -1 18 | #define rainbow_table_filename "D:\\RainbowTable\\Tablelist.txt" 19 | 20 | typedef unsigned char* ElemType; 21 | typedef struct Tree_Node{ 22 | ElemType head,value; 23 | char bf; // 节点的平衡因子 24 | struct Tree_Node *left, *right; // 左、右孩子指针 25 | } Tree_Node, *Tree_Node_ptr; 26 | 27 | void rainbow_table_gen(int length, int chainLength); 28 | unsigned char *Red(unsigned char* md5_cr, int round, int lenth, unsigned char* pre_str); 29 | bool insert_node_to_write(Tree_Node_ptr &head, Tree_Node_ptr &tail, Tree_Node_ptr ¤t); 30 | bool md5Cracker(unsigned char* md5code, Tree_Node_ptr &T); 31 | bool openRainbowTableFile(char *filename, Tree_Node_ptr &head); 32 | unsigned char encode(unsigned char); 33 | unsigned char* formatConvert(char *raw); 34 | 35 | Tree_Node_ptr Tree_search(Tree_Node_ptr head, ElemType value); 36 | 37 | bool Tree_inOrder_traverse(Tree_Node_ptr); 38 | bool Tree_preOrder_traverse(Tree_Node_ptr); 39 | bool Tree_lastOrder_traverse(Tree_Node_ptr); 40 | 41 | void R_Rotate(Tree_Node_ptr &p); 42 | void L_Rotate(Tree_Node_ptr &p); 43 | void LeftBalance(Tree_Node_ptr &T); 44 | void RightBalance(Tree_Node_ptr &T); 45 | 46 | bool Tree_insert_AVL(Tree_Node_ptr &T, ElemType head, ElemType e, bool &taller); 47 | #endif /* Rainbow_Table_Gen_hpp */ 48 | -------------------------------------------------------------------------------- /RainbowTable/Readme.md: -------------------------------------------------------------------------------- 1 | # Version Explaination 2 | * version 0.9: 发现一个致命bug,但是还没找到错误根源 3 | * version 1.0: 功能基本符合要求, 生成彩虹表可能耗时很久 4 | * version 1.1: 生成一个成功率在30%左右的彩虹表需要约20h,会生成约1.3G的文本文件 5 | 6 | # Guide 7 | * You need to modify the file path in "Rainbow_Table_head.hpp" 8 | * In case of plagiarizing, you should modify the Red() function in "Rainbow_Table_Gen.cpp" 9 | -------------------------------------------------------------------------------- /RainbowTable/avl_tree.cpp: -------------------------------------------------------------------------------- 1 | #include "Rainbow_Table_head.hpp" 2 | #include "string.h" 3 | void R_Rotate(Tree_Node_ptr &p){ 4 | /* 5 | 对以*p为根的二叉排序树进行右旋处理,处理之后p指向新的树根节点, 6 | 即旋转处理之前的左子树的根节点 7 | */ 8 | Tree_Node_ptr lc = p->left; 9 | p->left = lc->right; 10 | lc->right = p; 11 | p = lc; 12 | } // R_Rotate 13 | 14 | void L_Rotate(Tree_Node_ptr &p){ 15 | /* 16 | 对以*p为根的二叉排序树进行左旋处理,处理之后p指向新的树根节点, 17 | 即旋转处理之前的右子树的根节点 18 | */ 19 | Tree_Node_ptr lc = p->right; 20 | p->right = lc->left; 21 | lc->left = p; 22 | p = lc; 23 | } 24 | 25 | Tree_Node_ptr Tree_search(Tree_Node_ptr head, ElemType value){ 26 | // AVL树的搜索的非递归实现 27 | Tree_Node_ptr current = head; 28 | while (current != NULL && strcmp((char*)value, (char*)current->value) != 0) { 29 | if (strcmp((char*)value, (char*)current->value) < 0) 30 | current = current->left; 31 | else 32 | current = current->right; 33 | } 34 | return current; 35 | } 36 | 37 | bool Tree_inOrder_traverse(Tree_Node_ptr root){ 38 | // 二叉树的中序遍历 39 | // 先访问左子树 40 | if(root->left != NULL) 41 | Tree_inOrder_traverse(root->left); 42 | // 再访问根节点 43 | printf("%s -> ",root->value); 44 | // 最后访问右子树 45 | if (root->right != NULL) 46 | Tree_inOrder_traverse(root->right); 47 | return true; 48 | } 49 | 50 | bool Tree_preOrder_traverse(Tree_Node_ptr root){ 51 | // 二叉树的先序遍历 52 | // 先访问根节点 53 | printf("%s\n",root->value); 54 | // 再访问左子树 55 | if(root->left != NULL) 56 | Tree_preOrder_traverse(root->left); 57 | // 再访问右子树 58 | if (root->right != NULL) 59 | Tree_preOrder_traverse(root->right); 60 | return true; 61 | } 62 | 63 | bool Tree_lastOrder_traverse(Tree_Node_ptr root){ 64 | // 二叉树的先序遍历 65 | // 先访问左子树 66 | if(root->left != NULL) 67 | Tree_lastOrder_traverse(root->left); 68 | // 再访问右子树 69 | if (root->right != NULL) 70 | Tree_lastOrder_traverse(root->right); 71 | // 再访问根节点 72 | printf("%s -> ",root->value); 73 | return true; 74 | } 75 | 76 | bool Tree_insert_AVL(Tree_Node_ptr &T, ElemType head, ElemType e, bool &taller){ 77 | /* 78 | 若在平衡的二叉排序树T中不存在和 e 有相同关键字的节点 79 | 则插入一个数据元素为 e 的新节点,并返回 1 ,否则返回 0 80 | 若因插入而使二叉排序树失去平衡 81 | 则作平衡旋转处理,布尔变量 taller 反应 T 长高与否 82 | */ 83 | if (!T){ 84 | T = (Tree_Node_ptr)malloc(sizeof(Tree_Node)); 85 | T->value = e; 86 | T->head = head; 87 | T->right = T->left = NULL; 88 | T->bf = EH; taller = true; 89 | } 90 | else { 91 | if (strcmp((char*)e,(char*)T->value) == 0) { 92 | taller = false; 93 | return 0; 94 | } 95 | if (strcmp((char*)e,(char*)T->value) < 0) { 96 | if (!Tree_insert_AVL(T->left, head, e, taller)) 97 | return 0; // 未插入 98 | if (taller) 99 | switch (T->bf) { 100 | case LH: 101 | LeftBalance(T); 102 | taller = false; 103 | break; 104 | case EH: 105 | T->bf = LH; 106 | taller = true; 107 | break; 108 | case RH: 109 | T->bf = EH; 110 | taller = false; 111 | break; 112 | } 113 | } 114 | else { 115 | if (!Tree_insert_AVL(T->right, head, e, taller)) 116 | return 0; 117 | if (taller) { 118 | switch (T->bf) { 119 | case LH: 120 | T->bf = RH; 121 | taller = false; 122 | break; 123 | case EH: 124 | T->bf = RH; 125 | taller = true; 126 | break; 127 | case RH: 128 | RightBalance(T); 129 | taller = false; 130 | break; 131 | } 132 | } 133 | } 134 | } 135 | return 1; 136 | } 137 | void LeftBalance(Tree_Node_ptr &T){ 138 | /* 139 | 对以指针 T 所指结点为根的二叉树作作平衡旋转处理 140 | 结束时指针 T 指向新的根节点 141 | */ 142 | Tree_Node_ptr lc = T->left; 143 | switch (lc->bf) { 144 | case LH: 145 | T->bf = lc->bf = EH; 146 | R_Rotate(T); 147 | break; 148 | case RH: 149 | Tree_Node_ptr rd = lc->right; 150 | switch (rd->bf) { 151 | case LH: 152 | T->bf = RH; 153 | lc->bf = EH; 154 | break; 155 | case EH: 156 | T->bf = lc->bf = EH; 157 | break; 158 | case RH: 159 | T->bf = EH; 160 | lc->bf = LH; 161 | break; 162 | } 163 | rd->bf = EH; 164 | L_Rotate(T->left); 165 | R_Rotate(T); 166 | } 167 | } 168 | void RightBalance(Tree_Node_ptr &T){ 169 | /* 170 | 对以指针 T 所指结点为根的二叉树作作平衡旋转处理 171 | 结束时指针 T 指向新的根节点 172 | */ 173 | Tree_Node_ptr rd = T->right; 174 | switch (rd->bf) { 175 | case RH: 176 | T->bf = rd->bf = EH; 177 | L_Rotate(T); 178 | break; 179 | case LH: 180 | Tree_Node_ptr lc = rd->left; 181 | switch (lc->bf) { 182 | case LH: 183 | T->bf = EH; 184 | rd->bf = RH; 185 | break; 186 | case EH: 187 | T->bf = rd->bf = EH; 188 | break; 189 | case RH: 190 | T->bf = LH; 191 | rd->bf = EH; 192 | break; 193 | } 194 | lc->bf = EH; 195 | R_Rotate(T->right); 196 | L_Rotate(T); 197 | } 198 | } 199 | -------------------------------------------------------------------------------- /RainbowTable/main.cpp: -------------------------------------------------------------------------------- 1 | #include "Rainbow_Table_head.hpp" 2 | 3 | int main(void){ 4 | int op; 5 | printf("1) Generate Rainbow Table 2) md5 Decrypt\n"); 6 | scanf("%d",&op); 7 | switch (op) { 8 | case 1: 9 | // 能破译长度为 stringlength 的字符串(小写字母和数字) 10 | // 每条彩虹链中计算 nodeInChain 次节点 11 | rainbow_table_gen(stringlength, nodeInChain); 12 | break; 13 | case 2: 14 | { 15 | 16 | Tree_Node_ptr T = NULL; 17 | clock_t start = clock(); 18 | openRainbowTableFile("D:\\RainbowTable\\Tablelist.txt", T);//文件路径修改 19 | clock_t end = clock(); 20 | printf("Time cost : %lu",(end-start)/CLOCKS_PER_SEC); 21 | char md5Str[32] = {0}; 22 | while (true) { 23 | printf("\n请输入要解密的md5码:\n"); 24 | scanf("%32s",md5Str); 25 | // 将字符串转换成16进制 26 | unsigned char *md5 = formatConvert(md5Str); 27 | md5Cracker(md5, T); 28 | } 29 | break; 30 | } 31 | default: 32 | break; 33 | } 34 | 35 | } 36 | 37 | -------------------------------------------------------------------------------- /RainbowTable/md5Cracker.cpp: -------------------------------------------------------------------------------- 1 | #include "Rainbow_Table_head.hpp" 2 | 3 | bool md5Cracker(unsigned char* md5code, Tree_Node_ptr &T){ 4 | // 再依次假设其在彩虹表中的位置 5 | printf("searching....\n"); 6 | unsigned char* pass = md5code; 7 | for (int i = 0; i < nodeInChain; i++) { 8 | pass = Red(md5code, i, stringlength, NULL); 9 | for (int round = i+1; round < nodeInChain; round++) { 10 | unsigned char mdStr[16] = {0}; 11 | MD5(pass, stringlength, mdStr); 12 | pass = Red(mdStr, round, stringlength, NULL); 13 | } 14 | // 在二叉树中搜索该尾节点 15 | Tree_Node_ptr matched = Tree_search(T, pass); 16 | if (matched != NULL) { 17 | // 如果匹配到链尾相同, 则要从链头计算一遍 18 | unsigned char* chainHead = matched->head; 19 | for (int round = 0; round < i; round++) { 20 | unsigned char mdStr[16] = {0}; 21 | MD5(chainHead, stringlength, mdStr); 22 | chainHead = Red(mdStr, round, stringlength, NULL); 23 | } 24 | unsigned char mdStr[16] = {0}; 25 | MD5(chainHead, stringlength, mdStr); 26 | // 如果比较发现并不一致, 则认为是错误的链, 应该继续比较 27 | bool flag = 0; // 指示两者的比较情况 28 | for (int i = 0; i < 16; i++) 29 | if (mdStr[i] != md5code[i]) { 30 | flag = 1; 31 | break; 32 | } 33 | printf("head: %s\t tail: %s result:%s\n",matched->head, pass, chainHead); 34 | if (!flag){ 35 | printf("found! The result is:\n"); 36 | printf("%s\n",chainHead); 37 | return true; 38 | } 39 | } 40 | } 41 | // 匹配失败, 彩虹链中找不到这个md5 42 | printf("sorry, we failed!\n"); 43 | return true; 44 | } 45 | 46 | -------------------------------------------------------------------------------- /Report.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Billy1900/cryptography-course-project/7b182300889d400a6f258e1fb3488fb35eaac0d5/Report.pdf -------------------------------------------------------------------------------- /SPN/DifferentialAttack.cpp: -------------------------------------------------------------------------------- 1 | #include "Utils.h" 2 | 3 | const int Di_pairs = 8000; 4 | extern unsigned int HexKey; 5 | extern short Reverse_SubMap[]; 6 | unsigned int Ruler = 0x0b00; 7 | unsigned short Ruler_24 = 0x6; 8 | unsigned short Ruler_13 = 0x6; 9 | 10 | void gene_Di(unsigned short* Input, unsigned short* Output,unsigned short* _Input_,unsigned short* _Output_){ 11 | unsigned short x,y,_x_,_y_; 12 | srand((unsigned)time(nullptr)); 13 | for (int i = 0; i < Di_pairs; ++i) { 14 | x = rand() % 0xffff; 15 | SPN(x,y,HexKey); 16 | _x_ = x ^ Ruler; 17 | SPN(_x_,_y_,HexKey); 18 | Input[i] = x; 19 | Output[i] = y; 20 | _Input_[i] = _x_; 21 | _Output_[i] = _y_; 22 | //cout<>12; 34 | _y1_ = (_Output_[i] & 0xf000)>>12; 35 | y2 = (Output[i] & 0x0f00)>>8; 36 | _y2_ = (_Output_[i] & 0x0f00)>>8; 37 | y3 = (Output[i] & 0x00f0)>>4; 38 | _y3_ = (_Output_[i] & 0x00f0)>>4; 39 | y4 = (Output[i] & 0x000f); 40 | _y4_ = (_Output_[i] & 0x000f); 41 | //2,4 42 | if (y1 == _y1_ && y3 == _y3_) { 43 | for (short j = 0; j < 16; ++j) { 44 | L2 = j; 45 | for (short k = 0; k < 16; ++k) { 46 | L4 = k; 47 | V42 = L2 ^ y2; 48 | V44 = L4 ^ y4; 49 | U42 = Reverse_SubMap[V42]; 50 | U44 = Reverse_SubMap[V44]; 51 | _V42_ = L2 ^ _y2_; 52 | _V44_ = L4 ^ _y4_; 53 | _U42_ = Reverse_SubMap[_V42_]; 54 | _U44_ = Reverse_SubMap[_V44_]; 55 | uu42 = U42 ^ _U42_; 56 | uu44 = U44 ^ _U44_; 57 | if (uu42 == Ruler_24 && uu44 == Ruler_24) 58 | count_24[j][k]++; 59 | } 60 | } 61 | } 62 | //1,3 63 | if (y2 == _y2_ && y4 == _y4_){ 64 | for (short i = 0; i < 16; ++i) { 65 | L1 = i; 66 | for (short j = 0; j < 16; ++j) { 67 | L3 = j; 68 | V41 = y1 ^ L1; 69 | V43 = y3 ^ L3; 70 | U41 = Reverse_SubMap[V41]; 71 | U43 = Reverse_SubMap[V43]; 72 | _V41_ = _y1_ ^ L1; 73 | _V43_ = _y3_ ^ L3; 74 | _U41_ = Reverse_SubMap[_V41_]; 75 | _U43_ = Reverse_SubMap[_V43_]; 76 | uu41 = U41 ^ _U41_; 77 | uu43 = U43 ^ _U43_; 78 | if (uu41 == Ruler_13 && uu43 == Ruler_13) 79 | count_13[i][j]++; 80 | } 81 | } 82 | } 83 | } 84 | 85 | short max_24,max_13 = -1; 86 | unsigned short max_1,max_2,max_3,max_4; 87 | for (short i = 0; i < 16; ++i) { 88 | for (short j = 0; j < 16; ++j) { 89 | if (count_24[i][j] > max_24){ 90 | max_24 = count_24[i][j]; 91 | max_2 = i; 92 | max_4 = j; 93 | } 94 | if (count_13[i][j] > max_13){ 95 | max_13 = count_13[i][j]; 96 | max_1 = i; 97 | max_3 = j; 98 | } 99 | } 100 | } 101 | key_r16 = (max_1<<12) | (max_2<<8) | (max_3<<4) | (max_4); 102 | cout<>12; 26 | Y2 = (Output[i] & 0x0f00)>>8; 27 | Y3 = (Output[i] & 0x00f0)>>4; 28 | Y4 = (Output[i] & 0x000f); 29 | for (short j = 0; j < 16; ++j) { 30 | L4 = j; 31 | L1 = L4; 32 | for (short k = 0; k < 16; ++k) { 33 | L2 = k; 34 | L3 = L2; 35 | V_41 = Y1 ^ L1; 36 | V_42 = Y2 ^ L4; 37 | V_43 = Y3 ^ L3; 38 | V_44 = Y4 ^ L2; 39 | U_41 = Reverse_SubMap[V_41]; 40 | U_42 = Reverse_SubMap[V_42]; 41 | U_43 = Reverse_SubMap[V_43]; 42 | U_44 = Reverse_SubMap[V_44]; 43 | short Z_24 = ((Input[i] & 0x0800)>>11) ^ ((Input[i] & 0x0200)>>9) ^ ((Input[i] & 0x0100)>>8) 44 | ^ ((U_42 & 0x4)>>2) ^ (U_42 & 0x1) ^ ((U_44 & 0x4)>>2) ^ (U_44 & 0x1); 45 | if (Z_24 == 0) 46 | count_24[j][k]++; 47 | short Z_13 = ((Input[i] & 0x0400)>>10) ^ ((Input[i] & 0x0200)>>9) ^ ((Input[i] & 0x0100)>>8) 48 | ^ ((U_43 & 0x4)>>2) ^ (U_43 & 0x1) ^ ((U_41 & 0x4)>>2) ^ (U_41 & 0x1); 49 | if(Z_13 == 0) 50 | count_13[j][k]++; 51 | } 52 | } 53 | } 54 | 55 | short max_24 = -1; 56 | short max_13 = -1; 57 | unsigned short Max_1,Max_2,Max_3,Max_4 = 0x0; 58 | for (short i = 0; i < 16; ++i) { 59 | for (short j = 0; j < 16; ++j) { 60 | count_24[i][j] = abs(count_24[i][j] - pairs/2); 61 | count_13[i][j] = abs(count_13[i][j] - pairs/2); 62 | if(count_24[i][j] > max_24){ 63 | max_24 = count_24[i][j]; 64 | Max_2 = i; 65 | Max_4 = j; 66 | } 67 | if(count_13[i][j] > max_13){ 68 | max_13 = count_13[i][j]; 69 | Max_1 = i; 70 | Max_3 = j; 71 | } 72 | } 73 | } 74 | key_r16 = (Max_1<<12) | (Max_2<<8) | (Max_3<<4) | Max_4; 75 | //cout<>((7-j)*8); 34 | mask = mask>>8; 35 | } 36 | fout.write(t,8); 37 | 38 | count = 0; 39 | } 40 | } 41 | 42 | fin.close(); 43 | fout.close(); 44 | } 45 | 46 | void RandTest(){ 47 | Write(); 48 | Rand(); 49 | } 50 | 51 | -------------------------------------------------------------------------------- /SPN/SPN.cpp: -------------------------------------------------------------------------------- 1 | #include "Utils.h" 2 | 3 | unsigned int HexKey = 0x3a94d63f; 4 | 5 | unsigned short Sub_map_value[] = {0xE,0x4,0xD,0x1,0x2,0xF,0xB,0x8,0x3,0xA,0x6,0xC,0x5,0x9,0x0,0x7}; 6 | 7 | unsigned short Per_map_value[] = {1,5,9,13,2,6,10,14,3,7,11,15,4,8,12,16}; 8 | 9 | void Key_arrange(int i,unsigned short &Kr,unsigned int Key){ 10 | unsigned int mask = 0xffff0000; 11 | i -= 1; 12 | mask = mask>>(4*i); 13 | Kr = (Key & mask)>>(4-i)*4; 14 | } 15 | 16 | void Substi(unsigned short Ur, unsigned short &Vr){ 17 | unsigned short mask[] = {0xf000,0x0f00,0x00f0,0x000f}; 18 | unsigned short res; 19 | unsigned short temp = 0x0000; 20 | for (int i = 0; i < 4; ++i) { 21 | res = (Ur & mask[i])>>(4*(3-i)); 22 | temp |= (Sub_map_value[res]<<(4*(3-i))); 23 | } 24 | Vr = temp; 25 | } 26 | 27 | void Permutation(unsigned short Vr, unsigned short &w){ 28 | unsigned int mask = 0x10000; 29 | unsigned short temp; 30 | unsigned short res = 0x0000; 31 | for (int i = 0; i < 16; ++i) { 32 | mask = mask>>1; 33 | temp = (Vr & mask)>>(15-i); 34 | res = res | (temp<<(16-Per_map_value[i])); 35 | } 36 | w = res; 37 | } 38 | 39 | void SPN(unsigned short hex_x, unsigned short &res, unsigned int Key){ 40 | unsigned short w = hex_x; 41 | unsigned short Kr,Ur,Vr = 0x0000; 42 | int Nr = 4; 43 | for (int r = 1; r <= Nr-1; ++r) { 44 | Key_arrange(r, Kr, Key); 45 | //cout<<"Kr:"<>(64-4*(2*i+1));//4 bits 47 | y = (mask_y & Ur)>>(64-4*(2*i+1+1)); 48 | temp |= (Substi_box8[x][y] << (64 - 8 * (i + 1))); 49 | mask_x = mask_x>>8; 50 | mask_y = mask_y>>8; 51 | } 52 | Vr = temp; 53 | } 54 | 55 | void Permutation_Plus(unsigned long long Vr, unsigned long long &w){ 56 | unsigned long long mask = 0x8000000000000000;//64 bits 57 | unsigned long long temp,res = 0x0000000000000000; 58 | for (int k = 0; k < 64; ++k) { 59 | temp = (Vr & mask)>>(63-k); 60 | res |= (temp<<(64-PerMap_plus[k])); 61 | mask = mask>>1; 62 | } 63 | w = res; 64 | } 65 | 66 | void SPN_Plus(unsigned long long x, unsigned long long &res){ 67 | unsigned long long w = x; 68 | unsigned long long Kr,Ur,Vr = 0x0000000000000000;//64 bits 69 | int Nr = 8; 70 | for (int r = 1; r <= Nr-1; ++r) { 71 | Key_arrange_Plus(r,Kr,Key_Plus); 72 | //cout<<"Kr: "< 7 | #include 8 | #include 9 | #include 10 | using namespace std; 11 | 12 | 13 | void SPN_test(); 14 | void SPN(unsigned short hex_x, unsigned short &res, unsigned int Key); 15 | void Key_arrange(int i,unsigned short &Kr,unsigned int Key); 16 | 17 | void LinearAttack_test(); 18 | void Crack(unsigned short key_r16); 19 | void Dif_Attack_test(); 20 | 21 | void SPN_Plus_test(); 22 | void SPN_Plus(unsigned long long x, unsigned long long &res); 23 | 24 | void RandTest(); 25 | 26 | #endif //TEST_UTILS_H 27 | -------------------------------------------------------------------------------- /SPN/main.cpp: -------------------------------------------------------------------------------- 1 | #include "Utils.h" 2 | 3 | int main(){ 4 | //SPN_test(); 5 | clock_t start,end; 6 | start = clock(); 7 | //LinearAttack_test(); 8 | //Dif_Attack_test(); 9 | //SPN_Plus_test(); 10 | //RandTest(); 11 | end = clock(); 12 | cout<<(double)(end-start)<<"ms"; 13 | 14 | } 15 | --------------------------------------------------------------------------------