仿射密碼


仿射密碼是一種替換密碼,利用加密函數一個字母對一個字母的加密。

加密函數:E(x) = (ax + b) (mod m),其中

  • a和m互質
  • m是字母的數量

解密函數:D(x) = a-1(x - b) (mod m),其中a-1是a在Zm群的乘法逆元

仿射密碼 為單表加密的一種,字母系統中所有字母都藉一簡單數學方程加密,對應至數值,或轉回字母。 其仍有所有替代密碼之弱處。所有字母皆借由方程E(x) = (ax + b) (mod m)加密,b 為移動大小。

 

加密與解密

加密

以加密函數E(x) = (5x + 8) (mod 26)為例,以字母表26個字母作為編碼系統

 

明文 A F F I N E C I P H E R
x 0 5 5 8 13 4 2 8 15 7 4 17
5x+8
8 33 33 48 73 28 18 48 83 43 28 93
mod 26
8 7 7 22 21 2 18 22 5 17 2 15
密文 I H H W V C S W F R C P

對應的加密結果為:IHHWVCSWFRCP

解密

在已知a = 5,m = 26的情況下,我們需要求a關於模m的逆元,得到a-1 = 21

因此解密函數為:D(x) = 21(x - 8) (mod 26)

 

密文 I H H W V C S W F R C P
y
8 7 7 22 21 2 18 22 5 17 2 15
21(y8)
0 -21 -21 294 273 -126 210 294 -63 189 -126 147
mod 26
0 5 5 8 13 4 2 8 15 7 4 17
明文 A F F I N E C I P H E R

 

 

腳本

使用字母表加密解密的腳本:

# -*- coding:utf-8 -*-

import string

letters = string.ascii_letters

def encode(plaintext, a, b):
    encode_str = ''
    for s in plaintext:
        if s in letters:
            n = letters.find(s) % 26
            y = (a * n + b) % 26
            if s.isupper():
                y = y + 26
            encode_str += letters[y]
        else:
            encode_str += s
    return encode_str

def ext_euclid(a, m):
    if m == 0:
        return 1, 0
    else:
        x, y = ext_euclid(m, a % m)
        x, y = y, (x - (a // m) * y)
        return x,y

def decode(encodes, a, b):
    decode_str = ''
    x = ext_euclid(a,26)
    a = x[0]
    if a < 0:
        a = a + 26
    for s in encodes:
        if s in letters:
            n = letters.find(s) % 26
            y = a * (n - b) % 26
            if s.isupper():
                y += 26
            decode_str += letters[y]
        else:
            decode_str += s
    return decode_str

if __name__ == '__main__':
    plaintext = 'AFFINE CIPHER'
    a = 5
    b = 8
    s = encode(plaintext,a,b)
    print ("加密:"+ s)
    d = decode(s, a, b)
    print ("解密:" + d)

 

 

破解

首先,我們可以看到的是,仿射密碼對於任意兩個不同的字母,其最后得到的密文必然不一樣,所以其也具有最通用的特點。當密文長度足夠長時,我們可以使用頻率分析的方法來解決。

其次,我們可以考慮如何攻擊該密碼。可以看出當a=1時,仿射加密是凱撒加密。而一般來說,我們利用仿射密碼時,其字符集都用的是字母表,一般只有 26 個字母,而不大於 26 的與 26 互素(1,3,5,7,9,11,15,17,19,21,23,25)的個數一共有

 Φ(26) = Φ(2) x Φ(13) = 12

算上b的偏移可能,一共有可能的密鑰空間大小也就是

12 x 26 = 312

一般來說,對於該種密碼,我們至少得是在已知部分明文的情況下才可以攻擊。下面進行簡單的分析。

這種密碼由兩種參數來控制,如果我們知道其中任意一個參數,那我們便可以很容易地快速枚舉另外一個參數得到答案。

但是,假設我們已經知道采用的字母集,這里假設為 26 個字母,我們還有另外一種解密方式,我們只需要知道兩個加密后的字母 y1,y2即可進行解密。那么我們還可以知道

y1 = (ax1 + b) (mod 26)

y2 = (ax2 + b) (mod 26)

兩式相減得

y1 - y2 = a(x1 - x2) (mod 26)

這里 y1,y2已知,如果我們知道密文對應的兩個不一樣的字符 x1x2 ,那么我們就可以很容易得到 a ,進而就可以得到b 了。

 

例子

TWCTF 2016的super_express

import sys
key = '****CENSORED***************'
flag = 'TWCTF{*******CENSORED********}'

if len(key) % 2 == 1:
    print("Key Length Error")
    sys.exit(1)

n = len(key) / 2
encrypted = ''
for c in flag:
    c = ord(c)
    for a, b in zip(key[0:n], key[n:2*n]):
        c = (ord(a) * c + ord(b)) % 251
    encrypted += '%02x' % c

print encrypted

加密得到:805eed80cbbccb94c36413275780ec94a857dfec8da8ca94a8c313a8ccf9

對於 flag 中的每個字母都加密了 n 次,仔細分析,我們可以發現

        ca1b1

        c2 a2c1 b2

          a1a2a2b1 b2

          kd

根據第二行的推導,我們可以得到其實 cn 也是這樣的形式,可以看成 cn=xc+y​ ,並且,我們可以知道的是,key 是始終不變化的,所以說,其實這個就是仿射密碼。

此外,題目中還給出了密文以及部分部分密文對應的明文,那么我們就很容易利用已知明文攻擊的方法來攻擊了,利用代碼如下

# -*- coding:utf-8 -*-

import gmpy

key = '****CENSORED***************'
flag = 'TWCTF{*******CENSORED********}'

data = "805eed80cbbccb94c36413275780ec94a857dfec8da8ca94a8c313a8ccf9"
encrypted = [int(data[i:i + 2], 16) for i in range(0, len(data), 2)]
plaindelta = ord(flag[1]) - ord(flag[0])
cipherdalte = encrypted[1] - encrypted[0]
a = gmpy.invert(plaindelta, 251) * cipherdalte % 251
b = (encrypted[0] - a * ord(flag[0])) % 251
a_inv = gmpy.invert(a, 251)
result = ""
for c in encrypted:
    result += chr((c - b) * a_inv % 251)
print result

gmpy安裝方式:點擊進入

 

在線加密解密網站:https://crypto.interactive-maths.com/affine-cipher.html

 

參考

https://zh.wikipedia.org/wiki/%E4%BB%BF%E5%B0%84%E5%AF%86%E7%A2%BC

https://en.wikipedia.org/wiki/Affine_cipher

https://ctf-wiki.github.io/ctf-wiki/crypto/classical/monoalphabetic-zh/


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM