对常用的逆向算法进行了整理
# RC4
def RC4(data, key): | |
if type(data) == type('oacia'): # 判断是否为字符串 | |
data = [ord(i) for i in data] | |
if type(key) == type('oacia'): | |
key = [ord(i) for i in key] | |
S = list(range(256)) | |
j = 0 | |
out = [] | |
# KSA Phase | |
for i in range(256): | |
j = (j + S[i] + key[i % len(key)]) % 256 | |
S[i], S[j] = S[j], S[i] | |
# PRGA Phase | |
i = j = 0 | |
for ch in data: | |
i = (i + 1) % 256 | |
j = (j + S[i]) % 256 | |
S[i], S[j] = S[j], S[i] | |
out.append(ch ^ S[(S[i] + S[j]) % 256]) | |
return out | |
def RC4encrypt(plaintext, key): | |
return RC4(plaintext, key) | |
def RC4decrypt(ciphertext, key): | |
return RC4(ciphertext, key) | |
# Example usage | |
plaintext = "this is RC4,oacia" | |
key = "secret" | |
# 对明文进行加密 | |
ciphertext = RC4encrypt(plaintext, key) | |
print(f"ciphertext:{ciphertext}") | |
# 对密文进行解密 | |
decrypted = RC4decrypt(ciphertext, key) | |
print(f"decrypted:{decrypted}") | |
''' | |
ciphertext:[153, 94, 187, 111, 162, 205, 165, 134, 96, 136, 143, 240, 156, 135, 150, 94, 204] | |
decrypted:[116, 104, 105, 115, 32, 105, 115, 32, 82, 67, 52, 44, 111, 97, 99, 105, 97] | |
''' |
#include<stdio.h> | |
/* | |
RC4 初始化函数 | |
*/ | |
void rc4_init(unsigned char* s, unsigned char* key, unsigned long Len_k) | |
{ | |
int i = 0, j = 0; | |
char k[256] = { 0 }; | |
unsigned char tmp = 0; | |
for (i = 0; i < 256; i++) { | |
s[i] = i; | |
k[i] = key[i % Len_k]; | |
} | |
for (i = 0; i < 256; i++) { | |
j = (j + s[i] + k[i]) % 256; | |
tmp = s[i]; | |
s[i] = s[j]; | |
s[j] = tmp; | |
} | |
} | |
/* | |
RC4 加解密函数 | |
unsigned char* Data 加解密的数据 | |
unsigned long Len_D 加解密数据的长度 | |
unsigned char* key 密钥 | |
unsigned long Len_k 密钥长度 | |
*/ | |
void RC4(unsigned char* Data, unsigned long Len_D, unsigned char* key, unsigned long Len_k) // 加解密 | |
{ | |
unsigned char s[256]; | |
rc4_init(s, key, Len_k); | |
int i = 0, j = 0, t = 0; | |
unsigned long k = 0; | |
unsigned char tmp; | |
for (k = 0; k < Len_D; k++) { | |
i = (i + 1) % 256; | |
j = (j + s[i]) % 256; | |
tmp = s[i]; | |
s[i] = s[j]; | |
s[j] = tmp; | |
t = (s[i] + s[j]) % 256; | |
Data[k] = Data[k] ^ s[t]; | |
} | |
} | |
void RC4encrypt(unsigned char* Data, unsigned long Len_D, unsigned char* key, unsigned long Len_k) { | |
RC4(Data, Len_D, key, Len_k); | |
} | |
void RC4decrypt(unsigned char* Data, unsigned long Len_D, unsigned char* key, unsigned long Len_k) { | |
RC4(Data, Len_D, key, Len_k); | |
} | |
int main() | |
{ | |
// 字符串密钥 | |
unsigned char key[] = "secret"; | |
unsigned long key_len = sizeof(key) - 1;// 字符串最后还有一个 '/0' 所以需要 - 1 | |
// 数组密钥 | |
//unsigned char key[] = {'s','e','c','r','e','t'}; | |
//unsigned long key_len = sizeof(key); | |
unsigned char data[] = { 116, 104, 105, 115, 32, 105, 115, 32, 82, 67, 52, 44, 111, 97, 99, 105, 97 }; | |
// 对明文进行加密 | |
RC4encrypt(data, sizeof(data), key, key_len); | |
for (int i = 0; i < sizeof(data); i++) | |
{ | |
printf("%d, ", data[i]); | |
} | |
printf("\n"); | |
// 对密文进行解密 | |
RC4encrypt(data, sizeof(data), key, key_len); | |
for (int i = 0; i < sizeof(data); i++) | |
{ | |
printf("%c", data[i]); | |
} | |
printf("\n"); | |
return 0; | |
} | |
/* | |
153, 94, 187, 111, 162, 205, 165, 134, 96, 136, 143, 240, 156, 135, 150, 94, 204, | |
this is RC4,oacia | |
*/ |
# TEA
from ctypes import * | |
def encrypt(v, k): | |
v0, v1 = c_uint32(v[0]), c_uint32(v[1]) | |
delta = 0x9e3779b9 | |
k0, k1, k2, k3 = k[0], k[1], k[2], k[3] | |
total = c_uint32(0) | |
for i in range(32): | |
total.value += delta | |
v0.value += ((v1.value << 4) + k0) ^ (v1.value + total.value) ^ ((v1.value >> 5) + k1) | |
v1.value += ((v0.value << 4) + k2) ^ (v0.value + total.value) ^ ((v0.value >> 5) + k3) | |
return v0.value, v1.value | |
def decrypt(v, k): | |
v0, v1 = c_uint32(v[0]), c_uint32(v[1]) | |
delta = 0x9e3779b9 | |
k0, k1, k2, k3 = k[0], k[1], k[2], k[3] | |
total = c_uint32(delta * 32) | |
for i in range(32): | |
v1.value -= ((v0.value << 4) + k2) ^ (v0.value + total.value) ^ ((v0.value >> 5) + k3) | |
v0.value -= ((v1.value << 4) + k0) ^ (v1.value + total.value) ^ ((v1.value >> 5) + k1) | |
total.value -= delta | |
return v0.value, v1.value | |
# 待加密的明文,两个 32 位整型,即 64bit 的明文数据 | |
value = [0x6869216f, 0x61636961] | |
# 四个 key,每个是 32bit,即密钥长度为 128bit | |
key = [0x1, 0x2, 0x3, 0x4] | |
print("Data is : ", hex(value[0]), hex(value[1])) | |
res = encrypt(value, key) | |
print("Encrypted data is : ", hex(res[0]), hex(res[1])) | |
res = decrypt(res, key) | |
print("Decrypted data is : ", hex(res[0]), hex(res[1])) | |
""" | |
Data is : 0x6869216f 0x61636961 | |
Encrypted data is : 0x55d9ac0b 0x2df0479f | |
Decrypted data is : 0x6869216f 0x61636961 | |
""" |
#include <stdio.h> | |
#include <stdint.h> | |
// 加密函数 | |
void encrypt(uint32_t* v, uint32_t* k) { | |
uint32_t delta = 0x9e3779b9; | |
uint32_t v0 = v[0], v1 = v[1], sum = 0, i; | |
uint32_t k0 = k[0], k1 = k[1], k2 = k[2], k3 = k[3]; | |
for (i = 0; i < 32; i++) { | |
sum += delta; | |
v0 += ((v1 << 4) + k0) ^ (v1 + sum) ^ ((v1 >> 5) + k1); | |
v1 += ((v0 << 4) + k2) ^ (v0 + sum) ^ ((v0 >> 5) + k3); | |
} | |
v[0] = v0; v[1] = v1; | |
} | |
// 解密函数 | |
void decrypt(uint32_t* v, uint32_t* k) { | |
uint32_t delta = 0x9e3779b9; | |
uint32_t v0 = v[0], v1 = v[1], sum = 32*delta, i; | |
uint32_t k0 = k[0], k1 = k[1], k2 = k[2], k3 = k[3]; | |
for (i = 0; i<32; i++) { | |
v1 -= ((v0 << 4) + k2) ^ (v0 + sum) ^ ((v0 >> 5) + k3); | |
v0 -= ((v1 << 4) + k0) ^ (v1 + sum) ^ ((v1 >> 5) + k1); | |
sum -= delta; | |
} | |
v[0] = v0; v[1] = v1; | |
} | |
int main() | |
{ | |
//v 为要加解密的数据,两个 32 位无符号整数 | |
uint32_t v[2] = { 0x6869216f, 0x61636961 }; | |
//k 为加解密密钥,4 个 32 位无符号整数,密钥长度为 128 位 | |
uint32_t k[4] = { 0x1, 0x2, 0x3, 0x4 }; | |
int n = sizeof(v) / sizeof(uint32_t); | |
printf("Data is : 0x%x 0x%x\n", v[0], v[1]); | |
encrypt(v, k); | |
printf("Encrypted data is : 0x%x 0x%x\n", v[0], v[1]); | |
decrypt(v, k); | |
printf("Decrypted data is : 0x%x 0x%x\n", v[0], v[1]); | |
return 0; | |
} | |
/* | |
Data is : 0x6869216f 0x61636961 | |
Encrypted data is : 0x55d9ac0b 0x2df0479f | |
Decrypted data is : 0x6869216f 0x61636961 | |
*/ |
from ctypes import * | |
def encrypt(v, key): | |
v0, v1 = c_uint32(v[0]), c_uint32(v[1]) | |
delta = 0x9E3779B9 | |
total = c_uint32(0) | |
for i in range(32): | |
v0.value += (((v1.value << 4) ^ (v1.value >> 5)) + v1.value) ^ (total.value + key[total.value & 3]) | |
total.value += delta | |
v1.value += (((v0.value << 4) ^ (v0.value >> 5)) + v0.value) ^ (total.value + key[(total.value >> 11) & 3]) | |
return v0.value, v1.value | |
def decrypt(v, key): | |
v0, v1 = c_uint32(v[0]), c_uint32(v[1]) | |
delta = 0x9E3779B9 | |
total = c_uint32(delta * 32) | |
for i in range(32): | |
v1.value -= (((v0.value << 4) ^ (v0.value >> 5)) + v0.value) ^ (total.value + key[(total.value >> 11) & 3]) | |
total.value -= delta | |
v0.value -= (((v1.value << 4) ^ (v1.value >> 5)) + v1.value) ^ (total.value + key[total.value & 3]) | |
return v0.value, v1.value | |
# test | |
if __name__ == "__main__": | |
# 待加密的明文,两个 32 位整型,即 64bit 的明文数据 | |
value = [0x6869216f, 0x61636961] | |
# 四个 key,每个是 32bit,即密钥长度为 128bit | |
key = [0x1, 0x2, 0x3, 0x4] | |
print("Data is : ", hex(value[0]), hex(value[1])) | |
res = encrypt(value, key) | |
print("Encrypted data is : ", hex(res[0]), hex(res[1])) | |
res = decrypt(res, key) | |
print("Decrypted data is : ", hex(res[0]), hex(res[1])) | |
""" | |
Data is : 0x6869216f 0x61636961 | |
Encrypted data is : 0x39f25ea9 0x92754c5d | |
Decrypted data is : 0x6869216f 0x61636961 | |
""" |
#include <stdio.h> | |
#include <stdint.h> | |
// 加密函数 | |
void encrypt(uint32_t v[2], uint32_t const key[4]) { | |
unsigned int i; | |
uint32_t v0 = v[0], v1 = v[1], sum = 0, delta = 0x9E3779B9; | |
for (i = 0; i < 32; i++) { | |
v0 += (((v1 << 4) ^ (v1 >> 5)) + v1) ^ (sum + key[sum & 3]); | |
sum += delta; | |
v1 += (((v0 << 4) ^ (v0 >> 5)) + v0) ^ (sum + key[(sum >> 11) & 3]); | |
} | |
v[0] = v0; v[1] = v1; | |
} | |
// 解密函数 | |
void decrypt(uint32_t v[2], uint32_t const key[4]) { | |
unsigned int i; | |
uint32_t v0 = v[0], v1 = v[1], delta = 0x9E3779B9, sum = delta*32; | |
for (i = 0; i < 32; i++) { | |
v1 -= (((v0 << 4) ^ (v0 >> 5)) + v0) ^ (sum + key[(sum >> 11) & 3]); | |
sum -= delta; | |
v0 -= (((v1 << 4) ^ (v1 >> 5)) + v1) ^ (sum + key[sum & 3]); | |
} | |
v[0] = v0; v[1] = v1; | |
} | |
int main() | |
{ | |
//v 为要加解密的数据,两个 32 位无符号整数 | |
uint32_t v[2] = { 0x6869216f, 0x61636961 }; | |
//k 为加解密密钥,4 个 32 位无符号整数,密钥长度为 128 位 | |
uint32_t k[4] = { 0x1, 0x2, 0x3, 0x4 }; | |
int n = sizeof(v) / sizeof(uint32_t); | |
printf("Data is : 0x%x 0x%x\n", v[0], v[1]); | |
encrypt(v, k); | |
printf("Encrypted data is : 0x%x 0x%x\n", v[0], v[1]); | |
decrypt(v, k); | |
printf("Decrypted data is : 0x%x 0x%x\n", v[0], v[1]); | |
return 0; | |
} | |
/* | |
Data is : 0x6869216f 0x61636961 | |
Encrypted data is : 0x39f25ea9 0x92754c5d | |
Decrypted data is : 0x6869216f 0x61636961 | |
*/ |
from ctypes import * | |
def MX(z, y, total, key, p, e): | |
temp1 = (z.value >> 5 ^ y.value << 2) + (y.value >> 3 ^ z.value << 4) | |
temp2 = (total.value ^ y.value) + (key[(p & 3) ^ e.value] ^ z.value) | |
return c_uint32(temp1 ^ temp2) | |
def encrypt(n, v, key): | |
delta = 0x9e3779b9 | |
rounds = 6 + 52 // n | |
total = c_uint32(0) | |
z = c_uint32(v[n - 1]) | |
e = c_uint32(0) | |
while rounds > 0: | |
total.value += delta | |
e.value = (total.value >> 2) & 3 | |
for p in range(n - 1): | |
y = c_uint32(v[p + 1]) | |
v[p] = c_uint32(v[p] + MX(z, y, total, key, p, e).value).value | |
z.value = v[p] | |
y = c_uint32(v[0]) | |
v[n - 1] = c_uint32(v[n - 1] + MX(z, y, total, key, n - 1, e).value).value | |
z.value = v[n - 1] | |
rounds -= 1 | |
return v | |
def decrypt(n, v, key): | |
delta = 0x9e3779b9 | |
rounds = 6 + 52 // n | |
total = c_uint32(rounds * delta) | |
y = c_uint32(v[0]) | |
e = c_uint32(0) | |
while rounds > 0: | |
e.value = (total.value >> 2) & 3 | |
for p in range(n - 1, 0, -1): | |
z = c_uint32(v[p - 1]) | |
v[p] = c_uint32((v[p] - MX(z, y, total, key, p, e).value)).value | |
y.value = v[p] | |
z = c_uint32(v[n - 1]) | |
v[0] = c_uint32(v[0] - MX(z, y, total, key, 0, e).value).value | |
y.value = v[0] | |
total.value -= delta | |
rounds -= 1 | |
return v | |
# test | |
if __name__ == "__main__": | |
# 该算法中每次可加密不只 64bit 的数据,并且加密的轮数由加密数据长度决定 | |
v = [0x6869216f, 0x61636961] | |
k = [0x1, 0x2, 0x3, 0x4] | |
n = 2 | |
print("Data is : ", hex(v[0]), hex(v[1])) | |
res = encrypt(n, v, k) | |
print("Encrypted data is : ", hex(res[0]), hex(res[1])) | |
res = decrypt(n, res, k) | |
print("Decrypted data is : ", hex(res[0]), hex(res[1])) | |
""" | |
Data is : 0x6869216f 0x61636961 | |
Encrypted data is : 0x973cd3b0 0x797bf2ab | |
Decrypted data is : 0x6869216f 0x61636961 | |
""" |
#include <stdio.h> | |
#include <stdint.h> | |
#define DELTA 0x9e3779b9 | |
#define MX (((z>>5^y<<2) + (y>>3^z<<4)) ^ ((sum^y) + (key[(p&3)^e] ^ z))) | |
void btea(uint32_t *v, int n, uint32_t const key[4]) | |
{ | |
uint32_t y, z, sum; | |
unsigned p, rounds, e; | |
// 加密 | |
if (n > 1) | |
{ | |
rounds = 6 + 52 / n; | |
sum = 0; | |
z = v[n - 1]; | |
do | |
{ | |
sum += DELTA; | |
e = (sum >> 2) & 3; | |
for (p = 0; p<n - 1; p++) | |
{ | |
y = v[p + 1]; | |
z = v[p] += MX; | |
} | |
y = v[0]; | |
z = v[n - 1] += MX; | |
} while (--rounds); | |
} | |
// 解密 | |
else if (n < -1) | |
{ | |
n = -n; | |
rounds = 6 + 52 / n; | |
sum = rounds*DELTA; | |
y = v[0]; | |
do | |
{ | |
e = (sum >> 2) & 3; | |
for (p = n - 1; p>0; p--) | |
{ | |
z = v[p - 1]; | |
y = v[p] -= MX; | |
} | |
z = v[n - 1]; | |
y = v[0] -= MX; | |
sum -= DELTA; | |
} while (--rounds); | |
} | |
} | |
int main() | |
{ | |
/* | |
该算法中每次可加密不只 64bit 的数据,并且加密的轮数由加密数据长度决定 | |
*/ | |
uint32_t v[2] = {0x6869216f, 0x61636961 }; | |
uint32_t const k[4] = {0x1, 0x2, 0x3, 0x4}; | |
//n 的绝对值表示 v 的长度,取正表示加密,取负表示解密 | |
int n = sizeof(v) / sizeof(uint32_t); | |
printf("Data is : 0x%x 0x%x\n", v[0], v[1]); | |
btea(v, n, k); | |
printf("Encrypted data is : 0x%x 0x%x\n", v[0], v[1]); | |
btea(v, -n, k); | |
printf("Decrypted data is : 0x%x 0x%x\n", v[0], v[1]); | |
return 0; | |
} | |
/* | |
Data is : 0x6869216f 0x61636961 | |
Encrypted data is : 0x973cd3b0 0x797bf2ab | |
Decrypted data is : 0x6869216f 0x61636961 | |
*/ |
# AES
from Crypto.Cipher import AES | |
password = b'secret!!secret!!' # 秘钥必须为 16 字节或者 16 字节的倍数的字节型数据 | |
text = b'TextTextTextText' # 明文必须为 16 字节或者 16 字节的倍数的字节型数据,如果不够 16 字节需要进行补全 | |
aes = AES.new(password, AES.MODE_ECB) # 创建一个 aes 对象 | |
# AES.MODE_ECB 表示模式是 ECB 模式 | |
en_text = aes.encrypt(text) # 加密明文 | |
print("密文:", en_text) # 加密明文,bytes 类型 | |
de_text = aes.decrypt(en_text) # 解密密文 | |
print("明文:", de_text) | |
''' | |
密文: b'\t9\x9b\xc5\x19E\xeb4oL\x1a`\xc7\x8b\xd4\xb2' | |
明文: b'TextTextTextText' | |
''' |
todo |
#include <stdint.h> | |
#include <stdio.h> | |
#include <string.h> | |
typedef struct{ | |
uint32_t eK[44], dK[44]; // encKey, decKey | |
int Nr; // 10 rounds | |
}AesKey; | |
#define BLOCKSIZE 16 //AES-128 分组长度为 16 字节 | |
// uint8_t y[4] -> uint32_t x | |
#define LOAD32H(x, y) \ | |
do { (x) = ((uint32_t)((y)[0] & 0xff)<<24) | ((uint32_t)((y)[1] & 0xff)<<16) | \ | |
((uint32_t)((y)[2] & 0xff)<<8) | ((uint32_t)((y)[3] & 0xff));} while(0) | |
// uint32_t x -> uint8_t y[4] | |
#define STORE32H(x, y) \ | |
do { (y)[0] = (uint8_t)(((x)>>24) & 0xff); (y)[1] = (uint8_t)(((x)>>16) & 0xff); \ | |
(y)[2] = (uint8_t)(((x)>>8) & 0xff); (y)[3] = (uint8_t)((x) & 0xff); } while(0) | |
// 从 uint32_t x 中提取从低位开始的第 n 个字节 | |
#define BYTE(x, n) (((x) >> (8 * (n))) & 0xff) | |
/* used for keyExpansion */ | |
// 字节替换然后循环左移 1 位 | |
#define MIX(x) (((S[BYTE(x, 2)] << 24) & 0xff000000) ^ ((S[BYTE(x, 1)] << 16) & 0xff0000) ^ \ | |
((S[BYTE(x, 0)] << 8) & 0xff00) ^ (S[BYTE(x, 3)] & 0xff)) | |
//uint32_t x 循环左移 n 位 | |
#define ROF32(x, n) (((x) << (n)) | ((x) >> (32-(n)))) | |
//uint32_t x 循环右移 n 位 | |
#define ROR32(x, n) (((x) >> (n)) | ((x) << (32-(n)))) | |
/* for 128-bit blocks, Rijndael never uses more than 10 rcon values */ | |
// AES-128 轮常量 | |
static const uint32_t rcon[10] = { | |
0x01000000UL, 0x02000000UL, 0x04000000UL, 0x08000000UL, 0x10000000UL, | |
0x20000000UL, 0x40000000UL, 0x80000000UL, 0x1B000000UL, 0x36000000UL | |
}; | |
// S 盒 | |
unsigned char S[256] = { | |
0x63, 0x7C, 0x77, 0x7B, 0xF2, 0x6B, 0x6F, 0xC5, 0x30, 0x01, 0x67, 0x2B, 0xFE, 0xD7, 0xAB, 0x76, | |
0xCA, 0x82, 0xC9, 0x7D, 0xFA, 0x59, 0x47, 0xF0, 0xAD, 0xD4, 0xA2, 0xAF, 0x9C, 0xA4, 0x72, 0xC0, | |
0xB7, 0xFD, 0x93, 0x26, 0x36, 0x3F, 0xF7, 0xCC, 0x34, 0xA5, 0xE5, 0xF1, 0x71, 0xD8, 0x31, 0x15, | |
0x04, 0xC7, 0x23, 0xC3, 0x18, 0x96, 0x05, 0x9A, 0x07, 0x12, 0x80, 0xE2, 0xEB, 0x27, 0xB2, 0x75, | |
0x09, 0x83, 0x2C, 0x1A, 0x1B, 0x6E, 0x5A, 0xA0, 0x52, 0x3B, 0xD6, 0xB3, 0x29, 0xE3, 0x2F, 0x84, | |
0x53, 0xD1, 0x00, 0xED, 0x20, 0xFC, 0xB1, 0x5B, 0x6A, 0xCB, 0xBE, 0x39, 0x4A, 0x4C, 0x58, 0xCF, | |
0xD0, 0xEF, 0xAA, 0xFB, 0x43, 0x4D, 0x33, 0x85, 0x45, 0xF9, 0x02, 0x7F, 0x50, 0x3C, 0x9F, 0xA8, | |
0x51, 0xA3, 0x40, 0x8F, 0x92, 0x9D, 0x38, 0xF5, 0xBC, 0xB6, 0xDA, 0x21, 0x10, 0xFF, 0xF3, 0xD2, | |
0xCD, 0x0C, 0x13, 0xEC, 0x5F, 0x97, 0x44, 0x17, 0xC4, 0xA7, 0x7E, 0x3D, 0x64, 0x5D, 0x19, 0x73, | |
0x60, 0x81, 0x4F, 0xDC, 0x22, 0x2A, 0x90, 0x88, 0x46, 0xEE, 0xB8, 0x14, 0xDE, 0x5E, 0x0B, 0xDB, | |
0xE0, 0x32, 0x3A, 0x0A, 0x49, 0x06, 0x24, 0x5C, 0xC2, 0xD3, 0xAC, 0x62, 0x91, 0x95, 0xE4, 0x79, | |
0xE7, 0xC8, 0x37, 0x6D, 0x8D, 0xD5, 0x4E, 0xA9, 0x6C, 0x56, 0xF4, 0xEA, 0x65, 0x7A, 0xAE, 0x08, | |
0xBA, 0x78, 0x25, 0x2E, 0x1C, 0xA6, 0xB4, 0xC6, 0xE8, 0xDD, 0x74, 0x1F, 0x4B, 0xBD, 0x8B, 0x8A, | |
0x70, 0x3E, 0xB5, 0x66, 0x48, 0x03, 0xF6, 0x0E, 0x61, 0x35, 0x57, 0xB9, 0x86, 0xC1, 0x1D, 0x9E, | |
0xE1, 0xF8, 0x98, 0x11, 0x69, 0xD9, 0x8E, 0x94, 0x9B, 0x1E, 0x87, 0xE9, 0xCE, 0x55, 0x28, 0xDF, | |
0x8C, 0xA1, 0x89, 0x0D, 0xBF, 0xE6, 0x42, 0x68, 0x41, 0x99, 0x2D, 0x0F, 0xB0, 0x54, 0xBB, 0x16 | |
}; | |
// 逆 S 盒 | |
unsigned char inv_S[256] = { | |
0x52, 0x09, 0x6A, 0xD5, 0x30, 0x36, 0xA5, 0x38, 0xBF, 0x40, 0xA3, 0x9E, 0x81, 0xF3, 0xD7, 0xFB, | |
0x7C, 0xE3, 0x39, 0x82, 0x9B, 0x2F, 0xFF, 0x87, 0x34, 0x8E, 0x43, 0x44, 0xC4, 0xDE, 0xE9, 0xCB, | |
0x54, 0x7B, 0x94, 0x32, 0xA6, 0xC2, 0x23, 0x3D, 0xEE, 0x4C, 0x95, 0x0B, 0x42, 0xFA, 0xC3, 0x4E, | |
0x08, 0x2E, 0xA1, 0x66, 0x28, 0xD9, 0x24, 0xB2, 0x76, 0x5B, 0xA2, 0x49, 0x6D, 0x8B, 0xD1, 0x25, | |
0x72, 0xF8, 0xF6, 0x64, 0x86, 0x68, 0x98, 0x16, 0xD4, 0xA4, 0x5C, 0xCC, 0x5D, 0x65, 0xB6, 0x92, | |
0x6C, 0x70, 0x48, 0x50, 0xFD, 0xED, 0xB9, 0xDA, 0x5E, 0x15, 0x46, 0x57, 0xA7, 0x8D, 0x9D, 0x84, | |
0x90, 0xD8, 0xAB, 0x00, 0x8C, 0xBC, 0xD3, 0x0A, 0xF7, 0xE4, 0x58, 0x05, 0xB8, 0xB3, 0x45, 0x06, | |
0xD0, 0x2C, 0x1E, 0x8F, 0xCA, 0x3F, 0x0F, 0x02, 0xC1, 0xAF, 0xBD, 0x03, 0x01, 0x13, 0x8A, 0x6B, | |
0x3A, 0x91, 0x11, 0x41, 0x4F, 0x67, 0xDC, 0xEA, 0x97, 0xF2, 0xCF, 0xCE, 0xF0, 0xB4, 0xE6, 0x73, | |
0x96, 0xAC, 0x74, 0x22, 0xE7, 0xAD, 0x35, 0x85, 0xE2, 0xF9, 0x37, 0xE8, 0x1C, 0x75, 0xDF, 0x6E, | |
0x47, 0xF1, 0x1A, 0x71, 0x1D, 0x29, 0xC5, 0x89, 0x6F, 0xB7, 0x62, 0x0E, 0xAA, 0x18, 0xBE, 0x1B, | |
0xFC, 0x56, 0x3E, 0x4B, 0xC6, 0xD2, 0x79, 0x20, 0x9A, 0xDB, 0xC0, 0xFE, 0x78, 0xCD, 0x5A, 0xF4, | |
0x1F, 0xDD, 0xA8, 0x33, 0x88, 0x07, 0xC7, 0x31, 0xB1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xEC, 0x5F, | |
0x60, 0x51, 0x7F, 0xA9, 0x19, 0xB5, 0x4A, 0x0D, 0x2D, 0xE5, 0x7A, 0x9F, 0x93, 0xC9, 0x9C, 0xEF, | |
0xA0, 0xE0, 0x3B, 0x4D, 0xAE, 0x2A, 0xF5, 0xB0, 0xC8, 0xEB, 0xBB, 0x3C, 0x83, 0x53, 0x99, 0x61, | |
0x17, 0x2B, 0x04, 0x7E, 0xBA, 0x77, 0xD6, 0x26, 0xE1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0C, 0x7D | |
}; | |
/* copy in[16] to state[4][4] */ | |
int loadStateArray(uint8_t (*state)[4], const uint8_t *in) { | |
for (int i = 0; i < 4; ++i) { | |
for (int j = 0; j < 4; ++j) { | |
state[j][i] = *in++; | |
} | |
} | |
return 0; | |
} | |
/* copy state[4][4] to out[16] */ | |
int storeStateArray(uint8_t (*state)[4], uint8_t *out) { | |
for (int i = 0; i < 4; ++i) { | |
for (int j = 0; j < 4; ++j) { | |
*out++ = state[j][i]; | |
} | |
} | |
return 0; | |
} | |
// 秘钥扩展 | |
int keyExpansion(const uint8_t *key, uint32_t keyLen, AesKey *aesKey) { | |
if (NULL == key || NULL == aesKey){ | |
printf("keyExpansion param is NULL\n"); | |
return -1; | |
} | |
if (keyLen != 16){ | |
printf("keyExpansion keyLen = %d, Not support.\n", keyLen); | |
return -1; | |
} | |
uint32_t *w = aesKey->eK; // 加密秘钥 | |
uint32_t *v = aesKey->dK; // 解密秘钥 | |
/* keyLen is 16 Bytes, generate uint32_t W[44]. */ | |
/* W[0-3] */ | |
for (int i = 0; i < 4; ++i) { | |
LOAD32H(w[i], key + 4*i); | |
} | |
/* W[4-43] */ | |
for (int i = 0; i < 10; ++i) { | |
w[4] = w[0] ^ MIX(w[3]) ^ rcon[i]; | |
w[5] = w[1] ^ w[4]; | |
w[6] = w[2] ^ w[5]; | |
w[7] = w[3] ^ w[6]; | |
w += 4; | |
} | |
w = aesKey->eK+44 - 4; | |
// 解密秘钥矩阵为加密秘钥矩阵的倒序,方便使用,把 ek 的 11 个矩阵倒序排列分配给 dk 作为解密秘钥 | |
// 即 dk [0-3]=ek [41-44], dk [4-7]=ek [37-40]... dk [41-44]=ek [0-3] | |
for (int j = 0; j < 11; ++j) { | |
for (int i = 0; i < 4; ++i) { | |
v[i] = w[i]; | |
} | |
w -= 4; | |
v += 4; | |
} | |
return 0; | |
} | |
// 轮秘钥加 | |
int addRoundKey(uint8_t (*state)[4], const uint32_t *key) { | |
uint8_t k[4][4]; | |
/* i: row, j: col */ | |
for (int i = 0; i < 4; ++i) { | |
for (int j = 0; j < 4; ++j) { | |
k[i][j] = (uint8_t) BYTE(key[j], 3 - i); /* 把 uint32 key [4] 先转换为矩阵 uint8 k [4][4] */ | |
state[i][j] ^= k[i][j]; | |
} | |
} | |
return 0; | |
} | |
// 字节替换 | |
int subBytes(uint8_t (*state)[4]) { | |
/* i: row, j: col */ | |
for (int i = 0; i < 4; ++i) { | |
for (int j = 0; j < 4; ++j) { | |
state[i][j] = S[state[i][j]]; // 直接使用原始字节作为 S 盒数据下标 | |
} | |
} | |
return 0; | |
} | |
// 逆字节替换 | |
int invSubBytes(uint8_t (*state)[4]) { | |
/* i: row, j: col */ | |
for (int i = 0; i < 4; ++i) { | |
for (int j = 0; j < 4; ++j) { | |
state[i][j] = inv_S[state[i][j]]; | |
} | |
} | |
return 0; | |
} | |
// 行移位 | |
int shiftRows(uint8_t (*state)[4]) { | |
uint32_t block[4] = {0}; | |
/* i: row */ | |
for (int i = 0; i < 4; ++i) { | |
// 便于行循环移位,先把一行 4 字节拼成 uint_32 结构,移位后再转成独立的 4 个字节 uint8_t | |
LOAD32H(block[i], state[i]); | |
block[i] = ROF32(block[i], 8*i); | |
STORE32H(block[i], state[i]); | |
} | |
return 0; | |
} | |
// 逆行移位 | |
int invShiftRows(uint8_t (*state)[4]) { | |
uint32_t block[4] = {0}; | |
/* i: row */ | |
for (int i = 0; i < 4; ++i) { | |
LOAD32H(block[i], state[i]); | |
block[i] = ROR32(block[i], 8*i); | |
STORE32H(block[i], state[i]); | |
} | |
return 0; | |
} | |
/* Galois Field (256) Multiplication of two Bytes */ | |
// 两字节的伽罗华域乘法运算 | |
uint8_t GMul(uint8_t u, uint8_t v) { | |
uint8_t p = 0; | |
for (int i = 0; i < 8; ++i) { | |
if (u & 0x01) { // | |
p ^= v; | |
} | |
int flag = (v & 0x80); | |
v <<= 1; | |
if (flag) { | |
v ^= 0x1B; /* x^8 + x^4 + x^3 + x + 1 */ | |
} | |
u >>= 1; | |
} | |
return p; | |
} | |
// 列混合 | |
int mixColumns(uint8_t (*state)[4]) { | |
uint8_t tmp[4][4]; | |
uint8_t M[4][4] = <!--swig0-->; | |
/* copy state[4][4] to tmp[4][4] */ | |
for (int i = 0; i < 4; ++i) { | |
for (int j = 0; j < 4; ++j){ | |
tmp[i][j] = state[i][j]; | |
} | |
} | |
for (int i = 0; i < 4; ++i) { | |
for (int j = 0; j < 4; ++j) { // 伽罗华域加法和乘法 | |
state[i][j] = GMul(M[i][0], tmp[0][j]) ^ GMul(M[i][1], tmp[1][j]) | |
^ GMul(M[i][2], tmp[2][j]) ^ GMul(M[i][3], tmp[3][j]); | |
} | |
} | |
return 0; | |
} | |
// 逆列混合 | |
int invMixColumns(uint8_t (*state)[4]) { | |
uint8_t tmp[4][4]; | |
uint8_t M[4][4] = <!--swig1-->; // 使用列混合矩阵的逆矩阵 | |
/* copy state[4][4] to tmp[4][4] */ | |
for (int i = 0; i < 4; ++i) { | |
for (int j = 0; j < 4; ++j){ | |
tmp[i][j] = state[i][j]; | |
} | |
} | |
for (int i = 0; i < 4; ++i) { | |
for (int j = 0; j < 4; ++j) { | |
state[i][j] = GMul(M[i][0], tmp[0][j]) ^ GMul(M[i][1], tmp[1][j]) | |
^ GMul(M[i][2], tmp[2][j]) ^ GMul(M[i][3], tmp[3][j]); | |
} | |
} | |
return 0; | |
} | |
// AES-128 加密接口,输入 key 应为 16 字节长度,输入长度应该是 16 字节整倍数, | |
// 这样输出长度与输入长度相同,函数调用外部为输出数据分配内存 | |
int aesEncrypt(const uint8_t *key, uint32_t keyLen, const uint8_t *pt, uint8_t *ct, uint32_t len) { | |
AesKey aesKey; | |
uint8_t *pos = ct; | |
const uint32_t *rk = aesKey.eK; // 解密秘钥指针 | |
uint8_t out[BLOCKSIZE] = {0}; | |
uint8_t actualKey[16] = {0}; | |
uint8_t state[4][4] = {0}; | |
if (NULL == key || NULL == pt || NULL == ct){ | |
printf("param err.\n"); | |
return -1; | |
} | |
if (keyLen > 16){ | |
printf("keyLen must be 16.\n"); | |
return -1; | |
} | |
if (len % BLOCKSIZE){ | |
printf("inLen is invalid.\n"); | |
return -1; | |
} | |
memcpy(actualKey, key, keyLen); | |
keyExpansion(actualKey, 16, &aesKey); // 秘钥扩展 | |
// 使用 ECB 模式循环加密多个分组长度的数据 | |
for (int i = 0; i < len; i += BLOCKSIZE) { | |
// 把 16 字节的明文转换为 4x4 状态矩阵来进行处理 | |
loadStateArray(state, pt); | |
// 轮秘钥加 | |
addRoundKey(state, rk); | |
for (int j = 1; j < 10; ++j) { | |
rk += 4; | |
subBytes(state); // 字节替换 | |
shiftRows(state); // 行移位 | |
mixColumns(state); // 列混合 | |
addRoundKey(state, rk); // 轮秘钥加 | |
} | |
subBytes(state); // 字节替换 | |
shiftRows(state); // 行移位 | |
// 此处不进行列混合 | |
addRoundKey(state, rk+4); // 轮秘钥加 | |
// 把 4x4 状态矩阵转换为 uint8_t 一维数组输出保存 | |
storeStateArray(state, pos); | |
pos += BLOCKSIZE; // 加密数据内存指针移动到下一个分组 | |
pt += BLOCKSIZE; // 明文数据指针移动到下一个分组 | |
rk = aesKey.eK; // 恢复 rk 指针到秘钥初始位置 | |
} | |
return 0; | |
} | |
// AES128 解密, 参数要求同加密 | |
int aesDecrypt(const uint8_t *key, uint32_t keyLen, const uint8_t *ct, uint8_t *pt, uint32_t len) { | |
AesKey aesKey; | |
uint8_t *pos = pt; | |
const uint32_t *rk = aesKey.dK; // 解密秘钥指针 | |
uint8_t out[BLOCKSIZE] = {0}; | |
uint8_t actualKey[16] = {0}; | |
uint8_t state[4][4] = {0}; | |
if (NULL == key || NULL == ct || NULL == pt){ | |
printf("param err.\n"); | |
return -1; | |
} | |
if (keyLen > 16){ | |
printf("keyLen must be 16.\n"); | |
return -1; | |
} | |
if (len % BLOCKSIZE){ | |
printf("inLen is invalid.\n"); | |
return -1; | |
} | |
memcpy(actualKey, key, keyLen); | |
keyExpansion(actualKey, 16, &aesKey); // 秘钥扩展,同加密 | |
for (int i = 0; i < len; i += BLOCKSIZE) { | |
// 把 16 字节的密文转换为 4x4 状态矩阵来进行处理 | |
loadStateArray(state, ct); | |
// 轮秘钥加,同加密 | |
addRoundKey(state, rk); | |
for (int j = 1; j < 10; ++j) { | |
rk += 4; | |
invShiftRows(state); // 逆行移位 | |
invSubBytes(state); // 逆字节替换,这两步顺序可以颠倒 | |
addRoundKey(state, rk); // 轮秘钥加,同加密 | |
invMixColumns(state); // 逆列混合 | |
} | |
invSubBytes(state); // 逆字节替换 | |
invShiftRows(state); // 逆行移位 | |
// 此处没有逆列混合 | |
addRoundKey(state, rk+4); // 轮秘钥加,同加密 | |
storeStateArray(state, pos); // 保存明文数据 | |
pos += BLOCKSIZE; // 输出数据内存指针移位分组长度 | |
ct += BLOCKSIZE; // 输入数据内存指针移位分组长度 | |
rk = aesKey.dK; // 恢复 rk 指针到秘钥初始位置 | |
} | |
return 0; | |
} | |
// 方便输出 16 进制数据 | |
void printHex(uint8_t *ptr, int len, char *tag) { | |
printf("%s\ndata[%d]: ", tag, len); | |
for (int i = 0; i < len; ++i) { | |
printf("%.2X ", *ptr++); | |
} | |
printf("\n"); | |
} | |
//S 盒转逆 S 盒,S 盒不是标准的时候使用 | |
void get_S_rev(){ | |
uint8_t line=0,rol=0;// 位置 | |
for(int i=0;i<256;i++){ | |
line = (S[i]&0xf0)>>4; | |
rol = S[i]&0xf; | |
inv_S[line*16+rol] = i; | |
} | |
} | |
int main() { | |
//get_S_rev ();//S 盒有变化,需要求出逆 S 盒 | |
const uint8_t key[16] = {0x73,0x65,0x63,0x72,0x65,0x74,0x21,0x21,0x73,0x65,0x63,0x72,0x65,0x74,0x21,0x21}; | |
const uint8_t pt[16]={0x54,0x65,0x78,0x74,0x54,0x65,0x78,0x74,0x54,0x65,0x78,0x74,0x54,0x65,0x78,0x74}; | |
uint8_t ct[16] = {0}; // 外部申请输出数据内存,用于加密后的数据 | |
uint8_t plain[16] = {0}; // 外部申请输出数据内存,用于解密后的数据 | |
aesEncrypt(key, 16, pt, ct, 16); // 加密 | |
printHex(ct, 16, "after encryption:"); // 打印加密后的密文 | |
aesDecrypt(key, 16, ct, plain, 16); // 解密 | |
printHex(plain, 16, "after decryption:"); // 打印解密后的明文数据. | |
return 0; | |
} | |
/* | |
after encryption: | |
data[16]: 09 39 9B C5 19 45 EB 34 6F 4C 1A 60 C7 8B D4 B2 | |
after decryption: | |
data[16]: 54 65 78 74 54 65 78 74 54 65 78 74 54 65 78 74 | |
*/ |
from Crypto.Cipher import AES | |
password = b'secret!!secret!!' # 秘钥必须为 16 字节或者 16 字节的倍数的字节型数据 | |
iv = b'1234567812345678' # iv 偏移量,bytes 类型 | |
text = b'TextTextTextText' # 明文必须为 16 字节或者 16 字节的倍数的字节型数据,如果不够 16 字节需要进行补全 | |
aes = AES.new(password, AES.MODE_CBC, iv) # 创建一个 aes 对象 | |
# AES.MODE_CBC 表示模式是 CBC 模式 | |
en_text = aes.encrypt(text) | |
print("密文:", en_text) # 加密明文,bytes 类型 | |
aes = AES.new(password, AES.MODE_CBC, iv) # CBC 模式下解密需要重新创建一个 aes 对象 | |
de_text = aes.decrypt(en_text) | |
print("明文:", de_text) | |
''' | |
密文: b'v\rv`HDi\xbbV\xcb\xef\x02\x8f\x93\xb09' | |
明文: b'TextTextTextText' | |
''' |
todo |
todo |
# MD5
from hashlib import md5 | |
s = 'oacia' | |
new_md5 = md5() | |
new_md5.update(s.encode(encoding='utf-8')) | |
s_enc = new_md5.hexdigest() | |
print(s_enc)# 6a58e79a78afc9dd94485810106bc7e8 |
#include <stdio.h> | |
#include <string.h> | |
#include <stdlib.h> | |
#include "md5.h" | |
void md5_enc(unsigned char encrypt[],unsigned char decrypt[]){ | |
MD5_CTX md5; | |
MD5Init(&md5); | |
MD5Update(&md5,encrypt,strlen((char *)encrypt)); | |
MD5Final(&md5,decrypt); | |
} | |
int main(int argc, char *argv[]) | |
{ | |
char s[10] = "oacia"; | |
unsigned char* s_enc; | |
md5_enc(s,s_enc); | |
for(int i=0;i<16;i++){ | |
printf("%02x",s_enc[i]);//6a58e79a78afc9dd94485810106bc7e8 | |
} | |
return 0; | |
} |
#include <memory.h> | |
#include "md5.h" | |
unsigned char PADDING[]={0x80,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, | |
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, | |
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, | |
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; | |
void MD5Init(MD5_CTX *context) | |
{ | |
//md5 原始常量 | |
context->count[0] = 0; | |
context->count[1] = 0; | |
context->state[0] = 0x67452301; | |
context->state[1] = 0xEFCDAB89; | |
context->state[2] = 0x98BADCFE; | |
context->state[3] = 0x10325476; | |
} | |
void MD5Update(MD5_CTX *context,unsigned char *input,unsigned int inputlen) | |
{ | |
unsigned int i = 0,index = 0,partlen = 0; | |
index = (context->count[0] >> 3) & 0x3F; | |
partlen = 64 - index; | |
context->count[0] += inputlen << 3; | |
if(context->count[0] < (inputlen << 3)) | |
context->count[1]++; | |
context->count[1] += inputlen >> 29; | |
if(inputlen >= partlen) | |
{ | |
memcpy(&context->buffer[index],input,partlen); | |
MD5Transform(context->state,context->buffer); | |
for(i = partlen;i+64 <= inputlen;i+=64) | |
MD5Transform(context->state,&input[i]); | |
index = 0; | |
} | |
else | |
{ | |
i = 0; | |
} | |
memcpy(&context->buffer[index],&input[i],inputlen-i); | |
} | |
void MD5Final(MD5_CTX *context,unsigned char digest[16]) | |
{ | |
unsigned int index = 0,padlen = 0; | |
unsigned char bits[8]; | |
index = (context->count[0] >> 3) & 0x3F; | |
padlen = (index < 56)?(56-index):(120-index); | |
MD5Encode(bits,context->count,8); | |
MD5Update(context,PADDING,padlen); | |
MD5Update(context,bits,8); | |
MD5Encode(digest,context->state,16); | |
} | |
void MD5Encode(unsigned char *output,unsigned int *input,unsigned int len) | |
{ | |
unsigned int i = 0,j = 0; | |
while(j < len) | |
{ | |
output[j] = input[i] & 0xFF; | |
output[j+1] = (input[i] >> 8) & 0xFF; | |
output[j+2] = (input[i] >> 16) & 0xFF; | |
output[j+3] = (input[i] >> 24) & 0xFF; | |
i++; | |
j+=4; | |
} | |
} | |
void MD5Decode(unsigned int *output,unsigned char *input,unsigned int len) | |
{ | |
unsigned int i = 0,j = 0; | |
while(j < len) | |
{ | |
output[i] = (input[j]) | | |
(input[j+1] << 8) | | |
(input[j+2] << 16) | | |
(input[j+3] << 24); | |
i++; | |
j+=4; | |
} | |
} | |
void MD5Transform(unsigned int state[4],unsigned char block[64]) | |
{ | |
unsigned int a = state[0]; | |
unsigned int b = state[1]; | |
unsigned int c = state[2]; | |
unsigned int d = state[3]; | |
unsigned int x[64]; | |
MD5Decode(x,block,64); | |
FF(a, b, c, d, x[ 0], 7, 0xd76aa478); /* 1 */ | |
FF(d, a, b, c, x[ 1], 12, 0xe8c7b756); /* 2 */ | |
FF(c, d, a, b, x[ 2], 17, 0x242070db); /* 3 */ | |
FF(b, c, d, a, x[ 3], 22, 0xc1bdceee); /* 4 */ | |
FF(a, b, c, d, x[ 4], 7, 0xf57c0faf); /* 5 */ | |
FF(d, a, b, c, x[ 5], 12, 0x4787c62a); /* 6 */ | |
FF(c, d, a, b, x[ 6], 17, 0xa8304613); /* 7 */ | |
FF(b, c, d, a, x[ 7], 22, 0xfd469501); /* 8 */ | |
FF(a, b, c, d, x[ 8], 7, 0x698098d8); /* 9 */ | |
FF(d, a, b, c, x[ 9], 12, 0x8b44f7af); /* 10 */ | |
FF(c, d, a, b, x[10], 17, 0xffff5bb1); /* 11 */ | |
FF(b, c, d, a, x[11], 22, 0x895cd7be); /* 12 */ | |
FF(a, b, c, d, x[12], 7, 0x6b901122); /* 13 */ | |
FF(d, a, b, c, x[13], 12, 0xfd987193); /* 14 */ | |
FF(c, d, a, b, x[14], 17, 0xa679438e); /* 15 */ | |
FF(b, c, d, a, x[15], 22, 0x49b40821); /* 16 */ | |
/* Round 2 */ | |
GG(a, b, c, d, x[ 1], 5, 0xf61e2562); /* 17 */ | |
GG(d, a, b, c, x[ 6], 9, 0xc040b340); /* 18 */ | |
GG(c, d, a, b, x[11], 14, 0x265e5a51); /* 19 */ | |
GG(b, c, d, a, x[ 0], 20, 0xe9b6c7aa); /* 20 */ | |
GG(a, b, c, d, x[ 5], 5, 0xd62f105d); /* 21 */ | |
GG(d, a, b, c, x[10], 9, 0x2441453); /* 22 */ | |
GG(c, d, a, b, x[15], 14, 0xd8a1e681); /* 23 */ | |
GG(b, c, d, a, x[ 4], 20, 0xe7d3fbc8); /* 24 */ | |
GG(a, b, c, d, x[ 9], 5, 0x21e1cde6); /* 25 */ | |
GG(d, a, b, c, x[14], 9, 0xc33707d6); /* 26 */ | |
GG(c, d, a, b, x[ 3], 14, 0xf4d50d87); /* 27 */ | |
GG(b, c, d, a, x[ 8], 20, 0x455a14ed); /* 28 */ | |
GG(a, b, c, d, x[13], 5, 0xa9e3e905); /* 29 */ | |
GG(d, a, b, c, x[ 2], 9, 0xfcefa3f8); /* 30 */ | |
GG(c, d, a, b, x[ 7], 14, 0x676f02d9); /* 31 */ | |
GG(b, c, d, a, x[12], 20, 0x8d2a4c8a); /* 32 */ | |
/* Round 3 */ | |
HH(a, b, c, d, x[ 5], 4, 0xfffa3942); /* 33 */ | |
HH(d, a, b, c, x[ 8], 11, 0x8771f681); /* 34 */ | |
HH(c, d, a, b, x[11], 16, 0x6d9d6122); /* 35 */ | |
HH(b, c, d, a, x[14], 23, 0xfde5380c); /* 36 */ | |
HH(a, b, c, d, x[ 1], 4, 0xa4beea44); /* 37 */ | |
HH(d, a, b, c, x[ 4], 11, 0x4bdecfa9); /* 38 */ | |
HH(c, d, a, b, x[ 7], 16, 0xf6bb4b60); /* 39 */ | |
HH(b, c, d, a, x[10], 23, 0xbebfbc70); /* 40 */ | |
HH(a, b, c, d, x[13], 4, 0x289b7ec6); /* 41 */ | |
HH(d, a, b, c, x[ 0], 11, 0xeaa127fa); /* 42 */ | |
HH(c, d, a, b, x[ 3], 16, 0xd4ef3085); /* 43 */ | |
HH(b, c, d, a, x[ 6], 23, 0x4881d05); /* 44 */ | |
HH(a, b, c, d, x[ 9], 4, 0xd9d4d039); /* 45 */ | |
HH(d, a, b, c, x[12], 11, 0xe6db99e5); /* 46 */ | |
HH(c, d, a, b, x[15], 16, 0x1fa27cf8); /* 47 */ | |
HH(b, c, d, a, x[ 2], 23, 0xc4ac5665); /* 48 */ | |
/* Round 4 */ | |
II(a, b, c, d, x[ 0], 6, 0xf4292244); /* 49 */ | |
II(d, a, b, c, x[ 7], 10, 0x432aff97); /* 50 */ | |
II(c, d, a, b, x[14], 15, 0xab9423a7); /* 51 */ | |
II(b, c, d, a, x[ 5], 21, 0xfc93a039); /* 52 */ | |
II(a, b, c, d, x[12], 6, 0x655b59c3); /* 53 */ | |
II(d, a, b, c, x[ 3], 10, 0x8f0ccc92); /* 54 */ | |
II(c, d, a, b, x[10], 15, 0xffeff47d); /* 55 */ | |
II(b, c, d, a, x[ 1], 21, 0x85845dd1); /* 56 */ | |
II(a, b, c, d, x[ 8], 6, 0x6fa87e4f); /* 57 */ | |
II(d, a, b, c, x[15], 10, 0xfe2ce6e0); /* 58 */ | |
II(c, d, a, b, x[ 6], 15, 0xa3014314); /* 59 */ | |
II(b, c, d, a, x[13], 21, 0x4e0811a1); /* 60 */ | |
II(a, b, c, d, x[ 4], 6, 0xf7537e82); /* 61 */ | |
II(d, a, b, c, x[11], 10, 0xbd3af235); /* 62 */ | |
II(c, d, a, b, x[ 2], 15, 0x2ad7d2bb); /* 63 */ | |
II(b, c, d, a, x[ 9], 21, 0xeb86d391); /* 64 */ | |
state[0] += a; | |
state[1] += b; | |
state[2] += c; | |
state[3] += d; | |
} |
#ifndef MD5_H | |
#define MD5_H | |
typedef struct | |
{ | |
unsigned int count[2]; | |
unsigned int state[4]; | |
unsigned char buffer[64]; | |
}MD5_CTX; | |
#define F(x,y,z) ((x & y) | (~x & z)) | |
#define G(x,y,z) ((x & z) | (y & ~z)) | |
#define H(x,y,z) (x^y^z) | |
#define I(x,y,z) (y ^ (x | ~z)) | |
#define ROTATE_LEFT(x,n) ((x << n) | (x >> (32-n))) | |
#define FF(a,b,c,d,x,s,ac) \ | |
{ \ | |
a += F(b,c,d) + x + ac; \ | |
a = ROTATE_LEFT(a,s); \ | |
a += b; \ | |
} | |
#define GG(a,b,c,d,x,s,ac) \ | |
{ \ | |
a += G(b,c,d) + x + ac; \ | |
a = ROTATE_LEFT(a,s); \ | |
a += b; \ | |
} | |
#define HH(a,b,c,d,x,s,ac) \ | |
{ \ | |
a += H(b,c,d) + x + ac; \ | |
a = ROTATE_LEFT(a,s); \ | |
a += b; \ | |
} | |
#define II(a,b,c,d,x,s,ac) \ | |
{ \ | |
a += I(b,c,d) + x + ac; \ | |
a = ROTATE_LEFT(a,s); \ | |
a += b; \ | |
} | |
void MD5Init(MD5_CTX *context); | |
void MD5Update(MD5_CTX *context,unsigned char *input,unsigned int inputlen); | |
void MD5Final(MD5_CTX *context,unsigned char digest[16]); | |
void MD5Transform(unsigned int state[4],unsigned char block[64]); | |
void MD5Encode(unsigned char *output,unsigned int *input,unsigned int len); | |
void MD5Decode(unsigned int *output,unsigned char *input,unsigned int len); | |
#endif |
# DES
# base
import base64 | |
raw_table = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=' | |
# 如果遇到换表 base64, 修改 new_table!! | |
new_table = 'BACDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=' | |
dictionary_decode = str.maketrans(new_table, raw_table) # 创建字符映射关系 用于 base64decode | |
dictionary_encode = dict(zip(dictionary_decode.values(),dictionary_decode.keys())) # 创建一个与上面反向的映射关系用于 base64encode | |
result = 'qqq' # 123123 原始的数据 | |
result_b64 = base64.b64encode(result.encode()).decode() # 正常 base64 | |
new_result_b64 = result_b64.translate(dictionary_encode) # 换表 base64 | |
print(new_result_b64) |
import string | |
# base 字符集 | |
base64_charset = string.ascii_uppercase + string.ascii_lowercase + string.digits + '+/' | |
def encrypt(origin_bytes): | |
""" | |
将bytes类型编码为base64 | |
:param origin_bytes:需要编码的bytes | |
:return:base64字符串 | |
""" | |
# 将每一位 bytes 转换为二进制字符串 | |
base64_bytes = ['{:0>8}'.format(str(bin(b)).replace('0b', '')) for b in origin_bytes] | |
resp = '' | |
nums = len(base64_bytes) // 3 | |
remain = len(base64_bytes) % 3 | |
integral_part = base64_bytes[0:3 * nums] | |
while integral_part: | |
# 取三个字节,以每 6 比特,转换为 4 个整数 | |
tmp_unit = ''.join(integral_part[0:3]) | |
tmp_unit = [int(tmp_unit[x: x + 6], 2) for x in [0, 6, 12, 18]] | |
# 取对应 base64 字符 | |
resp += ''.join([base64_charset[i] for i in tmp_unit]) | |
integral_part = integral_part[3:] | |
if remain: | |
# 补齐三个字节,每个字节补充 0000 0000 | |
remain_part = ''.join(base64_bytes[3 * nums:]) + (3 - remain) * '0' * 8 | |
# 取三个字节,以每 6 比特,转换为 4 个整数 | |
# 剩余 1 字节可构造 2 个 base64 字符,补充 ==;剩余 2 字节可构造 3 个 base64 字符,补充 = | |
tmp_unit = [int(remain_part[x: x + 6], 2) for x in [0, 6, 12, 18]][:remain + 1] | |
resp += ''.join([base64_charset[i] for i in tmp_unit]) + (3 - remain) * '=' | |
return resp | |
def decrypt(base64_str): | |
""" | |
解码base64字符串 | |
:param base64_str:base64字符串 | |
:return:解码后的bytearray;若入参不是合法base64字符串,返回空bytearray | |
""" | |
if not valid_base64_str(base64_str): | |
return bytearray() | |
# 对每一个 base64 字符取下标索引,并转换为 6 为二进制字符串 | |
base64_bytes = ['{:0>6}'.format(str(bin(base64_charset.index(s))).replace('0b', '')) for s in base64_str if | |
s != '='] | |
resp = bytearray() | |
nums = len(base64_bytes) // 4 | |
remain = len(base64_bytes) % 4 | |
integral_part = base64_bytes[0:4 * nums] | |
while integral_part: | |
# 取 4 个 6 位 base64 字符,作为 3 个字节 | |
tmp_unit = ''.join(integral_part[0:4]) | |
tmp_unit = [int(tmp_unit[x: x + 8], 2) for x in [0, 8, 16]] | |
for i in tmp_unit: | |
resp.append(i) | |
integral_part = integral_part[4:] | |
if remain: | |
remain_part = ''.join(base64_bytes[nums * 4:]) | |
tmp_unit = [int(remain_part[i * 8:(i + 1) * 8], 2) for i in range(remain - 1)] | |
for i in tmp_unit: | |
resp.append(i) | |
return resp | |
def valid_base64_str(b_str): | |
""" | |
验证是否为合法base64字符串 | |
:param b_str: 待验证的base64字符串 | |
:return:是否合法 | |
""" | |
if len(b_str) % 4: | |
return False | |
for m in b_str: | |
if m not in base64_charset: | |
return False | |
return True | |
if __name__ == '__main__': | |
s = 'this is base64!' | |
ciphertext = encrypt(s.encode()) | |
print('ciphertext:', ciphertext) | |
decrypted = decrypt(ciphertext).decode() | |
print('decrypted:', decrypted) | |
''' | |
ciphertext: dGhpcyBpcyBiYXNlNjQh | |
decrypted: this is base64! | |
''' |
#include <stdio.h> | |
#include <string.h> | |
#include <stdlib.h> | |
unsigned char *base64_encode(unsigned char *str) | |
{ | |
long len; | |
long str_len; | |
unsigned char *res; | |
int i,j; | |
// 定义 base64 编码表 | |
unsigned char *base64_table="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; | |
// 计算经过 base64 编码后的字符串长度 | |
str_len=strlen(str); | |
if(str_len % 3 == 0) | |
len=str_len/3*4; | |
else | |
len=(str_len/3+1)*4; | |
res=malloc(sizeof(unsigned char)*len+1); | |
res[len]='\0'; | |
// 以 3 个 8 位字符为一组进行编码 | |
for(i=0,j=0;i<len-2;j+=3,i+=4) | |
{ | |
res[i]=base64_table[str[j]>>2]; // 取出第一个字符的前 6 位并找出对应的结果字符 | |
res[i+1]=base64_table[(str[j]&0x3)<<4 | (str[j+1]>>4)]; // 将第一个字符的后位与第二个字符的前 4 位进行组合并找到对应的结果字符 | |
res[i+2]=base64_table[(str[j+1]&0xf)<<2 | (str[j+2]>>6)]; // 将第二个字符的后 4 位与第三个字符的前 2 位组合并找出对应的结果字符 | |
res[i+3]=base64_table[str[j+2]&0x3f]; // 取出第三个字符的后 6 位并找出结果字符 | |
} | |
switch(str_len % 3) | |
{ | |
case 1: | |
res[i-2]='='; | |
res[i-1]='='; | |
break; | |
case 2: | |
res[i-1]='='; | |
break; | |
} | |
return res; | |
} | |
unsigned char *base64_decode(unsigned char *code) | |
{ | |
// 根据 base64 表,以字符找到对应的十进制数据 | |
int table[]={0,0,0,0,0,0,0,0,0,0,0,0, | |
0,0,0,0,0,0,0,0,0,0,0,0, | |
0,0,0,0,0,0,0,0,0,0,0,0, | |
0,0,0,0,0,0,0,62,0,0,0, | |
63,52,53,54,55,56,57,58, | |
59,60,61,0,0,0,0,0,0,0,0, | |
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,0,0,0,0,0,0,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 | |
}; | |
long len; | |
long str_len; | |
unsigned char *res; | |
int i,j; | |
// 计算解码后的字符串长度 | |
len=strlen(code); | |
// 判断编码后的字符串后是否有 = | |
if(strstr(code,"==")) | |
str_len=len/4*3-2; | |
else if(strstr(code,"=")) | |
str_len=len/4*3-1; | |
else | |
str_len=len/4*3; | |
res=malloc(sizeof(unsigned char)*str_len+1); | |
res[str_len]='\0'; | |
// 以 4 个字符为一位进行解码 | |
for(i=0,j=0;i < len-2;j+=3,i+=4) | |
{ | |
res[j]=((unsigned char)table[code[i]])<<2 | (((unsigned char)table[code[i+1]])>>4); // 取出第一个字符对应 base64 表的十进制数的前 6 位与第二个字符对应 base64 表的十进制数的后 2 位进行组合 | |
res[j+1]=(((unsigned char)table[code[i+1]])<<4) | (((unsigned char)table[code[i+2]])>>2); // 取出第二个字符对应 base64 表的十进制数的后 4 位与第三个字符对应 bas464 表的十进制数的后 4 位进行组合 | |
res[j+2]=(((unsigned char)table[code[i+2]])<<6) | ((unsigned char)table[code[i+3]]); // 取出第三个字符对应 base64 表的十进制数的后 2 位与第 4 个字符进行组合 | |
} | |
return res; | |
} | |
int main(int argc,char **argv) | |
{ | |
unsigned char *buf =NULL; | |
unsigned char *str = "this is base64!"; | |
buf = base64_encode(str); | |
printf("cipheytext: %s\n",buf); | |
buf = base64_decode(buf); | |
printf("decrypted: %s\n",buf); | |
free(buf); | |
return 0; | |
} | |
/* | |
cipheytext: dGhpcyBpcyBiYXNlNjQh | |
decrypted: this is base64! | |
*/ |
todo |
todo |
todo |
todo |
todo |
todo |