@Lin--
2020-01-02T12:39:51.000000Z
字数 11148
阅读 289
ComSec
'''
# File : AES_Box.py
# Author : Hongpei Lin
# Date : 20191111
# Purpose : In algorithm AES
# build S-Box in SubBytes
'''
#multilpy in GF(2^8)
def mul(a,b):
r=0
while b:
if b%2:
r=r^a #add operation : XOR
b=b>>1
if a&int('10000000',2)==0: #first bit's value = 0
a=a<<1
else: #first bit's value = 1
a=a<<1
a=a^283
return r
#compute the max index number which < 2^count
#return count, from 0
def highest_bit(n):
count = 0
while n:
count+=1
n=n>>1
return count-1
#division about polymerization
#return quotient and remainder
def div(a,b):
if a==b:
return 1,0
if a<b:
return 0,a
a_bit = highest_bit(a)
b_bit = highest_bit(b)
result = 0
while not a_bit<b_bit:
move=a_bit-b_bit
temp=b<<move
result=result+(1<<move)
a=a^temp
a_bit=highest_bit(a)
return result,a
#compute the inverse about a', where a*a'=1(mod m)
#the algorithrm likes EGCD
def inverse(a,m):
r0,s0,r1,s1=1,0,0,1
while m>0:
t=m
q,m=div(a,m)#q=a//m,m=a mod m
a=t#a=m
r0,r1=r1,r0^mul(q,r1)#sub operation:XOR
s0,s1=s1,s0^mul(q,s1)
return r0 #a'
#build the matrix to multiply b0-b7 in step 3
def build_T(T_value):
T_List=[]
for i in range(8):
T_List.append(T_value)
if T_value&1:
T_value=(T_value>>1)^int('10000000',2)
else:
T_value=T_value>>1
return T_List
#compute every value's inverse in a matrix
def S_inverse(S):
for i in range(len(S)):
for j in range(len(S[0])):
S[i][j]=inverse(S[i][j],283)
return S
def build_byte_order_S(S):
for i in range(len(S)):
for j in range(len(S[0])):
S[i][j]=(i<<4)+j
return S
def Compute_S_Box(T,S,c):
for i in range(len(S)):
for j in range(len(S[0])):
# In order to multiply matrix T,let every bit in a byte reverse.
Bit=list('{:08b}'.format(S[i][j]))
Bit.reverse()
Bit_s=""
for k in Bit:
Bit_s=Bit_s+str(k)
Bit=int(Bit_s,2)
# T */& b0-b7
T_result=[]
for l in T:
And=l&Bit
And_list=list('{:08b}'.format(And))
And_reslut=int(And_list[0],2)
for m in And_list[1:]:
And_reslut=And_reslut^int(m,2)
T_result.append(And_reslut)
T_result_s=""
for n in T_result:
T_result_s=T_result_s+str(n)
# get the reslut +/XOR c/63's reverse bits
S_temp=int(T_result_s,2)^c
S_temp=list('{:08b}'.format(S_temp))
S_temp.reverse()#reverse again, get the final answer
S_temp_s=""
for o in S_temp:
S_temp_s=S_temp_s+str(o)
S[i][j]=int(S_temp_s,2)
return S
def SubByte(S_BOX,n):
high_four=(n&int('11110000',2))>>4
low_four=(n&int('00001111',2))
return S_BOX[high_four][low_four]
T=[]
T_v=143
T_vi=37
c=int('11000110',2)
ci=int('10100000',2)
S1=[[0]*16 for i in range(16)]#S_Box
Si=[[0]*16 for i in range(16)]#S_Box_Inverse
#Generate S-Box
S1=build_byte_order_S(S1)
S1=S_inverse(S1)
T=build_T(T_v)
S1=Compute_S_Box(T,S1,c)
#Generate Inverse S-Box
Si=build_byte_order_S(Si)
T=build_T(T_vi)
Si=Compute_S_Box(T,Si,ci)
Si=S_inverse(Si)
'''
#print the S-Box
for i in range(16):
for j in range(16):
print(hex(Si[i][j])[2:],end=',')
print("")
'''
'''
# File : AES_ShiftRow.py
# Author : Hongpei Lin
# Date : 20191111
# Purpose : In algorithm AES (Step 2)
'''
def ShiftRow_Left_One(S):
temp=S[0]
for i in range(len(S)-1):
S[i]=S[i+1]
S[len(S)-1]=temp
return S
def ShiftRow_Left_All(S):
for i in range(len(S)):
for j in range(i):
S[i]=ShiftRow_Left_One(S[i])
return S
'''
Stest=[[1,2,3,4],[5,6,7,8],[9,10,11,12],[13,14,15,16]]
Stest=ShiftRow_Right_All(Stest)
for i in range(len(Stest)):
for j in range(len(Stest[0])):
print(Stest[i][j],end=",")
print("")
'''
'''
# File : AES_MixColunm.py
# Author : Hongpei Lin
# Date : 20191113
# Purpose : In algorithm AES (Step 3)
'''
import AES_Box
Mixcolumn=[[2,3,1,1],
[1,2,3,1],
[1,1,2,3],
[3,1,1,2]]
#Multiply two matrix in GF(2^8)
#matrix a and b have same rank, and thay are normal matrix, meaning row=colunm
def Matrix_Mul(a,b):
row=len(a)
c=[[0,0,0,0] for i in range(4)]
for i in range(row):
for j in range(row):#row=colunm
k=0
while k<row:
c[i][j]=c[i][j]^(AES_Box.mul(a[i][k],b[k][j]))
k+=1
return c
'''
examplem=[[int('87',16),int('f2',16),int('4d',16),int('97',16)],
[int('6e', 16),int('4c',16),int('90',16),int('ec',16)],
[int('46',16),int('e7',16),int('4a',16),int('c3',16)],
[int('a6',16),int('8c',16),int('d8',16),int('95',16)]]
test_mixcolunm=Matrix_Mul(Mixcolunm,examplem)
for i in range(4):
for j in range(4):
print(hex(test_mixcolunm[i][j])[2:],end=',')
print("")
'''
'''
# File : AES_KeyAndCounter.py
# Author : Hongpei Lin
# Date : 20191113
# Purpose : In algorithm AES (Step 4)
'''
import codecs
import random
def BuildRandomKey(n):
number=str(random.randint(0,1))
while n-1:
number=number+str(random.randint(0,1))
n=n-1
return number
#generate Key
fk=codecs.open("Key.txt","w")
fk.write(BuildRandomKey(128))
fk.close()
#generate counter
fc=codecs.open("Counter.txt","w")
fc.write(BuildRandomKey(128))
fc.close()
'''
# File : AES_AddRoundKey.py
# Author : Hongpei Lin
# Date : 20191113
# Purpose : In algorithm AES (Step 4)
'''
import codecs
import AES_ShiftRow
import AES_Box
fo=codecs.open("Key.txt","r")
KEY=fo.read()
fo.close()
#Zero round KEY,4*4 matrix,return string type
key0=[[0,0,0,0] for i in range(4)]
KEY_Index=0
for i in range(len(key0)):
for j in range(len(key0[0])):
key0[i][j]=KEY[KEY_Index:KEY_Index+8]
KEY_Index+=8
RC=[1,2,4,8,16,32,64,128,int('1b',16),int('36',16)]
#g function in AES step 4, w have 4 value,value's type is string(32 bits)
#return string type(32 bits)
def g_function(W,KeyRound):
B=[]
index=0
while index<len(W):#4 times
B.append(W[index:index+8])
index+=8
B=AES_ShiftRow.ShiftRow_Left_One(B)
for i in range(len(B)):
B[i]=AES_Box.SubByte(AES_Box.S1,int(B[i],2))#type=number
B[0]=B[0]^RC[KeyRound]
reslut=""
for i in B:
reslut+="{:08b}".format(i)
return reslut#string type
w=[0 for i in range(4)]#subkey
#w0-w3,w is string type
for i in range(len(key0)):
temp=""
for j in range(len(key0[0])):
temp+=key0[j][i]
w[i]=temp
#Generate all the Key,output string type
def build_subkey(W,KeyRoundTotal):
time=0
while time<KeyRoundTotal:
Wg=g_function(W[-1],time)
W_new=int(Wg,2)^int(W[len(W)-4],2)
W_new=bin(W_new)[2:]
while not len(W_new)==32:#高位填充
W_new="0"+W_new
W.append(W_new)
for i in range(3):
temp=int(W[-1],2)^int(W[len(W)-4],2)
temp=bin(temp)[2:]
while not len(temp)==32:
temp="0"+temp
W.append(temp)
time+=1
return W
#w_test=['00001111000101010111000111001001','01000111110110011110100001011001','00001100101101111010110111010110','10101111011111110110011110011000']
W_key=build_subkey(w,10)
#input strings state and key, both are 128bits
#output encripttext , string type, 128bits
def AddRoundKey(state,key):
state_matrix=[[0,0,0,0] for i in range(4)]
key_matrix=[[0,0,0,0] for i in range(4)]
result_matrix=[[0,0,0,0] for i in range(4)]
result_string=""
string_index=0
for i in range(4):
for j in range(4):
#change srtring to number, to compute
state_matrix[i][j]=int(state[string_index:string_index+8],2)
key_matrix[i][j]=int(key[string_index:string_index+8],2)
#XOR ,and change the reslut to string type,every value has 8 bits
result_matrix[i][j]=key_matrix[i][j]^state_matrix[i][j]
result_matrix[i][j]="{:08b}".format(result_matrix[i][j])
result_string=result_string+result_matrix[i][j]
string_index+=8
return result_string
'''
for i in range(4):
for j in range(4):
print(W_key[i][j],end=',')
print("")
'''
'''
# File : AES_CTR.py
# Author : Hongpei Lin
# Date : 20191113
# Purpose : AES CTR
'''
import codecs
import AES_Box
import AES_ShiftRow
import AES_MixColumn
import AES_AddRoundKey
import random
import re
#make a string become bitstream
def Str_to_Byte(s):
news=""
for i in s:
news=news+"{:08b}".format(ord(i))
return news
#block the plaintext, every block have 128 bits
#output list type, list's value is string(128 bits)
#first value is stuffing bits counts.
def Block_P(Plainfile):
#read the file
fo=codecs.open(Plainfile,"r",encoding='utf-8')
Plaintext=fo.read()
fo.close()
Block=[]
Plaintext=Str_to_Byte(Plaintext)
PlainLength=len(Plaintext)
#Byte stuffing counts, locat in lowest byte
stufy_bit=128-PlainLength%128
stufy_bit_str=AES_Box.SubByte(AES_Box.S1,stufy_bit)#use S-Box subbyte the number
stufy_bit_str="{:08b}".format(stufy_bit_str)
temp=""
for i in range(120):
temp=temp+str(random.randint(0,1))
stufy_bit_str=temp+stufy_bit_str
Block.append(stufy_bit_str)
zero=""
while stufy_bit:
zero=zero+str(random.randint(0,1))
stufy_bit-=1
Plaintext=zero+Plaintext
#stufy_bit=plaintext's index=0
while stufy_bit<len(Plaintext):
Block.append(Plaintext[stufy_bit:stufy_bit+128])
stufy_bit+=128
return Block
#Counter is a 128 bits's string
#output 128 bits string
def CTR(Counter):
# build state matrix,type is string
state=[[0,0,0,0] for i in range(4)]
Index=0
for i in range(len(state)):
for j in range(len(state[0])):
state[i][j]=Counter[Index:Index+8]
Index+=8
#Step1:SubByte
for i in range(len(state)):
for j in range(len(state[0])):
state[i][j]=AES_Box.SubByte(AES_Box.S1,int(state[i][j],2))#return int type
state[i][j]='{:08b}'.format(state[i][j])
#Step2:ShiftRow
state=AES_ShiftRow.ShiftRow_Left_All(state)
#Step3:MixColunm
for i in range(len(state)):
for j in range(len(state[0])):
state[i][j]=int(state[i][j],2)
state=AES_MixColumn.Matrix_Mul(AES_MixColumn.Mixcolumn,state)
for i in range(len(state)):
for j in range(len(state[0])):
state[i][j]="{:08b}".format(state[i][j])
#Step4:AddRoundKey,10 rounds
counter_string=""
#change matrix to string
for i in range(len(state)):
for j in range(len(state[0])):
counter_string=counter_string+state[i][j]
for i in range(10):
Temp_Key=""
for j in range(4):
Temp_Key+=AES_AddRoundKey.W_key[(i+1)*4+j]
counter_string=AES_AddRoundKey.AddRoundKey(counter_string,Temp_Key)#W_key from [4:44]
return counter_string
#Encrypt function,input filename
def AES_Encrypt(filename,counter):
Block_Text=Block_P(filename)
C=[]#encrypttext,string type
for i in Block_Text:
C.append(int(i,2)^int(counter,2))
counter=bin(int(counter,2)+1)[2:]
#bit stuffing
#every block text
for i in range(len(C)):
C[i]=bin(C[i])[2:]#string type
zero=""
stuffingLength=128-len(C[i])
while stuffingLength:
zero=zero+"0"
stuffingLength-=1
C[i]=zero+C[i]
#encode
writetext=""
for i in C:
s=re.findall(r".{8}",i)
for j in s:
writetext+=chr(int(j,2))
#print(len(writetext[1:]))
fw=codecs.open("AESEncryptText.txt","w",encoding='utf-8')
fw.write(writetext)
fw.close()
return True
#Decrypt function,input filename
def AES_Decrypt(filename,counter):
fr=codecs.open(filename,"r",encoding='utf-8')
Block_Text=fr.read()
fr.close()
Block_bitstream=Str_to_Byte(Block_Text)
P=[]
Text_Index=0
while Text_Index<len(Block_bitstream):
P.append(Block_bitstream[Text_Index:Text_Index+128])
Text_Index+=128
#Decrypt
for i in range(len(P)):
P[i]=bin(int(counter,2)^int(P[i],2))[2:]
counter = bin(int(counter, 2) + 1)[2:]
for i in range(len(P)):
stuffing_bit=128-len(P[i])
zero=""
while stuffing_bit:
zero+="0"
stuffing_bit-=1
P[i]=zero+P[i]
stufy_bit=AES_Box.SubByte(AES_Box.Si,int(P[0][-8:],2))# int type
Plain_Stream=""
for i in P[1:]:
Plain_Stream=Plain_Stream+i
Plain_Stream=Plain_Stream[stufy_bit:]#delete stuffing bits
#change bitstream to string(code)
Plain_Text=""
s=re.findall(r".{8}",Plain_Stream)
for j in s:
Plain_Text+=chr(int(j, 2))
fw=codecs.open("AESDecryptText.txt","w",encoding='utf-8')
fw.write(Plain_Text)
fw.close()
return True
'''
# File : AES_CMD.py
# Author : Hongpei Lin
# Date : 20191119
# Purpose : AES CMD program, running it in CMD view
'''
import sys
import getopt
import AES_CTR
import codecs
def __main__(argv):
fcr = codecs.open("Counter.txt", "r", encoding='utf-8')
counter = fcr.read()
fcr.close()
try:
opts,args=getopt.getopt(argv,"he:d:",["help","encrypt=","decrypt="])
except getopt.GetoptError:
print("ERROR:AES_CMD.py -e <filename> \n or:AES_CMD.py -d <filename>")
print(" or:AES_CMD.py --encrypt=<filename> \n or:AES_CMD.py --decrypt=<filename>")
sys.exit(2)
for opt,arg in opts:
if opt in ("-h","--help"):
print("Please input in these format")
print("AES_CMD.py -e <filename>\nAES_CMD.py -d <filename>")
print("AES_CMD.py --encrypt=<filename>\nAES_CMD.py --decrypt=<filename>")
sys.exit()
elif opt in ("-e","--encrypt"):
counter=AES_CTR.CTR(counter)
filename=arg
if AES_CTR.AES_Encrypt(filename,counter):
print("Encrypt Successfully! Wrote the CryptText in AESEncryptText.txt")
elif opt in ("-d","--decrypt"):
counter=AES_CTR.CTR(counter)
filename=arg
if AES_CTR.AES_Decrypt(filename,counter):
print("Decrypt Successfully! Wrote the PlainText in AESDecryptText.txt")
if __name__=="__main__":
__main__(sys.argv[1:])