DES相关分析


作业要求:

  • 网上搜索DES的源代码。

  • 利用DES源代码实现下面功能:

    1:给定某个Sbox的输入差分情况下,计算所有输入对和所有Sbox输出差分的分布情况

    2:统计DES算法在密钥固定情况,输入明文改变1位、2位,。。。64位时。输出密文位数改变情况。

    3:统计DES算法在明文固定情况,输入密钥改变1位、2位,。。。64位时。输出密文位数改变情况。

为了具有客观性,2,3小题需要对多次进行统计,并计算其平均值。

实现:

DES源码:https://github.com/sliveryou/des-python-cipher

编程语言为python,利用pyqt库实现GUI界面。

第一题

该程序也即要寻找满足公式:\(S_j(B_j)\bigoplus S_j(B_j\bigoplusΔB_j)=ΔS_j\)\(B_j\)的集合。

其中:\(S_j()\)为Sbox运算,\(ΔB_j\)为输入差分(6位),\(ΔS_j\)为输出差分(4位),\(B_j\)为所有可能的输入。

首先要求选定一个Sbox(S1,S2,S3,S4,S5,S6,S7,S8),再输入一个输入差分\(ΔB_j\)。可以通过PyQt5.QtWidgets.comboBoxPyQt5.QtWidgets.QLineEdit实现在GUI界面中选择Sbox和输入一个输入差分的功能。

拿到两个变量后,首先遍历4位的二进制数\(ΔS_j\),然后再遍历6位的二进制数\(B_j\),与输入差分\(ΔB_j\)先进行异或运算,然后进行Sbox运算,也即:\(S_j(B_j\bigoplusΔB_j)\)。另外同时再运算\(S_j(B_j)\),代码:

 for Delta_S in range(0, 16):
        #遍历4位的二进制数
        Delta_S = encrypt_function.convert_bin(Delta_S, 4)
        for num in range(0, 64):
        	#遍历6位的二进制数
            a = encrypt_function.convert_bin(num, 6)
            #进行异或运算
            b = encrypt_function.XOR(a, input2)
            
            #进行两次Sbox运算
            a_value = get_sbox_value(a, Sbox)
            b_value = get_sbox_value(b, Sbox)

根据公式,接下去就要对两次Sbox运算的结果进行异或运算\(S_j(B_j)\bigoplus S_j(B_j\bigoplusΔB_j)\),然后判断结果是否与\(ΔS_j\)相等,如果相等的话就把此时的\(B_j\)保存下来。代码:

xor_reasult = encrypt_function.XOR(a_value, b_value)
if xor_reasult == Delta_S:
    reasult = reasult + '  ' + a

最终再将保存的全部结果输出,可以通过PyQt5.QtWidgets.QTableWidgetItem实现在GUI界面中输出。代码:

    def addline(self, Delta_S, count, result):
        row = self.tableWidget.rowCount()
        self.tableWidget.setRowCount(row + 1)
        Delta_S_item = QtWidgets.QTableWidgetItem(Delta_S)
        Delta_S_item.setTextAlignment(QtCore.Qt.AlignCenter)
        self.tableWidget.setItem(row, 0, QtWidgets.QTableWidgetItem(Delta_S_item))
        count_item = QtWidgets.QTableWidgetItem(count)
        count_item.setTextAlignment(QtCore.Qt.AlignCenter)
        self.tableWidget.setItem(row, 1, count_item)
        self.tableWidget.setItem(row, 2, QtWidgets.QTableWidgetItem(result))

运行结果

指定Sbox为S1,输入差分为000001时,运行结果:

分析结果与书本中的分布情况一致。

第二题第三题

第二题与第三题由于实现原理大致相同,因此做了整合。要求首先确定是密钥固定,明文改变模式还是明文固定,密钥改变模式,然后再确定要进行多少次统计

仍然可以通过PyQt5.QtWidgets.comboBoxPyQt5.QtWidgets.QLineEdit实现在GUI界面中选择模式和输入要统计的次数。

随机生成密钥和明文

由于原先DES加密程序中,密钥和明文都是可输入字符,也即普通的ASCII码(32到127),同时为了多次统计的方便,因此考虑每一次统计都在在这个ASCII码区段随机生成8个字符的密钥和明文。代码:

import random

	# key_bin、key_str:密钥的二进制形式和字符串形式
    # text_bin、text_str:明文的二进制形式和字符串形式
	key_bin = ''
	text_bin = ''
    key_str = ''
	text_str = ''
    for i in range(0, 8):
        key = random.randint(32, 128)
        text = random.randint(32, 128)
        key_bin = key_bin + encrypt_function.convert_bin(key, 8)
        text_bin = text_bin + encrypt_function.convert_bin(text, 8)
        key_str = key_str + chr(key)
        text_str = text_str + chr(text)

每次改变明文(或密钥)位数

这里利用了异或运算的特点:无论是0和1,与1进行异或结果都会改变。

因此对于要改变的二进制数(假设为8位),那么只需要分别与0000000100000001100000111,······,11111111这8个二进制数进行异或运算,就可以实现改变1位,2位,3位,······,8位。而这8个二进制数对应的十进制数分别是:2^i-1,其中i=1,2,3,···,8,这可以利用for循环简单实现。

由于这里要改变的是明文(或密钥)是64位,同理就可以与64个二进制数进行异或运算。代码:

key_num=int(key_bin,2)

for i in range(1, 65):
    change_key_bin = encrypt_function.convert_bin(text_num ^ (2 ** i - 1), 64)

局限性在于:没有实现随机改变某一位,只是逐位进行了改变。

计算密文对应改变的位数

通过遍历密文改变前后的每一位,比较是否相同,如果不相同就计数加一,即可计算出改变的位数:

change_num=0
for j in range(0, 64):
    if change_cipher_bin[j] != cipher_bin[j]:
        change_num = change_num + 1

运行结果

密钥固定,明文改变,统计次数10次:

明文固定,密钥改变,统计次数10次:

总结:

无论是密钥固定、明文改变,还是明文固定、密钥改变;无论每次改变几位,最终密文的改变位数都为在32左右,也即总的64位的一半。每次都只变化50%的位数,使得企图通过该改变密钥或明文、根据密文变化来分析的攻击者根本难以分析出结果。DES不愧为当时著名的加密算法。


免责声明!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系本站邮箱yoyou2525@163.com删除。



 
粤ICP备18138465号  © 2018-2025 CODEPRJ.COM