仿射密码原理

文章详细介绍了仿射密码的加密和解密原理,通过一个Python代码示例展示了如何使用该密码系统。在给定的加密代码中,通过对已知明文和密文的分析,求得了加密参数a和b,从而成功解密出密文。解密过程中运用了gmpy2库来计算乘法逆元。
摘要由CSDN通过智能技术生成

仿射密码原理

讲解

在下面这道例题中,会通过题目直接告诉你仿射密码是怎么用的

  1. 首先会通过分析题目给出的源码去知道,这道题目采用了仿射密码的加密方式
  2. 然后通过已知的部分明文和全部密文去推出仿射密码的解题关键,元素a和b
  3. 最后用a和b直接调用仿射密码的解密公式

加密解密公式

加密

E(x)=(ax+b)(modm)

  • m表示编码系统的字母个数
  • x表示明文按照某种编码得到的数字
  • ab就是仿射密码的核心
解密

D(x)=a^-1(x−b)(mod m)

  • a^-1 是a的乘法逆元

例题

题目代码:
import sys
key = '****CENSORED***************'     #表明有一个密钥
flag = 'TWCTF{*******CENSORED********}'    #这是我们需要获取的flag

# 下面整个都是在告诉我们,这道题目在加密,我们需要通过分析代码,去判断他采用了什么加密方法,需要怎么去解密
#如果长度是奇数 则表示密钥错误
if len(key) % 2 == 1:                          
    print("Key Length Error")
    sys.exit(1)

#在密码是偶数的情况下 去加密
n = len(key) / 2
encrypted = ''

#对flag中的每一个字母进行操作,相当于对flag的每一个明文进行加密
for c in flag:
    c = ord(c)    #取该字母的ascii码值
    for a, b in zip(key[0:n], key[n:2*n]):
        #相当于进行n次这样的循环 
        #不要把zip想象成压缩,仅仅只是一个简单的合并打包过程
        #在key[0:n]取第一个给到a  在key[n:2*n]取也取第一个给到b
        c = (ord(a) * c + ord(b)) % 251   #把c进行加密
        #解释一下为什么要模251
        #因为加密对应要放到整数的范围中,ascii码表0~255 但是选一个质数更安全,既要大且要质数 所以2
        #最终选择了251
        #解释一下为什么能确定这是一个仿射密码
        #因为c1 = a1*c + b1
        #   c2 = a2 * c1 + b2
        #      = (a1 * a2)*c + a2*b1 + b2
        #  即为 k*c + d  的形式,并且有一个打包集合key始终保持不变  故判定为仿射密码
        
    encrypted += '%02x' % c    
    #这里'%02x'的意思是指去创建一个2位宽的16进制空字符串
    #  %c的意思不是对c取模 ,而是把c转换后放入到%02x的位置中去

print (encrypted)
# "805eed80cbbccb94c36413275780ec94a857dfec8da8ca94a8c313a8ccf9"
构建解密脚本思路解析
  • 涉及语句内容具体详解在后面的解密代码中
  1. 首先需要把上面加密最靠近输出层的那个加密给破解,即

    encrypted += '%02x' % c    
    

    所以要先把密文两个两个的读取转换成16进制,即

    encrypted = [int(data[i:i + 2], 16) for i in range(0, len(data), 2)]  
    
  2. 然后根据下列语句推断出是仿射密码:

    c = (ord(a) * c + ord(b)) % 251  
    

​ 所以确定目标,求解密中的a和b:

plaindelta = ord(flag[1]) - ord(flag[0])         #提取部分已知明文
cipherdalte = encrypted[1] - encrypted[0]        #提取已知密文
a = gmpy2.invert(plaindelta, 251) * cipherdalte % 251   #数据全部放在0~251之间
b = (encrypted[0] - a * ord(flag[0])) % 251        #数据全部放在0~251之间
  1. 根据a和b,带入到仿射密码的解密公式中,即

    a_inv = gmpy2.invert(a, 251)
    result += chr((c - b) * a_inv % 251)   #c是在encrypted列表中的每一个字符密文
    
解密代码
import gmpy2

#key = '****CENSORED***************'    #密钥 censored 被遮盖
flag = 'TWCTF{*******CENSORED********}'    #部分明文

data = "805eed80cbbccb94c36413275780ec94a857dfec8da8ca94a8c313a8ccf9"   #密文待解密

encrypted = [int(data[i:i + 2], 16) for i in range(0, len(data), 2)]   
#对密文进行操作
# range(0,len(cip),2):生成一个从 0 开始、以 2 为步长、不超过 data 长度的整数序列。这个序列中的每一个整数 i,都是 data 中两个字符的起始位置。

# data[i:i+2]:对于这个序列中的每一个整数 i,取 data 中从 i 开始、长度为 2 的子串。这样就可以把 data 中的所有字符两两分组。

# int(data[i:i+2],16):对于这个子串,使用 int 函数将其转换为一个 16 进制的整数。

# for i in range(0,len(data),2):将上述操作应用到 range 函数生成的整数序列中的每一个整数 i,得到一个整数列表。

# 最终的结果就是 encrypted 列表,它包含了 data 中所有字符两两分组后转换成的 16 进制整数。例如,如果 data 是字符串 "805eed80cbbccb94c36413275780ec94a857dfec8da8ca94a8c313a8ccf9",则 encrypted 是一个整数列表,它的值为 [128, 94, 237, 128, 203, 188, 185, 76, 195, 100, 19, 39, 87, 128, 236, 148, 168, 87, 223, 236, 141, 168, 202, 148, 168, 195, 19, 168, 204, 249]。


#去计算密钥key
plaindelta = ord(flag[1]) - ord(flag[0])         #提取部分已知明文
cipherdalte = encrypted[1] - encrypted[0]        #提取已知密文

#原来的加密公式
#y1 = (a * x1 + b) (mod 26)
#y2 = (a * x2 + b) (mod 26)
#故有
#y1 - y2 = a*(x1-x2)(mod 251) 

#想要求a  
#即为
#plaindelta = x1-x2
#cipherdalta = y1-y2
#cipherdalte = a * plaindelta(mod 251)    !!取模只是让最后的结果在0~251范围之间!!
#计算公式中的a,引入初等数论里面的内容
#ci = a * p % 251
#ci / p = a % 251
#在初等数论中 除相当于乘逆元
#故 ci * invert(p,251)= a (% 251) 
#所以%251只是一个对于整体结果的一个限制,在公式推到的时候可以忽略存在

a = gmpy2.invert(plaindelta, 251) * cipherdalte % 251   #数据全部放在0~251之间
#通过a计算b
b = (encrypted[0] - a * ord(flag[0])) % 251     #数据全部放在0~251之间

a_inv = gmpy2.invert(a, 251)
result = ""
for c in encrypted:
    result += chr((c - b) * a_inv % 251)
print(result)

我是哈皮,祝您每天嗨皮,我们下期再见!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值