XOR函数在特殊情况下失败

2024-09-26 22:10:49 发布

您现在位置:Python中文网/ 问答频道 /正文

首先,我想说,这个问题与python相关,与DES无关。 我为我的密码学课程做了一个DES加密程序。忽略密钥函数,此加密的一般格式为:明文->;(置换)——>;l0r0。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('\n\nstart of round ', (i+1),'\n\n')
            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

这里的isse是第二轮“newR:”开始前上一轮的第三个isse 这一行应包括前两行(不包括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:”一起输出的内容:

当i或L(i-1)与F(E(R(i-1)XOR K(i)),在这一点的每一轮上都会发生此错误

我不知道到底是什么导致了这个错误,但是我用来存储这个结果的变量在创建之前根本没有被使用。我使用的XOR方法是在之前和之后使用的,只有在每一轮的这个位置才是不正确的。每次,在这一点上,结果都是一个大小正确的所有1的列表。输入到我的XOR方法中的两个列表是先前输出的,因此它们存在并包含正确的元素

我将非常感谢您的帮助。正如一开始提到的,这可能是python问题而不是DES问题


Tags: selfboxforlenreturndefcollist
1条回答
网友
1楼 · 发布于 2024-09-26 22:10:49

问题是你在混合类型。。。有时使用字符列表'0''1',有时使用数字列表01

在Python中0 == '0'将返回False,因此X-Or将全部为1

只需将所有内容转换为使用字符或数字,不要混用它们

对于其他比较类型(例如<),python3可能会给出一个错误,但是对于相等性测试,不同的类型只是比较不同,不管值是什么

相关问题 更多 >

    热门问题