仿射密码

密码学 专栏收录该内容
6 篇文章 1 订阅

仿射密码定义原理:
  仿射密码为单表加密的一种,字母系统中所有字母都借一简单数学方程加密,对应至数值,或转回字母。 其仍有所有替代密码之弱处。所有字母皆借由方程加密,b为移动大小。
  在仿射加密中,大小为m之字母系统首先对应至0…m-1范围内之数值, 接着使用模数算数来将原文件中之字母转换为对应加密文件中的数字。 单一字母的加密函数为:
  在这里插入图片描述
取余m为字母系统大小且a和b为密码关键值。a之值必须使得a与m互质。
解密方程为
  在这里插入图片描述
举例说明:

代换密码算法的原理是使用替代法进行加密,就是将明文中的字符用其它字符替代后形成密文。例如,明文字母a、b、c、d,用D、E、F、G做对应替换后形成密文。
代换密码包括多种类型,如单表代换密码、多表代换密码等。下面介绍一种典型的单表代换密码——仿射密码。它的加密、解密过程可以表示为下面的函数:
在这里插入图片描述
仿射加密要求gcd(k1,26)=0,否则就褪化为 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)

运行结果:

在这里插入图片描述

小结:仿射密码是利用简单的置换原理,实现比较容易;增加了一个爆破函数,利用穷举爆破仿射密码。

  • 0
    点赞
  • 0
    评论
  • 8
    收藏
  • 打赏
    打赏
  • 扫一扫,分享海报

©️2022 CSDN 皮肤主题:数字20 设计师:CSDN官方博客 返回首页

打赏作者

1ance.

你的鼓励将是我创作的最大动力

¥2 ¥4 ¥6 ¥10 ¥20
输入1-500的整数
余额支付 (余额:-- )
扫码支付
扫码支付:¥2
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值