仿射密码

简述:

仿射密码为单表加密的一种,字母系统中所有字母都藉一简单数学方程加密,对应至数值,或转回字母。

加密:
E(x) = (ax + b) (mod m),其中 a与b互质,m是编码系统中字母的个数(通常都是26)。

解密:
D(x) = a^{-1} (x - b) (mod m),其中 a^{-1} 是 a 在Z_{m}群(此处为26)的乘法逆元。

代码:


# 创建字母表
def creatLetterList():
    letterList = []
    for i in range(ord("a"), ord("z") + 1):
        letterList.append(chr(i))
    return letterList

# 判断互质
def judgeCoPrime(a, b):
    # 求最大公因数
    def maxCommonFactor(m, n):
        result = 0
        while  m % n > 0:
            result = m % n
            m = n
            n = result
        return result
    if maxCommonFactor(a, b) == 1:
        return True
    return False

# 求逆元
def getInverse(a, b):
    # 扩展的欧几里得
    def extGcd(a_, b_, arr):
        if b_ == 0:
            arr[0] = 1
            arr[1] = 0
            return a_
        g = extGcd(b_, a_ % b_, arr)
        t = arr[0]
        arr[0] = arr[1]
        arr[1] = t - int(a_ / b_) * arr[1]
        return g
    # 求a模b的乘法逆x
    arr = [0,1,]
    gcd = extGcd(a, b, arr)
    if gcd == 1:
        return (arr[0] % b + b) % b
    else:
        return -1

# 加密
def encrypt(massage, keyOne, keyTwo):
    massageList = []     # 存储明文字母转换的对应数字
    cipherTextList = []  # 密文列表
    letterList = creatLetterList()  # 字母列表
    for i in massage:
        massageList.append(letterList.index(i))
    for i in massageList:
        cipherTextList.append((keyOne * i + keyTwo) % 26)
    return cipherTextList

# 解密
def decrypt(cipherTextList, keyOne, keyTwo):
    plainTextList = []
    letterList = creatLetterList()
    # 求keyOne对于26的逆元
    inverse_keyOne = getInverse(keyOne, 26)
    for i in cipherTextList:
        plainTextList.append((inverse_keyOne * (i - keyTwo)) % 26)
    for i in range(len(plainTextList)):
        plainTextList[i] = letterList[plainTextList[i]]
    # 将列表整合为字符串
    plianText = "".join(plainTextList)
    return plianText

# 输入并创建密钥
def creatKey():
    while True:
        keyOne = int(input("输入Key1(与26互质):"))
        if not judgeCoPrime(keyOne, 26):
            continue
        keyTwo = int(input("输入Key2:"))
        break
    # 创建keyOne的逆元
    inverse_keyOne = getInverse(keyOne, 26)
    return keyOne, keyTwo, inverse_keyOne

if __name__ == "__main__":
    while True:
        print("——————仿射密码——————")
        choice = input("1、加密    2、解密\n请选择:")
        if choice == "1":
            keyOne, keyTwo, inverse_keyOne = creatKey()
            print("创建密钥成功:  " %(keyOne, keyTwo, inverse_keyOne))
            massage = input("输入明文:")
            cipherTextList = encrypt(massage, keyOne, keyTwo)
            print("加密结果:", cipherTextList)
        elif choice == "2":
            cipherTextList = list(map(int, list(input("输入密文序列:").split(","))))
            keyOne, keyTwo, inverse_keyOne = creatKey()
            plainText = decrypt(cipherTextList, keyOne, keyTwo)
            print("解密结果:", plainText)
        else:
            continue

测试:

  • 加密

输入key1:17
输入key2:5
输入明文:abcdefg

产生的逆元:23
产生的密文:5, 22, 13, 4, 21, 12, 3
仿射密码_第1张图片

  • 解密

输入密文:5, 22, 13, 4, 21, 12, 3
输入key1:17
输入key2:5

解密的明文:abcdefg
仿射密码_第2张图片

你可能感兴趣的:(Cryptography)