【古典密码】 凯撒密码 移位变换 仿射变换 多表代换 Python

本文附有丰富的代码,故文章冗长,请对照目录查阅,各大板块均有上下文提示

目录

古典密码简介

仿射变换:

多表代换:

1.加密算法基础准备

2.仿射变换加密类的实现

3.多表代换加密类的实现

例题:仿射变换加密

例题:多表代换加密


古典密码简介

        古典密码主要有置换和代换的方法。置换:字母重新排列,字母本身不变,但其位置改变了(凯撒密码、移位变换)。代换:将明文中的字符替代成其他字符(仿射变换、多表代换)。

        在线性空间的变化中,古典加密就是移动并拉伸物体,让物体变得与原来不一样;解密解释将物体移动回去拉伸回去,恢复物体的原样。

        凯撒密码 移位变换 仿射变换可以理解为单表代换,这三种古典密码实质上可以归根于多表代换的特殊形式——单表代换,即一个字母一组。

        在此文中,考虑到凯撒密码、移位密码的简单性,仅介绍仿射变换、多表代换加密。加密算法的详细内容请自行查阅,以下仅列出变换公式

仿射变换:

加密:c \equiv am+b(mod 26)

解密:m \equiv a^{-1}(b-c)(mod 26)

其中a,b为密钥,且满足0\leq a,b\leq 25gcd(a, 26) = 1, a^{-1}a的乘法逆元。

多表代换:

将n个字母长的明文M分成M1,M2···Mi对每个分组:

加密:C_{_{i}}\equiv AM_{_{i}} + B(mod 26)

解密: M_{_{i}}\equiv A^{-1}(C_{_{i}}-B)(mod 26)

 (A,B) 为密钥,An\times n的可逆矩阵(即\left | A \right |> 0),且满足gcd(\left | A \right |, N) = 1C_{_{i}}为密文分组。

1.加密算法基础准备

        在这两种古典加密中最重要的是求逆元,即 a 的乘法逆元 a^{-1}A 的加密逆元 A^{-1}。两个逆元均用扩展欧几里得法。因此将扩展欧几里得、求逆元等算法封装在 类MathUitl 仿射变换、多表代换等加解密算法封装在 类TransAlgor 中,以供加解密使用。另一个 类IintiDeal 用与处理密钥输入等,现在不用关心。重要的地方均有注解,没注解就是你也一定会看懂!

# 本代码文件名:__util.py

import numpy as np

class MathUtil():
    """ 数学运算工具类 """

    def extendGcd(a, b):
        """扩展欧几里德算法"""
        if b == 0:
            return 1, 0
        else:
            x, y = MathUtil.extendGcd(b, a % b)
            x, y = y, x - (a//b) * y
            return x, y

    def modInvElem(a:int, m=26):
        """求整数a关于1模m的乘法逆元"""
        if (np.gcd(a, m) !=1): return -1
        inva, _ = MathUtil.extendGcd(a, m)
        inva %= m
        return inva

    def modInvMatrix(A, m=26):
        """求矩阵A关于1模m的乘法逆元"""
        detA = np.linalg.det(A)
        invA = np.linalg.inv(A)
        Adjoint = detA * invA
 
        inv_detA = MathUtil.modInvElem(round(detA), m)
        cipher_invA = ((inv_detA % m) * Adjoint) % m
        cipher_invA = np.round(cipher_invA).astype(int)

        return cipher_invA


class TransAlgor():
    """ 变换算法工具类 """

    def affine(code, A, B, m=26):
        """仿射变换1模26算法"""
        return (A * code + B) % m

    def invAffine(code, invA, B, m=26):
        """仿射变换1模26逆算法"""
        return invA * (code - B) % m

    def polyalphabet(code:list, A, B, m=26) -> list:
        """多表代换1模26算法"""
        group_len = len(B)
        code = np.mat(code).reshape(group_len,1)

        C = ((np.dot(A, code) + B) % m).reshape(-1)
        C = C.tolist()[0]

        return C

    def invpolyalpha(code:list, invA, B, m=26) -> list:
        """多表代换1模26逆算法"""
        group_len = len(B)
        code = np.mat(code).reshape(group_len, 1)

        M = (np.dot(invA, (code - B)) % m).reshape(-1)
        M = M.tolist()[0]

        return M


class InitDeal():
    """ 键盘输入处理类 """

    def inputKey() -> list:
        """ 用户从键盘输入密钥 """
        keyA = [[*map(eval, input("\n请输入n阶密钥方阵A:\n").split())]]
        for _ in range(len(*keyA) - 1):
            keyA.append([*map(eval, input().split())])
        keyB = [*map(eval, input("\n请输入n维密钥向量B:\n").split())]
        key = [keyA, keyB]

        return key

    def keyProcess(inputkey):
        """ 输入密钥进行处理->逆元cipher_invA等密钥 """
        A, B = inputkey
        group_len = len(B)
        A = np.mat(A).reshape(group_len,group_len)
        B = np.mat(B).reshape(group_len,1)
        try: cipher_invA = MathUtil.modInvMatrix(A)
        except: return False
        keylist = [A, B, cipher_invA]

        return keylist
        
    def dealText(textstr, group_len):
        """ 将文本进行分组处理
            @textstr: 字符串文本
            @group_len: 分组长度
        """
        # 文本字符串去空格, 长度用z补全, 如"abcabc" 
        textstr = textstr.replace(" ", "")
        blank = len(textstr) % group_len
        if blank != 0:
            textstr = textstr + (group_len-blank) * "z"

        # 统一转换成小写0~25编码列表, 如[0,1,2,0,1,2]
        textlist = list(textstr.lower())
        codelist = [ord(i)-97 for i in textlist]

        # 将编码列表进行分组, 即编码子向量, 如[[0,1,2],[0,1,2]]
        codegroup = []
        for i in range(0, len(codelist), group_len):
            codegroup.append(codelist[i:i+group_len])

        return codegroup


class HerkCode():
    """ 自定义编码类 """

    def enCode(text):
        """ 53编码 by Herk
            @text: 待编码的字符串, 如"abc"
            @return: 对应的编码流, 即"010203"
        """
        pool = " abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
        code = [(2-len(str(pool.index(i))))*'0'+str(pool.index(i)) for i in text]

        return ''.join(code)

    def deCode(code):
        """ 53解码 by Herk
            @code: 待解码的数字流, 如"010203"
            @return: 对应的字符串, 即为"abc"
        """
        pool = " abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
        text = [pool[int(code[i:i+2])] for i in range(0, len(code), 2)]

        return ''.join(text)

2.仿射变换加密类的实现

# 本代码文件名: affine.py
# 导入上面基础准备写好的类

from __util import *


class AffineCipher():
    """ 仿射变换加密 """
    
    def __init__(self, inputkey=None):
        """ 密钥初始化构建
            @inputkey: 例如[1, 3]
            若密钥为空则从键盘输入
        """
        self.inputkey  = inputkey
        self.buildKey()

    def buildKey(self):
        """ 生成相关密钥数据 """
        if self.inputkey == None:
            tips = "输入一对密钥: "      # 例如输入: 1 3 
            self.inputkey = [*map(eval, input(tips).split())]
        self.A, self.B = self.inputkey # 处理输入密钥, 得到密钥a,b
        self.invA = MathUtil.modInvElem(self.A) # 计算密钥a的逆元

    def enCrypt(self, messag):
        """ 仿射变化加密
            @messag: 明文字符串
            @return: 密文字符串
        """
        codelist = []
        cipherlist = []

        for i in messag:
            codelist.append(ord(i))

        for i in codelist:
            if 65 <= i <= 90:
                i -= 65
                i = TransAlgor.affine(i, self.A, self.B) + 65
            elif 97 <= i <= 122:
                i -= 97
                i = TransAlgor.affine(i, self.A, self.B) + 97
            cipherlist.append(chr(i))

        ciphertext = ''.join(cipherlist)

        return ciphertext

    def deCrypt(self, cipher):
        """ 仿射变换解密
            @cipher: 密文字符串
            @return: 明文字符串
        """
        codelist = []
        plainlist = []

        for i in cipher:
            codelist.append(ord(i))

        for i in codelist:
            if 65 <= i <= 90:
                i -= 65
                i = TransAlgor.invAffine(i, self.invA, self.B) + 65
            elif 97 <= i <= 122:
                i -= 97
                i = TransAlgor.invAffine(i, self.invA, self.B) + 97
            plainlist.append(chr(i))

        plaintext = ''.join(plainlist)

        return plaintext


if __name__ == '__main__':

    crypto = AffineCipher()

    messag = input("输入明文: ")
    print("加密结果:", crypto.enCrypt(messag))

    cipher = input("输入密文: ")
    print("解密结果:", crypto.deCrypt(cipher))

3.多表代换加密类的实现

# 本代码文件名: polyalphabet.py
# 导入上面基础准备写好的类

from __util import *


class PolyalphabetCipher():
    """ 多表代换加密 """
    
    def __init__(self, inputkey=None):
        """ 实例化类时需要复写的属性 """
        self.inputkey  = inputkey
        self.buildKey()

    def buildKey(self):
        """ 实例化对象后 必须构建密钥 """
        if self.inputkey == None:
            self.inputkey = InitDeal.inputKey()
        key = InitDeal.keyProcess(self.inputkey)
        self.A, self.B, self.invA = key

    def enCrypt(self, plaintext):
        """ 加密算法 返回密文 """
        ciphertext = ""
        codegroup = InitDeal.dealText(plaintext, len(self.B))

        for group in codegroup:
            group = TransAlgor.polyalphabet(group, self.A, self.B)
            group = [chr(i+97) for i in group] # 密文编码->字母串列表
            group = ''.join(group)             # 字母串列表->密文串
            ciphertext = ciphertext + group + " "

        return ciphertext

    def deCrypt(self, ciphertext):
        """ 加密算法 返回明文 """
        plaintext = ""
        codegroup = InitDeal.dealText(ciphertext, len(self.B))

        for group in codegroup:
            group = TransAlgor.invpolyalpha(group, self.invA, self.B)
            group = [chr(i+97) for i in group] # 明文编码->字母串列表
            group = ''.join(group)             # 字母串列表->明文串
            plaintext = plaintext + group + " "

        return plaintext


if __name__ == '__main__':

    crypto = PolyalphabetCipher()

    plaintext = input("输入明文: ")
    print("加密结果:", crypto.enCrypt(plaintext))

    ciphertext = input("输入密文: ")
    print("解密结果:", crypto.deCrypt(ciphertext))

例题:仿射变换加密

from affine import *

key = [7, 21]
messag = "security"
cipher = "vlxijh"

crypto = AffineCipher(key)
print("仿射变换密钥对为: 7 21")
print("security 加密为:", crypto.enCrypt(messag))
print("vlxijh   解密为:", crypto.deCrypt(cipher))

例题:多表代换加密

from polyalphabet import *

keyA = [[11, 2, 19],
        [5, 23, 25],
        [20, 7, 17]]
keyB =  [ 0, 0,  0]

# 实例化加密对象, 并传入参数进行构建
key = [keyA, keyB]
plaintext  = "your pin no is four one two six"
ciphertext = "wgi fgj tmr lhh xth wbx zps brb"

crypto = PolyalphabetCipher(key)
print("密钥为:", key)
print("加密为:", crypto.enCrypt(plaintext))
print("解密为:", crypto.deCrypt(ciphertext))

  • 6
    点赞
  • 24
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
c语言编写,欢迎扔板砖 //移位算法 #include #include #define SIZE 50 int main() { //i 用于计数输入个数,j 为临时变量, plain 存放明文, cipher 存放密文,decryption存放解密后文本,fpp 为明文文件指针,fpc 为密文文件指针 int i,j; char plain[SIZE],cipher[SIZE],decryption[SIZE],ciphertext[SIZE]; FILE * fpp,* fpc,* fpd; //加密 //建立新的明文TXT文件 printf("Caesar algorithm\n"); if((fpp=fopen("plain.txt","w+"))==NULL) { printf("creat new plain file error!\n"); exit(0); } //输入明文 printf("input plain alphabet:\n"); i=0; scanf("%c",&plain[i]); while(plain[i]!='\n'&&i<SIZE) { i++; scanf("%c",&plain[i]); } printf("success input %d characters\n",i); //将明文转存到文件中 for(j=0;j<i;j++) { if(fwrite(&plain[j],sizeof(char),1,fpp)!=1) { printf("saving plain file error!\n"); exit(0); } } printf("success saving plain text!\n"); //加密 for(j=0;j<i;j++) { cipher[j]=plain[j]+3; if(cipher[j]99) { printf("cipher %d = %c\n",j,cipher[j]); } else if(cipher[j]>122) { cipher[j]=cipher[j]%122+96; printf("cipher %d = %c\n",j,cipher[j]); } else if(cipher[j]>90) { cipher[j]=cipher[j]%90+64; printf("cipher %d = %c\n",j,cipher[j]); } else { printf("cipher %d = %c\n",j,cipher[j]); } } //建立密文文件 if((fpc=fopen("cipher.txt","w+"))==NULL) { printf("create new cipher file error!"); exit(0); } for(j=0;j<i;j++) { if(fwrite(&cipher[j],sizeof(char),1,fpc)!=1) { printf("saving cipher file error!"); exit(0); } } printf("success saving cipher file!"); printf("\n"); //解密 printf("input ciphertext alphabet:\n"); i=0; scanf("%c",&ciphertext[i]); while(ciphertext[i]!='\n'&&i<SIZE) { i++; scanf("%c",&ciphertext[i]); } for(j=0;j<i;j++) { decryption[j]=ciphertext[j]-3; if(decryption[j]90&&decryption[j]<97) { decryption[j]=123-(97-decryption[j]); printf("character %d = %c\n",j,decryption[j]); } else {
移位密码是一种简单的密码算法,它将明文中的每个字母按照指定的位数向左或向右移动,生成密文。例如,如果将明文中的每个字母都向右移动3位,那么A就变成了D,B变成了E,以此类推。 下面是一个用Python实现移位密码的代码示例: ```python def shift_cipher(text, shift): result = "" for char in text: if char.isalpha(): if char.isupper(): result += chr((ord(char) + shift - 65) % 26 + 65) else: result += chr((ord(char) + shift - 97) % 26 + 97) else: result += char return result ``` 其中,text是要加密的明文,shift是要移动的位数。代码中使用了ord和chr函数来获取字符的ASCII码和将ASCII码转换为字符。isalpha函数用于判断字符是否为字母,isupper函数用于判断字符是否为大写字母。 仿射密码是一种更加复杂的密码算法,它将明文中的每个字母先进行一次乘法变换,再进行一次加法变换,生成密文。仿射密码的加密公式为:E(x) = (ax + b) mod 26,其中a和b是密钥,x是明文中的字母,mod 26表示取模运算。 下面是一个用Python实现仿射密码的代码示例: ```python def affine_cipher(text, a, b): result = "" for char in text: if char.isalpha(): if char.isupper(): result += chr(((a * (ord(char) - 65) + b) % 26) + 65) else: result += chr(((a * (ord(char) - 97) + b) % 26) + 97) else: result += char return result ``` 其中,text是要加密的明文,a和b是密钥。代码中使用了ord和chr函数来获取字符的ASCII码和将ASCII码转换为字符。isalpha函数用于判断字符是否为字母,isupper函数用于判断字符是否为大写字母。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值