【自己动手设计一个简单的加密算法Python】

一 加密算法设计

本文设计的加密算法为对称加密中的分组加密算法,算法参考Feistel结构进行设计,分组长度为128比特,密钥长度为128比特,基于类Feistel的加密子结构,迭代次数为8次,每次迭代的密钥通过密钥拓展方法计算得到。因为加密算法是基于Feistel结构,故解密算法很容易得到。

1.1加密子结构设计

本文基于Feistel结构进行设计,将4个Feistel子结构进行并联和级联,期望达到更优的加密效果,加密子结构具体的实现如下:
将128比特的明文分为4个小组,每个小组为32比特,将其放入2个并行的Feistel结构中计算得到中间结果,并中间结果交错输入下一级的2个Feistel结构中,最终得到子结构的输出结果,如图1所示。
【自己动手设计一个简单的加密算法Python】_第1张图片

子加密结构中4 个F函数的密钥使用相同的32比特密钥。因为S盒至今没有发现致命弱点,且在DES、AES中都有使用,故在F函数中加入其以增加加密算法的扰乱性;同时加入比特移位,使得相邻字节相互干扰,以增加加密算法的扩散性。F函数具体实现如下:
F函数的输入为32比特,每个字节独立的输入16*16的S盒进行替换,字节高4比特作为行索引,低4比特作为列索引,S盒与AES算法中的相同;之后与32密钥异或,并循环左移1位bit,byte3的最高位移动到byte0的最低位,最输出计算结果。

S = [[0x63, 0x7C, 0x77, 0x7B, 0xF2, 0x6B, 0x6F, 0xC5, 0x30, 0x01, 0x67, 0x2B, 0xFE, 0xD7, 0xAB, 0x76],
         [0xCA, 0x82, 0xC9, 0x7D, 0xFA, 0x59, 0x47, 0xF0, 0xAD, 0xD4, 0xA2, 0xAF, 0x9C, 0xA4, 0x72, 0xC0],
         [0xB7, 0xFD, 0x93, 0x26, 0x36, 0x3F, 0xF7, 0xCC, 0x34, 0xA5, 0xE5, 0xF1, 0x71, 0xD8, 0x31, 0x15],
         [0x04, 0xC7, 0x23, 0xC3, 0x18, 0x96, 0x05, 0x9A, 0x07, 0x12, 0x80, 0xE2, 0xEB, 0x27, 0xB2, 0x75],
         [0x09, 0x83, 0x2C, 0x1A, 0x1B, 0x6E, 0x5A, 0xA0, 0x52, 0x3B, 0xD6, 0xB3, 0x29, 0xE3, 0x2F, 0x84],
         [0x53, 0xD1, 0x00, 0xED, 0x20, 0xFC, 0xB1, 0x5B, 0x6A, 0xCB, 0xBE, 0x39, 0x4A, 0x4C, 0x58, 0xCF],
         [0xD0, 0xEF, 0xAA, 0xFB, 0x43, 0x4D, 0x33, 0x85, 0x45, 0xF9, 0x02, 0x7F, 0x50, 0x3C, 0x9F, 0xA8],
         [0x51, 0xA3, 0x40, 0x8F, 0x92, 0x9D, 0x38, 0xF5, 0xBC, 0xB6, 0xDA, 0x21, 0x10, 0xFF, 0xF3, 0xD2],
         [0xCD, 0x0C, 0x13, 0xEC, 0x5F, 0x97, 0x44, 0x17, 0xC4, 0xA7, 0x7E, 0x3D, 0x64, 0x5D, 0x19, 0x73],
         [0x60, 0x81, 0x4F, 0xDC, 0x22, 0x2A, 0x90, 0x88, 0x46, 0xEE, 0xB8, 0x14, 0xDE, 0x5E, 0x0B, 0xDB],
         [0xE0, 0x32, 0x3A, 0x0A, 0x49, 0x06, 0x24, 0x5C, 0xC2, 0xD3, 0xAC, 0x62, 0x91, 0x95, 0xE4, 0x79],
         [0xE7, 0xC8, 0x37, 0x6D, 0x8D, 0xD5, 0x4E, 0xA9, 0x6C, 0x56, 0xF4, 0xEA, 0x65, 0x7A, 0xAE, 0x08],
         [0xBA, 0x78, 0x25, 0x2E, 0x1C, 0xA6, 0xB4, 0xC6, 0xE8, 0xDD, 0x74, 0x1F, 0x4B, 0xBD, 0x8B, 0x8A],
         [0x70, 0x3E, 0xB5, 0x66, 0x48, 0x03, 0xF6, 0x0E, 0x61, 0x35, 0x57, 0xB9, 0x86, 0xC1, 0x1D, 0x9E],
         [0xE1, 0xF8, 0x98, 0x11, 0x69, 0xD9, 0x8E, 0x94, 0x9B, 0x1E, 0x87, 0xE9, 0xCE, 0x55, 0x28, 0xDF],
         [0x8C, 0xA1, 0x89, 0x0D, 0xBF, 0xE6, 0x42, 0x68, 0x41, 0x99, 0x2D, 0x0F, 0xB0, 0x54, 0xBB, 0x16]]
# F 函数:x为32bits,但可以Nbits
def F(x,key):
     # 逐字节S盒置换操作
    x = bytes([S[(xbit&0xF0)>>4][xbit&0x0F] for xbit in x])
    # 与密钥异或
    x = bytes([xbit^kbit    for xbit,kbit in zip(x,key)])
    # 字节流左移位
    shift = x[1:] + x[:1]
    x = [((xbit&0x7F)<<1)|((sbit&0x80)>>7)   for xbit,sbit in zip(x,shift)]
    return  x   #x[1:] + x[:1]#x[::-1]

#Feistel子结构,支持任意字节长度输入。此处为2个4字节输入
def _Feistel(l,r,key):
    l_ = r
    r_ = [lbit^rbit    for lbit,rbit in zip(l,F(r,key))]
    return l_,r_
                         
#加密子结构
def _FeistelPlus(x1,x2,x3,x4,key):
    x1,x2 = _Feistel(x1,x2,key)
    x3,x4 = _Feistel(x3,x4,key)
    x1,x3 = _Feistel(x1,x3,key)
    x2,x4 = _Feistel(x2,x4,key)
    return x1,x2,x3,x4
                         
#解密子结构
def _DeFeistelPlus(x1,x2,x3,x4,key):
    x1,x3 = _Feistel(x1,x3,key)
    x2,x4 = _Feistel(x2,x4,key)
    x1,x2 = _Feistel(x1,x2,key)
    x3,x4 = _Feistel(x3,x4,key)
    return x1,x2,x3,x4

1.2 加密解码的整体流程

算法设计过程中,分组越长安全性越高,但加/解密的速度越低,本文设置
分组长度为128比特,因为子结构设计较为复杂,故迭代次数设置为8次。因为Feistel结构是对称的密码结构,对信息的加密和解密的过程极为相似,本文基于Feistel结构,加密解密过程同样也非常相似。值得注意的是,加/解密第8轮后需倒序排列x1、x2 、x3、x4,才可以正确加/解密,这一点与Feistel结构相似;解密流程中轮密钥需倒序使用,例如:第1轮解密使用第8轮的加密密钥K8 。整体的加/解密流程如图2所示:【自己动手设计一个简单的加密算法Python】_第2张图片
图2 加密流程图(左) 解密流程图(右)


#加密结构,输入为二进制数据,16bytes
def FeistelPlus(plaintext,key):
    x1 = plaintext[0:4]
    x2 = plaintext[4:8]
    x3 = plaintext[8:12]
    x4 = plaintext[12:16]
    expandKey = createKey(key) 
    for i in range(EPOCH):
        x1,x2,x3,x4 = _FeistelPlus(x1,x2,x3,x4,expandKey[i])
        #print(x1,x2,x3,x4)
    return bytes(x4+x3+x2+list(x1))
                         
#解密结构,输入为二进制数据,16bytes
def DeFeistelPlus(ciphertext,key):
    x1 = ciphertext[0:4]
    x2 = ciphertext[4:8]
    x3 = ciphertext[8:12]
    x4 = ciphertext[12:16]
    expandKey= createKey(key) 
    for i in range(EPOCH):    
        x1,x2,x3,x4 = _DeFeistelPlus(x1,x2,x3,x4,expandKey[EPOCH-i-1])
    return bytes(x4+x3+x2+list(x1))

1.3 密钥拓展

密钥长度越长越安全,64比特长度已经被证明不安全,故选择128比特的密钥长度。密钥拓展算法完全参考AES的密钥拓展算法:首先将初始密钥插入到4*4的矩阵中,如下图所示,由密钥K0、K1、K2、K3扩充新列,新列的产生方式:

  • K[i]=K[i-4]⊕K[i-1], i不为4的倍数时
  • K[i]=K[i-4]⊕T(K[i-1]), i为4的倍数时

由于每次循环使用一列密钥(32比特),所以只需再扩充4列。函数T由3部分组成:字循环、字节代换和轮常量异或。字循环将1个字中的4个字节循环左移一字节;对字循环的结果使用S盒代换,具体操作与加密过程中的S盒代换相同;将前两步的结果同轮常量Rcon[j]进行异或,其中j代表轮数。
【自己动手设计一个简单的加密算法Python】_第3张图片在这里插入代码片

图3 密钥拓展算法

#密钥为128位,参考AES的密钥拓展算法实现,但因为加密时只需要4bytes的密钥,所以不需要拓展44列,只需EPOCH列
#返回EPOCH*4的二维字列表
def createKey(key):
    #轮常量
    Ronj = b'\x01\x02\x04\x08\x10\x20\x40\x80\x1B\x36'
    def T(W_list,j):
        #字循环,左移一位
        W_list = W_list[1:] + W_list[:1]
        #字节S盒代换
        W_list = bytes([S[(xbit&0xF0)>>4][xbit&0x0F] for xbit in W_list])
        #轮常量异或。只需异或第一字节就可以
        W_list = bytes([W_list[0]^Ronj[j]])+W_list[1:]
        return W_list
    #构建前4列
    expandKey = list([ key[0:4] ])
    expandKey.append(key[4:8])
    expandKey.append(key[8:12])
    expandKey.append(key[12:16])
    if EPOCH <=4 :
        return expandKey
    for i in range(4,EPOCH):
        if((i+1)%4 == 0):
            expandKey.append(bytes([Abit^Bbit    for Abit,Bbit in zip(expandKey[i-4],expandKey[i-1])]))
        else:
            expandKey.append(bytes([Abit^Bbit    for Abit,Bbit in zip( expandKey[i-4], T(expandKey[i-1],i//4-1) )]))
    return expandKey

二、测试加密效果

加密算法程序基于python编程语言,jupyter notebook的开发环境下实现。

2.1 正确性检验

设置输入明文为’abcdefghabcdefgh’,密钥为’0123456776543210’,长度均为128bit,加密后的密文为’UG\xa9\x0c\xb7\xf4b9\xb3\xf0f5\x10<\xc0
xa6’(\x代表16进制显示)。将密文输入解密程序中,密钥正确时可以解密正确;当密钥错误时,无法恢复正确信息。如下表格所示:
【自己动手设计一个简单的加密算法Python】_第4张图片

EPOCH = 8
print(FeistelPlus(b'abcdefghabcdefgh',b"0123456776543210"))
print(DeFeistelPlus(b'UG\xa9\x0c\xb7\xf4b9\xb3\xf0f5\x10<\xc0\xa6',b"1123456776543210"))

2.2 雪崩效应测试

设置明文为’abcdefghabcdefgh’ ,分别设置密钥为’\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00’和’\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00’,测试密钥产生一位变化时对密文的影响。同样设置密钥为’abcdefghabcdefgh’时 ,分别设置明文为’\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00’和’\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00’,测试明文变化一位时对密文的影响。
如表2所示,密钥变化一位时,经过8轮循环后,有58位比特不同;明文变化一位时,经过8轮循环后,有60位比特不同。对与128位的密文来说,有近一半的比特位发生变化,基本满足加密算法的设计要求。
表2 密钥/原文变化对密文的影响(单位/位)
【自己动手设计一个简单的加密算法Python】_第5张图片

def findDifference(A,B):
    def findOneNum(byte):
        S = 0
        for i in range(8):
            S +=(byte>>i)&0x01
        return S
    #print([findOneNum(Abit^Bbit) for Abit,Bbit in zip(A,B)])
    #异或得到不同的位置,并统计数量
    return sum([findOneNum(Abit^Bbit) for Abit,Bbit in zip(A,B)])
#print(findDifference(b'\x01',b'\x80'))


# 雪崩效应测试
# 密钥改变一位
print('密钥改变一位')
key = b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
keyOneBit = b'\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
plaintext = b'abcdefghabcdefgh'
for i in range(1,17):
    global EPOCH 
    EPOCH = i
    num = findDifference(FeistelPlus(plaintext,key),FeistelPlus(plaintext,keyOneBit))
    print("EPOCH = ",i,"时,有",num,"不同")
# 原文改变一位
print('原文改变一位')
plaintext = b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
plainOneBit = b'\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
key = b'abcdefghabcdefgh'
for i in range(1,17):
    global EPOCH 
    EPOCH = i
    num = findDifference(FeistelPlus(plaintext,key),FeistelPlus(plainOneBit,key))
    print("EPOCH = ",i,"时,有",num,"不同")   

2.3 加密时间测试

测试本文所设计的加密算法加密不同字节数所用时间,并与现有的加密算法进行比较。DES、3DES、AES加密算法通过调用Python的pycryptodome库进行实现,由表3可见,本文加密算法的加密时间与现有的加密算法有较大差距,下文四种算法中AES算法计算的最快,加密10Mb数据仅需0.043s,是DES算法的3倍左右,是3DES加密算法的10倍,是本文所提加密方法的280倍,由此可见AES加密算法的优越性。同时本文所提的加密算法在程序实现、加密结构上有很大优化的空间。
【自己动手设计一个简单的加密算法Python】_第6张图片

密码学课程总结

通过对信息安全课程的学习,我了解掌握如下密码学和网络安全的基础知识。
当面全球电子互联互通时代,网络互联安全越来越重要,其中的OSI安全框架由安全攻击(主动/被动)、安全服务、安全机制构成,安全机制中最重要的之一就是密码编码机制。
密码学从经典密码学逐步发展为现代密码学,经典密码学中包括凯撒、单表代换、Playfair等经典的代换密码和置换密码。而现代密码学按照密钥特征的不同可以分为对称密码体制非对称密码体制,按照对明文的加密方式可以分为分组密码流密码(例如RC4算法),大多数分组对称密码都基于Feistel结构,例如DES加密算法。DES其作为上个世界的数据加密标准,但随着目前计算机算力的提升,其56位的密钥空间可能会被暴力破译,故推出了AES加密算法标准取代DES。非对称加密算法在现在应用更加广泛,例如RSA算法。
信息安全中除了考虑加密算法的设计,还需考虑加密的位置(链路加密和端到端加密)、密钥的分配管理方式、随机密钥的产生等问题。

你可能感兴趣的:(python,python)