三轮DES差分攻击

三轮DES差分攻击

欢迎大家访问我的GitHub博客

https://lunan0320.github.io/

1、写在前面

Readme~

关于DES的三轮差分攻击
 

希望大家弄明白原理,不要只要代码
 

除此之外,参考上一篇Des加、解密博客中的代码,有需要的读者可以移步DES加密、解密
 

这里因为latex写的报告拷贝出现乱码,就把我们实验报告中的原理部分以图片形式分享出来,供大家学习。

因为不希望大部分前来看博客的是为了代码而来,因此此处更新后删除了源代码,希望读者能够根据下述的详细原理看懂后完成。
如果理解了原理不懂如何写代码,那我觉得您应该移步Python Documentation contents

此处保留了部分不完整核心代码,仅用于参考,读者可以参考此部分或者自行完成

2、三轮差分原理

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

3、题目解答

明文:0x5E870BA0B559A8CF 密文:0X71BF939C0CEEE3B1
明文:0xE7C1F970B559A8CF 密文:0XEAA6CE7BC9DB808B
明文:0x5D6F0803ED9FAC45 密文:0XD99FDDD5A3016E53
明文:0x1EB2B007ED9FAC45 密文:0XB49E2F61B4172078
明文:0x7ECF80BD2FE0EA99 密文:0XC9BE22F6DA261B9A
明文:0x8B2CBE002FE0EA99 密文:0X2360C6F9ACD3982D
明文:0X97D2078984F010B4 密文:0X719849F28E5313BF
明文:0X4A5C783384F010B4 密文:0XE4DDEEDB66776D42
明文:0X641E10E96186B8A0 密文:0X7918C1C6400F4AA2
明文:0XCA4E94596186B8A0 密文:0XB8D0DC72CD2F6579

K3=0x48D642113646D1
K=0x1A624C89520DEC40

在这里插入图片描述
在这里插入图片描述

3、部分代码



#求输入差分L0与L0*的差分
################################注意此处是10个明密文,在索引的时候一定是2*i或者2*i+1 ##############################
def L_xor(text):
    L0_xor_list=[]
    for i in range(N):
        P1 = text[2*i]
        P2 = text[2*i + 1]
        L0_1 = P1[0:32]
        L0_2 = P2[0:32]
        L0_xor = ''.join('0' if L0_1[j] == L0_2[j] else '1' for j in range(0,32))
        L0_xor_list.append(L0_xor)
    return L0_xor_list

#求输出差分R3与R3*的差分
def R3_xor(ciphertext):
    R3_xor_list=[]
    for i in range(N):
        C1 = ciphertext[2*i]
        C2 = ciphertext[2*i + 1]
        R3_1 = C1[32:64]
        R3_2 = C2[32:64]
        R3_xor = ''.join('0' if R3_1[j] == R3_2[j] else '1' for j in range(32))
        R3_xor_list.append(R3_xor)
    return R3_xor_list

#六位二进制字符串过第n个S盒
def S(B,n):
    S_box_location =int(B[0] + B[-1], 2) * 16 + int(B[1:-1], 2)
    R = ''.join(hex_bin[hex(S_box[n][S_box_location])[-1]])
    return R

#S盒两个四位输出结果的差分
def S_box_xor(s1,s2):
    xor=''.join('0' if s1[i]==s2[i] else '1' for i in range(4))
    return int(xor,2)

#差分表
def Difference_table():
    table=[[[[]for k in range(16)] for i in range(64)]for j in range(8)]
    for n in range(8):
        for B1 in range(64):
            for B2 in range(64):
                B1_bin = int_bin6(B1)
                B2_bin = int_bin6(B2)
                S_B1 = S(B1_bin, n)
                S_B2 = S(B2_bin, n)
                S_xor=S_box_xor(S_B1,S_B2)
                table[n][B1 ^ B2][S_xor].append(B1)
    return table
table=Difference_table()
print(table)


#B_xor_B*
def B_xor_List():
    L3_xor_list = L_xor(ciphertext)
    B_xor_list=[]
    for m in L3_xor_list:
        text=translation(m,E)
        B_xor_list.append(text)
    return B_xor_list


#E扩展之后的L3的取值列表
###################################################注意此处也是2*N的索引,整个ciphertext是有10个###########################
def find_E_L3_list():
    E_L3_list = []
    for i in range(2*N):
        C = ciphertext[i]
        L3 = C[0:32]
        E_L3_list.append(translation(L3, E))
    return E_L3_list

E_L3_list=find_E_L3_list()


# 寻找K3可能出现的情况
def Differ_KEY3():
    key=[[]for i in range(8)]
    for k in range(N):
        bit6_list = [B_xor_list[k][i:i + 6] for i in range(0, 48, 6)]  # 将B^B*按6bit分组
        bit4_list = [S1_xor_S2_list[k][i:i + 4] for i in range(0, 32, 4)]  # 将S(B)^S(B*)按4bit分组
        ################################################注意此处,索引L3时候是2*k,因为E_L3_list是有10组,必须要单独的去取那一组#############################################
        bit6_list_L3=[E_L3_list[2*k][i:i+6]for i in range(0,48,6)] #对所有扩展后的L3,每一组明密文对中按6bit分组
        for i in range(8):
            row=int(bit6_list[i],2)
            col=int(bit4_list[i],2)
            for B in table[i][row][col]:
                B=int_bin6(B)
                E_L3=bit6_list_L3[i]
                K3 = ''.join('0' if B[j] == E_L3[j] else '1' for j in range(6))
                K3=int(K3,2)
                key[i].append(K3)
    return key

key3_list=Differ_KEY3()



def round3_DES(P,test_Key):
    #拿到的test_Key是56位的,P是不需要过IP置换的,最后也不需要过IP逆置换

    # 获取三轮轮秘钥 Kn,没有用global关键字,应该没有问题,如果有问题回来看一下
    Cn = [test_Key[:28]]
    Dn = [test_Key[28:]]
    for i in range(3):
        Cn.append(Cn[-1][Kleft_shift[i]:] + Cn[-1][:Kleft_shift[i]]) #注意轮秘钥K1的下标是1
        Dn.append(Dn[-1][Kleft_shift[i]:] + Dn[-1][:Kleft_shift[i]])
    Kn = [translation(Cn[i] + Dn[i], K56_48) for i in range(1, 4)]

    # 开始加密过程
    #print("P1",P)
    #p = ''.join(hex_bin[i] for i in P)
    #print("P2",p)
    l = P[0:32]
    r = P[32:]
    for i in range(3):
        # print("{:<10}Round{}".format(' ',i + 1))
        # print('{:<4}        {}'.format('Ki', Kn[i]))
        l, r = festial(l, r, Kn[i])
        # print('{:<4}        {}'.format('r', r))
        # print('{:<4}        {}\n'.format('l', l)
    return l + r

def getkey56(key48):
    temp_Key = ['6'] * 56

    # 先过PC2的逆
    for i in range(48):
        temp_Key[K56_48[i] - 1] = key48[i]

    # print(temp_Key)
    temp_Key = ''.join(temp_Key)
    # print('key48',temp_Key)

    temp_Key_l = temp_Key[:28]
    temp_Key_r = temp_Key[28:]
    # print('temp_Key_l',temp_Key_l)
    # print('temp_Key_r',temp_Key_r)
    shift = Kleft_shift[0] + Kleft_shift[1] + Kleft_shift[2]
    Key56_l = temp_Key_l[-shift:] + temp_Key_l[:-shift]
    Key56_r = temp_Key_r[-shift:] + temp_Key_r[:-shift]

    temp_Key56 = Key56_l + Key56_r

    guess_Key = ['0'] * 56
    guess_loca = []
    for i in range(56):
        if temp_Key56[i] == '6':
            guess_loca.append(i)  # 注意此处下标从0开始算的
        else:
            guess_Key[i] = temp_Key56[i]
    #print('guess_loca',guess_loca)
    right_Key56 = ''
    for i in range(2 ** 8):
        guess = '{:0>8}'.format(bin(i)[2:])
        for j in range(8):
            guess_Key[guess_loca[j]] = guess[j]
        test_Key = ''.join(guess_Key)
        #print(test_Key)
        # 接下来要用我们的test_Key去计算三轮秘钥,然后跑一次DES,如果可以把明文顺利加密为密文,就说明这个是对的秘钥
        p_lower=plaintext[0]
        test_cipher=round3_DES(p_lower, test_Key)
        #print("p",test_cipher)
        c_lower=ciphertext[0]
       # print("c",c_lower)
        if test_cipher == c_lower:
            right_Key56 = test_Key
            break
    print("right_Key56",hex(int(right_Key56,2)).upper())
    return right_Key56

def getkey64(key56):
    key56_=''.join(key56[i-1] for i in PC_1_1 if i!=-1)
    key64=''
    for i in range(8):
        key64+=key56_[7*i:7*(i+1):]+str((key56_[7*i:7*(i+1):].count('1')+1)%2)
    return key64


版权声明:本文为qq_51927659原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。