#python #encryption #des
#python #шифрование #des
Вопрос:
Я хочу предварить это, сказав, что проблема связана с python, а не с DES. Я создал программу шифрования DES для своего класса криптологии. игнорируя ключевые функции, общий формат этого шифрования: открытый текст -> (перестановка) -> L0 R0. L(i) = R (i-1). R (i) = L(i-1) XOR F(E(R(i-1) XOR K (i))) в настоящее время моя программа предназначена для вывода каждого шага этого процесса. на каждом шаге моя программа работает по назначению, пока я не доберусь до окончательного XOR до конца этого раунда шифрования. Метод XOR, который я использую, использовался до этой проблемы и работает по назначению. Вот класс, который я создал:
class DES:
def printListInX(self, l, x):
strList=""
for i in range(len(l)):
if i % x ==0:
strList =" "
strList =str(l[i])
return strList
def byteArrToInt(self,bits):
#generally only used for turning 3 bits to 1 num
temp=8*bits[0] 4*bits[1] 2*bits[2] bits[3]
return temp
def intTo4bits(self, n)->list:
bStr = ''
while n > 0:
bStr = str(n % 2) bStr
n = n >> 1
while len(bStr)<4:
bStr="0" bStr
return [int(x) for x in bStr]
def shiftLeft(self, h, num):
for i in range(num):
h=h[1:] [h[0]]
return h
def xorBytes(self, n=[], m=[])->list:
#assume n m of equal size
temp=[]
for i in range(len(n)):
if n[i] == m[i]:
temp.append(0)
else:
temp.append(1)
return temp
def get2from1(self, L):
temp1=[]
temp2=[]
half=len(L)/2 #len is assumed even so no need to floor
for i in range(len(L)):
if i <half:
temp1.append(L[i])
else:
temp2.append(L[i])
return temp1, temp2
def hexToBinList(self,h):
binDict={
"0":"0000","1":"0001","2":"0010","3":"0011","4":"0100",
"5":"0101","6":"0110","7":"0111","8":"1000","9":"1001",
"A":"1010","a":"1010","b":"1011","B":"1011",
"C":"1100","c":"1100","D":"1101","d":"1101",
"E":"1110","e":"1110","F":"1111","f":"1111"
}
if isinstance(h, str):
strList=list(h)
elif isinstance(h,list):
#assume its a list of hex values
strList=h
ans=[]
for c in strList:
ans =list(binDict[c])
return ans
def process(self, h):
if isinstance(h, str):
if len(h)==64:
#make into array of those ints
#assuming 64 len string is only 1 or 0
temp=list(h)
return [int(x) for x in temp]
elif len(h)==16:
return self.hexToBinList(h)
elif isinstance(h, list):
if len(h)==64:
#assume binary
return h
elif len(h)==16:
return self.hexToBinList(h)
#else? if int do i convert to hex?
def initialPermutation(self, ptList):
#reorder bits, newList[0]=ptList[57] (58 but indexing starts at 1 not 0)
newList=[]
for i in range(len(ptList)):
newList.append(ptList[self.ipTable[i] - 1])
return newList
def PC1(self,keyList):
pc1Table=[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]
#len(keyList)==64
#len(ans)==56
ans=[]
for i in range(56):
ans.append(keyList[pc1Table[i] - 1])
return ans
def PC2(self, keyList):
pc2Table=[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]
#len(keyList)=56
#len(ans)=48
ans=[]
for i in range(48):
ans.append(keyList[pc2Table[i] - 1])
return ans
def expansion(self, R:list)->list:
eTable=[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]
#len(R)=32
#len(ans)=48
ans=[]
for i in range(48):
ans.append(R[eTable[i] - 1])
return ans
def s1box(self, bits)->list:
#bits is R XOR K. will be broken and sent to each box class internally
box=[
[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]
]
usable=bits[:6]
bits=bits[6:]
row=int( (str(usable[0]) str(usable[-1])), 2)
col=self.byteArrToInt(usable[1:-1])
print('bits from s1box: ', self.intTo4bits(box[row][col]))
return self.intTo4bits(box[row][col]) self.s2box(bits)
def s2box(self, bits)->list:
box=[
[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]
]
usable=bits[:6]
bits=bits[6:]
row=int( (str(usable[0]) str(usable[-1])), 2)
col=self.byteArrToInt(usable[1:-1])
print('bits from s2box: ', self.intTo4bits(box[row][col]))
return self.intTo4bits(box[row][col]) self.s3box(bits)
def s3box(self, bits)->list:
box=[
[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]
]
usable=bits[:6]
bits=bits[6:]
row=int( (str(usable[0]) str(usable[-1])), 2)
col=self.byteArrToInt(usable[1:-1])
print('bits from s3box: ', self.intTo4bits(box[row][col]))
return self.intTo4bits(box[row][col]) self.s4box(bits)
def s4box(self, bits)->list:
box=[
[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]
]
usable=bits[:6]
bits=bits[6:]
row=int( (str(usable[0]) str(usable[-1])), 2)
col=self.byteArrToInt(usable[1:-1])
print('bits from s4box: ', self.intTo4bits(box[row][col]))
return self.intTo4bits(box[row][col]) self.s5box(bits)
def s5box(self, bits)->list:
box=[
[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]
]
usable=bits[:6]
bits=bits[6:]
row=int( (str(usable[0]) str(usable[-1])), 2)
col=self.byteArrToInt(usable[1:-1])
print('bits from s5box: ', self.intTo4bits(box[row][col]))
return self.intTo4bits(box[row][col]) self.s6box(bits)
def s6box(self, bits)->list:
box=[
[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]
]
usable=bits[:6]
bits=bits[6:]
row=int( (str(usable[0]) str(usable[-1])), 2)
col=self.byteArrToInt(usable[1:-1])
print('bits from s6box: ', self.intTo4bits(box[row][col]))
return self.intTo4bits(box[row][col]) self.s7box(bits)
def s7box(self, bits)->list:
box=[
[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]
]
usable=bits[:6]
bits=bits[6:]
row=int( (str(usable[0]) str(usable[-1])), 2)
col=self.byteArrToInt(usable[1:-1])
print('bits from s7box: ', self.intTo4bits(box[row][col]))
return self.intTo4bits(box[row][col]) self.s8box(bits)
def s8box(self, bits)->list:
box=[
[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]
]
#bits should not be len 6
row=int( (str(bits[0]) str(bits[-1])), 2)
col=self.byteArrToInt(bits[1:-1])
print('bits from s8box: ', self.intTo4bits(box[row][col]))
return self.intTo4bits(box[row][col])
def pBox(self, bits)->list:
box=[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]
ans=[]
for i in range(32):
ans.append(bits[box[i] - 1])
print('bits from pBox: ',self.printListInX(ans, 4))
return ans
def F(self, R:list, K:list)->list:
#expand R from 32 to 48 bits
expR=self.expansion(R)
print('R after expansion: ', self.printListInX(expR, 6))
#XOR newR with K
rXorK=self.xorBytes(expR,K)
print('R XOR K: ', self.printListInX(rXorK, 6))
#break into 8 sub lists (size 6 each) for S boxes
afterSbox=self.s1box(rXorK) #should now be 32 bits
#P box permutation
ans=self.pBox(afterSbox)
return ans
def finalPermutation(self, bits:list)->list:
newList=[]
for i in range(len(bits)):
newList.append(bits[self.ipTableINV[i] - 1])
return newList
def encrypt(self, pt, key, numRounds):
################# SOMETHIGN WRONG ALGORITHMETICALLY #####################
############ i think its because i get L0 and R0 but never actually use them in F
self.pt=self.process(pt) #will be type list
self.key = self.process(key)#will be type list
self.numRounds=numRounds #should always be 16
#do IP on pt to get L,R
newPtList=self.initialPermutation(self.pt)
print('PT after first permutation: ', self.printListInX(newPtList,4))
L,R=self.get2from1(newPtList)
print("L0: ", self.printListInX(L, 4), "tR0: ", self.printListInX(R, 4))
#do PC1 on key to get C,D
key56bits=self.PC1(self.key)
print('key after PC1: ', self.printListInX(key56bits, 4))
C,D=self.get2from1(key56bits)
print('initail C: ', self.printListInX(C, 4), 'ninitial D: ', self.printListInX(D, 4))
shift1=[0,1,8,15]
for i in range(numRounds):
print('nnstart of round ', (i 1),'nn')
newL=R
#newC=C (shifted left x times)
#newD=D (shifted left x times)
#x depends on roundnum
if i in shift1:
C=self.shiftLeft(C,1)
D=self.shiftLeft(D,1)
else:
C=self.shiftLeft(C,2)
D=self.shiftLeft(D,2)
#K=COMPRESS(newC,newD)
print('after shift C: ', self.printListInX(C, 4), 'nafter shift D: ', self.printListInX(D, 4))
K=self.PC2(C D)
print('K', (i 1), ': ', self.printListInX(K, 6))
#newR=L XOR F(R,K)
fOfRK=self.F(R,K)
print('F of R0,K1: ', self.printListInX(fOfRK, 4))
print('before final XOR')
print('L',i,': ', self.printListInX(L, 4))
print('F',(i 1),': ',self.printListInX(fOfRK,4))
################### start issue ################
newR=self.xorBytes(fOfRK,L)
################### end issue ##################
print('newR: ', self.printListInX(newR, 4))
#L=newL, R=newR, C=newC, D=newD
R=newR
L=newL
print('L', (i 1), ': ', self.printListInX(L, 4))
print('R', (i 1), ': ', self.printListInX(R, 4))
#now that rounds are done, do final permutation (ipTableINV)
self.encryptedBits=self.finalPermutation(L R)
return self.encryptedBits
def __init__(self):
self.ipTable=[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]
self.ipTableINV=[40,8,48,16,56,24,64,32,
39,7,47,15,55,23,63,31,
38,6,46,14,54,22,26,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]
это программа-драйвер, используемая для запуска и создания выходных данных:
from DES64Bit import DES
cipher=DES()
pt="0123456789ABCDEF"
key="0123456789ABCDEF"
cipher.encrypt(pt=pt, key=key, numRounds=2)
результат, полученный из этого, выглядит следующим образом
DES_OUTPUT
проблема здесь находится в третьем от последнего раунда перед началом второго раунда «newR: » эта строка должна состоять из двух предыдущих строк, исключающих or’d.
здесь у меня есть программа, использующая тот же метод, который используется внутри, а также ту же битовую строку
def xorBytes(n, m):
#assume n m of equal size
temp=[]
for i in range(len(n)):
if n[i] == m[i]:
temp.append(0)
else:
temp.append(1)
return temp
n=[1,1,1,1, 0,0,0,0, 1,0,1,0, 1,0,1,0, 1,1,1,1, 0,0,0,0, 1,0,1,0, 1,0,1,0]
m=[0,0,1,1, 1,0,0,0, 1,1,0,1, 1,0,1,1, 1,1,1,1, 1,0,0,1, 1,1,0,0, 1,0,1,1]
print(xorBytes(n,m))
(извиняюсь, я не смог включить последние 3 строки в пример кода)
вывод из этой программы выглядит следующим образом:
[1, 1, 0, 0, 1, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 1, 0, 1, 1, 0, 0, 0, 0, 1]
это то, что должно быть выведено вместе с «newR: «
эта ошибка возникает в каждом раунде на данный момент, когда я XOR L(i-1) с помощью F(E(R(i-1) XOR K(i)))
Я точно не знаю, что вызывает эту ошибку, но переменная, которую я использую для хранения этого результата, вообще не использовалась до ее создания там. Метод XOR, который я использую, используется ранее и после, только в этом месте в каждом раунде он неверен. Каждый раз на этом этапе результатом становится список всех единиц правильного размера. два списка, введенные в мой метод XOR, выводятся ранее, поэтому они существуют и содержат правильные элементы.
Я был бы признателен за любую помощь в этом. Как упоминалось в начале, это, скорее всего, скорее проблема python, чем проблема DES.
Комментарии:
1. Не могли бы вы привести более минимальный пример? Это некоторый код для чтения..
2. на предоставленном изображении последние 3 строки — «L0: …», «F1: …» и «newR: …». newR может быть L0 XOR ИЛИ F1. последний приведенный пример кода — это моя функция XOR, а также пример того, как эти два проходят через нее. при изоляции проблемы нет. Проблема возникает только в каждом раунде при последнем вызове XOR
3. в большом примере кода предпоследним методом является мой метод шифрования. вот где все происходит. строка, в которой существует эта проблема, окружена комментариями с надписью «начало проблемы» «конец проблемы»
Ответ №1:
Проблема в том, что вы смешиваете типы … иногда вы используете список символов '0'
, '1'
а иногда список чисел 0
и 1
.
В Python 0 == '0'
будет возвращен False
и, следовательно, X-Or будет всеми единицами.
Просто преобразуйте все, чтобы использовать символы или все, чтобы использовать числа, не смешивайте их.
Для других типов сравнения (например <
) Python 3 выдал бы ошибку, но для проверки равенства разные типы просто сравнивают разные, независимо от того, какое значение.