Affine(仿射密码)
原理
仿射密码是一种经典的加密方法,其加解密原理如下:
加密: 设 m m m 为字母表的大小(一般为 26 26 26), a a a 为加密时用到的一个常数,要求 a a a 与 m m m 互质, b b b 为加密时用到的另一个常数,可以是任意整数。对于明文中的每个字母 x x x,计算 ( a x + b ) m o d m (ax+b)\bmod m (ax+b)modm,得到密文中的对应字母 y y y。
解密: 首先求出 a a a 的逆元 a − 1 a^{-1} a−1,即满足 a × a − 1 ≡ 1 ( m o d m ) a \times a^{-1} \equiv 1 \pmod{m} a×a−1≡1(modm) 的整数 a − 1 a^{-1} a−1。然后对于密文中的每个字母 y y y,计算 a − 1 × ( y − b ) m o d m a^{-1} \times (y-b) \bmod m a−1×(y−b)modm,得到明文中的对应字母 x x x。
需要注意的是,加密和解密时使用的 a a a 和 b b b 值必须相同,否则无法正确解密。此外,如果使用的字母表大小 m m m 不同,则也需要使用不同的 a a a 和 b b b 值。
加解密脚本
import gmpy2
def affine_encrypt(plaintext: str, a: int, b: int) -> str:
"""
Affine encryption
:param plaintext:明文
:param a:要求与字母表大小(通常为26)互质
:param b:任意整数
:return:密文
"""
ciphertext = ""
for c in plaintext.upper():
ciphertext += chr(((ord(c) - 65) * a + b) % 26 + 65)
return ciphertext
def affine_decrypt(ciphertext: str, a: int, b: int) -> str:
"""
Affine decryption
:param ciphertext:密文
:param a:
:param b:
:return:
"""
plaintext = ""
a_inv = gmpy2.invert(a, 26)
for c in ciphertext:
plaintext += chr((ord(c) - 65 - b) * a_inv % 26 + 65)
return plaintext