Sky's blog

密码学课程设计之二手撸AES加解密程序

字数统计: 2,756阅读时长: 17 min
2017/12/24 Share

前记

本来以为和DES一样挺好写的,但是写的时候发现,差的挺多的……

一些基本功能函数

16进制异或

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
def xor(str1_hex,str2_hex):
hex_to_bin = {"0":"0000","1":"0001","2":"0010","3":"0011","4":"0100","5":"0101","6":"0110","7":"0111","8":"1000","9":"1001","A":"1010","B":"1011","C":"1100","D":"1101","E":"1110","F":"1111"}
str1 = ""
str2 = ""
for i in range(0,len(str1_hex)):
str1 += hex_to_bin[str1_hex[i]]
str2 += hex_to_bin[str2_hex[i]]
res = ""
for i in range(0,len(str1)):
xor_res = int(str1[i],10)^int(str2[i],10)
if xor_res == 1:
res +='1'
else:
res +='0'
return bintohex(res)

二进制转十六进制

1
2
3
4
5
def bintohex(str):
res = ''
for i in range(0,len(str),4):
res += hex(int(str[i:i+4],2))[2:]
return res.upper()

十六进制转二进制

1
2
3
4
5
6
def hex_to_bin(str_hex):
hex_to_bin = {"0":"0000","1":"0001","2":"0010","3":"0011","4":"0100","5":"0101","6":"0110","7":"0111","8":"1000","9":"1001","A":"1010","B":"1011","C":"1100","D":"1101","E":"1110","F":"1111"}
str = ""
for i in range(0, len(str_hex)):
str += hex_to_bin[str_hex[i]]
return str.upper()

伽罗华域(2^8)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
def G2(str):
str = hex_to_bin(str)
str = str[1:len(str)]+'0'
str = hex(int(str,2))[2:]
if len(str)!=2:
for i in range(0,2-len(str)):
str = '0'+str
return str.upper()

def G4(str):
str = hex_to_bin(str)
str = str[2:len(str)] + '00'
str = hex(int(str, 2))[2:]
if len(str) != 2:
for i in range(0, 2 - len(str)):
str = '0' + str
return str.upper()

def G8(str):
str = hex_to_bin(str)
str = str[3:len(str)] + '000'
str = hex(int(str, 2))[2:]
if len(str) != 2:
for i in range(0, 2 - len(str)):
str = '0' + str
return str.upper()

def G(str1,str2):
if str1 == "01":
return str2.upper()
elif str1 == "02":
return G2(str2)
elif str1 == "03":
tmp = hex(int(G2(str2),16)^int(str2,16))[2:]
if len(tmp) != 2:
for i in range(0, 2 - len(tmp)):
tmp = '0' + tmp
return tmp.upper()
elif str1 == "09":
tmp = hex(int(G8(str2), 16) ^ int(str2, 16))[2:]
if len(tmp) != 2:
for i in range(0, 2 - len(tmp)):
tmp = '0' + tmp
return tmp.upper()
elif str1 == "0B":
tmp = hex(int(G8(str2), 16) ^ int(G2(str2), 16)^int(str2, 16))[2:]
if len(tmp) != 2:
for i in range(0, 2 - len(tmp)):
tmp = '0' + tmp
return tmp.upper()
elif str1 == "0D":
tmp = hex(int(G8(str2), 16) ^ int(G4(str2), 16) ^ int(str2, 16))[2:]
if len(tmp) != 2:
for i in range(0, 2 - len(tmp)):
tmp = '0' + tmp
return tmp.upper()
elif str1 == "0E":
tmp = hex(int(G8(str2), 16) ^ int(G4(str2), 16) ^ int(G2(str2), 16))[2:]
if len(tmp) != 2:
for i in range(0, 2 - len(tmp)):
tmp = '0' + tmp
return tmp.upper()

字符串异或

1
2
3
4
5
6
7
8
9
10
11
def str_xor(str1,str2):
res = ""
for i in range(0,len(str1),2):
tmp = hex(int(str1[i:i+2],16)^int(str2[i:i+2],16))[2:]
if len(tmp)!=2:
for i in range(0,2-len(tmp)):
tmp = '0'+tmp
res +=tmp
else:
res +=tmp
return res.upper()

明文转16进制

1
2
3
4
5
6
7
8
9
10
11
def plain_to_hex(str):
res = ""
for i in str:
tmp = hex(ord(i))[2:]
if len(tmp)!=2:
for j in range(0,2-len(tmp)):
tmp = "0"+tmp
res += tmp
else:
res +=tmp
return res.upper()

移位函数

1
2
3
4
5
6
7
8
9
def yiwei(str,num):
num = num%4
word_list = []
for i in range(0,len(str),2):
word_list.append(str[i:i+2])
res = ""
for i in range(0,4):
res +=word_list[(num+i)%4]
return res

字符串转矩阵

1
2
3
4
5
6
7
8
def str_to_juzhen(str):
s = [[0 for i in range(4)] for i in range(4)]
k = 0
for i in range(0,len(s)):
for j in range(0,len(s[i])):
s[i][j] = str[k:k+2]
k = k+2
return s

16进制转明文

1
2
3
4
5
def hex_to_plain(str):
res = ""
for i in range(0,len(str),2):
res += chr(int(str[i:i+2],16))
return res

AES有关程序

S盒

1
2
3
4
5
6
def S(str):
res = ""
box_s = {"00":"63","01":"7C","02":"77","03":"7B","04":"F2","05":"6B","06":"6F","07":"C5","08":"30","09":"01","0A":"67","0B":"2B","0C":"FE","0D":"D7","0E":"AB","0F":"76","10":"CA","11":"82","12":"C9","13":"7D","14":"FA","15":"59","16":"47","17":"F0","18":"AD","19":"D4","1A":"A2","1B":"AF","1C":"9C","1D":"A4","1E":"72","1F":"C0","20":"B7","21":"FD","22":"93","23":"26","24":"36","25":"3F","26":"F7","27":"CC","28":"34","29":"A5","2A":"E5","2B":"F1","2C":"71","2D":"D8","2E":"31","2F":"15","30":"04","31":"C7","32":"23","33":"C3","34":"18","35":"96","36":"05","37":"9A","38":"07","39":"12","3A":"80","3B":"E2","3C":"EB","3D":"27","3E":"B2","3F":"75","40":"09","41":"83","42":"2C","43":"1A","44":"1B","45":"6E","46":"5A","47":"A0","48":"52","49":"3B","4A":"D6","4B":"B3","4C":"29","4D":"E3","4E":"2F","4F":"84","50":"53","51":"D1","52":"00","53":"ED","54":"20","55":"FC","56":"B1","57":"5B","58":"6A","59":"CB","5A":"BE","5B":"39","5C":"4A","5D":"4C","5E":"58","5F":"CF","60":"D0","61":"EF","62":"AA","63":"FB","64":"43","65":"4D","66":"33","67":"85","68":"45","69":"F9","6A":"02","6B":"7F","6C":"50","6D":"3C","6E":"9F","6F":"A8","70":"51","71":"A3","72":"40","73":"8F","74":"92","75":"9D","76":"38","77":"F5","78":"BC","79":"B6","7A":"DA","7B":"21","7C":"10","7D":"FF","7E":"F3","7F":"D2","80":"CD","81":"0C","82":"13","83":"EC","84":"5F","85":"97","86":"44","87":"17","88":"C4","89":"A7","8A":"7E","8B":"3D","8C":"64","8D":"5D","8E":"19","8F":"73","90":"60","91":"81","92":"4F","93":"DC","94":"22","95":"2A","96":"90","97":"88","98":"46","99":"EE","9A":"B8","9B":"14","9C":"DE","9D":"5E","9E":"0B","9F":"DB","A0":"E0","A1":"32","A2":"3A","A3":"0A","A4":"49","A5":"06","A6":"24","A7":"5C","A8":"C2","A9":"D3","AA":"AC","AB":"62","AC":"91","AD":"95","AE":"E4","AF":"79","B0":"E7","B1":"C8","B2":"37","B3":"6D","B4":"8D","B5":"D5","B6":"4E","B7":"A9","B8":"6C","B9":"56","BA":"F4","BB":"EA","BC":"65","BD":"7A","BE":"AE","BF":"08","C0":"BA","C1":"78","C2":"25","C3":"2E","C4":"1C","C5":"A6","C6":"B4","C7":"C6","C8":"E8","C9":"DD","CA":"74","CB":"1F","CC":"4B","CD":"BD","CE":"8B","CF":"8A","D0":"70","D1":"3E","D2":"B5","D3":"66","D4":"48","D5":"03","D6":"F6","D7":"0E","D8":"61","D9":"35","DA":"57","DB":"B9","DC":"86","DD":"C1","DE":"1D","DF":"9E","E0":"E1","E1":"F8","E2":"98","E3":"11","E4":"69","E5":"D9","E6":"8E","E7":"94","E8":"9B","E9":"1E","EA":"87","EB":"E9","EC":"CE","ED":"55","EE":"28","EF":"DF","F0":"8C","F1":"A1","F2":"89","F3":"0D","F4":"BF","F5":"E6","F6":"42","F7":"68","F8":"41","F9":"99","FA":"2D","FB":"0F","FC":"B0","FD":"54","FE":"BB","FF":"16"}
for i in range(0,len(str),2):
res += box_s[str[i:i+2]]
return res

逆S盒

1
2
3
4
5
6
def ni_S(str):
res = ""
box_s = {"00":"52","01":"09","02":"6A","03":"D5","04":"30","05":"36","06":"A5","07":"38","08":"BF","09":"40","0A":"A3","0B":"9E","0C":"81","0D":"F3","0E":"D7","0F":"FB","10":"7C","11":"E3","12":"39","13":"82","14":"9B","15":"2F","16":"FF","17":"87","18":"34","19":"8E","1A":"43","1B":"44","1C":"C4","1D":"DE","1E":"E9","1F":"CB","20":"54","21":"7B","22":"94","23":"32","24":"A6","25":"C2","26":"23","27":"3D","28":"EE","29":"4C","2A":"95","2B":"0B","2C":"42","2D":"FA","2E":"C3","2F":"4E","30":"08","31":"2E","32":"A1","33":"66","34":"28","35":"D9","36":"24","37":"B2","38":"76","39":"5B","3A":"A2","3B":"49","3C":"6D","3D":"8B","3E":"D1","3F":"25","40":"72","41":"F8","42":"F6","43":"64","44":"86","45":"68","46":"98","47":"16","48":"D4","49":"A4","4A":"5C","4B":"CC","4C":"5D","4D":"65","4E":"B6","4F":"92","50":"6C","51":"70","52":"48","53":"50","54":"FD","55":"ED","56":"B9","57":"DA","58":"5E","59":"15","5A":"46","5B":"57","5C":"A7","5D":"8D","5E":"9D","5F":"84","60":"90","61":"D8","62":"AB","63":"00","64":"8C","65":"BC","66":"D3","67":"0A","68":"F7","69":"E4","6A":"58","6B":"05","6C":"B8","6D":"B3","6E":"45","6F":"06","70":"D0","71":"2C","72":"1E","73":"8F","74":"CA","75":"3F","76":"0F","77":"02","78":"C1","79":"AF","7A":"BD","7B":"03","7C":"01","7D":"13","7E":"8A","7F":"6B","80":"3A","81":"91","82":"11","83":"41","84":"4F","85":"67","86":"DC","87":"EA","88":"97","89":"F2","8A":"CF","8B":"CE","8C":"F0","8D":"B4","8E":"E6","8F":"73","90":"96","91":"AC","92":"74","93":"22","94":"E7","95":"AD","96":"35","97":"85","98":"E2","99":"F9","9A":"37","9B":"E8","9C":"1C","9D":"75","9E":"DF","9F":"6E","A0":"47","A1":"F1","A2":"1A","A3":"71","A4":"1D","A5":"29","A6":"C5","A7":"89","A8":"6F","A9":"B7","AA":"62","AB":"0E","AC":"AA","AD":"18","AE":"BE","AF":"1B","B0":"FC","B1":"56","B2":"3E","B3":"4B","B4":"C6","B5":"D2","B6":"79","B7":"20","B8":"9A","B9":"DB","BA":"C0","BB":"FE","BC":"78","BD":"CD","BE":"5A","BF":"F4","C0":"1F","C1":"DD","C2":"A8","C3":"33","C4":"88","C5":"07","C6":"C7","C7":"31","C8":"B1","C9":"12","CA":"10","CB":"59","CC":"27","CD":"80","CE":"EC","CF":"5F","D0":"60","D1":"51","D2":"7F","D3":"A9","D4":"19","D5":"B5","D6":"4A","D7":"0D","D8":"2D","D9":"E5","DA":"7A","DB":"9F","DC":"93","DD":"C9","DE":"9C","DF":"EF","E0":"A0","E1":"E0","E2":"3B","E3":"4D","E4":"AE","E5":"2A","E6":"F5","E7":"B0","E8":"C8","E9":"EB","EA":"BB","EB":"3C","EC":"83","ED":"53","EE":"99","EF":"61","F0":"17","F1":"2B","F2":"04","F3":"7E","F4":"BA","F5":"77","F6":"D6","F7":"26","F8":"E1","F9":"69","FA":"14","FB":"63","FC":"55","FD":"21","FE":"0C","FF":"7D"}
for i in range(0, len(str), 2):
res += box_s[str[i:i + 2]]
return res

Rcon异或

1
2
3
4
def R(str,i):
Rcon = [0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80,0x1B,0x36]
str = hex(int(str[0:2],16)^Rcon[i-1])[2:]+str[2:]
return str

密钥编排函数T

1
2
3
4
5
6
def T(str,i):  # i位轮数
# 字循环1位
str = str[2:]+str[0:2]
str = S(str)
str = R(str,i)
return str

行移位

1
2
3
4
5
6
7
def row_pass(str):
res = ""
j = 0
for i in range(0,len(str),8):
res += yiwei(str[i:i+8],j)
j = j+1
return res

逆行移位

1
2
3
4
5
6
7
def ni_row_pass(str):
res = str[0:8]
j = 3
for i in range(8, len(str), 8):
res += yiwei(str[i:i + 8], j)
j = j - 1
return res

列混合

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
def col_mix(str):
col = [["02", "03", "01", "01"], ["01", "02", "03", "01"], ["01", "01", "02", "03"], ["03", "01", "01", "02"]]
s = str_to_juzhen(str)
res = ""
for i in range(0,len(s)): #i是行 j是列
for j in range(0,len(s[i])):
tmp_ascii = 0x00
for n in range(0,len(s[i])):
tmp_ascii = tmp_ascii^int(G(col[i][n],s[n][j]),16)
tmp = hex(tmp_ascii)[2:]
if len(tmp) != 2:
for sb in range(0, 2 - len(tmp)):
tmp = "0" + tmp
res += tmp
return res.upper()

逆列混合

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
def ni_col_mix(str):
col = [["0E", "0B", "0D", "09"], ["09", "0E", "0B", "0D"], ["0D", "09", "0E", "0B"], ["0B", "0D", "09", "0E"]]
s = str_to_juzhen(str)
res = ""
for i in range(0,len(s)): #i是行 j是列
for j in range(0,len(s[i])):
tmp_ascii = 0x00
for n in range(0,len(s[i])):
tmp_ascii = tmp_ascii ^ int(G(col[i][n], s[n][j]), 16)
tmp = hex(tmp_ascii)[2:]
if len(tmp) != 2:
for sb in range(0, 2 - len(tmp)):
tmp = "0" + tmp
res += tmp
return res.upper()

逆密钥与列混合

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
def ni_key_col_mix(str):
col = [["0E", "0B", "0D", "09"], ["09", "0E", "0B", "0D"], ["0D", "09", "0E", "0B"], ["0B", "0D", "09", "0E"]]
s = str_to_juzhen(str)
res = [["0E", "0B", "0D", "09"], ["09", "0E", "0B", "0D"], ["0D", "09", "0E", "0B"], ["0B", "0D", "09", "0E"]]
for i in range(0,len(s)): #i是行 j是列
for j in range(0,len(s[i])):
tmp_ascii = 0x00
for n in range(0,len(s[i])):
tmp_ascii = tmp_ascii ^ int(G(col[i][n], s[n][j]), 16)
tmp = hex(tmp_ascii)[2:]
if len(tmp) != 2:
for sb in range(0, 2 - len(tmp)):
tmp = "0" + tmp
res[i][j] = tmp.upper()
return res

def ni_key_mix(str1,str2):
my_str1 = ni_key_col_mix(str1)
my_str2 = ni_key_col_mix(str2)
res = ""
for i in range(0,len(my_str1)):
for j in range(0,len(my_str2)):
tmp = hex(int(my_str1[i][j],16)^int(my_str2[i][j],16))[2:]
if len(tmp) != 2:
for j in range(0, 2 - len(tmp)):
tmp = "0" + tmp
res +=tmp
return res.upper()

F函数

1
2
3
4
5
def F(str):
str = S(str) # 字节代换
str = row_pass(str)
str = col_mix(str)
return str

AES单组加密程序

1
2
3
4
5
6
7
8
9
10
11
12
def AES_enc_one(mes,key):
mes_hex = plain_to_hex(mes)
key_hex = plain_to_hex(key)
key_list = keygen(key_hex)
str = str_xor(mes_hex,key_list[0])
for i in range(1,10):
str = F(str)
str = str_xor(str,key_list[i])
str = S(str)
str = row_pass(str)
str = str_xor(str,key_list[10])
return str

AES单组解密程序

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
def AES_dec_one(cipher,key):
cipher_hex = plain_to_hex(cipher)
key_hex = plain_to_hex(key)
key_list = keygen(key_hex)
str = str_xor(cipher_hex, key_list[10])
i = 9
while i>=1:
str = ni_S(str)
str = ni_row_pass(str)
str = ni_key_mix(str,key_list[i])
i = i - 1
str = ni_S(str)
str = ni_row_pass(str)
str = str_xor(str, key_list[0])
return hex_to_plain(str)

后记

真的是贼鸡儿麻烦……当时写的时候都晕了,所以根本没管效率问题,只是想表达我所能理解的算法……
有空的话再改进吧,不过话说回来,= =谁会用自己写的AES,不都是掌握原理即可吗……

点击赞赏二维码,您的支持将鼓励我继续创作!
CATALOG
  1. 1. 前记
  2. 2. 一些基本功能函数
    1. 2.1. 16进制异或
    2. 2.2. 二进制转十六进制
    3. 2.3. 十六进制转二进制
    4. 2.4. 伽罗华域(2^8)
    5. 2.5. 字符串异或
    6. 2.6. 明文转16进制
    7. 2.7. 移位函数
    8. 2.8. 字符串转矩阵
    9. 2.9. 16进制转明文
  3. 3. AES有关程序
    1. 3.1. S盒
    2. 3.2. 逆S盒
    3. 3.3. Rcon异或
    4. 3.4. 密钥编排函数T
    5. 3.5. 行移位
    6. 3.6. 逆行移位
    7. 3.7. 列混合
    8. 3.8. 逆列混合
    9. 3.9. 逆密钥与列混合
    10. 3.10. F函数
    11. 3.11. AES单组加密程序
    12. 3.12. AES单组解密程序
  4. 4. 后记