常见逆向加解密整合
# preface:小做一点整理
# 流密码
# RC4
魔改的点一般就是在里面加别的操作吧,异或之类的
class RC4: | |
def __init__(self, key) -> None: | |
self.key = key | |
self.S = 0 | |
self.__rc4_init__() | |
def __rc4_init__(self): | |
S = [i for i in range(256)] | |
j = 0 | |
for i in range(256): | |
j = (j + S[i] + key[i % len(key)]) % 256 | |
S[i], S[j] = S[j], S[i] | |
self.S = S | |
def rc4_encrypt(self, plain) -> list: | |
i = 0 | |
j = 0 | |
cipher = [] | |
for p in plain: | |
i = (i + 1) % 256 | |
j = (j + self.S[i]) % 256 | |
self.S[i], self.S[j] = self.S[j], self.S[i] | |
k = p ^ self.S[(self.S[i] + self.S[j]) % 256] | |
cipher.append(k) | |
return cipher | |
key = [] | |
data = [] | |
rc4 = RC4(key) | |
plain = rc4.rc4_encrypt(data) | |
for i in plain: | |
print(chr(i),end = "") |
# Salsa20
需要注意 nonce 的初始填充
from Crypto.Cipher import Salsa20 | |
key = b'\x07\x05\x0B\x0D\x0F\x0D\x0B\x05\x07\x05\x1B\x1D\x1F\x1D\x1B\x05\x07\x05\x0B\x0D\x0F\x37\x35\x3B\x3D\x3F\x07\x05\x0B\x0D\x0F\x0D' | |
nonce = b'\x00\x00\x00\x00\x00\x00\x00\x00' | |
plaintext = b"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890_" | |
cipher = Salsa20.new(key=key , nonce=nonce) | |
ciphertext = cipher.encrypt(plaintext) | |
a = [hex(i) for i in ciphertext] | |
print(a) |
完整版
class Salsa: | |
def __init__(self, r=20): | |
assert r >= 0 | |
self._r = r # number of rounds | |
self._mask = 0xffffffff # 32-bit mask | |
def __call__(self, key=[0] * 32, nonce=[0] * 8, block_counter=[0] * 8): | |
assert len(key) == 32 | |
assert len(nonce) == 8 | |
assert len(block_counter) == 8 | |
# init state | |
k = [self._littleendian(key[4 * i:4 * i + 4]) for i in range(8)] | |
n = [self._littleendian(nonce[4 * i:4 * i + 4]) for i in range(2)] | |
b = [self._littleendian(block_counter[4 * i:4 * i + 4]) for i in range(2)] | |
c = [0x61707865, 0x3320646e, 0x79622d32, 0x6b206574] | |
s = [c[0], k[0], k[1], k[2], | |
k[3], c[1], n[0], n[1], | |
b[0], b[1], c[2], k[4], | |
k[5], k[6], k[7], c[3]] | |
# the state | |
self._s = s[:] | |
for i in range(self._r): | |
self._round() | |
# add initial state to the final one | |
self._s = [(self._s[i] + s[i]) & self._mask for i in range(16)] | |
return self._s | |
def _littleendian(self, b): | |
assert len(b) == 4 | |
return b[0] ^ (b[1] << 8) ^ (b[2] << 16) ^ (b[3] << 24) | |
def _round(self): | |
# quarterround 1 | |
self._s[4] ^= self._rotl32((self._s[0] + self._s[12]) & self._mask, 7) | |
self._s[8] ^= self._rotl32((self._s[0] + self._s[4]) & self._mask, 9) | |
self._s[12] ^= self._rotl32((self._s[4] + self._s[8]) & self._mask, 13) | |
self._s[0] ^= self._rotl32((self._s[8] + self._s[12]) & self._mask, 18) | |
# quarterround 2 | |
self._s[9] ^= self._rotl32((self._s[1] + self._s[5]) & self._mask, 7) | |
self._s[13] ^= self._rotl32((self._s[5] + self._s[9]) & self._mask, 9) | |
self._s[1] ^= self._rotl32((self._s[9] + self._s[13]) & self._mask, 13) | |
self._s[5] ^= self._rotl32((self._s[1] + self._s[13]) & self._mask, 18) | |
# quarterround 3 | |
self._s[14] ^= self._rotl32((self._s[6] + self._s[10]) & self._mask, 7) | |
self._s[2] ^= self._rotl32((self._s[10] + self._s[14]) & self._mask, 9) | |
self._s[6] ^= self._rotl32((self._s[2] + self._s[14]) & self._mask, 13) | |
self._s[10] ^= self._rotl32((self._s[2] + self._s[6]) & self._mask, 18) | |
# quarterround 4 | |
self._s[3] ^= self._rotl32((self._s[11] + self._s[15]) & self._mask, 7) | |
self._s[7] ^= self._rotl32((self._s[3] + self._s[15]) & self._mask, 9) | |
self._s[11] ^= self._rotl32((self._s[3] + self._s[7]) & self._mask, 13) | |
self._s[15] ^= self._rotl32((self._s[7] + self._s[11]) & self._mask, 18) | |
# transpose | |
self._s = [self._s[0], self._s[4], self._s[8], self._s[12], | |
self._s[1], self._s[5], self._s[9], self._s[13], | |
self._s[2], self._s[6], self._s[10], self._s[14], | |
self._s[3], self._s[7], self._s[11], self._s[15]] | |
def _rotl32(self, w, r): | |
# rotate left for 32-bits | |
return (((w << r) & self._mask) | (w >> (32 - r))) | |
if __name__ == '__main__': | |
salsa20 = Salsa() | |
# vectors = [ | |
# [[0]*32, [3,1,4,1,5,9,2,6], [7,0,0,0,0,0,0,0], # 这里就是参数!!! | |
# [ 0xb9a205a3,0x0695e150,0xaa94881a,0xadb7b12c, | |
# 0x798942d4,0x26107016,0x64edb1a4,0x2d27173f, | |
# 0xb1c7f1fa,0x62066edc,0xe035fa23,0xc4496f04, | |
# 0x2131e6b3,0x810bde28,0xf62cb407,0x6bdede3d ] ] ] | |
vectors = [ | |
[[0] * 32, [0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0]]] # 这里就是参数!!! | |
for i in range(len(vectors)): | |
v = vectors[i] | |
print(f"key => {v[0]}") | |
print(f"nonce => {v[1]}") | |
print(f"block_counter => {v[2]}") | |
s = salsa20(v[0], v[1], v[2]) | |
stream_key = [] | |
# for i in s: | |
# print(hex(i),end = " ") | |
for i in range(len(s)): | |
stream_key.append(s[i] & 0xff) | |
stream_key.append((s[i] & 0xff00) >> 8) | |
stream_key.append((s[i] & 0xff0000) >> 16) | |
stream_key.append((s[i] & 0xff000000) >> 24) | |
print() | |
cybertext = [1,1,1,1] | |
for i in range(len(stream_key)): | |
print(chr(stream_key[i] ^ cybertext[i]), end="") |
# chacha20
from Crypto.Cipher import ChaCha20 | |
key = b'\x07\x05\x0B\x0D\x0F\x0D\x0B\x05\x07\x05\x1B\x1D\x1F\x1D\x1B\x05\x07\x05\x0B\x0D\x0F\x37\x35\x3B\x3D\x3F\x07\x05\x0B\x0D\x0F\x0D' | |
plaintext = b"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890_" | |
nonce = b'\x00\x00\x00\x00\x00\x00\x00\x00' | |
cipher = ChaCha20.new(key=key,nonce=nonce) | |
ciphertext = cipher.encrypt(plaintext) | |
# 获取 nonce(用于解密) | |
# nonce = cipher.nonce | |
# 解密 | |
# cipher = ChaCha20.new(key=key, nonce=nonce) | |
# decrypted_text = cipher.decrypt(ciphertext) | |
a = [hex(i) for i in ciphertext] | |
print(a) |
#include <stdint.h> | |
#include <string.h> | |
#include <bits/stdc++.h> | |
static inline void u32t8le(uint32_t v, uint8_t p[4]) { | |
p[0] = v & 0xff; | |
p[1] = (v >> 8) & 0xff; | |
p[2] = (v >> 16) & 0xff; | |
p[3] = (v >> 24) & 0xff; | |
} | |
static inline uint32_t u8t32le(uint8_t p[4]) { | |
uint32_t value = p[3]; | |
value = (value << 8) | p[2]; | |
value = (value << 8) | p[1]; | |
value = (value << 8) | p[0]; | |
return value; | |
} | |
static inline uint32_t rotl32(uint32_t x, int n) { | |
// http://blog.regehr.org/archives/1063 | |
return x << n | (x >> (-n & 31)); | |
} | |
// https://tools.ietf.org/html/rfc7539##section-2.1 | |
static void chacha20_quarterround(uint32_t *x, int a, int b, int c, int d) { | |
x[a] += x[b]; x[d] = rotl32(x[d] ^ x[a], 16); | |
x[c] += x[d]; x[b] = rotl32(x[b] ^ x[c], 12); | |
x[a] += x[b]; x[d] = rotl32(x[d] ^ x[a], 8); | |
x[c] += x[d]; x[b] = rotl32(x[b] ^ x[c], 7); | |
} | |
static void chacha20_serialize(uint32_t in[16], uint8_t output[64]) { | |
int i; | |
for (i = 0; i < 16; i++) { | |
u32t8le(in[i], output + (i << 2)); | |
} | |
} | |
static void chacha20_block(uint32_t in[16], uint8_t out[64], int num_rounds) { //num_rounds 一般为 20 | |
int i; | |
uint32_t x[16]; | |
memcpy(x, in, sizeof(uint32_t) * 16); | |
for (i = num_rounds; i > 0; i -= 2) { | |
//odd round | |
chacha20_quarterround(x, 0, 4, 8, 12); | |
chacha20_quarterround(x, 1, 5, 9, 13); | |
chacha20_quarterround(x, 2, 6, 10, 14); | |
chacha20_quarterround(x, 3, 7, 11, 15); | |
//even round | |
chacha20_quarterround(x, 0, 5, 10, 15); | |
chacha20_quarterround(x, 1, 6, 11, 12); | |
chacha20_quarterround(x, 2, 7, 8, 13); | |
chacha20_quarterround(x, 3, 4, 9, 14); | |
} | |
for (i = 0; i < 16; i++) { | |
x[i] += in[i]; | |
} | |
chacha20_serialize(x, out); | |
} | |
// https://tools.ietf.org/html/rfc7539##section-2.3 | |
static void chacha20_init_state(uint32_t s[16], uint8_t key[32], uint32_t counter, uint8_t nonce[12]) { | |
int i; | |
// refer: https://dxr.mozilla.org/mozilla-beta/source/security/nss/lib/freebl/chacha20.c | |
// convert magic number to string: "expand 32-byte k" | |
s[0] = 0x61707865; | |
s[1] = 0x3320646e; | |
s[2] = 0x79622d32; | |
s[3] = 0x6b206574; | |
for (i = 0; i < 8; i++) { | |
s[4 + i] = u8t32le(key + i * 4); | |
} | |
s[12] = counter; | |
for (i = 0; i < 3; i++) { | |
s[13 + i] = u8t32le(nonce + i * 4); | |
} | |
} | |
void ChaCha20XOR(uint8_t key[32], uint32_t counter, uint8_t nonce[12], uint8_t *in, uint8_t *out, int inlen) { | |
int i, j; | |
uint32_t s[16]; | |
uint8_t block[64]; | |
chacha20_init_state(s, key, counter, nonce); | |
for (i = 0; i < inlen; i += 64) { | |
chacha20_block(s, block, 20); | |
s[12]++; | |
for (j = i; j < i + 64; j++) { | |
if (j >= inlen) { | |
break; | |
} | |
out[j] = in[j] ^ block[j - i]; | |
} | |
} | |
} | |
int main() { | |
int i; | |
uint8_t key[] = { | |
0x00, 0x01, 0x02, 0x03, | |
0x04, 0x05, 0x06, 0x07, | |
0x08, 0x09, 0x0a, 0x0b, | |
0x0c, 0x0d, 0x0e, 0x0f, | |
0x10, 0x11, 0x12, 0x13, | |
0x14, 0x15, 0x16, 0x17, | |
0x18, 0x19, 0x1a, 0x1b, | |
0x1c, 0x1d, 0x1e, 0x1f | |
}; | |
uint8_t nonce[] = { // 随机数 | |
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 | |
}; | |
uint8_t input[114] = { | |
0x4c, 0x61, 0x64, 0x69, 0x65, 0x73, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x47, 0x65, 0x6e, 0x74, 0x6c | |
}; | |
uint8_t encrypt[114]; | |
uint8_t decrypt[114]; | |
int counter = 1; | |
ChaCha20XOR(key, counter, nonce, input, encrypt, 114); | |
ChaCha20XOR(key, counter, nonce, encrypt, decrypt, 114); | |
printf("\nkey:"); | |
for (i = 0; i < 32; i++) { | |
if (!(i % 16)) { | |
printf("\n"); | |
} | |
printf("%02x ", key[i]); | |
} | |
printf("\n\nnonce:\n"); | |
for (i = 0; i < 12; i++) { | |
printf("%02x ", nonce[i]); | |
} | |
printf("\n\nplaintext:"); | |
for (i = 0; i < 114; i++) { | |
if (!(i % 16)) { | |
printf("\n"); | |
} | |
printf("%02x ", input[i]); | |
} | |
printf("\n\nencrypted:"); | |
for (i = 0; i < 114; i++) { | |
if (!(i % 16)) { | |
printf("\n"); | |
} | |
printf("%02x ", encrypt[i]); | |
} | |
printf("\n\ndecrypted:"); | |
for (i = 0; i < 114; i++) { | |
if (!(i % 16)) { | |
printf("\n"); | |
} | |
printf("%02x ", decrypt[i]); | |
} | |
printf("\n"); | |
return 0; | |
} |
# ZUC
未测试过,没找到合适的标准库
from math import ceil | |
S0 = [ | |
0x3E, 0x72, 0x5B, 0x47, 0xCA, 0xE0, 0x00, 0x33, 0x04, 0xD1, 0x54, 0x98, 0x09, 0xB9, 0x6D, 0xCB, | |
0x7B, 0x1B, 0xF9, 0x32, 0xAF, 0x9D, 0x6A, 0xA5, 0xB8, 0x2D, 0xFC, 0x1D, 0x08, 0x53, 0x03, 0x90, | |
0x4D, 0x4E, 0x84, 0x99, 0xE4, 0xCE, 0xD9, 0x91, 0xDD, 0xB6, 0x85, 0x48, 0x8B, 0x29, 0x6E, 0xAC, | |
0xCD, 0xC1, 0xF8, 0x1E, 0x73, 0x43, 0x69, 0xC6, 0xB5, 0xBD, 0xFD, 0x39, 0x63, 0x20, 0xD4, 0x38, | |
0x76, 0x7D, 0xB2, 0xA7, 0xCF, 0xED, 0x57, 0xC5, 0xF3, 0x2C, 0xBB, 0x14, 0x21, 0x06, 0x55, 0x9B, | |
0xE3, 0xEF, 0x5E, 0x31, 0x4F, 0x7F, 0x5A, 0xA4, 0x0D, 0x82, 0x51, 0x49, 0x5F, 0xBA, 0x58, 0x1C, | |
0x4A, 0x16, 0xD5, 0x17, 0xA8, 0x92, 0x24, 0x1F, 0x8C, 0xFF, 0xD8, 0xAE, 0x2E, 0x01, 0xD3, 0xAD, | |
0x3B, 0x4B, 0xDA, 0x46, 0xEB, 0xC9, 0xDE, 0x9A, 0x8F, 0x87, 0xD7, 0x3A, 0x80, 0x6F, 0x2F, 0xC8, | |
0xB1, 0xB4, 0x37, 0xF7, 0x0A, 0x22, 0x13, 0x28, 0x7C, 0xCC, 0x3C, 0x89, 0xC7, 0xC3, 0x96, 0x56, | |
0x07, 0xBF, 0x7E, 0xF0, 0x0B, 0x2B, 0x97, 0x52, 0x35, 0x41, 0x79, 0x61, 0xA6, 0x4C, 0x10, 0xFE, | |
0xBC, 0x26, 0x95, 0x88, 0x8A, 0xB0, 0xA3, 0xFB, 0xC0, 0x18, 0x94, 0xF2, 0xE1, 0xE5, 0xE9, 0x5D, | |
0xD0, 0xDC, 0x11, 0x66, 0x64, 0x5C, 0xEC, 0x59, 0x42, 0x75, 0x12, 0xF5, 0x74, 0x9C, 0xAA, 0x23, | |
0x0E, 0x86, 0xAB, 0xBE, 0x2A, 0x02, 0xE7, 0x67, 0xE6, 0x44, 0xA2, 0x6C, 0xC2, 0x93, 0x9F, 0xF1, | |
0xF6, 0xFA, 0x36, 0xD2, 0x50, 0x68, 0x9E, 0x62, 0x71, 0x15, 0x3D, 0xD6, 0x40, 0xC4, 0xE2, 0x0F, | |
0x8E, 0x83, 0x77, 0x6B, 0x25, 0x05, 0x3F, 0x0C, 0x30, 0xEA, 0x70, 0xB7, 0xA1, 0xE8, 0xA9, 0x65, | |
0x8D, 0x27, 0x1A, 0xDB, 0x81, 0xB3, 0xA0, 0xF4, 0x45, 0x7A, 0x19, 0xDF, 0xEE, 0x78, 0x34, 0x60 | |
] | |
S1 = [ | |
0x55, 0xC2, 0x63, 0x71, 0x3B, 0xC8, 0x47, 0x86, 0x9F, 0x3C, 0xDA, 0x5B, 0x29, 0xAA, 0xFD, 0x77, | |
0x8C, 0xC5, 0x94, 0x0C, 0xA6, 0x1A, 0x13, 0x00, 0xE3, 0xA8, 0x16, 0x72, 0x40, 0xF9, 0xF8, 0x42, | |
0x44, 0x26, 0x68, 0x96, 0x81, 0xD9, 0x45, 0x3E, 0x10, 0x76, 0xC6, 0xA7, 0x8B, 0x39, 0x43, 0xE1, | |
0x3A, 0xB5, 0x56, 0x2A, 0xC0, 0x6D, 0xB3, 0x05, 0x22, 0x66, 0xBF, 0xDC, 0x0B, 0xFA, 0x62, 0x48, | |
0xDD, 0x20, 0x11, 0x06, 0x36, 0xC9, 0xC1, 0xCF, 0xF6, 0x27, 0x52, 0xBB, 0x69, 0xF5, 0xD4, 0x87, | |
0x7F, 0x84, 0x4C, 0xD2, 0x9C, 0x57, 0xA4, 0xBC, 0x4F, 0x9A, 0xDF, 0xFE, 0xD6, 0x8D, 0x7A, 0xEB, | |
0x2B, 0x53, 0xD8, 0x5C, 0xA1, 0x14, 0x17, 0xFB, 0x23, 0xD5, 0x7D, 0x30, 0x67, 0x73, 0x08, 0x09, | |
0xEE, 0xB7, 0x70, 0x3F, 0x61, 0xB2, 0x19, 0x8E, 0x4E, 0xE5, 0x4B, 0x93, 0x8F, 0x5D, 0xDB, 0xA9, | |
0xAD, 0xF1, 0xAE, 0x2E, 0xCB, 0x0D, 0xFC, 0xF4, 0x2D, 0x46, 0x6E, 0x1D, 0x97, 0xE8, 0xD1, 0xE9, | |
0x4D, 0x37, 0xA5, 0x75, 0x5E, 0x83, 0x9E, 0xAB, 0x82, 0x9D, 0xB9, 0x1C, 0xE0, 0xCD, 0x49, 0x89, | |
0x01, 0xB6, 0xBD, 0x58, 0x24, 0xA2, 0x5F, 0x38, 0x78, 0x99, 0x15, 0x90, 0x50, 0xB8, 0x95, 0xE4, | |
0xD0, 0x91, 0xC7, 0xCE, 0xED, 0x0F, 0xB4, 0x6F, 0xA0, 0xCC, 0xF0, 0x02, 0x4A, 0x79, 0xC3, 0xDE, | |
0xA3, 0xEF, 0xEA, 0x51, 0xE6, 0x6B, 0x18, 0xEC, 0x1B, 0x2C, 0x80, 0xF7, 0x74, 0xE7, 0xFF, 0x21, | |
0x5A, 0x6A, 0x54, 0x1E, 0x41, 0x31, 0x92, 0x35, 0xC4, 0x33, 0x07, 0x0A, 0xBA, 0x7E, 0x0E, 0x34, | |
0x88, 0xB1, 0x98, 0x7C, 0xF3, 0x3D, 0x60, 0x6C, 0x7B, 0xCA, 0xD3, 0x1F, 0x32, 0x65, 0x04, 0x28, | |
0x64, 0xBE, 0x85, 0x9B, 0x2F, 0x59, 0x8A, 0xD7, 0xB0, 0x25, 0xAC, 0xAF, 0x12, 0x03, 0xE2, 0xF2 | |
] | |
D = [ | |
0x44D7, 0x26BC, 0x626B, 0x135E, 0x5789, 0x35E2, 0x7135, 0x09AF, | |
0x4D78, 0x2F13, 0x6BC4, 0x1AF1, 0x5E26, 0x3C4D, 0x789A, 0x47AC | |
] | |
def addition_uint31(a, b): | |
c = a + b | |
return (c & 0x7FFFFFFF) + (c >> 31) | |
def rotl_uint31(a, shift): | |
return ((a << shift) | (a >> (31 - shift))) & 0x7FFFFFFF | |
def rotl_uint32(a, shift): | |
return ((a << shift) | (a >> (32 - shift))) & 0xFFFFFFFF | |
def l1(x): | |
return (x ^ rotl_uint32(x, 2) ^ rotl_uint32(x, 10) ^ rotl_uint32(x, 18) ^ rotl_uint32(x, 24)) | |
def l2(x): | |
return (x ^ rotl_uint32(x, 8) ^ rotl_uint32(x, 14) ^ rotl_uint32(x, 22) ^ rotl_uint32(x, 30)) | |
def make_uint32(a, b, c, d): | |
return ((a << 24) & 0xffffffff) | ((b << 16) & 0xffffffff) | ((c << 8) & 0xffffffff) | d | |
def make_uint31(a, b, c): | |
return ((a << 23) & 0x7fffffff) | ((b << 8) & 0x7fffffff) | c | |
class ZUC(object): | |
def __init__(self, key, iv): | |
self.r = [0, 0] | |
self.lfsr = [0 for _ in range(16)] | |
self.x = [0, 0, 0, 0] | |
self.zuc_init(key, iv) | |
def bit_reorganization(self): | |
self.x[0] = ((self.lfsr[15] & 0x7FFF8000) << 1) | (self.lfsr[14] & 0xFFFF) | |
self.x[1] = ((self.lfsr[11] & 0xFFFF) << 16) | (self.lfsr[9] >> 15) | |
self.x[2] = ((self.lfsr[7] & 0xFFFF) << 16) | (self.lfsr[5] >> 15) | |
self.x[3] = ((self.lfsr[2] & 0xFFFF) << 16) | (self.lfsr[0] >> 15) | |
def lfsr_next(self): | |
f = self.lfsr[0] | |
v = rotl_uint31(self.lfsr[0], 8) | |
f = addition_uint31(f, v) | |
v = rotl_uint31(self.lfsr[4], 20) | |
f = addition_uint31(f, v) | |
v = rotl_uint31(self.lfsr[10], 21) | |
f = addition_uint31(f, v) | |
v = rotl_uint31(self.lfsr[13], 17) | |
f = addition_uint31(f, v) | |
v = rotl_uint31(self.lfsr[15], 15) | |
f = addition_uint31(f, v) | |
return f | |
def lfsr_append(self, f): | |
self.lfsr.append(f) | |
if len(self.lfsr) > 16: | |
self.lfsr.pop(0) | |
def lfsr_init(self, u): | |
self.lfsr_append(addition_uint31(self.lfsr_next(), u)) | |
def lfsr_shift(self): | |
self.lfsr_append(self.lfsr_next()) | |
def f(self): | |
W = ((self.x[0] ^ self.r[0]) + self.r[1]) & 0xffffffff | |
W1 = (self.r[0] + self.x[1]) & 0xffffffff | |
W2 = self.r[1] ^ self.x[2] | |
u = l1(((W1 & 0x0000ffff) << 16) | (W2 >> 16)) | |
v = l2(((W2 & 0x0000ffff) << 16) | (W1 >> 16)) | |
self.r = [make_uint32(S0[u >> 24], S1[(u >> 16) & 0xFF], | |
S0[(u >> 8) & 0xFF], S1[u & 0xFF]), | |
make_uint32(S0[v >> 24], S1[(v >> 16) & 0xFF], | |
S0[(v >> 8) & 0xFF], S1[v & 0xFF])] | |
return W | |
def zuc_init(self, key, iv): | |
# Expand key. | |
self.lfsr = [make_uint31(key[i], D[i], iv[i]) for i in range(16)] | |
self.r = [0, 0] | |
for i in range(32): | |
self.bit_reorganization() | |
w = self.f() | |
self.lfsr_init(w >> 1) | |
def zuc_generate_keystream(self, length): | |
keystream_buffer = [] | |
self.bit_reorganization() | |
self.f() # Discard the output of F. | |
def itor(): | |
self.lfsr_shift() | |
self.bit_reorganization() | |
return self.f() ^ self.x[-1] | |
keystream_buffer = [itor() for _ in range(length)] | |
self.lfsr_shift() | |
return keystream_buffer | |
def zuc_encrypt(self, input): | |
length = len(input) | |
key_stream = self.zuc_generate_keystream(length) | |
return [inp ^ key_stream[i] for i, inp in enumerate(input)] | |
if '__main__' == __name__: | |
key = [0x00] * 16 | |
iv = [0x00] * 16 | |
zuc = ZUC(key, iv) | |
# 加密过程 | |
out = zuc.zuc_encrypt(b"i love u") | |
print("加密得到的字流", ["%08x" % e for e in out]) | |
# 解密过程 | |
zuc2 = ZUC(key, iv) | |
out2 = zuc2.zuc_encrypt(out) | |
print("解密得到的字流", ["%08x" % e for e in out2]) | |
print(bytes(out2)) |
# 分组
# TEA
# TEA
#define uint unsigned int | |
void encrypt(uint *v, uint *key) | |
{ | |
uint l = v[0], r = v[1], sum = 0, delta = 0x9e3779b9; | |
for (int i = 1; i <= 32; ++i) | |
{ | |
sum += delta; | |
l += ((r << 4) + key[0]) ^ (r + sum) ^ ((r >> 5) + key[1]); | |
r += ((l << 4) + key[2]) ^ (l + sum) ^ ((l >> 5) + key[3]); | |
} | |
v[0] = l, v[1] = r; | |
} | |
void decrypt(uint *v, uint *key) | |
{ | |
uint l = v[0], r = v[1], sum = 0, delta = 0x9e3779b9; | |
sum = delta * 32; | |
for (int i = 1; i <= 32; ++i) | |
{ | |
r -= ((l << 4) + key[2]) ^ (l + sum) ^ ((l >> 5) + key[3]); | |
l -= ((r << 4) + key[0]) ^ (r + sum) ^ ((r >> 5) + key[1]); | |
sum -= delta; | |
} | |
v[0] = l, v[1] = r; | |
} |
# XTEA
#define uint unsigned int | |
void encrypt(uint *v, uint *key) | |
{ | |
uint l = v[0], r = v[1], sum = 0, delta = 0x9e3779b9; | |
for (int i = 1; i <= 32; ++i) | |
{ | |
l += (((r << 4) ^ (r >> 5)) + r) ^ (sum + key[sum & 3]); | |
sum += delta; | |
r += (((l << 4) ^ (l >> 5)) + l) ^ (sum + key[(sum >> 11) & 3]); | |
} | |
v[0] = l; | |
v[1] = r; | |
} | |
void decrypt(uint *v, uint *key) | |
{ | |
uint l = v[0], r = v[1], sum = 0, delta = 0x9e3779b9; | |
sum = delta * 32; | |
for (int i = 1; i <= 32; ++i) | |
{ | |
r -= (((l << 4) ^ (l >> 5)) + l) ^ (sum + key[(sum >> 11) & 3]); | |
sum -= delta; | |
l -= (((r << 4) ^ (r >> 5)) + r) ^ (sum + key[sum & 3]); | |
} | |
v[0] = l; | |
v[1] = r; | |
} |
# XXTEA
#include <cstdio> | |
#define uint unsigned int | |
#define MX (((z >> 5 ^ y << 2) + (y >> 3 ^ z << 4)) ^ ((sum ^ y) + (k[(i & 3) ^ e] ^ z))) | |
void xxtea(uint *v, int n, uint *k) | |
{ | |
uint y, z, sum, i, t, e, delta = 0x9e3779b9;; | |
if (n > 1) // encrypt | |
{ | |
t = 6 + 52 / n, sum = 0, z = v[n - 1]; | |
while (t--) | |
{ | |
sum += delta, e = (sum >> 2) & 3; | |
for (i = 0; i < n - 1; ++i) | |
{ | |
y = v[i + 1]; | |
z = v[i] += MX; | |
} | |
y = v[0]; | |
z = v[n - 1] += MX; | |
} | |
} | |
else if (n < -1) // decrypt | |
{ | |
n = -n, t = 6 + 52 / n, sum = t * delta, y = v[0]; | |
while (t--) | |
{ | |
e = (sum >> 2) & 3; | |
for (i = n - 1; i > 0; --i) | |
{ | |
z = v[i - 1]; | |
y = v[i] -= MX; | |
} | |
z = v[n - 1]; | |
y = v[0] -= MX; | |
sum -= delta; | |
} | |
} | |
} | |
int main() | |
{ | |
uint v[2]= {1,2}, k[4]= {2,2,3,4}; | |
int n = 2; // abs(n) = strlen(v) | |
printf("data: %u %u\n",v[0],v[1]); | |
xxtea(v, n, k); | |
printf("encrypt:%u %u\n",v[0],v[1]); | |
xxtea(v, -n, k); | |
printf("decrypt: %u %u\n",v[0],v[1]); | |
return 0; | |
} |
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 = [1374278842, 2136006540, 4191056815, 3248881376] | |
k = [0x67452301, 0xefcdab89, 0x98badcfe, 0x10325476] | |
n = 4 | |
res = decrypt(n, v, k) | |
# 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]), hex(res[2]), hex(res[3])) | |
""" | |
Data is : 0x12345678 0x78563412 | |
Encrypted data is : 0xef86c2bb 0x25f31b5e | |
Decrypted data is : 0x12345678 0x78563412 | |
""" |
# 其他
# DES
#include<stdio.h> | |
#include<string.h> | |
#include<stdlib.h> | |
void encryption(unsigned char * plaintext,unsigned char * ciphertext); | |
void decryption(unsigned char * ciphertext,unsigned char * plaintext); | |
void ip_replace(unsigned char * in,unsigned char *out); | |
void fp_replace(unsigned char * in,unsigned char *out); | |
void byte2Bit(unsigned char *in,unsigned char *out,int len); | |
void bit2Byte(unsigned char *in,unsigned char *out,int len); | |
void f_func(unsigned char *in,unsigned char * out,unsigned char *ki); | |
void get_subkey(unsigned char *key); | |
void byteXOR(unsigned char *a,unsigned char *b,int len); | |
void e_expand(unsigned char * in,unsigned char * out); | |
void s_replace(unsigned char * in,unsigned char * out); | |
void p_replace(unsigned char * in,unsigned char * out); | |
void pc1_replace(unsigned char * in,unsigned char * out); | |
void pc2_replace(unsigned char *in,unsigned char *out); | |
const char IP_Table[64]= { | |
58, 50, 42, 34, 26, 18, 10, 2, 60, 52, 44, 36, 28, 20, 12, 4, | |
62, 54, 46, 38, 30, 22, 14, 6, 64, 56, 48, 40, 32, 24, 16, 8, | |
57, 49, 41, 33, 25, 17, 9, 1, 59, 51, 43, 35, 27, 19, 11, 3, | |
61, 53, 45, 37, 29, 21, 13, 5, 63, 55, 47, 39, 31, 23, 15, 7 | |
}; | |
const char IPR_Table[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 | |
}; | |
const char E_Table[48] = { | |
32, 1, 2, 3, 4, 5, 4, 5, 6, 7, 8, 9, | |
8, 9, 10, 11, 12, 13, 12, 13, 14, 15, 16, 17, | |
16, 17, 18, 19, 20, 21, 20, 21, 22, 23, 24, 25, | |
24, 25, 26, 27, 28, 29, 28, 29, 30, 31, 32, 1 | |
}; | |
const char P_Table[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 | |
}; | |
const char PC1_Table[56] = { | |
57, 49, 41, 33, 25, 17, 9, 1, 58, 50, 42, 34, 26, 18, | |
10, 2, 59, 51, 43, 35, 27, 19, 11, 3, 60, 52, 44, 36, | |
63, 55, 47, 39, 31, 23, 15, 7, 62, 54, 46, 38, 30, 22, | |
14, 6, 61, 53, 45, 37, 29, 21, 13, 5, 28, 20, 12, 4 | |
}; | |
const char PC2_Table[48] = { | |
14, 17, 11, 24, 1, 5, 3, 28, 15, 6, 21, 10, | |
23, 19, 12, 4, 26, 8, 16, 7, 27, 20, 13, 2, | |
41, 52, 31, 37, 47, 55, 30, 40, 51, 45, 33, 48, | |
44, 49, 39, 56, 34, 53, 46, 42, 50, 36, 29, 32 | |
}; | |
const char LOOP_Table[16] = { | |
1,1,2,2,2,2,2,2,1,2,2,2,2,2,2,1 | |
}; | |
const char S_Box[8][4][16] = { | |
// S1 | |
14, 4, 13, 1, 2, 15, 11, 8, 3, 10, 6, 12, 5, 9, 0, 7, | |
0, 15, 7, 4, 14, 2, 13, 1, 10, 6, 12, 11, 9, 5, 3, 8, | |
4, 1, 14, 8, 13, 6, 2, 11, 15, 12, 9, 7, 3, 10, 5, 0, | |
15, 12, 8, 2, 4, 9, 1, 7, 5, 11, 3, 14, 10, 0, 6, 13, | |
// S2 | |
15, 1, 8, 14, 6, 11, 3, 4, 9, 7, 2, 13, 12, 0, 5, 10, | |
3, 13, 4, 7, 15, 2, 8, 14, 12, 0, 1, 10, 6, 9, 11, 5, | |
0, 14, 7, 11, 10, 4, 13, 1, 5, 8, 12, 6, 9, 3, 2, 15, | |
13, 8, 10, 1, 3, 15, 4, 2, 11, 6, 7, 12, 0, 5, 14, 9, | |
// S3 | |
10, 0, 9, 14, 6, 3, 15, 5, 1, 13, 12, 7, 11, 4, 2, 8, | |
13, 7, 0, 9, 3, 4, 6, 10, 2, 8, 5, 14, 12, 11, 15, 1, | |
13, 6, 4, 9, 8, 15, 3, 0, 11, 1, 2, 12, 5, 10, 14, 7, | |
1, 10, 13, 0, 6, 9, 8, 7, 4, 15, 14, 3, 11, 5, 2, 12, | |
// S4 | |
7, 13, 14, 3, 0, 6, 9, 10, 1, 2, 8, 5, 11, 12, 4, 15, | |
13, 8, 11, 5, 6, 15, 0, 3, 4, 7, 2, 12, 1, 10, 14, 9, | |
10, 6, 9, 0, 12, 11, 7, 13, 15, 1, 3, 14, 5, 2, 8, 4, | |
3, 15, 0, 6, 10, 1, 13, 8, 9, 4, 5, 11, 12, 7, 2, 14, | |
// S5 | |
2, 12, 4, 1, 7, 10, 11, 6, 8, 5, 3, 15, 13, 0, 14, 9, | |
14, 11, 2, 12, 4, 7, 13, 1, 5, 0, 15, 10, 3, 9, 8, 6, | |
4, 2, 1, 11, 10, 13, 7, 8, 15, 9, 12, 5, 6, 3, 0, 14, | |
11, 8, 12, 7, 1, 14, 2, 13, 6, 15, 0, 9, 10, 4, 5, 3, | |
// S6 | |
12, 1, 10, 15, 9, 2, 6, 8, 0, 13, 3, 4, 14, 7, 5, 11, | |
10, 15, 4, 2, 7, 12, 9, 5, 6, 1, 13, 14, 0, 11, 3, 8, | |
9, 14, 15, 5, 2, 8, 12, 3, 7, 0, 4, 10, 1, 13, 11, 6, | |
4, 3, 2, 12, 9, 5, 15, 10, 11, 14, 1, 7, 6, 0, 8, 13, | |
// S7 | |
4, 11, 2, 14, 15, 0, 8, 13, 3, 12, 9, 7, 5, 10, 6, 1, | |
13, 0, 11, 7, 4, 9, 1, 10, 14, 3, 5, 12, 2, 15, 8, 6, | |
1, 4, 11, 13, 12, 3, 7, 14, 10, 15, 6, 8, 0, 5, 9, 2, | |
6, 11, 13, 8, 1, 4, 10, 7, 9, 5, 0, 15, 14, 2, 3, 12, | |
// S8 | |
13, 2, 8, 4, 6, 15, 11, 1, 10, 9, 3, 14, 5, 0, 12, 7, | |
1, 15, 13, 8, 10, 3, 7, 4, 12, 5, 6, 11, 0, 14, 9, 2, | |
7, 11, 4, 1, 9, 12, 14, 2, 0, 6, 10, 13, 15, 3, 5, 8, | |
2, 1, 14, 7, 4, 10, 8, 13, 15, 12, 9, 0, 3, 5, 6, 11 | |
}; | |
unsigned char subkey[16][48]; | |
unsigned char result[]={0xef,0x34,0xd4,0xa3,0xc6,0x84,0xe4,0x23}; | |
int main() | |
{ | |
unsigned char key[9] = "DE3_En1C"; | |
unsigned char plaintext[20]; | |
//HarDd3s? | |
unsigned char ciphertext[8]; | |
int i=0; | |
puts("give me a string to encrypt:"); | |
scanf("%s",plaintext); | |
if(strlen((const char *)plaintext)!=8){ | |
system("pause"); | |
return -1; | |
} | |
//to generate 16 round subkey | |
get_subkey(key); | |
//to encrypt plaintext | |
encryption(plaintext,ciphertext); | |
for(i=0;i<8;++i){ | |
if(ciphertext[i]!=result[i]){ | |
puts("Wrong!!"); | |
system("pause"); | |
return -1; | |
} | |
} | |
puts("G00d Job!!"); | |
system("pause"); | |
return 0; | |
} | |
void encryption(unsigned char * plaintext,unsigned char * ciphertext){ | |
int i; | |
unsigned char array_plaintext[64]; | |
unsigned char f_result[32]; | |
unsigned char left_array[32]; | |
unsigned char right_array[32]; | |
byte2Bit(plaintext,array_plaintext,8); | |
ip_replace(array_plaintext,array_plaintext); | |
memcpy(left_array,array_plaintext,32); | |
memcpy(right_array,array_plaintext+32,32); | |
for(i=0;i<15;++i){ | |
f_func(right_array,f_result,&subkey[i][0]); | |
byteXOR(f_result,left_array,32); | |
memcpy(left_array,right_array,32); | |
memcpy(right_array,f_result,32); | |
} | |
f_func(right_array,f_result,&subkey[i][0]); | |
byteXOR(left_array,f_result,32); | |
memcpy(array_plaintext,left_array,32); | |
memcpy(array_plaintext+32,right_array,32); | |
fp_replace(array_plaintext,array_plaintext); | |
bit2Byte(array_plaintext,ciphertext,8); | |
} | |
void byte2Bit(unsigned char *in,unsigned char *out,int len){ | |
int i,j; | |
for(i=0;i<len;++i) | |
for(j=0;j<8;++j){ | |
out[i*8+j] = (in[i]>>(7-j))&0x1; | |
} | |
} | |
void bit2Byte(unsigned char *in,unsigned char *out,int len){ | |
int i,j; | |
unsigned char temp; | |
for(i=0;i<len;++i){ | |
temp = in[i*8]&0x1; | |
for(j=1;j<8;++j){ | |
temp = temp<<1; | |
temp = temp+(in[i*8+j]&0x1); | |
} | |
out[i]=temp; | |
} | |
} | |
//change the input 64 bit data to 64 bytes array, use ip table to replace 64 bytes array | |
void ip_replace(unsigned char * in,unsigned char *out){ | |
int i; | |
unsigned char temp[64]; | |
memcpy(temp,in,64); | |
//use ip table to replace 64 bytes(bit) array | |
for(i=0;i<64;++i){ | |
out[i] = temp[IP_Table[i]-1]; | |
//printf("%x ",out[i]); | |
} | |
} | |
void fp_replace(unsigned char *in,unsigned char* out){ | |
int i; | |
unsigned char temp[64]; | |
memcpy(temp,in,64); | |
for(i=0;i<64;++i) | |
out[i] = temp[IPR_Table[i]-1]; | |
} | |
void e_expand(unsigned char * in, unsigned char *out){ | |
unsigned char temp[48]; | |
int i; | |
memcpy(temp,in,48); | |
for(i=0;i<48;++i) | |
out[i] = temp[E_Table[i]-1]; | |
} | |
void s_replace(unsigned char * in,unsigned char *out){ | |
int i,j; | |
int raw,col; | |
char temp; | |
for(i=0,j=0;i<8;++i){ | |
raw = ((in[i*6]<<1)|(in[i*6+5]))&0x3; | |
col = ((in[i*6+1]<<3)|(in[i*6+2]<<2)|(in[i*6+3]<<1)|(in[i*6+4]))&0xF; | |
temp = S_Box[i][raw][col]&0xF; | |
out[j] = (temp>>3)&0x1; | |
out[j+1] = (temp>>2)&0x1; | |
out[j+2] = (temp>>1)&0x1; | |
out[j+3] = (temp)&0x1; | |
j+=4; | |
} | |
} | |
void p_replace(unsigned char * in,unsigned char * out){ | |
unsigned char temp[32]; | |
int i; | |
memcpy(temp,in,32); | |
for(i=0;i<32;++i){ | |
out[i] = temp[P_Table[i]-1]; | |
} | |
} | |
void byteXOR(unsigned char *a,unsigned char *b,int len){ | |
int i; | |
for(i=0;i<len;++i){ | |
a[i] = (a[i]+b[i])&0x1; | |
} | |
} | |
void f_func(unsigned char * in,unsigned char * out,unsigned char * ki){ | |
unsigned char expand_result[48]; | |
unsigned char replace_result[32]; | |
e_expand(in,expand_result); | |
byteXOR(expand_result,ki,48); | |
s_replace(expand_result,replace_result); | |
p_replace(replace_result,replace_result); | |
memcpy(out,replace_result,32); | |
} | |
void pc1_replace(unsigned char * in,unsigned char * out){ | |
int i; | |
for(i=0;i<56;++i) | |
out[i]=in[PC1_Table[i]-1]; | |
} | |
void pc2_replace(unsigned char *in,unsigned char *out){ | |
int i; | |
for(i=0;i<48;++i) | |
out[i] = in[PC2_Table[i]-1]; | |
} | |
void shift_left(unsigned char *in,unsigned char *out,int len){ | |
unsigned char temp[28]; | |
int i,j; | |
memcpy(temp,in,28); | |
for(i=len,j=0;i<28;++i) | |
out[j++]=temp[i]; | |
for(i=0;i<len;++i) | |
out[j++]=temp[i]; | |
} | |
//use user's input key to generate 16 subkey | |
void get_subkey(unsigned char *key){ | |
unsigned char key_temp[64]; | |
unsigned char pc1_result[56]; | |
unsigned char pc2_result[48]; | |
int i; | |
byte2Bit(key,key_temp,8); | |
pc1_replace(key_temp,pc1_result); | |
for(i=0;i<16;++i){ | |
shift_left(pc1_result,pc1_result,LOOP_Table[i]); | |
shift_left(pc1_result+28,pc1_result+28,LOOP_Table[i]); | |
pc2_replace(pc1_result,pc2_result); | |
memcpy(&subkey[i][0],pc2_result,48); | |
} | |
} |
# AES
#include <stdio.h> | |
#include <stdint.h> | |
#include <memory.h> | |
/****************************************************************************************************************/ | |
typedef enum { | |
AES_CYPHER_128, | |
AES_CYPHER_192, | |
AES_CYPHER_256, | |
} AES_CYPHER_T; | |
/****************************************************************************************************************/ | |
/* | |
* Encryption Rounds | |
*/ | |
int g_aes_key_bits[] = { | |
/* AES_CYPHER_128 */ 128, | |
/* AES_CYPHER_192 */ 192, | |
/* AES_CYPHER_256 */ 256, | |
}; | |
int g_aes_rounds[] = { | |
/* AES_CYPHER_128 */ 10, | |
/* AES_CYPHER_192 */ 12, | |
/* AES_CYPHER_256 */ 14, | |
}; | |
int g_aes_nk[] = { | |
/* AES_CYPHER_128 */ 4, | |
/* AES_CYPHER_192 */ 6, | |
/* AES_CYPHER_256 */ 8, | |
}; | |
int g_aes_nb[] = { | |
/* AES_CYPHER_128 */ 4, | |
/* AES_CYPHER_192 */ 4, | |
/* AES_CYPHER_256 */ 4, | |
}; | |
/****************************************************************************************************************/ | |
/* | |
* aes Rcon: | |
* | |
* WARNING: Rcon is designed starting from 1 to 15, not 0 to 14. | |
* FIPS-197 Page 9: "note that i starts at 1, not 0" | |
* | |
* i | 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 | |
* -----+------------------------------------------------------------------------------------------ | |
* | [01] [02] [04] [08] [10] [20] [40] [80] [1b] [36] [6c] [d8] [ab] [4d] [9a] | |
* RCON | [00] [00] [00] [00] [00] [00] [00] [00] [00] [00] [00] [00] [00] [00] [00] | |
* | [00] [00] [00] [00] [00] [00] [00] [00] [00] [00] [00] [00] [00] [00] [00] | |
* | [00] [00] [00] [00] [00] [00] [00] [00] [00] [00] [00] [00] [00] [00] [00] | |
*/ | |
static const uint32_t g_aes_rcon[] = { | |
0x01000000, 0x02000000, 0x04000000, 0x08000000, 0x10000000, 0x20000000, 0x40000000, 0x80000000, | |
0x1b000000, 0x36000000, 0x6c000000, 0xd8000000, 0xab000000, 0xed000000, 0x9a000000 | |
}; | |
/****************************************************************************************************************/ | |
/* | |
* aes sbox and invert-sbox | |
*/ | |
static const uint8_t g_aes_sbox[256] = { | |
/* 0 1 2 3 4 5 6 7 8 9 A B C D E F */ | |
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 | |
}; | |
static const uint8_t g_inv_sbox[256] = { | |
/* 0 1 2 3 4 5 6 7 8 9 A B C D E F */ | |
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 | |
}; | |
/****************************************************************************************************************/ | |
uint8_t aes_sub_sbox(uint8_t val) | |
{ | |
return g_aes_sbox[val]; | |
} | |
/****************************************************************************************************************/ | |
uint32_t aes_sub_dword(uint32_t val) | |
{ | |
uint32_t tmp = 0; | |
tmp |= ((uint32_t)aes_sub_sbox((uint8_t)((val >> 0) & 0xFF))) << 0; | |
tmp |= ((uint32_t)aes_sub_sbox((uint8_t)((val >> 8) & 0xFF))) << 8; | |
tmp |= ((uint32_t)aes_sub_sbox((uint8_t)((val >> 16) & 0xFF))) << 16; | |
tmp |= ((uint32_t)aes_sub_sbox((uint8_t)((val >> 24) & 0xFF))) << 24; | |
return tmp; | |
} | |
/****************************************************************************************************************/ | |
uint32_t aes_rot_dword(uint32_t val) | |
{ | |
uint32_t tmp = val; | |
return (val >> 8) | ((tmp & 0xFF) << 24); | |
} | |
/****************************************************************************************************************/ | |
uint32_t aes_swap_dword(uint32_t val) | |
{ | |
return (((val & 0x000000FF) << 24) | | |
((val & 0x0000FF00) << 8) | | |
((val & 0x00FF0000) >> 8) | | |
((val & 0xFF000000) >> 24)); | |
} | |
/****************************************************************************************************************/ | |
/* | |
* nr: number of rounds | |
* nb: number of columns comprising the state, nb = 4 dwords (16 bytes) | |
* nk: number of 32-bit words comprising cipher key, nk = 4, 6, 8 (KeyLength/(4*8)) | |
*/ | |
void aes_key_expansion(AES_CYPHER_T mode, uint8_t *key, uint8_t *round) | |
{ | |
uint32_t *w = (uint32_t *)round; | |
uint32_t t; | |
int i = 0; | |
do { | |
w[i] = *((uint32_t *)&key[i * 4 + 0]); | |
} while (++i < g_aes_nk[mode]); | |
do { | |
if ((i % g_aes_nk[mode]) == 0) { | |
t = aes_rot_dword(w[i - 1]); | |
t = aes_sub_dword(t); | |
t = t ^ aes_swap_dword(g_aes_rcon[i / g_aes_nk[mode] - 1]); | |
} | |
else if (g_aes_nk[mode] > 6 && (i % g_aes_nk[mode]) == 4) { | |
t = aes_sub_dword(w[i - 1]); | |
} | |
else { | |
t = w[i - 1]; | |
} | |
w[i] = w[i - g_aes_nk[mode]] ^ t; | |
} while (++i < g_aes_nb[mode] * (g_aes_rounds[mode] + 1)); | |
} | |
/****************************************************************************************************************/ | |
void aes_add_round_key(AES_CYPHER_T mode, uint8_t *state, | |
uint8_t *round, int nr) | |
{ | |
uint32_t *w = (uint32_t *)round; | |
uint32_t *s = (uint32_t *)state; | |
int i; | |
for (i = 0; i < g_aes_nb[mode]; i++) { | |
s[i] ^= w[nr * g_aes_nb[mode] + i]; | |
} | |
} | |
/****************************************************************************************************************/ | |
void aes_sub_bytes(AES_CYPHER_T mode, uint8_t *state) | |
{ | |
int i, j; | |
for (i = 0; i < g_aes_nb[mode]; i++) { | |
for (j = 0; j < 4; j++) { | |
state[i * 4 + j] = aes_sub_sbox(state[i * 4 + j]); | |
} | |
} | |
} | |
/****************************************************************************************************************/ | |
void aes_shift_rows(AES_CYPHER_T mode, uint8_t *state) | |
{ | |
uint8_t *s = (uint8_t *)state; | |
int i, j, r; | |
for (i = 1; i < g_aes_nb[mode]; i++) { | |
for (j = 0; j < i; j++) { | |
uint8_t tmp = s[i]; | |
for (r = 0; r < g_aes_nb[mode]; r++) { | |
s[i + r * 4] = s[i + (r + 1) * 4]; | |
} | |
s[i + (g_aes_nb[mode] - 1) * 4] = tmp; | |
} | |
} | |
} | |
/****************************************************************************************************************/ | |
uint8_t aes_xtime(uint8_t x) | |
{ | |
return ((x << 1) ^ (((x >> 7) & 1) * 0x1b)); | |
} | |
/****************************************************************************************************************/ | |
uint8_t aes_xtimes(uint8_t x, int ts) | |
{ | |
while (ts-- > 0) { | |
x = aes_xtime(x); | |
} | |
return x; | |
} | |
/****************************************************************************************************************/ | |
uint8_t aes_mul(uint8_t x, uint8_t y) | |
{ | |
/* | |
* encrypt: y has only 2 bits: can be 1, 2 or 3 | |
* decrypt: y could be any value of 9, b, d, or e | |
*/ | |
return ((((y >> 0) & 1) * aes_xtimes(x, 0)) ^ | |
(((y >> 1) & 1) * aes_xtimes(x, 1)) ^ | |
(((y >> 2) & 1) * aes_xtimes(x, 2)) ^ | |
(((y >> 3) & 1) * aes_xtimes(x, 3)) ^ | |
(((y >> 4) & 1) * aes_xtimes(x, 4)) ^ | |
(((y >> 5) & 1) * aes_xtimes(x, 5)) ^ | |
(((y >> 6) & 1) * aes_xtimes(x, 6)) ^ | |
(((y >> 7) & 1) * aes_xtimes(x, 7))); | |
} | |
/****************************************************************************************************************/ | |
void aes_mix_columns(AES_CYPHER_T mode, uint8_t *state) | |
{ | |
uint8_t y[16] = { 2, 3, 1, 1, 1, 2, 3, 1, 1, 1, 2, 3, 3, 1, 1, 2 }; | |
uint8_t s[4]; | |
int i, j, r; | |
for (i = 0; i < g_aes_nb[mode]; i++) { | |
for (r = 0; r < 4; r++) { | |
s[r] = 0; | |
for (j = 0; j < 4; j++) { | |
s[r] = s[r] ^ aes_mul(state[i * 4 + j], y[r * 4 + j]); | |
} | |
} | |
for (r = 0; r < 4; r++) { | |
state[i * 4 + r] = s[r]; | |
} | |
} | |
} | |
/****************************************************************************************************************/ | |
int aes_encrypt(AES_CYPHER_T mode, uint8_t *data, int len, uint8_t *key) | |
{ | |
uint8_t w[4 * 4 * 15] = { 0 }; /* round key */ | |
uint8_t s[4 * 4] = { 0 }; /* state */ | |
int nr, i, j; | |
/* key expansion */ | |
aes_key_expansion(mode, key, w); | |
/* start data cypher loop over input buffer */ | |
for (i = 0; i < len; i += 4 * g_aes_nb[mode]) { | |
/* init state from user buffer (plaintext) */ | |
for (j = 0; j < 4 * g_aes_nb[mode]; j++) | |
s[j] = data[i + j]; | |
/* start AES cypher loop over all AES rounds */ | |
for (nr = 0; nr <= g_aes_rounds[mode]; nr++) { | |
if (nr > 0) { | |
/* do SubBytes */ | |
aes_sub_bytes(mode, s); | |
/* do ShiftRows */ | |
aes_shift_rows(mode, s); | |
if (nr < g_aes_rounds[mode]) { | |
/* do MixColumns */ | |
aes_mix_columns(mode, s); | |
} | |
} | |
/* do AddRoundKey */ | |
aes_add_round_key(mode, s, w, nr); | |
} | |
/* save state (cypher) to user buffer */ | |
for (j = 0; j < 4 * g_aes_nb[mode]; j++) | |
data[i + j] = s[j]; | |
} | |
return 0; | |
} | |
/****************************************************************************************************************/ | |
int aes_encrypt_ecb(AES_CYPHER_T mode, uint8_t *data, int len, uint8_t *key) | |
{ | |
return aes_encrypt(mode, data, len, key); | |
} | |
/****************************************************************************************************************/ | |
int aes_encrypt_cbc(AES_CYPHER_T mode, uint8_t *data, int len, uint8_t *key, uint8_t *iv) | |
{ | |
uint8_t w[4 * 4 * 15] = { 0 }; /* round key */ | |
uint8_t s[4 * 4] = { 0 }; /* state */ | |
uint8_t v[4 * 4] = { 0 }; /* iv */ | |
int nr, i, j; | |
/* key expansion */ | |
aes_key_expansion(mode, key, w); | |
memcpy(v, iv, sizeof(v)); | |
/* start data cypher loop over input buffer */ | |
for (i = 0; i < len; i += 4 * g_aes_nb[mode]) { | |
/* init state from user buffer (plaintext) */ | |
for (j = 0; j < 4 * g_aes_nb[mode]; j++) | |
s[j] = data[i + j] ^ v[j]; | |
/* start AES cypher loop over all AES rounds */ | |
for (nr = 0; nr <= g_aes_rounds[mode]; nr++) { | |
if (nr > 0) { | |
/* do SubBytes */ | |
aes_sub_bytes(mode, s); | |
/* do ShiftRows */ | |
aes_shift_rows(mode, s); | |
if (nr < g_aes_rounds[mode]) { | |
/* do MixColumns */ | |
aes_mix_columns(mode, s); | |
} | |
} | |
/* do AddRoundKey */ | |
aes_add_round_key(mode, s, w, nr); | |
} | |
/* save state (cypher) to user buffer */ | |
for (j = 0; j < 4 * g_aes_nb[mode]; j++) | |
data[i + j] = v[j] = s[j]; | |
} | |
return 0; | |
} | |
/****************************************************************************************************************/ | |
void inv_shift_rows(AES_CYPHER_T mode, uint8_t *state) | |
{ | |
uint8_t *s = (uint8_t *)state; | |
int i, j, r; | |
for (i = 1; i < g_aes_nb[mode]; i++) { | |
for (j = 0; j < g_aes_nb[mode] - i; j++) { | |
uint8_t tmp = s[i]; | |
for (r = 0; r < g_aes_nb[mode]; r++) { | |
s[i + r * 4] = s[i + (r + 1) * 4]; | |
} | |
s[i + (g_aes_nb[mode] - 1) * 4] = tmp; | |
} | |
} | |
} | |
/****************************************************************************************************************/ | |
uint8_t inv_sub_sbox(uint8_t val) | |
{ | |
return g_inv_sbox[val]; | |
} | |
/****************************************************************************************************************/ | |
void inv_sub_bytes(AES_CYPHER_T mode, uint8_t *state) | |
{ | |
int i, j; | |
for (i = 0; i < g_aes_nb[mode]; i++) { | |
for (j = 0; j < 4; j++) { | |
state[i * 4 + j] = inv_sub_sbox(state[i * 4 + j]); | |
} | |
} | |
} | |
/****************************************************************************************************************/ | |
void inv_mix_columns(AES_CYPHER_T mode, uint8_t *state) | |
{ | |
uint8_t y[16] = { 0x0e, 0x0b, 0x0d, 0x09, 0x09, 0x0e, 0x0b, 0x0d, | |
0x0d, 0x09, 0x0e, 0x0b, 0x0b, 0x0d, 0x09, 0x0e }; | |
uint8_t s[4]; | |
int i, j, r; | |
for (i = 0; i < g_aes_nb[mode]; i++) { | |
for (r = 0; r < 4; r++) { | |
s[r] = 0; | |
for (j = 0; j < 4; j++) { | |
s[r] = s[r] ^ aes_mul(state[i * 4 + j], y[r * 4 + j]); | |
} | |
} | |
for (r = 0; r < 4; r++) { | |
state[i * 4 + r] = s[r]; | |
} | |
} | |
} | |
/****************************************************************************************************************/ | |
int aes_decrypt(AES_CYPHER_T mode, uint8_t *data, int len, uint8_t *key) | |
{ | |
uint8_t w[4 * 4 * 15] = { 0 }; /* round key */ | |
uint8_t s[4 * 4] = { 0 }; /* state */ | |
int nr, i, j; | |
/* key expansion */ | |
aes_key_expansion(mode, key, w); | |
/* start data cypher loop over input buffer */ | |
for (i = 0; i < len; i += 4 * g_aes_nb[mode]) { | |
/* init state from user buffer (cyphertext) */ | |
for (j = 0; j < 4 * g_aes_nb[mode]; j++) | |
s[j] = data[i + j]; | |
/* start AES cypher loop over all AES rounds */ | |
for (nr = g_aes_rounds[mode]; nr >= 0; nr--) { | |
/* do AddRoundKey */ | |
aes_add_round_key(mode, s, w, nr); | |
if (nr > 0) { | |
if (nr < g_aes_rounds[mode]) { | |
/* do MixColumns */ | |
inv_mix_columns(mode, s); | |
} | |
/* do ShiftRows */ | |
inv_shift_rows(mode, s); | |
/* do SubBytes */ | |
inv_sub_bytes(mode, s); | |
} | |
} | |
/* save state (cypher) to user buffer */ | |
for (j = 0; j < 4 * g_aes_nb[mode]; j++) | |
data[i + j] = s[j]; | |
} | |
return 0; | |
} | |
/****************************************************************************************************************/ | |
int aes_decrypt_ecb(AES_CYPHER_T mode, uint8_t *data, int len, uint8_t *key) | |
{ | |
return aes_decrypt(mode, data, len, key); | |
} | |
/****************************************************************************************************************/ | |
int aes_decrypt_cbc(AES_CYPHER_T mode, uint8_t *data, int len, uint8_t *key, uint8_t *iv) | |
{ | |
uint8_t w[4 * 4 * 15] = { 0 }; /* round key */ | |
uint8_t s[4 * 4] = { 0 }; /* state */ | |
uint8_t v[4 * 4] = { 0 }; /* iv */ | |
int nr, i, j; | |
/* key expansion */ | |
aes_key_expansion(mode, key, w); | |
memcpy(v, iv, sizeof(v)); | |
/* start data cypher loop over input buffer */ | |
for (i = 0; i < len; i += 4 * g_aes_nb[mode]) { | |
/* init state from user buffer (cyphertext) */ | |
for (j = 0; j < 4 * g_aes_nb[mode]; j++) | |
s[j] = data[i + j]; | |
/* start AES cypher loop over all AES rounds */ | |
for (nr = g_aes_rounds[mode]; nr >= 0; nr--) { | |
/* do AddRoundKey */ | |
aes_add_round_key(mode, s, w, nr); | |
if (nr > 0) { | |
if (nr < g_aes_rounds[mode]) { | |
/* do MixColumns */ | |
inv_mix_columns(mode, s); | |
} | |
/* do ShiftRows */ | |
inv_shift_rows(mode, s); | |
/* do SubBytes */ | |
inv_sub_bytes(mode, s); | |
} | |
} | |
/* save state (cypher) to user buffer */ | |
for (j = 0; j < 4 * g_aes_nb[mode]; j++) { | |
uint8_t p = s[j] ^ v[j]; | |
v[j] = data[i + j]; | |
data[i + j] = p; | |
} | |
} | |
return 0; | |
} | |
/****************************************************************************************************************/ | |
void aes_cypher_128_test() | |
{ | |
#if 1 | |
uint8_t buf[] = { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, | |
0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff }; | |
uint8_t key[] = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, | |
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f }; | |
#else | |
uint8_t buf[] = { 0x32, 0x43, 0xf6, 0xa8, 0x88, 0x5a, 0x30, 0x8d, | |
0x31, 0x31, 0x98, 0xa2, 0xe0, 0x37, 0x07, 0x34 }; | |
uint8_t key[] = { 0x2b, 0x7e, 0x15, 0x16, 0x28, 0xae, 0xd2, 0xa6, | |
0xab, 0xf7, 0x15, 0x88, 0x09, 0xcf, 0x4f, 0x3c }; | |
#endif | |
aes_encrypt(AES_CYPHER_128, buf, sizeof(buf), key); | |
aes_decrypt(AES_CYPHER_128, buf, sizeof(buf), key); | |
} | |
/****************************************************************************************************************/ | |
void aes_cypher_192_test() | |
{ | |
uint8_t buf[] = { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, | |
0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff }; | |
uint8_t key[] = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, | |
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, | |
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17 }; | |
aes_encrypt(AES_CYPHER_192, buf, sizeof(buf), key); | |
aes_decrypt(AES_CYPHER_192, buf, sizeof(buf), key); | |
} | |
/****************************************************************************************************************/ | |
void aes_cypher_256_test() | |
{ | |
uint8_t buf[] = { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, | |
0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff }; | |
uint8_t key[] = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, | |
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, | |
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, | |
0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f }; | |
aes_encrypt(AES_CYPHER_256, buf, sizeof(buf), key); | |
aes_decrypt(AES_CYPHER_256, buf, sizeof(buf), key); | |
} | |
/****************************************************************************************************************/ | |
int main() | |
{ | |
// 数据 | |
uint8_t buf[] = { 78, 204, 144, 217, 57, 62, 169, 79, 165, 219, 206, 216, 180, 137, 206, 138 }; | |
// 密钥 | |
uint8_t key[] = { 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112 }; | |
// 向量 | |
//uint8_t iv[] = {}; | |
switch (sizeof(key)) | |
{ | |
//ECB | |
case 16:aes_decrypt(AES_CYPHER_128, buf, sizeof(buf), key); break; | |
case 24:aes_decrypt(AES_CYPHER_192, buf, sizeof(buf), key); break; | |
case 32:aes_decrypt(AES_CYPHER_256, buf, sizeof(buf), key); break; | |
//CBC | |
/* | |
case 16:aes_decrypt_cbc(AES_CYPHER_128, buf, sizeof(buf), key, iv); break; | |
case 24:aes_decrypt_cbc(AES_CYPHER_192, buf, sizeof(buf), key, iv); break; | |
case 32:aes_decrypt_cbc(AES_CYPHER_256, buf, sizeof(buf), key, iv); break; | |
*/ | |
} | |
for (int i = 0; i < sizeof(buf); i++) | |
{ | |
printf("%c", buf[i] & 0xFF); | |
} | |
printf("\n"); | |
return 0; | |
} |
from Crypto.Cipher import AES | |
from binascii import b2a_hex, a2b_hex | |
def add_to_16(text): | |
if len(text.encode('utf-8')) % 16: | |
add = 16 - (len(text.encode('utf-8')) % 16) | |
else: | |
add = 0 | |
text = text + ('\0' * add) | |
return text.encode('utf-8') | |
def encrypt(text): | |
key = '\x4D\x4C\x57\x4E\x46\x7C\x19\x0A\x4D\x4C\x57\x4E\x46\x7C\x7B\x67'.encode('utf-8') | |
mode = AES.MODE_ECB | |
text = add_to_16(text) | |
cryptos = AES.new(key, mode) | |
cipher_text = cryptos.encrypt(text) | |
return cipher_text | |
def decrypt(text): | |
key = '\x4D\x4C\x57\x4E\x46\x7C\x19\x0A\x4D\x4C\x57\x4E\x46\x7C\x7B\x67'.encode('utf-8') | |
mode = AES.MODE_ECB | |
cryptor = AES.new(key, mode) | |
plain_text = cryptor.decrypt(a2b_hex(text)) | |
return bytes.decode(plain_text).rstrip('\0') | |
data = b'\x96\x7f\x37\x7c\x26\x30\x03\xeb\x61\x6d\xa3\xda\x0c\x77\x3e\x7c\xdf\x18\x5d\x4e\xd9\xbe\x0a\x5c\x02\x36\x87\x37\xb4\x2f\xb1\x9f' | |
data = b2a_hex(data) | |
ans = decrypt(data) | |
print(ans) |
# RC5
# RC6
# SM4
#include <string.h> | |
#include <stdio.h> | |
#ifndef GET_ULONG_BE | |
#define GET_ULONG_BE(n,b,i) \ | |
{ \ | |
(n) = ( (unsigned long) (b)[(i) ] << 24 ) \ | |
| ( (unsigned long) (b)[(i) + 1] << 16 ) \ | |
| ( (unsigned long) (b)[(i) + 2] << 8 ) \ | |
| ( (unsigned long) (b)[(i) + 3] ); \ | |
} | |
#endif | |
#ifndef PUT_ULONG_BE | |
#define PUT_ULONG_BE(n,b,i) \ | |
{ \ | |
(b)[(i) ] = (unsigned char) ( (n) >> 24 ); \ | |
(b)[(i) + 1] = (unsigned char) ( (n) >> 16 ); \ | |
(b)[(i) + 2] = (unsigned char) ( (n) >> 8 ); \ | |
(b)[(i) + 3] = (unsigned char) ( (n) ); \ | |
} | |
#endif | |
#define SHL(x,n) (((x) & 0xFFFFFFFF) << n) | |
#define ROTL(x,n) (SHL((x),n) | ((x) >> (32 - n))) | |
#define SWAP(a,b) { unsigned long t = a; a = b; b = t; t = 0; } | |
static const unsigned char SboxTable[16][16] = { | |
{0xd6,0x90,0xe9,0xfe,0xcc,0xe1,0x3d,0xb7,0x16,0xb6,0x14,0xc2,0x28,0xfb,0x2c,0x05}, | |
{0x2b,0x67,0x9a,0x76,0x2a,0xbe,0x04,0xc3,0xaa,0x44,0x13,0x26,0x49,0x86,0x06,0x99}, | |
{0x9c,0x42,0x50,0xf4,0x91,0xef,0x98,0x7a,0x33,0x54,0x0b,0x43,0xed,0xcf,0xac,0x62}, | |
{0xe4,0xb3,0x1c,0xa9,0xc9,0x08,0xe8,0x95,0x80,0xdf,0x94,0xfa,0x75,0x8f,0x3f,0xa6}, | |
{0x47,0x07,0xa7,0xfc,0xf3,0x73,0x17,0xba,0x83,0x59,0x3c,0x19,0xe6,0x85,0x4f,0xa8}, | |
{0x68,0x6b,0x81,0xb2,0x71,0x64,0xda,0x8b,0xf8,0xeb,0x0f,0x4b,0x70,0x56,0x9d,0x35}, | |
{0x1e,0x24,0x0e,0x5e,0x63,0x58,0xd1,0xa2,0x25,0x22,0x7c,0x3b,0x01,0x21,0x78,0x87}, | |
{0xd4,0x00,0x46,0x57,0x9f,0xd3,0x27,0x52,0x4c,0x36,0x02,0xe7,0xa0,0xc4,0xc8,0x9e}, | |
{0xea,0xbf,0x8a,0xd2,0x40,0xc7,0x38,0xb5,0xa3,0xf7,0xf2,0xce,0xf9,0x61,0x15,0xa1}, | |
{0xe0,0xae,0x5d,0xa4,0x9b,0x34,0x1a,0x55,0xad,0x93,0x32,0x30,0xf5,0x8c,0xb1,0xe3}, | |
{0x1d,0xf6,0xe2,0x2e,0x82,0x66,0xca,0x60,0xc0,0x29,0x23,0xab,0x0d,0x53,0x4e,0x6f}, | |
{0xd5,0xdb,0x37,0x45,0xde,0xfd,0x8e,0x2f,0x03,0xff,0x6a,0x72,0x6d,0x6c,0x5b,0x51}, | |
{0x8d,0x1b,0xaf,0x92,0xbb,0xdd,0xbc,0x7f,0x11,0xd9,0x5c,0x41,0x1f,0x10,0x5a,0xd8}, | |
{0x0a,0xc1,0x31,0x88,0xa5,0xcd,0x7b,0xbd,0x2d,0x74,0xd0,0x12,0xb8,0xe5,0xb4,0xb0}, | |
{0x89,0x69,0x97,0x4a,0x0c,0x96,0x77,0x7e,0x65,0xb9,0xf1,0x09,0xc5,0x6e,0xc6,0x84}, | |
{0x18,0xf0,0x7d,0xec,0x3a,0xdc,0x4d,0x20,0x79,0xee,0x5f,0x3e,0xd7,0xcb,0x39,0x48} | |
}; | |
static const unsigned long FK[4] = {0xa3b1bac6,0x56aa3350,0x677d9197,0xb27022dc}; | |
static const unsigned long CK[32] = { | |
0x00070e15,0x1c232a31,0x383f464d,0x545b6269, | |
0x70777e85,0x8c939aa1,0xa8afb6bd,0xc4cbd2d9, | |
0xe0e7eef5,0xfc030a11,0x181f262d,0x343b4249, | |
0x50575e65,0x6c737a81,0x888f969d,0xa4abb2b9, | |
0xc0c7ced5,0xdce3eaf1,0xf8ff060d,0x141b2229, | |
0x30373e45,0x4c535a61,0x686f767d,0x848b9299, | |
0xa0a7aeb5,0xbcc3cad1,0xd8dfe6ed,0xf4fb0209, | |
0x10171e25,0x2c333a41,0x484f565d,0x646b7279 | |
}; | |
static unsigned char sm4Sbox(unsigned char inch) { | |
unsigned char *pTable = (unsigned char *)SboxTable; | |
unsigned char retVal = (unsigned char)(pTable[inch]); | |
return retVal; | |
} | |
static unsigned long sm4Lt(unsigned long ka) { | |
unsigned long bb = 0; | |
unsigned long c = 0; | |
unsigned char a[4]; | |
unsigned char b[4]; | |
PUT_ULONG_BE(ka,a,0) | |
b[0] = sm4Sbox(a[0]); | |
b[1] = sm4Sbox(a[1]); | |
b[2] = sm4Sbox(a[2]); | |
b[3] = sm4Sbox(a[3]); | |
GET_ULONG_BE(bb,b,0) | |
c =bb^(ROTL(bb, 2))^(ROTL(bb, 10))^(ROTL(bb, 18))^(ROTL(bb, 24)); | |
return c; | |
} | |
static unsigned long sm4F(unsigned long x0, unsigned long x1, unsigned long x2, unsigned long x3, unsigned long rk) { | |
return (x0^sm4Lt(x1^x2^x3^rk)); | |
} | |
static void sm4_one_round( unsigned long sk[32], | |
unsigned char input[16], | |
unsigned char output[16] ) { | |
unsigned long i = 0; | |
unsigned long ulbuf[36]; | |
memset(ulbuf, 0, sizeof(ulbuf)); | |
GET_ULONG_BE( ulbuf[0], input, 0 ) | |
GET_ULONG_BE( ulbuf[1], input, 4 ) | |
GET_ULONG_BE( ulbuf[2], input, 8 ) | |
GET_ULONG_BE( ulbuf[3], input, 12 ) | |
while(i<32) { | |
ulbuf[i+4] = sm4F(ulbuf[i], ulbuf[i+1], ulbuf[i+2], ulbuf[i+3], sk[i]); | |
i++; | |
} | |
PUT_ULONG_BE(ulbuf[35],output,0); | |
PUT_ULONG_BE(ulbuf[34],output,4); | |
PUT_ULONG_BE(ulbuf[33],output,8); | |
PUT_ULONG_BE(ulbuf[32],output,12); | |
} | |
static unsigned long sm4CalciRK(unsigned long ka) { | |
unsigned long bb = 0; | |
unsigned long rk = 0; | |
unsigned char a[4]; | |
unsigned char b[4]; | |
PUT_ULONG_BE(ka,a,0) | |
b[0] = sm4Sbox(a[0]); | |
b[1] = sm4Sbox(a[1]); | |
b[2] = sm4Sbox(a[2]); | |
b[3] = sm4Sbox(a[3]); | |
GET_ULONG_BE(bb,b,0) | |
rk = bb^(ROTL(bb, 13))^(ROTL(bb, 23)); | |
return rk; | |
} | |
static void sm4_setkey( unsigned long sk[32], unsigned char key[16] ) { | |
unsigned long MK[4]; | |
unsigned long k[36]; | |
unsigned long i = 0; | |
GET_ULONG_BE( MK[0], key, 0 ); | |
GET_ULONG_BE( MK[1], key, 4 ); | |
GET_ULONG_BE( MK[2], key, 8 ); | |
GET_ULONG_BE( MK[3], key, 12 ); | |
k[0] = MK[0]^FK[0]; | |
k[1] = MK[1]^FK[1]; | |
k[2] = MK[2]^FK[2]; | |
k[3] = MK[3]^FK[3]; | |
for(; i<32; i++) { | |
k[i+4] = k[i] ^ (sm4CalciRK(k[i+1]^k[i+2]^k[i+3]^CK[i])); | |
sk[i] = k[i+4]; | |
} | |
} | |
int main() { | |
unsigned char key[16] = {0x01,0x23,0x45,0x67,0x89,0xab,0xcd,0xef,0xfe,0xdc,0xba,0x98,0x76,0x54,0x32,0x10}; | |
unsigned char input[16] = {0x01,0x23,0x45,0x67,0x89,0xab,0xcd,0xef,0xfe,0xdc,0xba,0x98,0x76,0x54,0x32,0x10}; | |
unsigned char output[16]; | |
unsigned long sk[32]; | |
unsigned long i; | |
sm4_setkey(sk,key); | |
sm4_one_round(sk, input,output); | |
for(i=0; i<16; i++) | |
printf("%02x ", output[i]); | |
printf("\n"); | |
return 0; | |
} |
# Blowfish
# Twofish
# Serpent
在线工具请:
http://serpent.online-domain-tools.com/
# PRESENT
Sbox = [12, 5, 6, 11, 9, 0, 10, 13, 3, 14, 15, 8, 4, 7, 1, 2] | |
Sbox_inv = [Sbox.index(x) for x in range(16)] | |
PBox = [ | |
0, 16, 32, 48, 1, 17, 33, 49, 2, 18, 34, 50, 3, 19, 35, 51, | |
4, 20, 36, 52, 5, 21, 37, 53, 6, 22, 38, 54, 7, 23, 39, 55, | |
8, 24, 40, 56, 9, 25, 41, 57, 10, 26, 42, 58, 11, 27, 43, 59, | |
12, 28, 44, 60, 13, 29, 45, 61, 14, 30, 46, 62, 15, 31, 47, 63 | |
] | |
PBox_inv = [PBox.index(x) for x in range(64)] | |
def addRoundKey(state, roundkey): | |
return state ^ roundkey | |
def sBoxLayer(state): | |
output = 0 | |
for i in range(16): | |
output += Sbox[(state >> (i * 4)) & 15] << (i * 4) | |
return output | |
def pLayer(state): | |
output = 0 | |
for i in range(64): | |
output += ((state >> i) & 1) << PBox[i] | |
return output | |
def string2number(i): | |
return sum([(ord(i[c]) << (8 * c)) for c in range(8)]) | |
def generateRoundkeys80(key, rounds): | |
roundkeys = [] | |
for i in range(1, rounds + 1): | |
roundkeys.append(key >> 16) | |
key = ((key & 524287) << 61) + (key >> 19) | |
key = (Sbox[key >> 76] << 76) + (key & ((2 ** 76) - 1)) | |
key ^= i << 15 | |
return roundkeys | |
def encrypt(blocks): | |
rounds = 32 | |
roundkeys = generateRoundkeys80(85354531916197809168417, rounds) | |
out = [] | |
for block in blocks: | |
state = string2number(block) | |
for i in range(rounds - 1): | |
state = addRoundKey(state, roundkeys[i]) | |
state = sBoxLayer(state) | |
state = pLayer(state) | |
cipher = addRoundKey(state, roundkeys[-1]) | |
out.append(cipher) | |
return out | |
inp = input('pls input ur flag:') | |
if len(inp) != 32: | |
print('wrong!') | |
exit(0) | |
blocks = [inp[:8], inp[8:16], inp[16:24], inp[24:32]] | |
out_blocks = encrypt(blocks) | |
解密脚本直接逆着写就行,这里的输入是32位的,然后分块。 | |
```python | |
Sbox = [12, 5, 6, 11, 9, 0, 10, 13, 3, 14, 15, 8, 4, 7, 1, 2] | |
Sbox_inv = [Sbox.index(x) for x in range(16)] | |
PBox = [ | |
0, 16, 32, 48, 1, 17, 33, 49, 2, 18, 34, 50, 3, 19, 35, 51, | |
4, 20, 36, 52, 5, 21, 37, 53, 6, 22, 38, 54, 7, 23, 39, 55, | |
8, 24, 40, 56, 9, 25, 41, 57, 10, 26, 42, 58, 11, 27, 43, 59, | |
12, 28, 44, 60, 13, 29, 45, 61, 14, 30, 46, 62, 15, 31, 47, 63 | |
] | |
PBox_inv = [PBox.index(x) for x in range(64)] | |
def addRoundKey(state, roundkey): | |
return state ^ roundkey | |
def generateRoundkeys80(key, rounds): | |
roundkeys = [] | |
for i in range(1, rounds + 1): | |
roundkeys.append(key >> 16) | |
key = ((key & 524287) << 61) + (key >> 19) | |
key = (Sbox[key >> 76] << 76) + (key & ((2 ** 76) - 1)) | |
key ^= (i << 15) | |
return roundkeys | |
def inv_sBoxLayer(state): | |
output = 0 | |
for i in range(16): | |
output += Sbox_inv[(state >> (i * 4)) & 15] << (i * 4) | |
return output | |
def inv_pLayer(state): | |
output = 0 | |
for i in range(64): | |
output += ((state >> i) & 1) << PBox_inv[i] | |
return output | |
def number2string(n): | |
chars = [] | |
for i in range(8): | |
chars.append(chr((n >> (i * 8)) & 0xFF)) | |
return ''.join(chars) | |
def decrypt(ciphers): | |
rounds = 32 | |
roundkeys = generateRoundkeys80(85354531916197809168417, rounds) | |
out = [] | |
for cipher in ciphers: | |
state = cipher | |
for i in range(rounds - 1, 0, -1): | |
state = addRoundKey(state, roundkeys[i]) | |
state = inv_pLayer(state) | |
state = inv_sBoxLayer(state) | |
block = addRoundKey(state, roundkeys[0]) | |
out.append(number2string(block)) | |
return ''.join(out) | |
cmps = [120617461261311902, 16357837616839286114, 312508749794633008, 1843701600916795272] | |
decrypted_flag = decrypt(cmps) | |
print(decrypted_flag) | |
## 非对称 | |
#### RSA | |
```python | |
import gmpy2 | |
from Crypto.Util.number import long_to_bytes | |
e = 65537 | |
n = 36618139579386063246087882054063631367923586826293230665209915187491823328978276724908066032487515386697740611819366867179565337532194305783987450587518624526250530134446397 | |
c = 3053043969587277731075013823380664207370991627277672374256662715889363487017560381573682876563907215099359894935326265406537547932246927604121814198201993671878573628633125 | |
p=[521,521,521,541,547,557,557,577,587,593,601,607,631,631,631,631,641,643,683,701,701,719,727,727,727,733,739,739,743,757,761,769,773,787,787,809,821,821,821,863,877,877,881,907,907,907,907,907,919,919,929,937,953,953,967,967,991,997,997,1019] | |
p.append(521) | |
phi=1 | |
a=0 | |
for i in p: | |
if (a==i): | |
phi*=i | |
phi*=i-1 | |
a=i | |
# phi = (p - 1) * (q - 1) | |
# n = p * q | |
d = gmpy2.invert(e, phi) | |
m = pow(c, d, n) | |
print(long_to_bytes(m)) |
# 校验
# sha 系列
cyberchef 本地请
#include<stdio.h> | |
#include<stdlib.h> | |
#include<string.h> | |
#include <math.h> | |
#define GROUP_SIZE 64 | |
#define MAX_SIZE 1024 | |
unsigned int const K[64] ={ | |
0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5, | |
0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174, | |
0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da, | |
0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967, | |
0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85, | |
0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070, | |
0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3, | |
0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2 | |
}; | |
unsigned int ROR(unsigned int x, unsigned int n); | |
unsigned int SHR(unsigned int x,unsigned int n); | |
unsigned int Ch(unsigned int E,unsigned int F,unsigned int G); | |
unsigned int Maj(unsigned int A,unsigned int B,unsigned int C); | |
unsigned int Lsigma_0(unsigned int A); | |
unsigned int Lsigma_1(unsigned int E); | |
unsigned int Ssigma_0(unsigned int x); | |
unsigned int Ssigma_1(unsigned int x); | |
void sha_init(unsigned int *A,unsigned int *B,unsigned int *C,unsigned int *D,unsigned int *E,unsigned int *F,unsigned int *G,unsigned int *H); | |
size_t sha_update(unsigned char **out, char const *input, size_t inLen); | |
void sha_transform(unsigned int *out, char *input); | |
void data_round(unsigned int *A,unsigned int *B,unsigned int *C,unsigned int *D,unsigned int *E,unsigned int *F,unsigned int *G,unsigned int *H,unsigned int const *M); | |
void sha_calc(char *out, char const *input, size_t inLen); |
# CRC32
uint32_t crc32(const void* buf, size_t size) { | |
const uint8_t* p = buf; | |
uint32_t crc = ~0U; | |
while (size--) { | |
crc = crc32_tab[(crc ^ *p++) & 0xFF] ^ (crc >> 8); | |
} | |
return ~crc; | |
} | |
uint crc32(byte *data, int size) | |
{ | |
uint r = ~0; byte *end = data + size; | |
while(data < end) | |
{ | |
r ^= *data++; | |
for(int i = 0; i < 8; i++) | |
{ | |
uint t = ~((r&1) — 1); r = (r>>1) ^ (0xEDB88320 & t); | |
} | |
} | |
return ~r; | |
} |
# md5
cyberchef 本地请
#include "md5.h" | |
unsigned int ROTATE_LEFT(unsigned int x, unsigned int n) { | |
return ((x << n) | (x >> (32 - n))); | |
} | |
unsigned int F(unsigned int X, unsigned int Y, unsigned int Z) { | |
return (X & Y) | ((~X) & Z); | |
} | |
unsigned int G(unsigned int X, unsigned int Y, unsigned int Z) { | |
return (X & Z) | (Y & (~Z)); | |
} | |
unsigned int H(unsigned int X, unsigned int Y, unsigned int Z) { | |
return (X ^ Y ^ Z); | |
} | |
unsigned int I(unsigned int X, unsigned int Y, unsigned int Z) { | |
return (Y ^ (X | (~Z))); | |
} | |
void FF(unsigned int *a,unsigned int b,unsigned int c,unsigned int d,unsigned int m,unsigned int const t,unsigned int s){ | |
*a += F(b,c,d) + m + t; | |
*a = ROTATE_LEFT(*a,s); | |
*a += b; | |
return; | |
} | |
void GG(unsigned int *a,unsigned int b,unsigned int c,unsigned int d,unsigned int m,unsigned int const t,unsigned int s){ | |
*a += G(b,c,d) + m + t; | |
*a = ROTATE_LEFT(*a,s); | |
*a += b; | |
return; | |
} | |
void HH(unsigned int *a,unsigned int b,unsigned int c,unsigned int d,unsigned int m,unsigned int const t,unsigned int s){ | |
*a += H(b,c,d) + m + t; | |
*a = ROTATE_LEFT(*a,s); | |
*a += b; | |
return; | |
} | |
void II(unsigned int *a,unsigned int b,unsigned int c,unsigned int d,unsigned int m,unsigned int const t,unsigned int s){ | |
*a += I(b,c,d) + m + t; | |
*a = ROTATE_LEFT(*a,s); | |
*a += b; | |
return; | |
} | |
unsigned int shift(unsigned int a){ | |
unsigned int t1,t2,t3,t4; | |
t1 = (a & 0xFF) << 24; | |
t2 = (a & 0xFF00) << 8; | |
t3 = (a >> 8) & 0xFF00; | |
t4 = (a >> 24) & 0xFF; | |
//printf("%x\n",t1 + t2 + t3 + t4); | |
return (t1 + t2 + t3 + t4); | |
} | |
/* MD5 initialization */ | |
void md5_init(unsigned int *A,unsigned int *B,unsigned int *C,unsigned int *D){ | |
unsigned char data[] = { | |
0x01, 0x23, 0x45, 0x67, | |
0x89, 0xAB, 0xCD, 0xEF, | |
0xFE, 0xDC, 0xBA, 0x98, | |
0x76, 0x54, 0x32, 0x10 | |
}; | |
memcpy(A, data, 4); | |
memcpy(B, data + 4, 4); | |
memcpy(C, data + 8, 4); | |
memcpy(D, data + 12, 4); | |
return; | |
} | |
size_t md5_update(char **out, char const *input, size_t inLen){ | |
int i; | |
int j; | |
size_t bitLen = inLen * 8; // the bit length of input | |
//size_t fillLen = 64 - (inLen - 56) % 64; // the length of padding | |
//printf("len:%d\n",fillLen); | |
size_t fillLen = 56 - (inLen % 64); | |
//printf("temp:%d\n",temp); | |
size_t filledLen = inLen + fillLen + 8; // the length after padding | |
char *outBuf = (char*)calloc(filledLen, sizeof(char)); | |
memcpy(outBuf, input, inLen); | |
outBuf[inLen] = 0x80;// padding 1 | |
j = sizeof(inLen); // the length of input_lengh | |
for (i = 0; i < j; i++) { | |
memcpy(outBuf + filledLen - 8 + i, (char*)(&bitLen) + i, 1); // LittleEndian | |
//memcpy(outBuf + filledLen - 4 + i, (char*)(&bitLen) + j - 1 - i, 1); | |
} | |
*out = outBuf; // the data after padding | |
return filledLen; | |
} | |
void md5_transform(unsigned int *out, char *input){ | |
memcpy(out,input,GROUP_SIZE); | |
return; | |
} | |
void data_round(unsigned int *A, unsigned int *B, unsigned int *C, unsigned int *D, unsigned int const *m){ | |
//int k; | |
unsigned int a = *A; | |
unsigned int b = *B; | |
unsigned int c = *C; | |
unsigned int d = *D; | |
/* round 1 */ | |
FF(&a,b,c,d,m[0],T[0],S[0]); | |
FF(&d,a,b,c,m[1],T[1],S[1]); | |
FF(&c,d,a,b,m[2],T[2],S[2]); | |
FF(&b,c,d,a,m[3],T[3],S[3]); | |
FF(&a,b,c,d,m[4],T[4],S[0]); | |
FF(&d,a,b,c,m[5],T[5],S[1]); | |
FF(&c,d,a,b,m[6],T[6],S[2]); | |
FF(&b,c,d,a,m[7],T[7],S[3]); | |
FF(&a,b,c,d,m[8],T[8],S[0]); | |
FF(&d,a,b,c,m[9],T[9],S[1]); | |
FF(&c,d,a,b,m[10],T[10],S[2]); | |
FF(&b,c,d,a,m[11],T[11],S[3]); | |
FF(&a,b,c,d,m[12],T[12],S[0]); | |
FF(&d,a,b,c,m[13],T[13],S[1]); | |
FF(&c,d,a,b,m[14],T[14],S[2]); | |
FF(&b,c,d,a,m[15],T[15],S[3]); | |
/* round 2 */ | |
GG(&a,b,c,d,m[1],T[16],S[4]); | |
GG(&d,a,b,c,m[6],T[17],S[5]); | |
GG(&c,d,a,b,m[11],T[18],S[6]); | |
GG(&b,c,d,a,m[0],T[19],S[7]); | |
GG(&a,b,c,d,m[5],T[20],S[4]); | |
GG(&d,a,b,c,m[10],T[21],S[5]); | |
GG(&c,d,a,b,m[15],T[22],S[6]); | |
GG(&b,c,d,a,m[4],T[23],S[7]); | |
GG(&a,b,c,d,m[9],T[24],S[4]); | |
GG(&d,a,b,c,m[14],T[25],S[5]); | |
GG(&c,d,a,b,m[3],T[26],S[6]); | |
GG(&b,c,d,a,m[8],T[27],S[7]); | |
GG(&a,b,c,d,m[13],T[28],S[4]); | |
GG(&d,a,b,c,m[2],T[29],S[5]); | |
GG(&c,d,a,b,m[7],T[30],S[6]); | |
GG(&b,c,d,a,m[12],T[31],S[7]); | |
/* round 3 */ | |
HH(&a,b,c,d,m[5],T[32],S[8]); | |
HH(&d,a,b,c,m[8],T[33],S[9]); | |
HH(&c,d,a,b,m[11],T[34],S[10]); | |
HH(&b,c,d,a,m[14],T[35],S[11]); | |
HH(&a,b,c,d,m[1],T[36],S[8]); | |
HH(&d,a,b,c,m[4],T[37],S[9]); | |
HH(&c,d,a,b,m[7],T[38],S[10]); | |
HH(&b,c,d,a,m[10],T[39],S[11]); | |
HH(&a,b,c,d,m[13],T[40],S[8]); | |
HH(&d,a,b,c,m[0],T[41],S[9]); | |
HH(&c,d,a,b,m[3],T[42],S[10]); | |
HH(&b,c,d,a,m[6],T[43],S[11]); | |
HH(&a,b,c,d,m[9],T[44],S[8]); | |
HH(&d,a,b,c,m[12],T[45],S[9]); | |
HH(&c,d,a,b,m[15],T[46],S[10]); | |
HH(&b,c,d,a,m[2],T[47],S[11]); | |
/* round 4 */ | |
II(&a,b,c,d,m[0],T[48],S[12]); | |
II(&d,a,b,c,m[7],T[49],S[13]); | |
II(&c,d,a,b,m[14],T[50],S[14]); | |
II(&b,c,d,a,m[5],T[51],S[15]); | |
II(&a,b,c,d,m[12],T[52],S[12]); | |
II(&d,a,b,c,m[3],T[53],S[13]); | |
II(&c,d,a,b,m[10],T[54],S[14]); | |
II(&b,c,d,a,m[1],T[55],S[15]); | |
II(&a,b,c,d,m[8],T[56],S[12]); | |
II(&d,a,b,c,m[15],T[57],S[13]); | |
II(&c,d,a,b,m[6],T[58],S[14]); | |
II(&b,c,d,a,m[13],T[59],S[15]); | |
II(&a,b,c,d,m[4],T[60],S[12]); | |
II(&d,a,b,c,m[11],T[61],S[13]); | |
II(&c,d,a,b,m[2],T[62],S[14]); | |
II(&b,c,d,a,m[9],T[63],S[15]); | |
*A += a; | |
*B += b; | |
*C += c; | |
*D += d; | |
} | |
void md5_calc(char *out, char const *input, size_t inLen){ | |
int i; | |
size_t filledLen; | |
char *filledData; | |
unsigned int A,B,C,D; | |
unsigned int *M = (unsigned int*)malloc(GROUP_SIZE); | |
filledLen = md5_update(&filledData,input,inLen); | |
//printf("input:%s\n",input); | |
md5_init(&A,&B,&C,&D); | |
//printf("%x\n%x\n%x\n%x\n",A,B,C,D); | |
for(i = 0;i < filledLen / GROUP_SIZE;i++){ | |
md5_transform(M, filledData + i * 64); //char to int | |
data_round(&A,&B,&C,&D,M); | |
} | |
//printf("%x\n%x\n%x\n%x\n",A,B,C,D); | |
sprintf(out,"%08x%08x%08x%08x",shift(A),shift(B),shift(C),shift(D)); | |
free(M); | |
M = NULL; | |
free(filledData); | |
filledData = NULL; | |
return; | |
} |
# 其他
# 大数计算
# base 系列
# base64 换表
""" | |
Customized base64 algorithm | |
You can set you own indexing string using the config() method. | |
Usage: | |
b = CusBase64() | |
b.encode('binary\x00string') # Output: YmluYXJ5AHN0cmluZw== | |
b.decode('YmluYXJ5AHN0cmluZw==') # Output: binary\x00string | |
b.config('aABCDEFGHIJKLMNOPQRSTUVWXYZbcdefghijklmnopqrstuvwxyz0123456789+/') | |
b.decode('c2UsYi1kYWM0cnUjdFlvbiAjb21wbFU0YP==') # Output: self-destruction complete | |
""" | |
class CusBase64(object): | |
DEFAULT = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/" | |
def __init__(self): | |
self.idx_str = CusBase64.DEFAULT | |
def encode(self, str): | |
""" | |
Encode string using the customized indexing string. | |
- args: | |
str: String to be encoded | |
""" | |
# Get the binary string | |
binary = ''.join([format(ord(c),'0>8b') for c in str]) | |
# Add additional zero | |
binary = self.padding(binary) | |
# Get the index in indexing string | |
idxs = [int(binary[6*i:6*i+6], 2) for i in range(len(binary)//6)] | |
result = ''.join([self.idx_str[i] for i in idxs]) | |
# add '=' | |
if len(str)%3 != 0: | |
result = result + (3-len(str)%3)*'=' | |
print("%r" % result) | |
def decode(self, str): | |
""" | |
Decode string using the customized indexing string. | |
- args: | |
str: String to be decoded | |
""" | |
if len(str) == 0: | |
return | |
# remove '=' | |
while str[-1]=='=': | |
str = str[:-1] | |
try: | |
# Get the binary string | |
binary = ''.join([format(self.idx_str.index(c), '0>6b') for c in str]) | |
# Remove additional zero | |
binary = self.remove(binary) | |
result = ''.join([chr(int(binary[8*i:8*i+8], 2)) for i in range(len(binary)//8)]) | |
except ValueError: | |
result = "Please check again!" | |
print("%r" % result) | |
def remove(self, binary): | |
""" | |
Remove additional zero while decoding string. | |
- args: | |
binary: Binary format of the index. | |
- returns: | |
Binary string without additional zero. | |
""" | |
if len(binary)%8 == 0: | |
return binary | |
else: | |
return binary[:-(len(binary)%8)] | |
def padding(self, binary): | |
""" | |
Add additional zero while encoding string. | |
- args: | |
binary: Binary format of the string. | |
- returns: | |
Binary string with additional zero. | |
""" | |
if len(binary)%6 == 0: | |
return binary | |
n = 6 - len(binary)%6 | |
binary = binary + n * '0' | |
return binary | |
def config(self, str): | |
""" | |
Set customized indexing string. | |
""" | |
self.idx_str = str | |
print("New indexing string is %r" % self.idx_str) | |
b = CusBase64() | |
b.config('ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/') | |
b.encode('flag{this_is_a_sample_flag}') | |
b.decode('mg6CITV6GEaFDTYnObFmENOAVjKcQmGncF90WhqvCFyhhsyqq1s=') |
# base58
package main | |
import ( | |
"bytes" | |
"math/big" | |
) | |
var b58Alphabet = []byte("123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz") | |
func Base58Encode(input []byte) []byte { | |
var result []byte | |
x := big.NewInt(0).SetBytes(input) | |
base := big.NewInt(int64(len(b58Alphabet))) | |
zero := big.NewInt(0) | |
mod := &big.Int{} | |
for x.Cmp(zero) != 0 { | |
x.DivMod(x, base, mod) | |
result = append(result, b58Alphabet[mod.Int64()]) | |
} | |
ReverseBytes(result) | |
for _, b := range input { | |
if b == 0x00 { | |
result = append([]byte{b58Alphabet[0]}, result...) | |
} else { | |
break | |
} | |
} | |
return result | |
} | |
func Base58Decode(input []byte) []byte { | |
result := big.NewInt(0) | |
zeroBytes := 0 | |
for _, b := range input { | |
if b != b58Alphabet[0] { | |
break | |
} | |
zeroBytes++ | |
} | |
payload := input[zeroBytes:] | |
for _, b := range payload { | |
charIndex := bytes.IndexByte(b58Alphabet, b) | |
result.Mul(result, big.NewInt(int64(len(b58Alphabet)))) | |
result.Add(result, big.NewInt(int64(charIndex))) | |
} | |
decoded := result.Bytes() | |
decoded = append(bytes.Repeat([]byte{byte(0x00)}, zeroBytes), decoded...) | |
return decoded | |
} |