仿射密码(Affine)
-
加密对象: 英文字母
-
原理:
- 该密码运用了乘法逆元和模运算
- a~z对应于0~25, 将明文的每个字符转为对应的数字
a b c d e f g h i j k l m n o p q r s t u v w x y z 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 - 加密函数:D(x) = (a*x+b) (mod 26),这里a,b变量就是密钥,注意 a必须和26互质
- 通过加密函数得到密文的数字,在查表,组合在一起就构成了密文。
- 解密过程与加密类似
- 解密函数: E(x) = a-1(x-b) (mod 26), 这里a-1是a关于26的乘法逆元。
-
代码:
# write by 2021/6/28 DIC = "abcdefghijklmnopqrstuvwxyz" # 辗转相除法 def gcd(a, b): a, b = b, a % b # print(a, b) if b == 0: return a else: return gcd(a, b) # 扩展欧几里得算法 def exgcd(a, b): if b == 0: return 1, 0 x, y = exgcd(b, a % b) return y, x-(a//b)*y def encrypt_affine(string, a, b): ciphertext = "" if gcd(a, 26) != 1 and gcd(a, 26) != -1: return -1 for i in string.lower(): if i not in DIC: ciphertext += i else: ciphertext += DIC[(a*DIC.index(i)+b) % 26] return ciphertext # 直接遍历所有26可能,找到为止 def decrypt2_affine(string, a, b): plaintext = "" if gcd(a, 26) != 1 and gcd(a, 26) != -1: return -1 for i in string.lower(): if i not in DIC: plaintext += i # (x*7+3)%26 = 4 else: for x in range(26): if (x*a + b) % 26 == DIC.index(i): # print("x=", x) plaintext += DIC[x] break return plaintext # 根据扩展欧几里得算法找到乘法逆元,在求解 def decrypt_affine(string, a, b): plaintext = "" if gcd(a, 26) != 1 and gcd(a, 26) != -1: return -1 a_26_inv = exgcd(a, 26)[0] for i in string: if i not in DIC: return -1 plaintext += DIC[a_26_inv*(DIC.index(i)-b) % 26] return plaintext if __name__ == '__main__': # print(exgcd(3, 26)) a, b = 2, 21 ciphertext_ = encrypt_affine("AFFINECIPHER", a, b) plaintext_ = decrypt_affine(ciphertext_, a, b) plaintext_2 = decrypt2_affine(ciphertext_, a, b) print(f"{plaintext_}: {ciphertext_}") print(f"{plaintext_2}: {ciphertext_}")