古典密碼之仿射密碼


一杯敬故鄉,一杯敬遠方。

算法分析

1.仿射密碼結合了移位密碼和乘數密碼的特點,是移位密碼和乘數密碼的組合。
2.仿射密碼的加密算法就是一個線性變化,即對明文字符x,對應的密文字符為y=ax+b(mod26) 其中,a, b屬於Z26gcd(a,b)=1
3.實現過程:

  • 選取a,b兩個參數,其中gcd(a, 26)=1
  • 加密變換: c= a∗𝑚+b 𝑚𝑜𝑑 26
    a=1時,移位密碼
    b=1時,乘數密碼
  • 解密變換: 𝑚= (c−b)∗a^(−1) 𝑚𝑜𝑑 26

算法實現

# 暴力破解
la = [1, 3, 5, 7, 9, 11, 15, 17, 19, 21, 23, 25]
lb = [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]

# 最大公約數
def gcd(a, b):
    while b != 0:
        tem = a % b
        a = b
        b = tem
    return a

# 加密
def encrypt(m, c, a, b):
    for i in range(len(m)):
        # 加密成相應的大寫字母
        c.append(chr(((ord(m[i]) - 97) * a + b) % 26 + 65))
    d = ''.join(c)
    print(d)

# 求逆元
def niyuan(a, b):
    ny = 1
    while (a * ny) % b != 1:
        ny += 1
    return ny

# 解密
def decrypt(c, k, b):
    mw = []
    for i in range(len(c)):
        tem = ord(c[i]) - 65 - b
        if tem < 0:
            tem += 26
        mw.append(chr((k * tem) % 26 + 97))
    print("k=" + str(k) + ", b=" + str(b) + "時,解密后的明文為:")
    res = ''.join(mw)
    print(res)

#實現
if __name__ == "__main__":
    # 明文
    m = 'ifnottothesunforsmilingwarmisstillinthesuntherebutwewilllaughmoreconfidentcalmifturnedtofoundhisownshadowappropriateescapethesunwillbethroughtheheartwarmeachplacebehindthecornerifanoutstretchedpalmcannotfallbutterflythenclenchedwavingarmsgivenpowerificanthavebrightsmileitwillfacetothesunshineandsunshinesmiletogetherinfullbloom'
    # 密文
    c = []
    x, y = input("請輸入a和b: ").split()
    a = int(x)
    b = int(y)
    while gcd(a, b) != 1:
        x, y = input("a和b不互素,請重新輸入a和b: ").split()
        a = int(x)
        b = int(y)
    print("明文內容為:")
    print(m)
    print("加密后的密文為:")
    encrypt(m, c, a, b)
    print("知道密鑰破解:")
    k = niyuan(a, 26)
    decrypt(c, k, b)
    print("不知道秘鑰破解,暴力破解如下: ")
    for i in range(0, 12):
        for j in range(0, 26):
            decrypt(c, la[i], lb[j])

加密與解密

  • 加密:輸入a = 3, b = 4時,加密結果如圖所示:

  • 解密:知道秘鑰k = 9, b = 4 (k為a的逆元)時,解出相應明文。

正確性

由於算法的前提要求gcd(a,26)==1, 從而使加密函數c= a∗𝑚+b 𝑚𝑜𝑑 26是一個單射函數,故其解必然是唯一的。即,gcd(a,26)==1保證了仿射加密函數是一個雙射函數,故算法正確。

安全性分析

1.此密碼算法安全性較弱。由算法的實現可知,此算法的秘鑰空間大小為12*26 – 1 ==311(去除a = 1, b = 0時的情況)且a = 1,3,5,7,9,11,15,17,19,21,23,25 故很容易便能夠通過暴力破解獲得明文。

2.還可以通過統計分析破解:代碼如下

#統計破解仿射密碼

# 最大公約數
def gcd(a, b):
    while b != 0:
        tem = a % b
        a = b
        b = tem
    return a

if __name__ == "__main__":
    # a = 3, b = 4時的密文
    m = "CTRUJJUJZQGMRTUDGOCLCRWSEDOCGGJCLLCRJZQGMRJZQDQHMJSQSCLLLEMWZOUDQKURTCNQRJKELOCTJMDRQNJUTUMRNZCGUSRGZENUSEXXDUXDCEJQQGKEXQJZQGMRSCLLHQJZDUMWZJZQZQEDJSEDOQEKZXLEKQHQZCRNJZQKUDRQDCTERUMJGJDQJKZQNXELOKERRUJTELLHMJJQDTLYJZQRKLQRKZQNSEPCRWEDOGWCPQRXUSQDCTCKERJZEPQHDCWZJGOCLQCJSCLLTEKQJUJZQGMRGZCRQERNGMRGZCRQGOCLQJUWQJZQDCRTMLLHLUUO"
    # 根據統計而得出的實際各字母出現的概率
    reality = dict(a=0.082, b=0.015, c=0.028, d=0.043, e=0.127, f=0.022, g=0.02, h=0.061, i=0.07,
                   j=0.002, k=0.008, l=0.04, m=0.024, n=0.067, o=0.075, p=0.019, q=0.001, r=0.06,
                   s=0.063, t=0.091, u=0.028, v=0.01, w=0.023, x=0.001, y=0.02, z=0.001)
    # 對字典中各字母出現的概率進行降序排序
    order = dict(sorted(reality.items(), key = lambda x:x[1], reverse = True))
    print("統計中各字母出現的概率從小到大如下: ")
    print(order)
    # 統計密文中各字母出現的次數
    example = {}
    for i in m:
      example[i] = m.count(i)
    # 對字典中各字母出現的次數進行降序排序
    result = dict(sorted(example.items(), key = lambda x:x[1], reverse = True))
    print("計算得的密文中個字母的出現的次數從大到小如下: ")
    print(result)

    # #從結果可推測:Q由e加密而得,J由t加密而得,進行驗算。
    # (a*4+b)%26==16
    # (a*19+b)%26==9
    # 從而計算出a=3,b=4
    # (a*K)%26==1,求得k=9
    # 用k=9,b=4進行解密可得出明文
    print("根據統計分析,加密所用的a, b可能為:")
    for i in range(1,26):
        for j in range(1,26):
            if (i*4+j)%26==16 and (i*19+j)%26==9:
                if gcd(i, j)==1:
                    print("a="+str(i), "b="+str(j))

運行結果為(此處以破解a=3, b=4時得出的密文):

如圖所示,正確解出a, b再用(a*k)%26==1,求得k=9 k=9,b=4進行解密可得出明文。
3.還可以通過差分分析進行破解。對於仿射密碼來說,“差分”是模26減法,那么,在不知道兩對明密文對(M1,C1)(M2, C2)的情況下,只需要知道M1-M2C1-C2便可以確定a。因為

C1 = aM1 + b(mod26)
C2 = a
M2 + b(mod26)
易得,a = (C1 – C2)/(M1 – M2) (mod26)

得到a 后,進一步找到b就很容易了。


免責聲明!

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



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