python实现AES-128#实现加密字符串和加密文件

这篇具有很好参考价值的文章主要介绍了python实现AES-128#实现加密字符串和加密文件。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

综述

这篇文章是对之前的一篇文章的重写和优化AES加密算法基于python实现
脚本语言:Python

已实现的功能

  • 明文和密密钥可以是任意字符:中文,字符,数字或符号。

​ 明文长度任意,密钥的字节数不能超过16字节。默认编码为utf-8所以,密钥最多支持5个中文字符

  • 待加密的数据:可以是字符串,也可以对文本文件进行加密

实验参考:

  • 应用密码学(第三版)P108-P228

算法描述

AES-128

  • 密钥长度:4个字(即128bit,16字节)
  • 分组大小:4个字
  • 轮数:10轮

基本运算

  1. 字节代替SubBytes
  2. 行移位ShiftRows
  3. 列混淆Mixcolumns
  4. 轮密钥加AddRoundKey

加解密流程图

python aes-128,脚本/主题,python,开发语言,矩阵

算法实现

用到了以下python库

import numpy as np 
import argparse
import functools
import operator

主要从下面几个部分展开讲解:

  1. 字节代替SubBytes
  2. 行移位ShiftRows
  3. 列混淆Mixcolumns
  4. 轮密钥加AddRoundKey
  5. 输入预处理(这个也很重要)

字节代替

输入:是一个4x4的矩阵:在这是二维的ndarray数组

输出:输出二维数组

其中S盒是常量

代码

def subBytes(state):
    state=state.reshape(16)
    if FLAG:
        box=S_BOX
    else:
        box=I_SBOX
    for _ in range(16):
        row=(state[_]>>4)&0b1111
        col=state[_]&0b1111
        state[_]=box[row][col]
    return state.reshape(4,4)

代码解释

第2行:先将4x4的二维矩阵变成一维数组进行处理。

第3-6行:根据FLAG判断操作是加密还是解密,然后选取S盒

第7-10行:算法主体

​ 第8行:取高四位作为行号(右移4位然后做逻辑运算)

​ 第9行:取低四位作为列号

​ 第10行:然后查S盒

行移位

移动规则:

对4x4矩阵做如下操作:

加密:

  • 第一行不动
  • 第二行循环左移1字节
  • 第三行循环左移2字节
  • 第四行循环左移3字节

解密

  • 第一行不动
  • 第二行循环右移1字节
  • 第三行循环右移2字节
  • 第四行循环右移3字节

代码:

def shiftrows(state):
    '''-1 if FLAG else 1 如果加密就向左移位,如果解密就向右移位'''
    return np.vstack(
        (
            state[0,:],#第一行不移动
            np.roll(state[1,:],-1 if FLAG else 1),#第2行:循环向左(或向右)移动一个字节
            np.roll(state[2,:],-2 if FLAG else 2),#第3行:循环向左(或向右)移动2个字节
            np.roll(state[3,:],-3 if FLAG else 3),#第4行:循环向左(或向右)移动3个字节
        )
    )

解释:

np.roll(ag1,ag2)方法,ag1是待循环移动的对象,ag2是移动向量,负数向左移,正数向右移

np数组的操作:state[1,:]是取state的第一行

np.vstack():对数组进行竖直方向的拼接。

列混淆

描述

思路来源于书上

列混淆的难点在于G(2^8)域上的乘法运算

1 加法(异或运算):(01110011)+(10010101)=(01110011)⊕(10010101)=(11100110)

2 乘法:res=(x0000010)*(00000010)mod(100011011)(等价于将x0000010左移一位)

  • 当x=1时:

    res=(00000100)⊕(00011011)

  • 当x=0时:

​ res=(00000100)

其中(100000000)mod(100011011)=(00011011)

​ (100011011)为G(2^8)上不可约多项式

思路

所以我们可以将其中一个数拆成2^n次方型相加

例如:(00001110)=(00000010)+(00000100)+(00001000)

这样相乘时就是不断将被乘数左移,根据被乘数的最高位的值运用上面的规则得到相应的值。

0e*47=(00001110)*(01000111)
=[(00000010)⊕(00000100)⊕(00001000)]*(01000111)
=(00000010)*(01000111)⊕(00000100)*(01000111)⊕(00001000)*(01000111)
=(10001110)⊕[(00011100)*(00011011)]⊕(00001000)*(01000111)
=(10001110)⊕(00000111)⊕(00001110)
=(10000111)

代码实现

这部分涉及到了下面五个函数

'''列混淆处理
1、bit_split(): 将十进制数分解成二进制形式表示,如7=(1+10+100)二进制,被gmul调用
2、_gmul(a,b):  特殊的G(2^8)上的乘法运算:第一个参数的值是2的n次方,被gmul调用
3、gmul():  完整的G(2^8)上的乘法运算: 如0e*47=87
4、multi: 列混淆常数矩阵的一行*状态矩阵,返回一维矩阵,被mixcolumns调用
5、mixcolumns():列混淆常数矩阵*状态矩阵
'''
bit_split()

这个函数的主要作用就是将十进制数拆成因数为2的多项式,在做乘法前将乘数进行预处理。返回的是一个多项式的列表

例如:

​ 21=20+22+24

​ =(00000001)+(000000100)+(00010000)

代码

def bit_split(num):
    '''将num分成形如(0b1+0b10+0b100+...),返回一个列表,被gmul调用'''
    li=[]
    arg=[int(i) for i in format(num,'b')][::-1]
    if arg[0]:
        li.append(1)
    base=1
    for offset in arg[1:]:
        base=base<<1
        if offset:
            li.append(base)
    return li

代码解读:

第4行代码:将十进制数num先用format()函数格式化为二进制字符串,然后将每一个bit取出来int()处理,为一个列表。最后将列表反转。(方便后面移位运算判断)

其中x=2

可以看成多项式num=a7x7+a6x6+a5x5+a45x4+a3x3+a2x2+a1x1+a0x0

例如:

​ 19=(10011)2

​ =>[1,0,0,1,1]=>反转=>[1,1,0,0,1]然后进行下一步处理

第5-6行:判断20的系数,为1:列表中要加上(00000001)2

第7-11行:就是拆分过程,这就解释了为啥需要将列表反转了。

​ arg[1]为1:base=2,将base加入li中

​ arg[1]为0:base=2,进行下一次循环。

_gmul(a,b)

这个函数是一个特殊的域上乘法运算:参数a是2的n次方数(形如20,23,25,…)

代码

def _gmul(a,b):
    '''被gmul调用(a为2的n次方)'''
    while a>>1:
        a=a>>1
        x=(b&0b1111111)<<1
        y=(b>>7)*0b11011
        b=x^y
    return b

a每次右移一位,当b的第八位是1时,b左移一位后需要异或(0b11011)。当b第八位为0,b只需左移一位。当a=1时,乘法结束,返回运算后的结果。

gmul()

gmul函数是真正实现G(28)域上乘法。它调用bit_split()和_gmul()函数。

代码

def gmul(a,b):
    '''在G(2^8)上的乘法a*b'''
    a_li=bit_split(a)
    func=functools.partial(_gmul,b=b)
    return functools.reduce(operator.xor,list(map(func,a_li)))

分析

第三行:调用bit_split函数将a拆成2n的多项式。

第四行:将_gmul设置成偏函数,b参数固定。

第五行:涉及两个操作。

  1. 先将拆分后的多项式的每一项与b进行特殊的乘法运算。
  2. 然后将所有的结果进行异或运算,最后返回异或后的结果。
multi()

这个函数是cons乘以4x4的state的每一列

代码

def multi(cons,state):
    '''const每一行 * state 返回一行数据'''
    li=[]
    for _ in range(4):
        li.append(functools.reduce(operator.xor,list(map(gmul,cons,state[:,_]))))
    return li
mixcolumns()

python aes-128,脚本/主题,python,开发语言,矩阵

这是最上层的函数,操作对象是常数矩阵和状态矩阵。都是4x4的。

代码

def mixcolumns(state):
    li=[]
    const_M=MIX_C if FLAG else I_MIXC #常数矩阵的选择
    const_M=np.array(const_M) #转化为np数组
    for _ in range(4):
        li.append(multi(const_M[_,:],state))
    return np.array(li)

根据加密解密操作,选择正确的常数矩阵。

然后常数矩阵的每一行乘以状态矩阵。返回每一行运算后的结果。

最后返回一个4x4的矩阵结果。

密钥扩展

初始密钥是一个4个字(16字节的序列,128比特)。输入密钥直接被复制到扩展密钥的前四个字中,得到w[1],w[2],w[3],w[4];然后每次用4个字填充扩展余下的部分,AES128总共需要44个字。在扩展密钥数组中,w[i]的值依赖于w[i-1]和w[i-4](i>=4)。

对w数组中下标不为4的倍数的元素,只是简单地异或,其逻辑关系为:

w[i]=w[i-1] ⊕ w[i-4] (i不为4的倍数)

对w数组下标为4的倍数的元素,采用如下计算方法:

(1)RotWord(),将输入的4个字节循环左移一个字节。expandkey()函数的第12行实现

(2)subword(),基于S盒对输入字中的每个字节进行S代替,subword()函数实现。

(3)将步骤2的结果再和轮常量Rcon[i//4]相异或。

(4)将步骤3的结果与w[i-4]异或。

密钥扩展这块当时搞错了,排查了很久

temp=w[i-1][:]#深拷贝

我一开始写成了temp=w[i-1],这样导致我后面修改temp的值的时候,实际是修改的w里面的数据

算法实现

我分成了两个函数进行实现

subword()
expandkey()

subword就是一个字节替换函数和加密操作的字节替代的操作一样

代码

def subword(temp: list):
    li=[]
    for i in temp:
        col=i&0b1111
        row=i>>4
        li.append(S_BOX[row][col])
    return li

expandkey

代码

def expandkey(key: bytes):
    '''密钥扩展:初始密钥为16字节'''
    key=[i for i in key]#把字节读成列表
    w=[]
    i=0
    while i<4:
        w.append([key[4*i],key[4*i+1],key[4*i+2],key[4*i+3]])
        i+=1
    while i<44:
        temp=w[i-1][:]#深拷贝
        if i%4==0:
            temp.append(temp.pop(0))#循环左移一个字节
            temp=subword(temp)#字节替换
            temp=list(map(operator.xor,temp,RCon[i//4 -1]))#与轮常量异或
        w.append(list(map(operator.xor,w[i-4],temp)))#与w[i-1]异或
        i=i+1
    return np.array(w).transpose()

expandkey函数最后得到的是一个4x44的矩阵。

轮秘钥加

python aes-128,脚本/主题,python,开发语言,矩阵

代码

def addroundkey(state,key):
    '''state和key都是4x4的np数组'''
    li=[]
    for _ in range(4):
        li.append(list(map(operator.xor,state[:,_],key[:,_])))
    return np.array(li).transpose() #需要进行转置

预处理

预处理这块针对的是明文和密钥

1 初始化

根据调用脚本,传入的参数进行加密或解密之前的初始化

位置参数:

  • t:数据类型:string字符串,file文件
  • message:待处理的数据
  • key:密钥

可选参数

  • flag指定操作: True为加密,False为解密,默认加密。解密时,需要加上–flag参数

  • encoding:指定编码,默认为utf-8(主要是处理非ascii字符)

2 补位

明文长度不是16的倍数

​ 需要算出明文长度,当最后一个分组缺少对少个字节就补上空白字符,且补的最后一个字节表示的是补的字节的个数

注意的是,当明文长度刚好是16的倍数时,依然要补位,补上16字节的数据。最后一个字节表示补数据的个数。

​ 对于最后一个字节的处理:补充字节数+65=对应的ascii字符。最后解密的时候需要删掉补充的字符。

代码

def group_handle(b_m):
    '''将原明文或密文进行分组,然后加解密'''
    b_size=len(b_m)//16
    li=[]
    group=[]
    for i in range(b_size):
        li.append(b_m[i*16:i*16+16])
    for i in li:
        state=bytes2matri(i)
        group.append(process(state,key))
    return group

密钥长度小于16字节

​ 密钥长度小于16字节时,补上空白字符,补充后,密钥长度为16字节

代码

def handlekey(key:str,encoding='utf-8')->bytes:
    '''对key进行预处理,转化为bytes
    key超过16字节,报错,不足16字节末尾补零
    '''
    size=len(key.encode(encoding))
    if size>16:
        print('密钥不符合要求,长度超过16字节')
        exit()
    key=key+' '*(16-size)
    return key.encode(encoding)  

3 输入数据

当输入的数据是字符串时

​ 当输入的数据是字符串时,字符集默认是utf-8,如果不是,需要在运行脚本的时候加上–encoding参数指定编码

当输入的数据是文本文件时

​ 为文本文件时,我们需要以指定字符集打开文件,读取到字符串,然后进行加密之前的预处理。分组补位。

加密后的数据保存在cipher.txt文件中。

解密的数据保存在plain.txt中

加密

加密解密一个分组的实现都写在了一个函数中

def process(state,key):
    '''单个分组加解密处理'''
    if FLAG:
        state=addroundkey(state,key[:,0:4])
        for i in range(1,10):#前9轮
            state=subBytes(state)
            state=shiftrows(state)
            state=mixcolumns(state)
            state=addroundkey(state,key[:,i*4:i*4+4])
        #第10轮
        state=subBytes(state)
        state=shiftrows(state)
        state=addroundkey(state,key[:,40:])
    else:
        state=addroundkey(state,key[:,40:])
        for i in range(10,1,-1):
            state=shiftrows(state)
            state=subBytes(state)
            state=addroundkey(state,key[:,4*i-4:4*i])
            state=mixcolumns(state)
            
        #第10轮
        state=shiftrows(state)
        state=subBytes(state)
        state=addroundkey(state,key[:,0:4])
    return matri2bytes(state).hex()

解密输入代码

def encrypt(message,encoding='utf-8'):
    '''明文加密'''
    size=len(message.encode(encoding))
    rem=size%16
    if rem==0:
        message=message+' '*15+chr(65+16)
    else:#chr(65+16-rem),将补充数表示为ascii字符,占一个字节
        message=message+' '*(16-1-rem)+chr(65+16-rem)
    #现在的message字节数为16的整数倍
    b_m=message.encode(encoding)
    cipher=group_handle(b_m)
    return  functools.reduce(operator.add,cipher)

解密

解密输入数据代码

def decrypt(message,encoding='utf-8'):
    '''密文解密'''
    b_m=bytes.fromhex(message)
    m=group_handle(b_m)
    m=bytes.fromhex(functools.reduce(operator.add,m))
    num=m[-1]-65 #之前加上了65,现在减掉65后得到补充的0的个数
    return m[:len(m)-num].decode(encoding)

功能测试

使用方法

AES> python AES.py -h
usage: AES [-h] [--flag] [--encoding ENCODING] {string,file} message key

positional arguments:
  {string,file}        输入数据的类型:文件或字符串}
  message              待加密或解密的字符串或文件
  key                  密钥:length<=16 bytes

optional arguments:
  -h, --help           show this help message and exit
  --flag               要进行的操作: 默认加密,带上--flag为解密
  --encoding ENCODING  文本字符集指定,默认UTF-8

加解密字符串

python aes-128,脚本/主题,python,开发语言,矩阵

加解密文件

python aes-128,脚本/主题,python,开发语言,矩阵

算法评价

对于AES-128算法,当攻击者获得一轮密钥是,如果想猜测下一轮密钥是,不仅需要获得本轮密钥,还需要假定前一轮的四个轮密钥字,每个轮密钥字都是32位,这样便需要2128次猜测,其时间复杂度已经与穷尽密钥强力攻击相当。同样的道理,如果想通过一轮获得密钥向前推算,也需要对后一轮密钥的猜测,其时间复杂度是2128。所以一轮密钥的获取对于破解出初始密钥没有任何帮助,其破解强度一样等同于穷举密钥强力攻击。以此,Square攻击,能量攻击方法对AES算法的威胁,产生了有效的消减作用,使其不能通过对一轮子密钥的猜测成功二顺利推测出前后轮密钥,甚至是初始密钥。

AES算法优点:

  1. 运算速度快。
  2. 对内存的需求非常低,适合于受限环境。
  3. 分组长度和密钥长度设计灵活。
  4. AES标准支持可变分组长度,分组长度可设定为32比特的任意倍数,最小值为128比特,最大值为256比特。
  5. AES的密钥长度比DES大,它也可设定为32比特的任意倍数,最小值为128比特,最大值为256比特,所以用穷举法是不可能破解的。
  6. 很好的抵抗差分密码分析及线性密码分析的能力。

AES算法缺点:

目前尚未存在对AES 算法完整版的成功攻击,但已经提出对其简化算法的攻击。

源代码

两个文件
静态数据boxdata.py在AES.py中导入
脚本文件AES.py文章来源地址https://www.toymoban.com/news/detail-532095.html

AES.py文件

from boxdata import * #s盒等数据
import numpy as np #方便操作字节数组
import argparse
import functools
import operator


#功能函数
def subBytes(state):
    '''
    字节替换函数,参数是np数组
    根据FLAG字段决定是加密还是解密
    '''
    state=state.reshape(16)
    if FLAG:
        box=S_BOX
    else:
        box=I_SBOX
    for _ in range(16):
        row=(state[_]>>4)&0b1111
        col=state[_]&0b1111
        state[_]=box[row][col]
    return state.reshape(4,4)

def shiftrows(state):
    '''-1 if FLAG else 1 如果加密就向左移位,如果解密就向右移位'''
    return np.vstack(
        (
            state[0,:],#第一行不移动
            np.roll(state[1,:],-1 if FLAG else 1),#第2行:循环向左(或向右)移动一个字节
            np.roll(state[2,:],-2 if FLAG else 2),#第3行:循环向左(或向右)移动2个字节
            np.roll(state[3,:],-3 if FLAG else 3),#第4行:循环向左(或向右)移动3个字节
        )
    )

'''列混淆处理
1、bit_split(): 将十进制数分解成二进制形式表示,如7=(1+10+100)二进制,被gmul调用
2、_gmul(a,b):  特殊的G(2^8)上的乘法运算:第一个参数的值是2的n次方,被gmul调用
3、gmul():  完整的G(2^8)上的乘法运算: 如0e*47=87
4、multi: 列混淆常数矩阵的一行*状态矩阵,返回一维矩阵,被mixcolumns调用
5、mixcolumns():列混淆常数矩阵*状态矩阵
'''
def bit_split(num):
    '''将num分成形如(0b1+0b10+0b100+...),返回一个列表,被gmul调用'''
    li=[]
    arg=[int(i) for i in format(num,'b')][::-1]
    if arg[0]:
        li.append(1)
    base=1
    for offset in arg[1:]:
        base=base<<1
        if offset:
            li.append(base)
    return li
def _gmul(a,b):
    '''被gmul调用(a为2的n次方)'''
    while a>>1:
        a=a>>1
        x=(b&0b1111111)<<1
        y=(b>>7)*0b11011
        b=x^y
    return b
def gmul(a,b):
    '''在G(2^8)上的乘法a*b'''
    a_li=bit_split(a)
    func=functools.partial(_gmul,b=b)
    return functools.reduce(operator.xor,list(map(func,a_li)))
def multi(cons,state):
    '''const每一行 * state 返回一行数据'''
    li=[]
    for _ in range(4):
        li.append(functools.reduce(operator.xor,list(map(gmul,cons,state[:,_]))))
    return li
def mixcolumns(state):
    '''
    域上乘法,调用gmul()
    '''
    li=[]
    const_M=MIX_C if FLAG else I_MIXC #常数矩阵的选择
    const_M=np.array(const_M) #转化为np数组
    for _ in range(4):
        li.append(multi(const_M[_,:],state))
    return np.array(li)


def addroundkey(state,key):
    '''state和key都是4x4的np数组'''
    li=[]
    for _ in range(4):
        li.append(list(map(operator.xor,state[:,_],key[:,_])))
    return np.array(li).transpose() #需要进行转置
    

#输入处理以及密钥扩展
def subword(temp: list):
    li=[]
    for i in temp:
        col=i&0b1111
        row=i>>4
        li.append(S_BOX[row][col])
    return li

def expandkey(key: bytes):
    '''密钥扩展:初始密钥为16字节'''
    key=[i for i in key]#把字节读成列表
    w=[]
    i=0
    while i<4:
        w.append([key[4*i],key[4*i+1],key[4*i+2],key[4*i+3]])
        i+=1
    while i<44:
        temp=w[i-1][:]#深拷贝
        if i%4==0:
            temp.append(temp.pop(0))#循环左移一个字节
            temp=subword(temp)#字节替换
            temp=list(map(operator.xor,temp,RCon[i//4 -1]))#与轮常量异或
        w.append(list(map(operator.xor,w[i-4],temp)))#与w[i-1]异或
        i=i+1
    return np.array(w).transpose()
#--------------------------------------------------------------
def matri2bytes(matrix)->bytes:
    '''将4x4状态矩阵转换为字节序列'''
    li=list(matrix.transpose().reshape(16))
    li=list(map(lambda x: format(x,'02x'),li))
    li=''.join(li)
    return bytes.fromhex(li)

def process(state,key):
    '''单个分组加解密处理'''
    if FLAG:
        state=addroundkey(state,key[:,0:4])
        for i in range(1,10):#前9轮
            state=subBytes(state)
            state=shiftrows(state)
            state=mixcolumns(state)
            state=addroundkey(state,key[:,i*4:i*4+4])
        #第10轮
        state=subBytes(state)
        state=shiftrows(state)
        state=addroundkey(state,key[:,40:])
    else:
        state=addroundkey(state,key[:,40:])
        for i in range(10,1,-1):
            state=shiftrows(state)
            state=subBytes(state)
            state=addroundkey(state,key[:,4*i-4:4*i])
            state=mixcolumns(state)
            
        #第10轮
        state=shiftrows(state)
        state=subBytes(state)
        state=addroundkey(state,key[:,0:4])
    return matri2bytes(state).hex()


def handlekey(key:str,encoding='utf-8')->bytes:
    '''对key进行预处理,转化为bytes
    key超过16字节,报错,不足16字节末尾补零
    '''
    size=len(key.encode(encoding))
    if size>16:
        print('密钥不符合要求,长度超过16字节')
        exit()
    key=key+' '*(16-size)
    return key.encode(encoding)   
def setargs():    
    parser=argparse.ArgumentParser(prog='AES',prefix_chars='-',epilog=None,add_help=True)
    parser.add_argument('Type',type=str,choices=['string','file'],help='输入数据的类型:文件或字符串}')
    parser.add_argument('message',type=str,help="待加密或解密的字符串或文件")
    parser.add_argument('key',type=str,help='密钥:length<=16 bytes')
    parser.add_argument('--flag',action='store_false',help="要进行的操作: 默认加密,带上--flag为解密")
    parser.add_argument('--encoding',type=str,default='utf-8',help='文本字符集指定,默认gbk')
    return parser.parse_args()

def bytes2matri(by):
    '''将字节序列转化为4x4矩阵'''
    t=[x for x in by]
    return np.array(t).reshape(4,4).transpose()
def group_handle(b_m):
    '''将原明文或密文进行分组,然后加解密'''
    b_size=len(b_m)//16
    li=[]
    group=[]
    for i in range(b_size):
        li.append(b_m[i*16:i*16+16])
    for i in li:
        state=bytes2matri(i)
        group.append(process(state,key))
    return group

def encrypt(message,key,encoding='utf-8'):
    '''明文加密'''
    size=len(message.encode(encoding))
    rem=size%16
    if rem==0:
        message=message+' '*15+chr(65+16)
    else:#chr(65+16-rem),将补充数表示为ascii字符,占一个字节
        message=message+' '*(16-1-rem)+chr(65+16-rem)
    #现在的message字节数为16的整数倍
    b_m=message.encode(encoding)
    cipher=group_handle(b_m)
    return  functools.reduce(operator.add,cipher)

def decrypt(message,key,encoding='utf-8'):
    '''密文解密'''
    b_m=bytes.fromhex(message)
    m=group_handle(b_m)
    m=bytes.fromhex(functools.reduce(operator.add,m))
    num=m[-1]-65 #之前加上了65,现在减掉65后得到补充的0的个数
    return m[:len(m)-num].decode(encoding)


if __name__=='__main__':
    args=setargs()
    
    FLAG=args.flag
    encode=args.encoding
    key=expandkey(handlekey(args.key,encode))
    #判断加解密:
    if FLAG:
        if args.Type=='file':
            with open(args.message,'r',encoding=encode) as f:
                message=f.read()
            cipher=encrypt(message,key,encode)
            with open('cipher.txt','w',encoding=encode) as fi:
                fi.write(cipher)
            print('生成密文文件,cipher.txt')
        else:
            message=args.message
            cipher=encrypt(message,key,encode)
            print()
            print("+"*15,'密文',"+"*15)
            print(cipher)
    else:
        if args.Type=='file':
            with open(args.message,'r',encoding=encode) as f:
                message=f.read()
            plain=decrypt(message,key,encode)
            with open('plain.txt','w',encoding=encode) as fi:
                fi.write(plain)
            print('生成明文文件,plain.txt')
        else:
            message=args.message
            plain=decrypt(message,key,encode)
            print()
            print("+"*15,'明文',"+"*15)
            print(plain)

boxdata.py

#列混淆常数矩阵
MIX_C  = [[0x2, 0x3, 0x1, 0x1], [0x1, 0x2, 0x3, 0x1], [0x1, 0x1, 0x2, 0x3], [0x3, 0x1, 0x1, 0x2]]
#逆列混淆矩阵
I_MIXC = [[0xe, 0xb, 0xd, 0x9], [0x9, 0xe, 0xb, 0xd], [0xd, 0x9, 0xe, 0xb], [0xb, 0xd, 0x9, 0xe]]
RCon   = [[0x01,0x00,0x00,0x00], 
       [0x02,0x00,0x00,0x00], 
       [0x04,0x00,0x00,0x00],
       [0x08,0x00,0x00,0x00], 
       [0x10,0x00,0x00,0x00], 
       [0x20,0x00,0x00,0x00], 
       [0x40,0x00,0x00,0x00], 
       [0x80,0x00,0x00,0x00], 
       [0x1B,0x00,0x00,0x00], 
       [0x36,0x00,0x00,0x00]
       ]
#S盒子
S_BOX = [[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]]
#逆S盒
I_SBOX = [[0x52, 0x09, 0x6A, 0xD5, 0x30, 0x36, 0xA5, 0x38, 0xBF, 0x40, 0xA3, 0x9E, 0x81, 0xF3, 0xD7, 0xFB],
       [0x7C, 0xE3, 0x39, 0x82, 0x9B, 0x2F, 0xFF, 0x87, 0x34, 0x8E, 0x43, 0x44, 0xC4, 0xDE, 0xE9, 0xCB],
       [0x54, 0x7B, 0x94, 0x32, 0xA6, 0xC2, 0x23, 0x3D, 0xEE, 0x4C, 0x95, 0x0B, 0x42, 0xFA, 0xC3, 0x4E],
       [0x08, 0x2E, 0xA1, 0x66, 0x28, 0xD9, 0x24, 0xB2, 0x76, 0x5B, 0xA2, 0x49, 0x6D, 0x8B, 0xD1, 0x25],
       [0x72, 0xF8, 0xF6, 0x64, 0x86, 0x68, 0x98, 0x16, 0xD4, 0xA4, 0x5C, 0xCC, 0x5D, 0x65, 0xB6, 0x92],
       [0x6C, 0x70, 0x48, 0x50, 0xFD, 0xED, 0xB9, 0xDA, 0x5E, 0x15, 0x46, 0x57, 0xA7, 0x8D, 0x9D, 0x84],
       [0x90, 0xD8, 0xAB, 0x00, 0x8C, 0xBC, 0xD3, 0x0A, 0xF7, 0xE4, 0x58, 0x05, 0xB8, 0xB3, 0x45, 0x06],
       [0xD0, 0x2C, 0x1E, 0x8F, 0xCA, 0x3F, 0x0F, 0x02, 0xC1, 0xAF, 0xBD, 0x03, 0x01, 0x13, 0x8A, 0x6B],
       [0x3A, 0x91, 0x11, 0x41, 0x4F, 0x67, 0xDC, 0xEA, 0x97, 0xF2, 0xCF, 0xCE, 0xF0, 0xB4, 0xE6, 0x73],
       [0x96, 0xAC, 0x74, 0x22, 0xE7, 0xAD, 0x35, 0x85, 0xE2, 0xF9, 0x37, 0xE8, 0x1C, 0x75, 0xDF, 0x6E],
       [0x47, 0xF1, 0x1A, 0x71, 0x1D, 0x29, 0xC5, 0x89, 0x6F, 0xB7, 0x62, 0x0E, 0xAA, 0x18, 0xBE, 0x1B],
       [0xFC, 0x56, 0x3E, 0x4B, 0xC6, 0xD2, 0x79, 0x20, 0x9A, 0xDB, 0xC0, 0xFE, 0x78, 0xCD, 0x5A, 0xF4],
       [0x1F, 0xDD, 0xA8, 0x33, 0x88, 0x07, 0xC7, 0x31, 0xB1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xEC, 0x5F],
       [0x60, 0x51, 0x7F, 0xA9, 0x19, 0xB5, 0x4A, 0x0D, 0x2D, 0xE5, 0x7A, 0x9F, 0x93, 0xC9, 0x9C, 0xEF],
       [0xA0, 0xE0, 0x3B, 0x4D, 0xAE, 0x2A, 0xF5, 0xB0, 0xC8, 0xEB, 0xBB, 0x3C, 0x83, 0x53, 0x99, 0x61],
       [0x17, 0x2B, 0x04, 0x7E, 0xBA, 0x77, 0xD6, 0x26, 0xE1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0C, 0x7D]]


到了这里,关于python实现AES-128#实现加密字符串和加密文件的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • Java实现字符串加密与解密

    我们在设计登录程序时需要用到保存用户名和密码的功能,如果是直接写入到txt文件中保存很容易被木马程序识破,所以就必须先对密码加密,只留存密文。 今天介绍的是使用 十六进 制转换的方式加密数据。 得到结果: 757376662d312d6d7064626d697074752d323534342d717974646b 现在我们将

    2024年02月11日
    浏览(51)
  • python加密字符串安全保护你的数据

    Python加密字符串可以使用标准库中的hashlib模块,该模块提供了常见的摘要算法,如MD5,SHA1等。下面是一个示例代码: Python加密字符串可以使用标准库中的hashlib模块,该模块提供了常见的摘要算法,如MD5,SHA1等。下面是一个示例代码: 运行结果:

    2024年02月07日
    浏览(58)
  • 【Python】【完整代码】秀!巧用Python实现对单个文件或多个文件中的指定字符串进行批量修改/替换(超详细)

    目录 1. 对单份文件 1.1 将替换后的内容保存到新文件中 1.2 直接替换当前文件中的字符

    2024年02月21日
    浏览(54)
  • [虚幻引擎] UE DTBase64 插件说明 使用蓝图对字符串或文件进行Base64加密解密

    本插件可以在虚幻引擎中使用蓝图对字符串,字节数组,文件进行Base64的加密和解密。 目录 1. 节点说明 String To Base64 Base64 To String Binary To Base64 Base64 To Binary File To Base64 Base64 To File 2. 案例演示 3. 插件下载 String To Base64 对字符串进行Base64加密,字符串会自动转换成UTF8的格式,这

    2024年02月13日
    浏览(82)
  • python提取文件中特定字符串

    目录 1. Python3文件操作 1.1 打开和关闭文件 1.1.1 open( ) 函数 1.1.2 close( ) 函数 1.2  读写文件 1.2.1 write( ) 函数 1.2.2 read( ) 函数 2. 提取文件中特定字符串 代码如下(示例): 1.1.1 open( ) 函数 1.1.2 close( ) 函数   注意: 使用 open() 方法一定要保证关闭文件对象,即调用 close(

    2024年02月04日
    浏览(64)
  • 字符串压缩加密算法(可逆)

    业务场景:App下单后的订单,需要在另一个内部系统中进行扫码打印。两个程序包括服务器之间网络不互通,所以想到了通过二维码携带内容做数据交互,但是将内容转为base64后发现字符串太长,放入二维码后二维码密度相当大,几乎无法被扫描,所以就想到了给字符串进行

    2024年02月11日
    浏览(49)
  • 华为OD-字符串加密

    有一种技巧可以对数据进行加密,它使用一个单词作为它的密匙。下面是它的工作原理:首先,选择一个单词作为密匙,如TRAILBLAZERS。如果单词中包含有重复的字母,只保留第1个,将所得结果作为新字母表开头,并将新建立的字母表中未出现的字母按照正常字母表顺序加入新

    2024年02月11日
    浏览(51)
  • 摩尔斯电码加密字符串

    摩尔斯电码滴答“.-”,加密字符串。   (本笔记适合熟悉循环和列表的 coder 翻阅) 【学习的细节是欢悦的历程】 Python 官网 :https://www.python.org/ Free :大咖免费“ 圣经 ”教程《 python 完全自学教程 》,不仅仅是基础那么简单…… 地址:https://lqpybook.readthedocs.io/   自学并

    2024年02月06日
    浏览(53)
  • 华为OD真题--字符串加密

    2023华为OD统一考试(A+B卷)题库清单-带答案(持续更新)or2023年华为OD真题机考题库大全-带答案(持续更新) \\\"给你一串未加密的字符串str,通过对字符串的每一个字母进行改变来实现加密,加密方式是在每一个字母str[i]偏移特定数组元素a[i]的量, 数组a前三位已经赋值:

    2024年02月13日
    浏览(46)
  • Android StringFog 字符串自动加密

    一、StringFog 作用 一款自动对dex/aar/jar文件中的字符串进行加密Android插件工具,正如名字所言,给字符串加上一层雾霭,使人难以窥视其真面目。可以用于增加反编译难度,防止字符串代码重复。 支持java/kotlin。 支持app打包生成的apk加密。 支持aar和jar等库文件加密。 支持加

    2024年02月02日
    浏览(43)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包