├── readme ├── rsa.py ├── sha256sum.py ├── md5.py ├── ecc.py ├── des.py └── aes.py /readme: -------------------------------------------------------------------------------- 1 | 2 | # 用python实现几种加密算法和hash算法 3 | 4 | hash:md5,sha256 5 | 对称加密:aes,des 6 | 非对称加密:ecc,rsa 7 | 8 | -------------------------------------------------------------------------------- /rsa.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # vim:fenc=utf-8 3 | # 4 | # Copyright © 2019 frey 5 | # blog:https://www.vhcffh.com 6 | # 7 | # Distributed under terms of the MIT license. 8 | import random 9 | 10 | 11 | # 判断是否是素数 12 | def is_prime(n): 13 | if n == 2: 14 | return True 15 | for i in range(2, n // 2 + 1): 16 | if n % i == 0: 17 | return False 18 | return True 19 | 20 | 21 | # 生成两个不同的素数p,q 22 | def get_pq(): 23 | p, q = 0, 0 24 | while True: 25 | p, q = random.randint(10, 100), random.randint(10, 100) 26 | if is_prime(p) and is_prime(q) and p != q: 27 | return p, q 28 | 29 | 30 | # 生成e和d 31 | def get_ed(p, q): 32 | phn = (p - 1) * (q - 1) # n的欧拉函数 33 | while True: 34 | e = random.randint(2, 50) 35 | if is_prime(e): 36 | for d in range(2, 1000): 37 | if e * d % phn == 1: 38 | return e, d 39 | 40 | 41 | if __name__ == '__main__': 42 | p, q = get_pq() 43 | n = p * q 44 | e, d = get_ed(p, q) 45 | print("公钥: (n,e) =", (n, e)) 46 | print("私钥: (n,d) =", (n, d)) 47 | m = [random.randint(2, 100) for i in range(10)] 48 | c = [mi ** e % n for mi in m] 49 | print("明文 m =", m) 50 | print("密文 c =", c) 51 | print("解密 m =", [ci ** d % n for ci in c]) 52 | -------------------------------------------------------------------------------- /sha256sum.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # vim:fenc=utf-8 3 | # 4 | # Copyright © 2019 frey 5 | # blog:https://www.vhcffh.com 6 | # 7 | # Distributed under terms of the MIT license. 8 | def Sha256sum(message: bytes) -> bytes: 9 | # 定义常量 10 | # 前8个素数2..19的平方根的小数部分的前32位 11 | h0 = 0x6a09e667 12 | h1 = 0xbb67ae85 13 | h2 = 0x3c6ef372 14 | h3 = 0xa54ff53a 15 | h4 = 0x510e527f 16 | h5 = 0x9b05688c 17 | h6 = 0x1f83d9ab 18 | h7 = 0x5be0cd19 19 | 20 | # 定义常数K 64 21 | # 前64个素数2..311的立方根的小数部分的前32位 22 | K = (0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1, 23 | 0x923f82a4, 0xab1c5ed5, 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, 24 | 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174, 0xe49b69c1, 0xefbe4786, 25 | 0x0fc19dc6, 0x240ca1cc, 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da, 26 | 0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147, 27 | 0x06ca6351, 0x14292967, 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, 28 | 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85, 0xa2bfe8a1, 0xa81a664b, 29 | 0xc24b8b70, 0xc76c51a3, 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070, 30 | 0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a, 31 | 0x5b9cca4f, 0x682e6ff3, 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, 32 | 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2) 33 | 34 | # R为循环右移, 35 | # 右移之后可能会超过32位,所以要和0xffffffff做与运算,确保结果为32位。 36 | R = lambda x, n: ((x >> n) | (x << (32 - n))) & 0xffffffff 37 | # 大端 0x12,0x34,0x56,0x78 -> 0x12345678 38 | W = lambda i1, i2, i3, i4: (i1 << 24) | (i2 << 16) | (i3 << 8) | i4 39 | 40 | 41 | # 对每一个输入先添加一个'0x80',即'10000000', 即128 42 | ascii_list = list(map(lambda x: x, message)) 43 | msg_length = len(ascii_list) * 8 44 | ascii_list.append(128) 45 | 46 | # 补充0 47 | while (len(ascii_list) * 8 + 64) % 512 != 0: 48 | ascii_list.append(0) 49 | 50 | # 最后64为存放消息长度,以大端数存放。 51 | # 例如,消息为'a',则长度为'0x0000000000000008' 52 | for i in range(8): 53 | ascii_list.append(msg_length >> (8 * (7 - i)) & 0xff) 54 | 55 | # print(ascii_list) 56 | # print(len(ascii_list)//64) 57 | for i in range(len(ascii_list) // 64): # 64*8=512bits 58 | # print(ascii_list[i*64:(i+1)*64]) 59 | # 每个512bits的块进行循环 60 | w = [] 61 | # 将512bits扩展到64*32bits=2048bits存入32位无符号数数组 62 | for j in range(16): 63 | s = i * 64 + j * 4 64 | w.append(W(ascii_list[s], ascii_list[s + 1], ascii_list[s + 2], ascii_list[s + 3])) 65 | for j in range(16, 64): 66 | s0 = (R(w[j - 15], 7)) ^ (R(w[j - 15], 18)) ^ (w[j - 15] >> 3) 67 | s1 = (R(w[j - 2], 17)) ^ (R(w[j - 2], 19)) ^ (w[j - 2] >> 10) 68 | w.append((w[j - 16] + s0 + w[j - 7] + s1) & 0xffffffff) 69 | # print(hex(s0)+':'+hex(s1)+':' + hex(R(w[j - 2], 17))) 70 | # 初始化 71 | a, b, c, d, e, f, g, h = h0, h1, h2, h3, h4, h5, h6, h7 72 | # for j in w: 73 | # print(hex(j)[2:]) 74 | for j in range(64): 75 | s0 = R(a, 2) ^ R(a, 13) ^ R(a, 22) 76 | maj = (a & b) ^ (a & c) ^ (b & c) 77 | t2 = s0 + maj 78 | s1 = R(e, 6) ^ R(e, 11) ^ R(e, 25) 79 | ch = (e & f) ^ ((~e) & g) 80 | t1 = h + s1 + ch + K[j] + w[j] 81 | h = g & 0xffffffff 82 | g = f & 0xffffffff 83 | f = e & 0xffffffff 84 | e = (d + t1) & 0xffffffff 85 | d = c & 0xffffffff 86 | c = b & 0xffffffff 87 | b = a & 0xffffffff 88 | a = (t1 + t2) & 0xffffffff 89 | 90 | h0 = (h0 + a) & 0xffffffff 91 | h1 = (h1 + b) & 0xffffffff 92 | h2 = (h2 + c) & 0xffffffff 93 | h3 = (h3 + d) & 0xffffffff 94 | h4 = (h4 + e) & 0xffffffff 95 | h5 = (h5 + f) & 0xffffffff 96 | h6 = (h6 + g) & 0xffffffff 97 | h7 = (h7 + h) & 0xffffffff 98 | 99 | digest = (h0 << 224) | (h1 << 192) | (h2 << 160) | (h3 << 128) 100 | digest |= (h4 << 96) | (h5 << 64) | (h6 << 32) | h7 101 | # print(hex(digest)[2:]) # .rjust(32, '0')) 102 | return hex(digest)[2:] # .rjust(32, '0') 103 | 104 | 105 | if __name__ == '__main__': 106 | print("自己实现sha256(https://www.vhcffh.com)") 107 | print(Sha256sum(b"https://www.vhcffh.com")) 108 | 109 | import hashlib 110 | t = hashlib.sha256() 111 | t.update(b"https://www.vhcffh.com") 112 | print("调用hashlib库sha256(https://www.vhcffh.com)") 113 | print(t.hexdigest()) 114 | -------------------------------------------------------------------------------- /md5.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # vim:fenc=utf-8 3 | # 4 | # Copyright © 2019 frey 5 | # blog:https://www.vhcffh.com 6 | # 7 | # Distributed under terms of the MIT license. 8 | def Md5sum(message: bytes) -> bytes: 9 | # 定义常量,用于初始化128位变量,注意字节顺序,A=0x01234567,这里低值存放低字节, 10 | # 即01 23 45 67,所以运算时A=0x67452301,其他类似。 11 | # 用字符串的形势,是为了和hex函数的输出统一,hex(10)输出为'0xA',注意结果为字符串。 12 | h0 = 0x67452301 13 | h1 = 0xefcdab89 14 | h2 = 0x98badcfe 15 | h3 = 0x10325476 16 | 17 | # 定义每轮中循环左移的位数,用元组表示 4*4*4=64 18 | R = (7, 12, 17, 22) * 4 + (5, 9, 14, 20) * 4 + \ 19 | (4, 11, 16, 23) * 4 + (6, 10, 15, 21) * 4 20 | # 定义常数K 64 21 | # K[i] = (int(abs(math.sin(i + 1)) * 2 ** 32)) & 0xffffffff 22 | K = (0xd76aa478, 0xe8c7b756, 0x242070db, 0xc1bdceee, 23 | 0xf57c0faf, 0x4787c62a, 0xa8304613, 0xfd469501, 0x698098d8, 24 | 0x8b44f7af, 0xffff5bb1, 0x895cd7be, 0x6b901122, 0xfd987193, 25 | 0xa679438e, 0x49b40821, 0xf61e2562, 0xc040b340, 0x265e5a51, 26 | 0xe9b6c7aa, 0xd62f105d, 0x02441453, 0xd8a1e681, 0xe7d3fbc8, 27 | 0x21e1cde6, 0xc33707d6, 0xf4d50d87, 0x455a14ed, 0xa9e3e905, 28 | 0xfcefa3f8, 0x676f02d9, 0x8d2a4c8a, 0xfffa3942, 0x8771f681, 29 | 0x6d9d6122, 0xfde5380c, 0xa4beea44, 0x4bdecfa9, 0xf6bb4b60, 30 | 0xbebfbc70, 0x289b7ec6, 0xeaa127fa, 0xd4ef3085, 0x04881d05, 31 | 0xd9d4d039, 0xe6db99e5, 0x1fa27cf8, 0xc4ac5665, 0xf4292244, 32 | 0x432aff97, 0xab9423a7, 0xfc93a039, 0x655b59c3, 0x8f0ccc92, 33 | 0xffeff47d, 0x85845dd1, 0x6fa87e4f, 0xfe2ce6e0, 0xa3014314, 34 | 0x4e0811a1, 0xf7537e82, 0xbd3af235, 0x2ad7d2bb, 0xeb86d391) 35 | 36 | # 定义每轮中用到的函数。L为循环左移, 37 | # 左移之后可能会超过32位,所以要和0xffffffff做与运算,确保结果为32位。 38 | F = lambda x, y, z: ((x & y) | ((~x) & z)) 39 | G = lambda x, y, z: ((x & z) | (y & (~z))) 40 | H = lambda x, y, z: (x ^ y ^ z) 41 | I = lambda x, y, z: (y ^ (x | (~z))) 42 | 43 | L = lambda x, n: ((x << n) | (x >> (32 - n))) & 0xffffffff 44 | # 小端 0x12,0x34,0x56,0x78 -> 0x78563412 45 | # 将四个8位无符号数转化为一个32位无符号数 46 | W = lambda i4, i3, i2, i1: (i1 << 24) | (i2 << 16) | (i3 << 8) | i4 47 | # 字节翻转 0x12345678 -> 0x78563412 将一个32位无符号数的高位和低位进行对换 48 | reverse = lambda x: (x << 24) & 0xff000000 | (x << 8) & 0x00ff0000 | \ 49 | (x >> 8) & 0x0000ff00 | (x >> 24) & 0x000000ff 50 | 51 | 52 | # 对每一个输入先添加一个'0x80',即'10000000', 即128 53 | ascii_list = list(map(lambda x: x, message)) 54 | msg_length = len(ascii_list) * 8 55 | ascii_list.append(128) 56 | 57 | # 补充0 58 | while (len(ascii_list) * 8 + 64) % 512 != 0: 59 | ascii_list.append(0) 60 | 61 | # 最后64为存放消息长度,以小端数存放。 62 | # 例如,消息为'a',则长度是8,则添加'0x0800000000000000' 63 | for i in range(8): 64 | ascii_list.append((msg_length >> (8 * i)) & 0xff) 65 | 66 | # print(ascii_list) 67 | # print(len(ascii_list)//64) 68 | # 对每一消息块进行迭代 69 | for i in range(len(ascii_list) // 64): 70 | # print(ascii_list[i*64:(i+1)*64]) 71 | # 对每一个消息块进行循环,每个消息块512bits=16*32bits=64*8bits 72 | a, b, c, d = h0, h1, h2, h3 73 | for j in range(64): 74 | # 64轮的主循环 75 | if 0 <= j <= 15: 76 | f = F(b, c, d) & 0xffffffff 77 | g = j 78 | elif 16 <= j <= 31: 79 | f = G(b, c, d) & 0xffffffff 80 | g = ((5 * j) + 1) % 16 81 | elif 32 <= j <= 47: 82 | f = H(b, c, d) & 0xffffffff 83 | g = ((3 * j) + 5) % 16 84 | else: 85 | f = I(b, c, d) & 0xffffffff 86 | g = (7 * j) % 16 87 | aa, dd, cc = d, c, b 88 | # 第i个chunk,第g个32-bit 89 | s = i * 64 + g * 4 90 | w = W(ascii_list[s], ascii_list[s + 1], ascii_list[s + 2], ascii_list[s + 3]) 91 | bb = (L((a + f + K[j] + w) & 0xffffffff, R[j]) + b) & 0xffffffff 92 | a, b, c, d = aa, bb, cc, dd 93 | # print(b) 94 | h0 = (h0 + a) & 0xffffffff 95 | h1 = (h1 + b) & 0xffffffff 96 | h2 = (h2 + c) & 0xffffffff 97 | h3 = (h3 + d) & 0xffffffff 98 | h0, h1, h2, h3 = reverse(h0), reverse(h1), reverse(h2), reverse(h3) 99 | digest = (h0 << 96) | (h1 << 64) | (h2 << 32) | h3 100 | return hex(digest)[2:].rjust(32, '0') 101 | 102 | 103 | if __name__ == '__main__': 104 | print("自己实现md5(b'https://www.vhcffh.com')") 105 | print(Md5sum(b"https://www.vhcffh.com")) 106 | 107 | import hashlib 108 | t = hashlib.md5() 109 | t.update(b"https://www.vhcffh.com") 110 | print("调用hashlib库md5(b'https://www.vhcffh.com')") 111 | print(t.hexdigest()) 112 | -------------------------------------------------------------------------------- /ecc.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # vim:fenc=utf-8 3 | # 4 | # Copyright © 2019 frey 5 | # blog:https://www.vhcffh.com 6 | # 7 | # Distributed under terms of the MIT license. 8 | 9 | """ 10 | 椭圆加密算法中的椭圆和基点是公开的 11 | 例如国密SM2的公开参数 12 | 推荐使用素数域256位椭圆曲线。 13 | 椭圆曲线方程:y ^ 2 = x ^ 3 + ax + b。 14 | 曲线参数: 15 | p = FFFFFFFE FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF 00000000 FFFFFFFF FFFFFFFF 16 | a = FFFFFFFE FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF 00000000 FFFFFFFF FFFFFFFC 17 | b = 28E9FA9E 9D9F5E34 4D5A9E4B CF6509A7 F39789F5 15AB8F92 DDBCBD41 4D940E93 18 | n = FFFFFFFE FFFFFFFF FFFFFFFF FFFFFFFF 7203DF6B 21C6052B 53BBF409 39D54123 19 | Gx = 32C4AE2C 1F198119 5F990446 6A39C994 8FE30BBF F2660BE1 715A4589 334C74C7 20 | Gy = BC3736A2 F4F6779C 59BDCEE3 6B692153 D0A9877C C62A4740 02DF32E5 2139F0A0 21 | """ 22 | import random 23 | 24 | 25 | def inv_mod(b, p): 26 | if b < 0 or p <= b: 27 | b = b % p 28 | c, d = b, p 29 | uc, vc, ud, vd, temp = 1, 0, 0, 1, 0 30 | while c != 0: 31 | temp = c 32 | q, c, d = d // c, d % c, temp 33 | uc, vc, ud, vd = ud - q * uc, vd - q * vc, uc, vc 34 | 35 | assert d == 1 36 | if ud > 0: 37 | return ud 38 | else: 39 | return ud + p 40 | 41 | 42 | def leftmost_bit(x): 43 | assert x > 0 44 | result = 1 45 | while result <= x: 46 | result = 2 * result 47 | return result // 2 48 | 49 | 50 | class CurveFp(object): 51 | 52 | def __init__(self, p, a, b): 53 | """ 椭圆曲线方程y^2 = x^3 + a*x + b (mod p).""" 54 | self.p = p 55 | self.a = a 56 | self.b = b 57 | 58 | def contains_point(self, x, y): 59 | return (y * y - (x * x * x + self.a * x + self.b)) % self.p == 0 60 | 61 | def show_all_points(self): 62 | return [(x, y) for x in range(self.p) for y in range(self.p) if 63 | (y * y - (x * x * x + self.a * x + self.b)) % self.p == 0] 64 | 65 | def __repr__(self): 66 | return "Curve(p={0:d}, a={1:d}, b={2:d})".format(self.p, self.a, self.b) 67 | 68 | # def plain_embed(self, x): 69 | # if x > self.p: 70 | # assert False 71 | # for i in range(self.p): 72 | # y = (x ** 3 + self.a * x + self.b) ** (1/2) 73 | # if int(y) - y == 0: 74 | # return Point(self, x, int(y)) 75 | 76 | 77 | class Point(object): 78 | 79 | def __init__(self, curve, x, y, order=None): 80 | 81 | self.curve = curve 82 | self.x = x 83 | self.y = y 84 | self.order = order 85 | # self.curve is allowed to be None only for INFINITY: 86 | if self.curve: 87 | assert self.curve.contains_point(x, y) 88 | if order: 89 | assert self * order == INFINITY 90 | 91 | def __eq__(self, other): 92 | """两个点是否重合""" 93 | if self.curve == other.curve \ 94 | and self.x == other.x \ 95 | and self.y == other.y: 96 | return True 97 | else: 98 | return False 99 | 100 | def __add__(self, other): 101 | """两个点‘相加’""" 102 | 103 | if other == INFINITY: 104 | return self 105 | if self == INFINITY: 106 | return other 107 | assert self.curve == other.curve 108 | 109 | if self.x == other.x: 110 | if (self.y + other.y) % self.curve.p == 0: 111 | return INFINITY 112 | else: 113 | return self.double() 114 | 115 | p = self.curve.p 116 | l = ((other.y - self.y) * \ 117 | inv_mod(other.x - self.x, p)) % p 118 | 119 | x3 = (l * l - self.x - other.x) % p 120 | y3 = (l * (self.x - x3) - self.y) % p 121 | 122 | return Point(self.curve, x3, y3) 123 | 124 | def __mul__(self, other): 125 | e = other 126 | if self.order: 127 | e = e % self.order 128 | if e == 0: 129 | return INFINITY 130 | if self == INFINITY: 131 | return INFINITY 132 | 133 | e3 = 3 * e 134 | negative_self = Point(self.curve, self.x, -self.y, self.order) 135 | i = leftmost_bit(e3) // 2 136 | result = self 137 | 138 | while i > 1: 139 | result = result.double() 140 | if (e3 & i) != 0 and (e & i) == 0: 141 | result = result + self 142 | if (e3 & i) == 0 and (e & i) != 0: 143 | result = result + negative_self 144 | i = i // 2 145 | return result 146 | 147 | def __rmul__(self, other): 148 | """一个点乘以一个整数""" 149 | return self * other 150 | 151 | def __repr__(self): 152 | if self == INFINITY: 153 | return "infinity" 154 | return "({0},{1})".format(self.x, self.y) 155 | 156 | def double(self): 157 | """the double point.""" 158 | if self == INFINITY: 159 | return INFINITY 160 | 161 | p = self.curve.p 162 | a = self.curve.a 163 | l = ((3 * self.x * self.x + a) * \ 164 | inv_mod(2 * self.y, p)) % p 165 | 166 | x3 = (l * l - 2 * self.x) % p 167 | y3 = (l * (self.x - x3) - self.y) % p 168 | 169 | return Point(self.curve, x3, y3) 170 | 171 | def invert(self): 172 | if self.y is None: 173 | return Point(None, None, None) 174 | return Point(self.curve, self.x, -self.y % self.curve.p) 175 | 176 | 177 | 178 | 179 | INFINITY = Point(None, None, None) 180 | 181 | if __name__ == '__main__': 182 | p, a, b = 29, 4, 20 183 | curve = CurveFp(p, a, b) 184 | G = Point(curve, 3, 1) # 38 185 | k = 33 # 私钥 186 | K = k * G # 公钥 187 | print("(公开)椭圆曲线E{}({},{})".format(p, a, b)) 188 | print("(公开)基点G{}".format(G)) 189 | print("私钥: k =", k) 190 | print("公钥: K =", K) 191 | m = [Point(curve, 6, 17), Point(curve, 10, 4), Point(curve, 10, 25), Point(curve, 24, 7), Point(curve, 5, 7)] 192 | print("明文: m=", m) 193 | # mp = [curve.plain_embed(i) for i in m] 194 | # print("明文嵌入: mp=", mp) 195 | # 公钥K加密 196 | r = [random.randint(2,38) for i in m] 197 | C1 = [i + ri * K for ri,i in zip(r,m)] 198 | C2 = [ri * G for ri,i in zip(r,m)] 199 | print("密文 C1 =", C1) 200 | print("密文 C2 =", C2) 201 | print("解密 mm =", [c1 + k*c2.invert() for c1, c2 in zip(C1, C2)]) 202 | 203 | -------------------------------------------------------------------------------- /des.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # vim:fenc=utf-8 3 | # 4 | # Copyright © 2019 frey 5 | # blog:https://www.vhcffh.com 6 | # 7 | # Distributed under terms of the MIT license. 8 | IP = (58, 50, 42, 34, 26, 18, 10, 2, 9 | 60, 52, 44, 36, 28, 20, 12, 4, 10 | 62, 54, 46, 38, 30, 22, 14, 6, 11 | 64, 56, 48, 40, 32, 24, 16, 8, 12 | 57, 49, 41, 33, 25, 17, 9, 1, 13 | 59, 51, 43, 35, 27, 19, 11, 3, 14 | 61, 53, 45, 37, 29, 21, 13, 5, 15 | 63, 55, 47, 39, 31, 23, 15, 7) 16 | FP = (40, 8, 48, 16, 56, 24, 64, 32, 17 | 39, 7, 47, 15, 55, 23, 63, 31, 18 | 38, 6, 46, 14, 54, 22, 62, 30, 19 | 37, 5, 45, 13, 53, 21, 61, 29, 20 | 36, 4, 44, 12, 52, 20, 60, 28, 21 | 35, 3, 43, 11, 51, 19, 59, 27, 22 | 34, 2, 42, 10, 50, 18, 58, 26, 23 | 33, 1, 41, 9, 49, 17, 57, 25) 24 | E = (32, 1, 2, 3, 4, 5, 25 | 4, 5, 6, 7, 8, 9, 26 | 8, 9, 10, 11, 12, 13, 27 | 12, 13, 14, 15, 16, 17, 28 | 16, 17, 18, 19, 20, 21, 29 | 20, 21, 22, 23, 24, 25, 30 | 24, 25, 26, 27, 28, 29, 31 | 28, 29, 30, 31, 32, 1) 32 | P = (16, 7, 20, 21, 33 | 29, 12, 28, 17, 34 | 1, 15, 23, 26, 35 | 5, 18, 31, 10, 36 | 2, 8, 24, 14, 37 | 32, 27, 3, 9, 38 | 19, 13, 30, 6, 39 | 22, 11, 4, 25) 40 | S = [[[14, 4, 13, 1, 2, 15, 11, 8, 3, 10, 6, 12, 5, 9, 0, 7], 41 | [0, 15, 7, 4, 14, 2, 13, 1, 10, 6, 12, 11, 9, 5, 3, 8], 42 | [4, 1, 14, 8, 13, 6, 2, 11, 15, 12, 9, 7, 3, 10, 5, 0], 43 | [15, 12, 8, 2, 4, 9, 1, 7, 5, 11, 3, 14, 10, 0, 6, 13]], 44 | 45 | [[15, 1, 8, 14, 6, 11, 3, 4, 9, 7, 2, 13, 12, 0, 5, 10], 46 | [3, 13, 4, 7, 15, 2, 8, 14, 12, 0, 1, 10, 6, 9, 11, 5], 47 | [0, 14, 7, 11, 10, 4, 13, 1, 5, 8, 12, 6, 9, 3, 2, 15], 48 | [13, 8, 10, 1, 3, 15, 4, 2, 11, 6, 7, 12, 0, 5, 14, 9]], 49 | 50 | [[10, 0, 9, 14, 6, 3, 15, 5, 1, 13, 12, 7, 11, 4, 2, 8], 51 | [13, 7, 0, 9, 3, 4, 6, 10, 2, 8, 5, 14, 12, 11, 15, 1], 52 | [13, 6, 4, 9, 8, 15, 3, 0, 11, 1, 2, 12, 5, 10, 14, 7], 53 | [1, 10, 13, 0, 6, 9, 8, 7, 4, 15, 14, 3, 11, 5, 2, 12]], 54 | 55 | [[7, 13, 14, 3, 0, 6, 9, 10, 1, 2, 8, 5, 11, 12, 4, 15], 56 | [13, 8, 11, 5, 6, 15, 0, 3, 4, 7, 2, 12, 1, 10, 14, 9], 57 | [10, 6, 9, 0, 12, 11, 7, 13, 15, 1, 3, 14, 5, 2, 8, 4], 58 | [3, 15, 0, 6, 10, 1, 13, 8, 9, 4, 5, 11, 12, 7, 2, 14]], 59 | 60 | [[2, 12, 4, 1, 7, 10, 11, 6, 8, 5, 3, 15, 13, 0, 14, 9], 61 | [14, 11, 2, 12, 4, 7, 13, 1, 5, 0, 15, 10, 3, 9, 8, 6], 62 | [4, 2, 1, 11, 10, 13, 7, 8, 15, 9, 12, 5, 6, 3, 0, 14], 63 | [11, 8, 12, 7, 1, 14, 2, 13, 6, 15, 0, 9, 10, 4, 5, 3]], 64 | 65 | [[12, 1, 10, 15, 9, 2, 6, 8, 0, 13, 3, 4, 14, 7, 5, 11], 66 | [10, 15, 4, 2, 7, 12, 9, 5, 6, 1, 13, 14, 0, 11, 3, 8], 67 | [9, 14, 15, 5, 2, 8, 12, 3, 7, 0, 4, 10, 1, 13, 11, 6], 68 | [4, 3, 2, 12, 9, 5, 15, 10, 11, 14, 1, 7, 6, 0, 8, 13]], 69 | 70 | [[4, 11, 2, 14, 15, 0, 8, 13, 3, 12, 9, 7, 5, 10, 6, 1], 71 | [13, 0, 11, 7, 4, 9, 1, 10, 14, 3, 5, 12, 2, 15, 8, 6], 72 | [1, 4, 11, 13, 12, 3, 7, 14, 10, 15, 6, 8, 0, 5, 9, 2], 73 | [6, 11, 13, 8, 1, 4, 10, 7, 9, 5, 0, 15, 14, 2, 3, 12]], 74 | 75 | [[13, 2, 8, 4, 6, 15, 11, 1, 10, 9, 3, 14, 5, 0, 12, 7], 76 | [1, 15, 13, 8, 10, 3, 7, 4, 12, 5, 6, 11, 0, 14, 9, 2], 77 | [7, 11, 4, 1, 9, 12, 14, 2, 0, 6, 10, 13, 15, 3, 5, 8], 78 | [2, 1, 14, 7, 4, 10, 8, 13, 15, 12, 9, 0, 3, 5, 6, 11]]] 79 | PC_1L = (57, 49, 41, 33, 25, 17, 9, 80 | 1, 58, 50, 42, 34, 26, 18, 81 | 10, 2, 59, 51, 43, 35, 27, 82 | 19, 11, 3, 60, 52, 44, 36) 83 | PC_1R = (63, 55, 47, 39, 31, 23, 15, 84 | 7, 62, 54, 46, 38, 30, 22, 85 | 14, 6, 61, 53, 45, 37, 29, 86 | 21, 13, 5, 28, 20, 12, 4) 87 | PC_2 = (14, 17, 11, 24, 1, 5, 88 | 3, 28, 15, 6, 21, 10, 89 | 23, 19, 12, 4, 26, 8, 90 | 16, 7, 27, 20, 13, 2, 91 | 41, 52, 31, 37, 47, 55, 92 | 30, 40, 51, 45, 33, 48, 93 | 44, 49, 39, 56, 34, 53, 94 | 46, 42, 50, 36, 29, 32) 95 | 96 | 97 | def Permute(block, b_len, PP): 98 | # 通过置换矩阵PP对block进行置换,b_len是块长度(位,bit) 99 | res = 0 100 | for i in PP: 101 | res = res << 1 102 | # 第i-1的位置 即倒数第 103 | res |= (block >> (b_len - i)) & 0x01 104 | return res 105 | 106 | 107 | def bytesToblocks(m): 108 | # 字节序列转换位blocks b'\x00\x01\x02\x03\xff\xff\xff\xff' -> [0x00010203,0xffffffff] 109 | while len(m) % 8 != 0: 110 | m += b'\x00' 111 | blocks = [] 112 | for i in range(len(m) // 4): 113 | blocks.append((m[4 * i] << 24) | (m[4 * i + 1] << 16) | 114 | (m[4 * i + 2] << 8) | (m[4 * i + 3])) 115 | return blocks 116 | 117 | 118 | def blocksTobytes(blocks): 119 | # blocks转换为字节序列 [0x00010203,0xffffffff] -> b'\x00\x01\x02\x03\xff\xff\xff\xff' 120 | res = b'' 121 | for i in blocks: 122 | res += i.to_bytes(4, byteorder="big") 123 | return res 124 | 125 | 126 | L = lambda x, n: ((x << n) | (x >> (28 - n))) & 0x0fffffff 127 | # 对一个28bits的数x进行循环左移n位 128 | 129 | class DES(object): 130 | 131 | def F(self, block, subKeyid): 132 | """ 133 | 134 | :param block: 32bits 135 | :param subKeyid: 136 | :return: res: 32bits 137 | """ 138 | temp = Permute(block, 32, E) ^ self.subKs[subKeyid] 139 | res = 0 140 | for i in range(8): 141 | res = res << 4 142 | yxxxxy = (temp >> 6 * (7 - i)) & 0x3f 143 | xxxx = (yxxxxy & 0x1f) >> 1 144 | yy = ((yxxxxy >> 5) << 1) | (yxxxxy & 0x01) 145 | res |= S[i][yy][xxxx] 146 | res = Permute(res, 32, P) 147 | return res & 0xffffffff 148 | 149 | def __init__(self, K: bytes): 150 | # 通过密钥K生成实例 151 | self.K = K 152 | self.K_blocks = bytesToblocks(K)[:2] 153 | # 生成字密钥self.subKs[16] 154 | self.subKs = None 155 | self.generate_subKs() 156 | 157 | def Encrypt(self, m: bytes) -> bytes: 158 | # 加密 159 | blocks = bytesToblocks(m) 160 | cblocks = [] 161 | for i in range(len(blocks) // 2): 162 | # 每个64bits的高32bits,低32bits 163 | high, low = blocks[2 * i], blocks[2 * i + 1] 164 | # 第一步:初始置换IP 165 | temp = Permute((high << 32) | low, 64, IP) & 0xffffffffffffffff 166 | # 第二步:获取 Li 和 Ri 167 | high, low = temp >> 32, temp & 0xffffffff 168 | # 第三步:共16轮迭代 169 | for j in range(16): 170 | high, low = low, (high ^ self.F(low, j)) 171 | # 第四步:合并L16和R16,注意合并为 R16L16 172 | high, low = low, high 173 | # 第五步:末尾置换FP 174 | temp = Permute((high << 32) | low, 64, FP) & 0xffffffffffffffff 175 | high, low = temp >> 32, temp & 0xffffffff 176 | cblocks.append(high) 177 | cblocks.append(low) 178 | return blocksTobytes(cblocks) 179 | 180 | def Decrypt(self, e: bytes) -> bytes: 181 | # 解密 182 | blocks = bytesToblocks(e) 183 | cblocks = [] 184 | for i in range(len(blocks) // 2): 185 | # 每个64bits的高32bits,低32bits 186 | high, low = blocks[2 * i], blocks[2 * i + 1] 187 | # 第一步:初始置换IP 188 | temp = Permute((high << 32) | low, 64, IP) & 0xffffffffffffffff 189 | # 第二步:获取 Li 和 Ri 190 | high, low = temp >> 32, temp & 0xffffffff 191 | # 第三步:共16轮迭代, 子密钥逆序 192 | for j in range(16): 193 | high, low = low, (high ^ self.F(low, 15 - j)) 194 | # 第四步:合并L16和R16,注意合并为 R16L16 195 | high, low = low, high 196 | # 第五步:末尾置换FP 197 | temp = Permute((high << 32) | low, 64, FP) & 0xffffffffffffffff 198 | high, low = temp >> 32, temp & 0xffffffff 199 | cblocks.append(high) 200 | cblocks.append(low) 201 | return blocksTobytes(cblocks) 202 | 203 | def generate_subKs(self): 204 | # print(bin((self.K_blocks[0] << 32) | self.K_blocks[1])[2:].rjust(32, '0')) 205 | C = Permute((self.K_blocks[0] << 32) | self.K_blocks[1], 64, PC_1L) & 0x0fffffff 206 | D = Permute((self.K_blocks[0] << 32) | self.K_blocks[1], 64, PC_1R) & 0x0fffffff 207 | # print(bin(C)[2:].rjust(28, '0')) 208 | # print(bin(D)[2:].rjust(28, '0')) 209 | self.subKs = [] 210 | for i in range(16): 211 | if i in (0, 1, 8, 15): 212 | C, D = L(C, 1), L(D, 1) 213 | else: 214 | C, D = L(C, 2), L(D, 2) 215 | self.subKs.append(Permute((C << 28) | D, 56, PC_2)) 216 | # print(hex(self.subKs[i])) 217 | 218 | def getK(self) -> bytes: 219 | # 返回密钥K 220 | return self.K 221 | 222 | def generateK(self) -> bytes: 223 | # 随机产生密钥K 224 | pass 225 | 226 | 227 | def print_bytes_hex(m): 228 | for i in m: 229 | print(hex(i)[2:].rjust(2, '0'), end='') 230 | print() 231 | 232 | 233 | if __name__ == '__main__': 234 | # 密钥不足64bits 添零,多于64bits 使用前64bits 235 | # messages 不足64bits的倍数 补零 236 | m = b'https://www.vhcffh.com' # 明文 237 | k = b'123456' # 密钥 238 | a = DES(k) 239 | cc = a.Encrypt(m) 240 | mm = a.Decrypt(cc) 241 | print("明文:", end='') 242 | print(m) 243 | print("密钥:", end='') 244 | print(a.K) 245 | print("密文:", end='') 246 | print_bytes_hex(cc) # 以bytes输出 247 | print("解密:", end='') 248 | print(mm) 249 | 250 | 251 | # http://www.hankcs.com/security/des-algorithm-illustrated.html 252 | 253 | -------------------------------------------------------------------------------- /aes.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # vim:fenc=utf-8 3 | # 4 | # Copyright © 2019 frey 5 | # blog:https://www.vhcffh.com 6 | # 7 | # Distributed under terms of the MIT license. 8 | S_Box = [ 9 | [0x63, 0x7C, 0x77, 0x7B, 0xF2, 0x6B, 0x6F, 0xC5, 10 | 0x30, 0x01, 0x67, 0x2B, 0xFE, 0xD7, 0xAB, 0x76], 11 | [0xCA, 0x82, 0xC9, 0x7D, 0xFA, 0x59, 0x47, 0xF0, 12 | 0xAD, 0xD4, 0xA2, 0xAF, 0x9C, 0xA4, 0x72, 0xC0], 13 | [0xB7, 0xFD, 0x93, 0x26, 0x36, 0x3F, 0xF7, 0xCC, 14 | 0x34, 0xA5, 0xE5, 0xF1, 0x71, 0xD8, 0x31, 0x15], 15 | [0x04, 0xC7, 0x23, 0xC3, 0x18, 0x96, 0x05, 0x9A, 16 | 0x07, 0x12, 0x80, 0xE2, 0xEB, 0x27, 0xB2, 0x75], 17 | [0x09, 0x83, 0x2C, 0x1A, 0x1B, 0x6E, 0x5A, 0xA0, 18 | 0x52, 0x3B, 0xD6, 0xB3, 0x29, 0xE3, 0x2F, 0x84], 19 | [0x53, 0xD1, 0x00, 0xED, 0x20, 0xFC, 0xB1, 0x5B, 20 | 0x6A, 0xCB, 0xBE, 0x39, 0x4A, 0x4C, 0x58, 0xCF], 21 | [0xD0, 0xEF, 0xAA, 0xFB, 0x43, 0x4D, 0x33, 0x85, 22 | 0x45, 0xF9, 0x02, 0x7F, 0x50, 0x3C, 0x9F, 0xA8], 23 | [0x51, 0xA3, 0x40, 0x8F, 0x92, 0x9D, 0x38, 0xF5, 24 | 0xBC, 0xB6, 0xDA, 0x21, 0x10, 0xFF, 0xF3, 0xD2], 25 | [0xCD, 0x0C, 0x13, 0xEC, 0x5F, 0x97, 0x44, 0x17, 26 | 0xC4, 0xA7, 0x7E, 0x3D, 0x64, 0x5D, 0x19, 0x73], 27 | [0x60, 0x81, 0x4F, 0xDC, 0x22, 0x2A, 0x90, 0x88, 28 | 0x46, 0xEE, 0xB8, 0x14, 0xDE, 0x5E, 0x0B, 0xDB], 29 | [0xE0, 0x32, 0x3A, 0x0A, 0x49, 0x06, 0x24, 0x5C, 30 | 0xC2, 0xD3, 0xAC, 0x62, 0x91, 0x95, 0xE4, 0x79], 31 | [0xE7, 0xC8, 0x37, 0x6D, 0x8D, 0xD5, 0x4E, 0xA9, 32 | 0x6C, 0x56, 0xF4, 0xEA, 0x65, 0x7A, 0xAE, 0x08], 33 | [0xBA, 0x78, 0x25, 0x2E, 0x1C, 0xA6, 0xB4, 0xC6, 34 | 0xE8, 0xDD, 0x74, 0x1F, 0x4B, 0xBD, 0x8B, 0x8A], 35 | [0x70, 0x3E, 0xB5, 0x66, 0x48, 0x03, 0xF6, 0x0E, 36 | 0x61, 0x35, 0x57, 0xB9, 0x86, 0xC1, 0x1D, 0x9E], 37 | [0xE1, 0xF8, 0x98, 0x11, 0x69, 0xD9, 0x8E, 0x94, 38 | 0x9B, 0x1E, 0x87, 0xE9, 0xCE, 0x55, 0x28, 0xDF], 39 | [0x8C, 0xA1, 0x89, 0x0D, 0xBF, 0xE6, 0x42, 0x68, 40 | 0x41, 0x99, 0x2D, 0x0F, 0xB0, 0x54, 0xBB, 0x16]] 41 | 42 | Inv_S_Box = [ 43 | [0x52, 0x09, 0x6A, 0xD5, 0x30, 0x36, 0xA5, 0x38, 44 | 0xBF, 0x40, 0xA3, 0x9E, 0x81, 0xF3, 0xD7, 0xFB], 45 | [0x7C, 0xE3, 0x39, 0x82, 0x9B, 0x2F, 0xFF, 0x87, 46 | 0x34, 0x8E, 0x43, 0x44, 0xC4, 0xDE, 0xE9, 0xCB], 47 | [0x54, 0x7B, 0x94, 0x32, 0xA6, 0xC2, 0x23, 0x3D, 48 | 0xEE, 0x4C, 0x95, 0x0B, 0x42, 0xFA, 0xC3, 0x4E], 49 | [0x08, 0x2E, 0xA1, 0x66, 0x28, 0xD9, 0x24, 0xB2, 50 | 0x76, 0x5B, 0xA2, 0x49, 0x6D, 0x8B, 0xD1, 0x25], 51 | [0x72, 0xF8, 0xF6, 0x64, 0x86, 0x68, 0x98, 0x16, 52 | 0xD4, 0xA4, 0x5C, 0xCC, 0x5D, 0x65, 0xB6, 0x92], 53 | [0x6C, 0x70, 0x48, 0x50, 0xFD, 0xED, 0xB9, 0xDA, 54 | 0x5E, 0x15, 0x46, 0x57, 0xA7, 0x8D, 0x9D, 0x84], 55 | [0x90, 0xD8, 0xAB, 0x00, 0x8C, 0xBC, 0xD3, 0x0A, 56 | 0xF7, 0xE4, 0x58, 0x05, 0xB8, 0xB3, 0x45, 0x06], 57 | [0xD0, 0x2C, 0x1E, 0x8F, 0xCA, 0x3F, 0x0F, 0x02, 58 | 0xC1, 0xAF, 0xBD, 0x03, 0x01, 0x13, 0x8A, 0x6B], 59 | [0x3A, 0x91, 0x11, 0x41, 0x4F, 0x67, 0xDC, 0xEA, 60 | 0x97, 0xF2, 0xCF, 0xCE, 0xF0, 0xB4, 0xE6, 0x73], 61 | [0x96, 0xAC, 0x74, 0x22, 0xE7, 0xAD, 0x35, 0x85, 62 | 0xE2, 0xF9, 0x37, 0xE8, 0x1C, 0x75, 0xDF, 0x6E], 63 | [0x47, 0xF1, 0x1A, 0x71, 0x1D, 0x29, 0xC5, 0x89, 64 | 0x6F, 0xB7, 0x62, 0x0E, 0xAA, 0x18, 0xBE, 0x1B], 65 | [0xFC, 0x56, 0x3E, 0x4B, 0xC6, 0xD2, 0x79, 0x20, 66 | 0x9A, 0xDB, 0xC0, 0xFE, 0x78, 0xCD, 0x5A, 0xF4], 67 | [0x1F, 0xDD, 0xA8, 0x33, 0x88, 0x07, 0xC7, 0x31, 68 | 0xB1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xEC, 0x5F], 69 | [0x60, 0x51, 0x7F, 0xA9, 0x19, 0xB5, 0x4A, 0x0D, 70 | 0x2D, 0xE5, 0x7A, 0x9F, 0x93, 0xC9, 0x9C, 0xEF], 71 | [0xA0, 0xE0, 0x3B, 0x4D, 0xAE, 0x2A, 0xF5, 0xB0, 72 | 0xC8, 0xEB, 0xBB, 0x3C, 0x83, 0x53, 0x99, 0x61], 73 | [0x17, 0x2B, 0x04, 0x7E, 0xBA, 0x77, 0xD6, 0x26, 74 | 0xE1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0C, 0x7D]] 75 | 76 | # 轮常数,密钥扩展中用到。(AES-128只需要10轮) 77 | Rcon = [0x01000000, 0x02000000, 0x04000000, 0x08000000, 0x10000000, 78 | 0x20000000, 0x40000000, 0x80000000, 0x1b000000, 0x36000000] 79 | 80 | 81 | # 密钥扩展 82 | # 字循环左移一个字节 83 | def RotWord(x): 84 | return ((x << 8) | (x >> 24)) & 0xffffffff 85 | 86 | 87 | # S盒变换 88 | def SubWord(x): 89 | temp = 0 90 | temp = (temp << 8) | S_Box[(x >> 28) & 0x0f][(x >> 24) & 0x0f] 91 | temp = (temp << 8) | S_Box[(x >> 20) & 0x0f][(x >> 16) & 0x0f] 92 | temp = (temp << 8) | S_Box[(x >> 12) & 0x0f][(x >> 8) & 0x0f] 93 | temp = (temp << 8) | S_Box[(x >> 4) & 0x0f][(x >> 0) & 0x0f] 94 | return temp 95 | 96 | 97 | # 加密过程 98 | # 轮密钥加变换 - 将每一列与扩展密钥进行异或 99 | def AddRoundKey(mtx, ikey): 100 | rmtx = [] 101 | for i in range(4): 102 | for j in range(4): 103 | rmtx.append((mtx[4 * i + j] ^ ((ikey[j] << 8 * i) >> 24)) & 0xff) 104 | return bytes(rmtx) 105 | 106 | 107 | # S盒变换 - 前4位为行号,后4位为列号 108 | def Subbytes(mtx): 109 | rmtx = [] 110 | for i in mtx: 111 | rmtx.append(S_Box[i >> 4][i & 0x0f]) 112 | return bytes(rmtx) 113 | 114 | 115 | # 行变换 - 按字节循环移位 116 | def ShiftRows(mtx): 117 | rmtx = b'' 118 | rmtx += mtx[0:4] + \ 119 | mtx[5:8] + mtx[4:5] + \ 120 | mtx[10:12] + mtx[8:10] + \ 121 | mtx[15:16] + mtx[12:15] 122 | return rmtx 123 | 124 | 125 | # 有限域上的乘法 GF(2^8) 126 | def GFMul(a, b): 127 | p, hi_bit_set = 0, 0 128 | for counter in range(8): 129 | if b & 1 != 0: 130 | p ^= a 131 | hi_bit_set = a & 0x80 132 | a = (a << 1) & 0xff 133 | if hi_bit_set != 0: 134 | a ^= 0x1b # x^8 + x^4 + x^3 + x + 1 135 | b >>= 1 136 | return p & 0xff 137 | 138 | 139 | # 列变换 140 | def MixColumns(mtx): 141 | rmtx = [0] * 16 142 | for i in range(4): 143 | arr = [] 144 | for j in range(4): 145 | arr.append(mtx[i + j * 4]) 146 | rmtx[i] = GFMul(0x02, arr[0]) ^ GFMul(0x03, arr[1]) ^ arr[2] ^ arr[3] 147 | rmtx[i + 4] = arr[0] ^ GFMul(0x02, arr[1]) ^ GFMul(0x03, arr[2]) ^ arr[3] 148 | rmtx[i + 8] = arr[0] ^ arr[1] ^ GFMul(0x02, arr[2]) ^ GFMul(0x03, arr[3]) 149 | rmtx[i + 12] = GFMul(0x03, arr[0]) ^ arr[1] ^ arr[2] ^ GFMul(0x02, arr[3]) 150 | return bytes(rmtx) 151 | 152 | 153 | # 解密过程 154 | # 逆行变换 - 按字节循环移位 155 | def InvShiftRows(mtx): 156 | rmtx = b'' 157 | rmtx += mtx[0:4] + \ 158 | mtx[7:8] + mtx[4:7] + \ 159 | mtx[10:12] + mtx[8:10] + \ 160 | mtx[13:16] + mtx[12:13] 161 | return rmtx 162 | 163 | 164 | # 逆S盒变换 - 前4位为行号,后4位为列号 165 | def InvSubbytes(mtx): 166 | rmtx = [] 167 | for i in mtx: 168 | rmtx.append(Inv_S_Box[i >> 4][i & 0x0f]) 169 | return bytes(rmtx) 170 | 171 | 172 | # 逆列变换 173 | def InvMixColumns(mtx): 174 | rmtx = [0] * 16 175 | for i in range(4): 176 | arr = [] 177 | for j in range(4): 178 | arr.append(mtx[i + j * 4]) 179 | rmtx[i] = GFMul(0x0e, arr[0]) ^ GFMul(0x0b, arr[1]) ^ GFMul(0x0d, arr[2]) ^ GFMul(0x09, arr[3]) 180 | rmtx[i + 4] = GFMul(0x09, arr[0]) ^ GFMul(0x0e, arr[1]) ^ GFMul(0x0b, arr[2]) ^ GFMul(0x0d, arr[3]) 181 | rmtx[i + 8] = GFMul(0x0d, arr[0]) ^ GFMul(0x09, arr[1]) ^ GFMul(0x0e, arr[2]) ^ GFMul(0x0b, arr[3]) 182 | rmtx[i + 12] = GFMul(0x0b, arr[0]) ^ GFMul(0x0d, arr[1]) ^ GFMul(0x09, arr[2]) ^ GFMul(0x0e, arr[3]) 183 | return bytes(rmtx) 184 | 185 | 186 | class AES(object): 187 | # AES-128 188 | # Nk密钥长度(双字),Nb分组大小(双字),Nr轮数 189 | # 128 4 4 10 190 | # 192 6 4 12 191 | # 256 8 4 14 192 | # 128 4*4*8=128bits 4*4*8=128bits 10轮 193 | def __init__(self, K: bytes): 194 | self.Nk, self.Nb, self.Nr = 4, 4, 10 195 | # 通过密钥K生成实例,密钥K位数不足补零 196 | self.K = K[:self.Nk * 4] 197 | while len(self.K) < self.Nk * 4: 198 | self.K += b'\x00' 199 | self.W = self.KeyExpansion() 200 | 201 | def Encrypt(self, m: bytes) -> bytes: 202 | # 加密 203 | # 明文不足16*8bits补零 204 | while len(m) % 16 != 0: 205 | m += b'\x00' 206 | c = b'' 207 | for i in range(len(m) // 16): 208 | # 对每一个16*8bits的块进行循环 209 | mtx = m[i * 16:i * 16 + 16] 210 | ikey = self.W[:4] 211 | mtx = AddRoundKey(mtx, ikey) 212 | for round in range(1, self.Nr): 213 | mtx = Subbytes(mtx) 214 | mtx = ShiftRows(mtx) 215 | mtx = MixColumns(mtx) 216 | ikey = self.W[4*round:4*round+4] 217 | mtx = AddRoundKey(mtx, ikey) 218 | mtx = Subbytes(mtx) 219 | mtx = ShiftRows(mtx) 220 | ikey = self.W[4 * self.Nr:] 221 | mtx = AddRoundKey(mtx, ikey) 222 | c += mtx 223 | return c 224 | 225 | def Decrypt(self, m: bytes) -> bytes: 226 | # 解密 227 | c = b'' 228 | for i in range(len(m) // 16): 229 | mtx = m[i * 16:i * 16 + 16] 230 | ikey = self.W[self.Nr * 4:] 231 | mtx = AddRoundKey(mtx, ikey) 232 | for round in range(self.Nr-1, 0, -1): 233 | mtx = InvShiftRows(mtx) 234 | mtx = InvSubbytes(mtx) 235 | ikey = self.W[4 * round:4 * round + 4] 236 | mtx = AddRoundKey(mtx, ikey) 237 | mtx = InvMixColumns(mtx) 238 | mtx = InvShiftRows(mtx) 239 | mtx = InvSubbytes(mtx) 240 | ikey = self.W[:4] 241 | mtx = AddRoundKey(mtx, ikey) 242 | c += mtx 243 | return c 244 | 245 | def KeyExpansion(self): 246 | # 密钥扩展函数,密钥 K 扩展生成 Nb(Nr+1)个字 4*4*8bits=128bits -> 4*(10+1)*32bits=1408bits 247 | w = [] 248 | for i in range(self.Nk): 249 | temp = 0 250 | for j in range(4): 251 | temp = (temp << 8) | self.K[4 * i + j] 252 | w.append(temp) 253 | for i in range(self.Nk, self.Nb * (self.Nr + 1)): 254 | temp = w[i - 1] 255 | if i % self.Nk == 0: 256 | temp = SubWord(RotWord(temp)) ^ Rcon[i // self.Nk - 1] 257 | elif self.Nk > 6 and i % self.Nk == 4: 258 | temp = SubWord(temp) 259 | w.append(w[i - self.Nk] ^ temp) 260 | return w 261 | 262 | def getK(self) -> bytes: 263 | # 返回密钥K 264 | return self.K 265 | 266 | def generateK(self) -> bytes: 267 | # 随机产生密钥K 268 | pass 269 | 270 | 271 | def print_bytes_hex(m): 272 | for i in m: 273 | print(hex(i)[2:].rjust(2, '0'), end='') 274 | print() 275 | 276 | 277 | if __name__ == '__main__': 278 | # AES-128 279 | # 密钥不足128bits 添零,多余128bits 截取前128bits 280 | # messages 不足128bits的倍数 补零 281 | m = b'https://www.vhcffh.com' 282 | key = b'123456' 283 | a = AES(key) 284 | cc = a.Encrypt(m) 285 | mm = a.Decrypt(cc) 286 | print("明文:", end='') 287 | print(m) 288 | print("密钥:", end='') 289 | print(a.K) 290 | print("密文:", end='') 291 | print_bytes_hex(cc) # 以bytes输出 292 | print("解密:", end='') 293 | print(mm) 294 | 295 | 296 | # 参考 297 | # https://songlee24.github.io/2014/12/13/aes-encrypt/ 298 | # https://zh.wikipedia.org/wiki/%E9%AB%98%E7%BA%A7%E5%8A%A0%E5%AF%86%E6%A0%87%E5%87%86 --------------------------------------------------------------------------------