前言 打比赛的时候遇到了加解密脚本编写,所以想写一篇总结,正好把逆向常见的那几个加密算法也总结总结,虽然自己也不太想学密码,但是该来的跑不掉 本来这篇文章我想的标题是常见加密算法,但考虑到MD5是hash,base是编码,所以就给这篇文章起名为常见密码学算法
编码 把数据从一种格式转换为另一种格式,用于传输或存储,不需要密码
base64 Base64编码每3个字节为一个编码组,对应的24个二进制位,然后按照每6位进行分组,分为4组,计算每组的值通过映射Base64编码表获得对应的值 下述实例为base64.b64decode(Man)=TWFu
c代码实现
1 2 3 4 out[o++] = b64_table[(b0 >> 2 ) & 0x3F ]; out[o++] = b64_table[((b0 & 0x3 ) << 4 ) | ((b1 >> 4 ) & 0x0F )]; out[o++] = b64_table[((b1 & 0x0F ) << 2 ) | ((b2 >> 6 ) & 0x03 )]; out[o++] = b64_table[b2 & 0x3F ];
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 import base64table1 = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ+/=' table2 = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=' def custom_base64_decode (data ): std_b64 = '' .join(table2[table1.index(c)] if c in table1 else c for c in data) return base64.b64decode(std_b64) def custom_base64_encode (raw_bytes ): std_b64 = base64.b64encode(raw_bytes).decode() return '' .join(table1[table2.index(c)] if c in table2 else c for c in std_b64) encoded = 'pCNxpTIUejgMhkgQdiQOdjB3bjwTdPgJgzcSdyQRgPoNcz16c44Vh31Z' flag = custom_base64_decode(encoded) print (flag.decode('utf-8' , errors='ignore' ))print (custom_base64_encode(flag))
对称加密 块密码 TEA / XTEA / XXTEA TEA(Tiny Encryption Algorithm,微型加密算法)是一种结构简单、速度快、实现容易的分组对称加密算法,曾广泛用于早期嵌入式设备、游戏加密、移动通信协议。
算法还是很简单的,就是v1和v0不断相互作为参数进行加密迭代,左脚踩右脚,解密就是倒着来一遍
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 #include <stdio.h> #include <stdint.h> void encrypt (uint32_t * v, const uint32_t * k) { uint32_t v0 = v[0 ], v1 = v[1 ]; uint32_t sum = 0 ; uint32_t delta = 0x9e3779b9 ; for (int i = 0 ; i < 32 ; i++) { sum += delta; v0 += ((v1 << 4 ) + k[0 ]) ^ (v1 + sum) ^ ((v1 >> 5 ) + k[1 ]); v1 += ((v0 << 4 ) + k[2 ]) ^ (v0 + sum) ^ ((v0 >> 5 ) + k[3 ]); } v[0 ] = v0; v[1 ] = v1; } void decrypt (uint32_t * v, const uint32_t * k) { uint32_t v0 = v[0 ], v1 = v[1 ]; uint32_t delta = 0x9e3779b9 ; uint32_t sum = delta * 32 ; for (int i = 0 ; i < 32 ; i++) { v1 -= ((v0 << 4 ) + k[2 ]) ^ (v0 + sum) ^ ((v0 >> 5 ) + k[3 ]); v0 -= ((v1 << 4 ) + k[0 ]) ^ (v1 + sum) ^ ((v1 >> 5 ) + k[1 ]); sum -= delta; } v[0 ] = v0; v[1 ] = v1; } int main () { uint32_t v[2 ] = {0x12345678 , 0x9abcdef0 }; uint32_t k[4 ] = {0x11111111 , 0x22222222 , 0x33333333 , 0x44444444 }; printf ("原文: %08X %08X\n" , v[0 ], v[1 ]); encrypt(v, k); printf ("加密: %08X %08X\n" , v[0 ], v[1 ]); decrypt(v, k); printf ("解密: %08X %08X\n" , v[0 ], v[1 ]); return 0 ; }
XTEA 是 TEA 的扩展,也称做 TEAN,四个子密钥采取不正规的方式进行混合以阻止密钥表攻击 XTEA与TEA的不同点在for循环里
1 2 3 4 5 6 7 8 v0 += (((v1 << 4 ) ^ (v1 >> 5 )) + v1) ^ (sum + key[sum & 3 ]); sum += DELTA; v1 += (((v0 << 4 ) ^ (v0 >> 5 )) + v0) ^ (sum + key[(sum >> 11 ) & 3 ]); v1 -= (((v0 << 4 ) ^ (v0 >> 5 )) + v0) ^ (sum + key[(sum >> 11 ) & 3 ]); sum -= DELTA; v0 -= (((v1 << 4 ) ^ (v1 >> 5 )) + v1) ^ (sum + key[sum & 3 ]);
前面的xtea和tea,在加密前需要两两分组,然后组内多轮相交 XXTEA 每轮都会让每个块都和它的前后块交互:每个块同时受到上下邻块的影响 → 扩散非常彻底。并且XXTEA支持任意长度(n×32位)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 #include <stdio.h> #include <stdint.h> #include <stdlib.h> #define DELTA 0x9e3779b9 void xxtea_encrypt (uint32_t *v, int n, const uint32_t k[4 ]) { if (n < 2 ) return ; uint32_t sum = 0 ; uint32_t rounds = 6 + 52 /n; uint32_t z = v[n-1 ], y, e, p; while (rounds-- > 0 ) { sum += DELTA; e = (sum >> 2 ) & 3 ; for (p = 0 ; p < n-1 ; p++) { y = v[p+1 ]; v[p] += (((z >> 5 ) ^ (y << 2 )) + ((y >> 3 ) ^ (z << 4 ))) ^ ((sum ^ y) + (k[(p & 3 ) ^ e] ^ z)); z = v[p]; } y = v[0 ]; v[n-1 ] += (((z >> 5 ) ^ (y << 2 )) + ((y >> 3 ) ^ (z << 4 ))) ^ ((sum ^ y) + (k[(p & 3 ) ^ e] ^ z)); z = v[n-1 ]; } } void xxtea_decrypt (uint32_t *v, int n, const uint32_t k[4 ]) { if (n < 2 ) return ; uint32_t rounds = 6 + 52 /n; uint32_t sum = rounds * DELTA; uint32_t z, y = v[0 ], e, p; while (sum != 0 ) { e = (sum >> 2 ) & 3 ; for (p = n-1 ; p > 0 ; p--) { z = v[p-1 ]; v[p] -= (((z >> 5 ) ^ (y << 2 )) + ((y >> 3 ) ^ (z << 4 ))) ^ ((sum ^ y) + (k[(p & 3 ) ^ e] ^ z)); y = v[p]; } z = v[n-1 ]; v[0 ] -= (((z >> 5 ) ^ (y << 2 )) + ((y >> 3 ) ^ (z << 4 ))) ^ ((sum ^ y) + (k[(0 & 3 ) ^ e] ^ z)); y = v[0 ]; sum -= DELTA; } }
DES 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 from Crypto.Cipher import DESfrom Crypto.Util.Padding import pad, unpadfrom Crypto.Random import get_random_byteskey = b'12345678' data = b'hello world' data_padded = pad(data, 8 ) print ("填充后的明文:" , data_padded) cipher_ecb = DES.new(key, DES.MODE_ECB) encrypted_ecb = cipher_ecb.encrypt(data_padded) print ("DES-ECB 加密:" , encrypted_ecb.hex ())decrypted_ecb_padded = cipher_ecb.decrypt(encrypted_ecb) decrypted_ecb = unpad(decrypted_ecb_padded, 8 ) print ("DES-ECB 解密:" , decrypted_ecb)iv = get_random_bytes(8 ) cipher_cbc = DES.new(key, DES.MODE_CBC, iv) encrypted_cbc = cipher_cbc.encrypt(data_padded) print ("DES-CBC 加密:" , encrypted_cbc.hex ())cipher_cbc_dec = DES.new(key, DES.MODE_CBC, iv) decrypted_cbc_padded = cipher_cbc_dec.decrypt(encrypted_cbc) decrypted_cbc = unpad(decrypted_cbc_padded, 8 ) print ("DES-CBC 解密:" , decrypted_cbc)
AES 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 from Crypto.Cipher import AESfrom Crypto.Util.Padding import pad, unpadfrom Crypto.Random import get_random_byteskey = b'1234567812345678' data = b'hello world' data_padded = pad(data, 16 ) print (data_padded) cipher = AES.new(key, AES.MODE_ECB) encrypted = cipher.encrypt(data_padded) print ("AES-ECB 加密:" , encrypted.hex ())decrypted_padded = cipher.decrypt(encrypted) decrypted = unpad(decrypted_padded, 16 ) print ("AES-ECB 解密:" , decrypted)iv = get_random_bytes(16 ) cipher_cbc = AES.new(key, AES.MODE_CBC, iv) encrypted_cbc = cipher_cbc.encrypt(data_padded) print ("AES-CBC 加密:" , encrypted_cbc.hex ())cipher_cbc_dec = AES.new(key, AES.MODE_CBC, iv) decrypted_cbc_padded = cipher_cbc_dec.decrypt(encrypted_cbc) decrypted_cbc = unpad(decrypted_cbc_padded, 16 ) print ("AES-CBC 解密:" , decrypted_cbc)
流密码 RC4 1 2 3 4 5 6 7 8 9 10 11 12 from Crypto.Cipher import ARC4key = b'mysecretkey' cipher = ARC4.new(key) data = b'Hello, World!' encrypted_data = cipher.encrypt(data) print ("Encrypted:" , encrypted_data)cipher_dec = ARC4.new(key) decrypted_data = cipher_dec.decrypt(encrypted_data) print ("Decrypted:" , decrypted_data)
具体实现 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 #include <stdio.h> #include <string.h> void rc4_init (unsigned char *s, unsigned char *key, int keylen) { int i, j = 0 ; unsigned char temp; for (i = 0 ; i < 256 ; i++) s[i] = i; for (i = 0 ; i < 256 ; i++) { j = (j + s[i] + key[i % keylen]) % 256 ; temp = s[i]; s[i] = s[j]; s[j] = temp; } } void rc4_crypt (unsigned char *s, unsigned char *data, int datalen) { int i = 0 , j = 0 , k, t; unsigned char temp; for (k = 0 ; k < datalen; k++) { i = (i + 1 ) % 256 ; j = (j + s[i]) % 256 ; temp = s[i]; s[i] = s[j]; s[j] = temp; t = (s[i] + s[j]) % 256 ; data[k] ^= s[t]; } } int main () { unsigned char key[] = "secret" ; unsigned char data[] = "Hello, RC4!" ; unsigned char s[256 ]; rc4_init(s, key, strlen ((char *)key)); rc4_crypt(s, data, strlen ((char *)data)); printf ("加密后: " ); for (int i = 0 ; i < strlen ((char *)data); i++) printf ("%02X " , data[i]); printf ("\n" ); rc4_init(s, key, strlen ((char *)key)); rc4_crypt(s, data, strlen ((char *)data)); printf ("解密后: %s\n" , data); return 0 ; }
非对称加密 RSA 原始rsa是纯数学加密,就是直接把明文通过数学公式变成密文,而没有额外随机性或结构。 现代rsa引入填充机制,在加密前加入随机掩码,解决纯数学加密的“同明文密文固定”问题
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 from Crypto.PublicKey import RSAfrom Crypto.Cipher import PKCS1_OAEPkey = RSA.generate(2048 ) private_key = key.export_key() public_key = key.publickey().export_key() print ("私钥:\n" , private_key.decode()[:100 ], "..." ) print ("公钥:\n" , public_key.decode()[:100 ], "..." )message = b"Hello RSA!" pub_key = RSA.import_key(public_key) cipher_encrypt = PKCS1_OAEP.new(pub_key) encrypted_data = cipher_encrypt.encrypt(message) print ("加密后:" , encrypted_data.hex ()[:60 ], "..." ) priv_key = RSA.import_key(private_key) cipher_decrypt = PKCS1_OAEP.new(priv_key) decrypted_data = cipher_decrypt.decrypt(encrypted_data) print ("解密后:" , decrypted_data.decode())
哈希函数 哈希(Hash,也叫散列或摘要)是一种单向映射函数:你能从明文得到哈希,不能从哈希反推出明文。输入任意数据 → 输出固定长度字符串(通常是十六进制)。
文件的hash ,就是将文件数据作为输入,计算出hash,这时只要修改文件,文件的hash值就会改变
MD5 MD5可以将任意长度的数据 → 映射为 128 位(16 字节)的固定长度哈希值,最后呈现结果是结果32位十六进制字符
1 2 3 4 5 6 7 8 import hashlibs = "hello" md5_hash = hashlib.md5(s.encode()).hexdigest() print (md5_hash)print (md5_hash[8 :-8 ])
SHA 系列 SHA 跟MD5相比输出长,更安全
1 2 3 4 5 6 7 8 9 10 11 import hashlibtext = "hello world" sha1 = hashlib.sha1(text.encode()).hexdigest() sha256 = hashlib.sha256(text.encode()).hexdigest() sha512 = hashlib.sha512(text.encode()).hexdigest() print ("SHA1:" , sha1)print ("SHA256:" , sha256)print ("SHA512:" , sha512)