代換密碼的另一個特殊情形是仿射密碼,它的加密函數定義為 e(x)=(ax+b)mod 26,其中a,b∈Z26 —— 因為這樣的函數被稱為仿射函數,所以這樣的密碼體制也被稱為仿射密碼(當a=1時,正好是移位密碼)。
為了能對密文進行解密,必須保證所選用的仿射函數是一個單射函數,則對於任意的y∈Z26,同余方程ax+b≡y(mod 26)有唯一解x,並且等價於ax≡y-b(mod 26)。當y遍歷Z26時,y-b也遍歷Z26,故同余方程有唯一解的充要條件是gcd(a,26)=1。
單射:設f是由集合A到集合B的映射,如果所有x,y∈A,且x≠y,都有f(x)≠f(y),則稱f為由A到B的單射 —— 百度百科
gcd:最大公約數
定理 1.1:設a∈Zm,對任意的b∈Zm,同余方程ax≡b(mod m)有唯一解x∈Zm的充要條件是gcd(a,m)=1。故當m=26,所有與26互素的數為a=1,3,5,7,9,11,15,17,19,21,23,25,b的取值可以為Z26中的任何數,因此仿射密碼的密鑰空間為12*26=312。(密鑰空間很小,很不安全)
定理1.2:假定
這里pi均為素數且互不相同,ei>0, 1≤i≤n。則
如果m=60,則Φ(60)=2*2*4=16,所以此仿射密碼的密鑰空間大小為16*60=960。
根據定理1.2,60=22*3*5,98=2*72
乘法逆:設a∈Zm,若存在a'∈Zm,使得aa'≡a'a≡1(mod m),則a'稱為a在上的乘法逆,將其記為a-1mod m。在m是固定的情形下,也可將其簡記為a-1。根據定理1.1,定理1.2和乘法逆,有如下仿射密碼的定義:
代碼實現(Python 3)
def affine_cipher_encrypt(message:str, keyA=7, keyB=3): SYMBOLS = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' translated = '' message = message.upper() for symbol in message: if symbol in SYMBOLS: symbolIndex = SYMBOLS.find(symbol) translatedIndex= (keyA * symbolIndex + keyB)%26 translated = translated + SYMBOLS[translatedIndex] else: translated = translated + symbol print(translated) def affine_cipher_decrypt(message:str, keyA=7, keyB=3): SYMBOLS = 'abcdefghijklmnopqrstuvwxyz' translated = '' message = message.lower() keyA1 = multiplicative_inverse(keyA) for symbol in message: if symbol in SYMBOLS: symbolIndex = SYMBOLS.find(symbol) translatedIndex= (keyA1 * (symbolIndex - keyB))%26 translated = translated + SYMBOLS[translatedIndex] else: translated = translated + symbol print(translated) def multiplicative_inverse(key,m=26): for n in range(m): if key*n%m==1: print(f'The multiplicative_inverse of key {key} is {n}.') return n return -1