仿射密码定义原理:
仿射密码为单表加密的一种,字母系统中所有字母都借一简单数学方程加密,对应至数值,或转回字母。 其仍有所有替代密码之弱处。所有字母皆借由方程加密,b为移动大小。
在仿射加密中,大小为m之字母系统首先对应至0…m-1范围内之数值, 接着使用模数算数来将原文件中之字母转换为对应加密文件中的数字。 单一字母的加密函数为:
取余m为字母系统大小且a和b为密码关键值。a之值必须使得a与m互质。
解密方程为
举例说明:代换密码算法的原理是使用替代法进行加密,就是将明文中的字符用其它字符替代后形成密文。例如,明文字母a、b、c、d,用D、E、F、G做对应替换后形成密文。
代换密码包括多种类型,如单表代换密码、多表代换密码等。下面介绍一种典型的单表代换密码——仿射密码。它的加密、解密过程可以表示为下面的函数:
仿射加密要求gcd(k1,26)=1,否则就褪化为 y=f(k)=k2(mod 26)。
故密钥空间大小为: (k1,k2)=12x26=312
例如:密钥k=(7,3),7-1(mod 26)=15
加密函数: y=f(x)=7x+3(mod 26)
解密函数: x=f^(-1)(y)=15(y-3)(mod 26)=15y-9(mod 26)
设明文:China,首先转换为数字:2,7,8,13,0
原始消息“China”得到恢复
1、实验目的:
通过编程实现代换密码算法——仿射密码和简单置换密码算法,加深对古典密码体制的了解,为深入学习密码学奠定基础。
2、实验内容:
根据仿射密码的实现原理,实现利用仿射密码进行加密和解密的程序。
(1)设计加密程序:能够根据用户输入明文的内容产生加密的密文并输出。
(2)设计解密程序:能够对输入的密文内容破解并输出得到其对应的明文。
# -*- coding: UTF-8 -*-
import math
"""
仿射密码加密解密模块
@author WQ
@time 2020/11/18
"""
class Affine():
"""
仿射密码
Encrypt:加密方法
Decrypt:解密方法
letters:字母数字对应字典
"""
def __init__(self):
self.ciphertext='' #加密后的密文
self.plaintext='' #解密后的明文
self.reverse=0 #秘钥a的逆元
self.list_keya=[3,5,7,9,11,15,17,19,21,23,25] #秘钥a可能取值
self.letters = {
'a': 0, 'b': 1, 'c': 2, 'd': 3, 'e': 4, 'f': 5, 'g':6, 'h': 7,
'i': 8, 'j': 9, 'k': 10, 'l': 11, 'm': 12, 'n': 13, 'o': 14,
'p': 15, 'q': 16, 'r': 17, 's': 18, 't': 19, 'u': 20,
'v': 21, 'w': 22, 'x': 23, 'y': 24, 'z': 25}
def gcd(self,a,b=26):
if(a<b):
return self.gcd(b,a)
while(a%b!=0):
temp = b
b = a%b
a = temp
return b
def Encrypt(self,a=0,b=0,input=""):
"""
对输入的字符串进行加密
加密算法:c=Ea,b(m)=am+b(mod26) m是单个明文字母
args={
a,b:秘钥
input:用于加密的明文
}
"""
if(self.gcd(a)!=1):
print("秘钥a错误,应与26互质,请重输!")
exit(0)
if(b>=26):
print("秘钥b错误[0~26],请重输!")
exit(0)
input=input.lower()
digitals=[]
#加密转化成密文对应数字
for i in input:
for j in self.letters:
if(i==j):
d=(a*self.letters[i]+b)%26
digitals.append(d)
#将对应数字转化对应密文字母
for i in digitals:
for j in self.letters:
if(i==self.letters[j]):
self.ciphertext=self.ciphertext+j
def Decrypt(self, a, b, input=""):
"""
对输入的字符串进行解密
解密算法:m=Da,b(m)=a(-1)(c-b)(mod26) c是单个密文字母
args={
a(-1):秘钥a的逆元
b:秘钥
input:用于解密的秘文
}
"""
if(self.gcd(a)!=1):
print("秘钥a错误,应与26互质,请重输!")
exit(0)
if(b>=26):
print("秘钥b错误[0~26],请重输!")
exit(0)
digitals=[]
self.reverse=self.Inverse(a) #求逆元
for i in input:#解密 密文转化成对应数字
for j in self.letters:
if(i==j):
digitals.append(self.letters[j])
#解密
for i in digitals:
t=(self.reverse*(i-b))%26
for j in self.letters:
if(t==self.letters[j]):
self.plaintext=self.plaintext+j
def BruteForce(self, input=''):
#暴力破解仿射密码
digitals=[]
plaintext=''
for i in input: #解密 密文转化成对应数字
for j in self.letters:
if(i==j):
digitals.append(self.letters[j])
for keya in self.list_keya:
a=self.Inverse(keya)
for keyb in range(0,26):
for i in digitals:
t=(keya*(i-keyb))%26
for j in self.letters:
if(t==self.letters[j]):
plaintext=plaintext+j
break
print(plaintext)
plaintext=''
def Inverse(self, a,mod=26):
#求秘钥a的逆元 欧几里得算法
x1,x2,x3 = 1,0,mod
y1,y2,y3 = 0,1,a
while(1):
if(y3==0):
g=x3
break
if(y3==1):
g=y3
break
q=math.floor(x3/y3)#向下取整
t1,t2,t3=x1-q*y1,x2-q*y2,x3-q*y3
x1,x2,x3=y1,y2,y3
y1,y2,y3=t1,t2,t3
return y2 #逆元求得为y2,y3为gcd(a,26),最大公因数
if __name__ == "__main__":
test=Affine()
#a=test.Inverse(615647919867658945209035999713482421889581801898774401730949,691310408299283134015133178155232316338199895735303344369216)
#print(a)
inputs=input("请输入待加密明文:")
a=int(input("请输入秘钥[a]:"))
b=int(input("请输入秘钥[b]:"))
test.Encrypt(a,b,inputs)
test.Decrypt(a,b,test.ciphertext)
s1 = "加密为:" + test.ciphertext
s2 ="解密为:" + test.plaintext
s3 = str(a) + "的逆元为: " + str(test.reverse)
print(s1)
print(s2)
print(s3)
#test.BruteForce(test.ciphertext)
运行结果:
小结:仿射密码是利用简单的置换原理,实现比较容易;增加了一个爆破函数,利用穷举爆破仿射密码。