首頁>Club>
8
回覆列表
  • 1 # 小羊看科技

    AES對稱加密,有CBC,EBC,CFB,OFB等4種模式,以CBC模式來說,明文每次加密的長度可以是16位元組,但金鑰長度可以是16位元組,24位元組,32位元組。加密過程是輪金鑰加->位元組替換->行位移->列混淆,解密過程就是加密的逆序。不懂的可以私信我提供原始碼

  • 2 # Markering木槿

    1.對稱密碼基礎

    加密是為了防止要傳達的內容被別人知道。例如,你如果想在課堂上傳小紙條給後位小紅說:i love coding,但又怕在遞紙條的過程中被老師看到,知道了你的心思,於是將每個字母變字母表中的後一個字母(如a變成b,i變成j,z變成a),得到密文:j mpwf dpejoh,這樣即老師人拿到這紙條,也不知道你說的是什麼。

    這就是一個加密的過程,把原本的內容稱為明文,一般用p表示;加密後得到的內容稱為密文,一般用c表示;而加密的這個過程可以看做是一個加密函式E,即

    c=E(p)

    E是指Encrypt,函式輸入是明文,輸出是加密之後的密文。上面的例子中i love coding便是明文,j mpwf dpejoh便是密文,而把字母在字母表中向後移動一位的操作就是加密函式。

    在小紅得到小紙條後,可以根據你加密的方法,將每個字母變成字母表中的前一個字母,就可以從你的密文小紙條得到你要說的內容i love coding,心領神會,順便還會懷疑一下你的腦袋……無論怎樣,這個解密的過程就也可以看做是一個解密函式D,即

    p=D(c)

    D是指Decrypt,函式輸入是密文,輸出是解密之後的明文。

    在這個過程這種,小紅能夠成功解密小紙條的前提是,你得和她在課前約定好你加密的時候移動的是1位,2位還是幾位,不然他就會和老師一樣一臉懵逼,不知道你在說啥。你們提前約定好的這個“幾位”,就是加密和解密的金鑰k,你會根據這個秘鑰來進行加密,小紅會根據這個秘鑰來進行解密。

    所以你的傳紙條的動作抽象成這個過程:

    明文p---->加密函式E---->密文c---->傳輸---->密文c----->解密函式D---->明文p

    或者用公式來表達是:

    c=Dk(Ek(c))

    用大白話說就是:明文用同一個金鑰先加密再解密得到的還是同一個明文(等於沒說…)

    從這裡我們可以總結出加密體質的五個要素:{明文p,密文c,金鑰k,加密函式E,解密函式D},對稱解密的的意思就是說,加密和解密的金鑰是一樣的,上面的過程是不是正好很對稱呢?

    為了方便使用,不用每次自己手動掰手指數字符,你還寫了Python程式:

    # 移位密碼

    def _move_leter(letter, n):

    """

    把字母變為字母表後n位的字母,z後面接a

    :param letter: 小寫字母

    :param n: 要移動的字母

    :return: 移動的結果

    """

    return chr((ord(letter) - ord("a") + n) % 26 + ord("a"))

    def Encrypt(k, p):

    """

    移位密碼加密函式E

    :param k: 秘鑰k,每個字母在字母表中移動k位

    :param p: 明文p

    :return: 密文c

    """

    letter_list = list(p.lower())

    c = "".join([_move_leter(x, k) for x in letter_list])

    return c

    def Decrypt(k, c):

    """

    移位密碼解密函式D

    :param k: 秘鑰k,每個字母在字母表中移動k位

    :param c: 密文c

    :return: 明文p

    """

    letter_list = list(c.lower())

    p = "".join([_move_leter(x, -k) for x in letter_list])

    return p

    if __name__ == "__main__":

    p = "ilovecoding"

    print("明文:" + p)

    print("密文:" + Encrypt(1, p))

    print("解密:" + Decrypt(1, Encrypt(1, p)))

    assert Decrypt(1, Encrypt(1, p)) == p

    執行這段程式碼,就可以看到輸出了:

    明文:ilovecoding

    密文:jmpwfdpejoh

    解密:ilovecoding

    終於,現在你能和你的小紅秘密地傳達紙條內容了,迎來全班人羨慕的目光,從此走上人生巔峰,本文到此結束。

    …Hey,醒醒…

    2.密碼分析

    面對你倆日益頻繁的紙條往來,老師終於坐不住了,他想知道你倆寫的到底是啥,於是在某次逮到你遞紙條之後,決定下功夫破解你所使用的密碼,也就是密碼分析。

    根據他的瞭解,以你的水平,最可能用的就是移位密碼,但具體每次移動了幾位,無法直接觀察得出。不過他又一想,你移動的位數頂多是25位,因為,移動26位的效果等於沒移動,移27位的效果不就跟移動1位的效果是一樣的嘛!這就是說,你的密碼只能是0-25中的某一個數字,而不可能是其他的,就這麼二十幾個秘鑰,一個一個試就能知道你寫的是啥!

    老師果然聰明絕頂,關鍵是也還會Python,就索性寫了一個程式,每次嘗試用不同的秘鑰來進行解密,並觀察解密出來的內容是否有意義:

    def analyze(c):

    """

    移位密碼分析

    :param c: 密文c

    :return:

    """

    for k in range(26):

    # 用不同的秘鑰k嘗試解密

    print("秘鑰%d:" % k + Decrypt(k, c))

    if __name__ == "__main__":

    c = "jmpwfdpejoh"

    analyze(c)

    執行程式輸出結果為:

    秘鑰0:jmpwfdpejoh

    秘鑰1:ilovecoding

    秘鑰2:hknudbnchmf

    秘鑰3:gjmtcambgle

    ...........

    逐行觀察輸出結果,到第二行的時候就能看到原來的明文,也就知道了你要對小紅說的內容以及你們所約定的秘鑰。面對你冒著巨大風險在課堂上所傳遞的紙條內容,老師心裡可能也是複雜的…

    Anyway,你的小秘密已經被老師知道了,此時比較灰心,一直在想,究竟是什麼原因致使紙條計劃失敗?其實原因很明顯,各位也看出來了,小明所使用的加密體制中,可用的秘鑰太少,或者說秘鑰空間太小,別人直接一一列舉進行窮搜就能破解,這就提示我們:一個好的加密體制,它的秘鑰空間應該是足夠大的。

    其實,你此次所用的移位密碼是古典的加密體制之一,據說凱撒打仗時就用這種方法與將軍們聯絡,所以位移密碼也叫凱撒密碼(Caesar cipher)。類似的還有代換密碼,仿設射密碼等等,都是將單個字母替換成別的字母,來達到加密的目的。報紙上的猜謎遊戲就經常用這些方法,一般根據字母頻率進行破解,有興趣可以進行進一步的瞭解。

    所以到底要用什麼樣的加密方法,才能保證我和小紅的秘密不被人偷窺呢?

    2.1 密碼分析情形

    俗話說,知己知彼,百戰不殆,瞭解破解者的密碼分析方法,或許能夠幫助我們想出更安全的密碼體制。可以在不同的情形下考察密碼體制的安全性,一般我們都假設破解者知道我們所使用的密碼體制,也就是說,不把密碼體制的安全性寄託在加密和解密方法的保密性上,而是放在秘鑰上。

    破解者的目的就是找出所使用的秘鑰,常見的有以下幾種攻擊情形:

    唯密文攻擊: 破解者擁有密文c。這就是老師破解紙條的情形。

    已知明文攻擊: 破解者擁有一些明文p及其對應的密文c。考慮到實際情形,這個假設是比較合理的,例如破解者獲得一封郵件加密後的密文,可以猜測一個詞很可能是"hi"或者"dear",這樣就可能找到一個明文–密文對。

    選擇明文攻擊: 破解者能夠指定一個明文p,獲得其對應的密文c,較強的假設。

    選擇密文攻擊: 破解者指定一個密文c,獲得其對應的明文,較強的假設。

    天啊,你不禁驚呼,在這麼強的假設下,真的會有密碼體制能夠存活嗎?

    答案是有,而且這種密碼體制已經被廣泛應用,甚至可以說無處不在,它就是AES(Advanced Encryption Standard)。

    3.SPN網路

    難道不是要介紹AES嗎,怎麼會變成SPN網路,這是啥?可以吃嗎?

    AES、DES等很多現代對稱加密方法的核心就是SPN網路,它是代換-置換網路(Substitution-Permutation Network)的縮寫,是現代對稱加密方法設計的藍本。可以說,瞭解SPN網路,就基本瞭解了AES。

    很巧的是,這個網路正好是容易理解的。SPN網路的思想很簡單:既然加密一次不夠安全,那我就加密多次,把第一次加密產生的密文再進行加密,解密的時候我連續進行兩次解密就可以了,這樣是不是就安全了一些呢?

    對於密碼體制 S1 ,其加密與解密函式為 E1 與 D1,對於密碼體制 S2,其加密與解密函式為 E2 與 D2 ,我構造出一個新的密碼體制 S3,其加密函式為:

    c=E2(E1(p))

    解密函式為:

    p=D1(D2(c))

    記為 S3=S1*S2

    這樣破解 S3 就可能會困難些。這個想法是不是很直接呢?這個思想在1949年才被提出,而提出者,可能理科生都多少聽過他的名字——夏農(Shannon)。

    注意,不是任何的加密體制都可以這樣“乘”起來變得更強,例如對於你的移位密碼,巢狀起來還是移位密碼(為什麼?),沒有任何改善,即 S1*S1=S1,這樣的密碼體制被稱為冪等的。

    如果密碼體制不是冪等的,那麼多次迭代就可能能夠提高安全性,SPN就是使用這種思想,包含多輪的迭代,每輪的操作都是相同的。下面,介紹SPN單輪的操作:

    3.1 SPN單輪操作

    SPN網路是對一定長度的位元進行操作的,在本文中的SPN網路中,一次加密的長度為16個位元,即2位元組,也就是說每次加密16位元的明文,輸出16位元的密文。

    一個SPN網路包含多輪迭代,每輪迭代的操作內容都一樣是:異或運算–>分組代換–>單位元置換

    3.1.1 第一步——異或運算

    異或運算是比較常見的二元位元運算,用⊕表示,其規則就是“相同得0,不同得1”:

    0 ⊕ 0 = 0

    1 ⊕ 1 = 0

    1 ⊕ 0 = 1

    0 ⊕ 1 = 1

    對於位元串,直接按每一位對應進行計算即可以了:

    0011 ⊕ 1010 = 1001

    異或的有比較有意思的性質:一個位元串亦或另一個位元串兩遍,還是等於他自己,即a ⊕ b ⊕ b = a,這是因為a ⊕ b ⊕ b = a ⊕ ( b ⊕ b ) =a ⊕ 0 = a,可以帶入一些例子試試看。

    SPN網路中,每一輪的第一步就是把輸入的位元串w和秘鑰k進行亦或:u = w ⊕ k,如:

    0001110000100011 = 0010011010110111 ⊕ 0011101010010100

    這一步的目的是根據秘鑰對明文進行混淆。如果你只知道輸出u而不知道秘鑰k,那麼你就猜不出實際輸入的w是什麼,它是什麼都可能,而且是等機率的。例如對於1 = a ⊕ b,不告訴你b是0還是1,你就不知道a是什麼。而對於和操作,如果知道1 = a and b,那麼就能確定a與b都是1。

    這就是第一步,是不是很簡單呢?

    3.1.2 第二步——分組代換

    這一步也很簡單,將第一步輸出的16位元的串分為4組,每組4位元,即0001110000100011寫成0001 1100 0010 0011。然後對於每組再根據事先所定的表進行代換,代換表長這樣:

    圖1

    就拿第一列來說,表的意思是:如果你是0(0000),那麼我要把你換成成E(1110),就是一個簡單的對映操作。

    原位元串長這樣:0001 1100 0010 0011 <==> 1 C 2 3,再對每個字母查表得到:4 5 D 1 <==> 0100 0101 1101 0001,這樣就得到代換後的位元串0100 0101 1101 0001,完成了第二步。

    這個表一般稱為S盒(Substitution),這個過程可以用v = S(u)表示,u是第一步異或的結果,也是第二步分組代換的輸入,v是第二步的輸出。需要注意,S盒的輸入和輸出一般是非線性的關係。

    3.1.3 第三步——單位元置換

    單位元置換是將16位元中的每一位元,根據P盒(Permutation)移動挪位,這樣說很不直觀,直接上例子,P盒長這樣:

    圖2

    拿第二列來說,表的意思是:第2個位元要挪到第5個位元的位置,舉個好看的例子:

    0100 0000 0000 0000 置換後為==> 0000 1000 0000 0000

    這個例子裡面第二個位元的1挪到了第五的位置,而其他位置的位元都是0,挪位置之後還是0。

    對於第二部輸出的結果1100 1101 1100 0100,置換後的位元串為0010 1110 0000 0111,這樣就完成了第三步。

    這一步可以用W = S(v)表示,v是第二部的輸出,也是第三步的輸入,W是第三步的輸出,P盒置換是一種線性的變換。

    這三步放在一起結果如下,建議讀者自己計算一遍:

    w = 0010 0110 1011 0111

    k = 0011 1010 1001 0100

    第一步,異或運算:

    u = w ⊕ k = 0001 1100 0010 0011

    第二步,分組代換:

    v = S(u) = 0100 0101 1101 0001

    第三步,單位元置換:

    W = P(v) = 0010 1110 0000 0111

    可以寫成:W = P( S(w ⊕ k) ),這樣就完成了一輪迭代,裡面用到的引數有k,S盒與P盒,如圖(圖片來自維基百科):圖3

    3.2 SPN的多輪迭代

    弄清楚一輪的流程,SPN整體就很容易明白了,就是一輪一輪的乘起來,上一輪的輸出作為這一輪的輸入:

    w0 = x

    w1 = P(S(w0 ⊕ k1))

    w2 = P(S(w1 ⊕ k2))

    w3 = P(S(w2 ⊕ k3))

    w4 = P(S(w3 ⊕ k4))

    y = w4

    w0就是16位元的明文,w4是4輪操作後的16位元密文結果,是不是很簡單?需要注意的是,每一輪迭代的秘鑰k是不一樣的,一般是由一個基礎秘鑰經特定秘鑰編排演算法生成的,而使用的S盒P盒都是相同的,會提前確定好,並且是公開的。

    下圖是一個三輪SPN網路的示意圖(圖片來自維基百科):圖4

    注意在最後一輪去掉了代換操作,這樣做可以使加密演算法稍微做一些調整就可以用來進行解密。

    OK! SPN網路就是這些內容,你已經掌握了它,如果你還想和小紅傳紙條的話,可以試試用它加密,會比移位密碼更安全一些。

    什麼?自己手動代換置換太麻煩?不用怕,貼心的我已經為你準備好了Python程式碼。

    3.3 用Python實現SPN網路

    我實現的是4輪迭代的SPN網路,以及加密和解密演算法,其結構圖如下(圖片來自 Cryptography Theory and Practice ):圖5

    每次加密輸入16位元的明文,輸出16位元的密文,程式碼如下:

    # S盒引數

    S_Box = [14, 4, 13, 1, 2, 15, 11, 8, 3, 10, 6, 12, 5, 9, 0, 7]

    # P盒引數

    P_Box = [1, 5, 9, 13, 2, 6, 10, 14, 3, 7, 11, 15, 4, 8, 12, 16]

    def gen_K_list(K):

    """

    秘鑰編排演算法,由一個32位元秘鑰生成5個16位元子秘鑰

    :param K: 32位元秘鑰

    :return: [k1,k2,k3,k4,k5],五個16位元子秘鑰

    """

    Ks = []

    for i in range(5, 0, -1):

    ki = K % (2 ** 16)

    Ks.insert(0, ki)

    K = K >> 4

    return Ks

    def pi_s(s_box, ur):

    """

    分組代換操作

    :param s_box:S盒引數

    :param ur:輸入位元串,16位元

    :return:輸出位元串,16位元

    """

    vr = 0

    for i in range(4):

    uri = ur % (2 ** 4)

    vri = s_box[uri]

    vr = vr + (vri << (4 * i))

    ur = ur >> 4

    return vr

    def pi_p(p_box, vr):

    """

    單位元置換操作

    :param p_box:P盒引數

    :param vr:輸入位元串,16位元

    :return:輸出位元串,16位元

    """

    wr = 0

    for i in range(15, -1, -1):

    vri = vr % 2

    vr = vr >> 1

    wr = wr + (vri << (16 - p_box[i]))

    return wr

    def reverse_Sbox(s_box):

    """

    求S盒的逆

    :param s_box:S盒引數

    :return:S盒的逆

    """

    re_box = [-1] * 16

    for i in range(16):

    re_box[s_box[i]] = i

    return re_box

    def reverse_Pbox(p_box):

    """

    求P盒的逆

    :param s_box:P盒引數

    :return:P盒的逆

    """

    re_box = [-1] * 16

    for i in range(16):

    re_box[p_box[i] - 1] = i + 1

    return re_box

    def do_SPN(x, s_box, p_box, Ks):

    """

    4輪的SPN網路,可以用來進行加密或解密

    :param x: 16位元輸入

    :param s_box: S盒引數

    :param p_box: P盒引數

    :param Ks: [k1,k2,k3,k4,k5],五個16位元子秘鑰

    :return: 16位元輸出

    """

    wr = x

    for r in range(3):

    ur = wr ^ Ks[r] # 異或操作

    vr = pi_s(s_box, ur) # 分組代換

    wr = pi_p(p_box, vr) # 單位元置換

    ur = wr ^ Ks[3]

    vr = pi_s(s_box, ur)

    y = vr ^ Ks[4]

    return y

    def encrypt(K, x):

    """

    根據秘鑰K對16位元明文x進行加密

    :param K:32位元秘鑰

    :param x:16位元明文

    :return:16位元密文

    """

    Ks = gen_K_list(K)

    return do_SPN(x, S_Box, P_Box, Ks)

    def decrypt(K, y):

    """

    根據秘鑰K對16位元密文y進行解密。

    :param K:32位元秘鑰

    :param y:16位元密文

    :return:16位元明文

    """

    Ks = gen_K_list(K)

    Ks.reverse() # 秘鑰逆序編排

    # 秘鑰置換

    Ks[1] = pi_p(P_Box, Ks[1])

    Ks[2] = pi_p(P_Box, Ks[2])

    Ks[3] = pi_p(P_Box, Ks[3])

    s_rbox = reverse_Sbox(S_Box) # S盒求逆

    p_rbox = reverse_Pbox(P_Box) # P盒求逆

    return do_SPN(y, s_rbox, p_rbox, Ks)

    if __name__ == "__main__":

    x = 0b0010011010110111

    K = 0b00111010100101001101011000111111

    print("初始明文:", format(x, "016b"))

    print("加密密文:", format(encrypt(K, x), "016b"))

    print("解密結果:", format(decrypt(K, encrypt(K, x)), "016b"))

    assert decrypt(K, encrypt(K, x)) == x

    可以直接看do_SPN函式,函數里面迴圈3次,對應3輪迭代,第4輪迭代沒有置換操作。encrypt與decrypt函式呼叫do_SPN函式即可進行加密和解密操作(為什麼可以呼叫SPN進行解密?可以對照程式碼觀察SPN的結構想一想),執行程式輸出為:

    初始明文: 0010011010110111

    加密密文: 1011110011010110

    解密結果: 0010011010110111

    至此,SPN網路已經完全實現!那麼它的安全性如何呢?

    首先,我們知道,這個SPN網路的秘鑰是32位的,大約是有4百萬的候選秘鑰,這個數量的秘鑰,手動窮搜是很難的,用計算機來窮搜就會比較容易了,不過我們隨時對它進行改造,增加秘鑰長度,如256位,這時候機器窮搜也不行了。

  • 3 # 嘉靖不上朝

    對稱加密

    什麼是對稱加密?對稱加密就是指,加密和解密使用同一個金鑰的加密方式。對稱加密的工作過程傳送方使用金鑰將明文資料加密成密文,然後傳送出去,接收方收到密文後,使用同一個金鑰將密文解密成明文讀取。對稱加密的優點加密計算量小、速度塊,適合對大量資料進行加密的場景。

    常見的對稱加密演算法有DES、3DES、Blowfish、IDEA、RC4、RC5、RC6和AES。

    對稱加密的兩大不足

    金鑰傳輸問題:如上所說,由於對稱加密的加密和解密使用的是同一個金鑰,所以對稱加密的安全性就不僅僅取決於加密演算法本身的強度,更取決於金鑰是否被安全的保管,因此加密者如何把金鑰安全的傳遞到解密者手裡,就成了對稱加密面臨的關鍵問題。(比如,我們客戶端肯定不能直接儲存對稱加密的金鑰,因為被反編譯之後,金鑰就洩露了,資料安全性就得不到保障,所以實際中我們一般都是客戶端向服務端請求對稱加密的金鑰,而且金鑰還得用非對稱加密加密後再傳輸。)金鑰管理問題:再者隨著金鑰數量的增多,金鑰的管理問題會逐漸顯現出來。比如我們在加密使用者的資訊時,不可能所有使用者都用同一個金鑰加密解密吧,這樣的話,一旦金鑰洩漏,就相當於洩露了所有使用者的資訊,因此需要為每一個使用者單獨的生成一個金鑰並且管理,這樣金鑰管理的代價也會非常大。

    AES加密

    AES加密演算法就是眾多對稱加密演算法中的一種,它的英文全稱是Advanced Encryption Standard,翻譯過來是高階加密標準,它是用來替代之前的DES加密演算法的。AES為分組密碼,分組密碼也就是把明文分成一組一組的,每組長度相等,每次加密一組資料,直到加密完整個明文。在AES標準規範中,分組長度只能是128位,也就是說,每個分組為16個位元組(每個位元組8位)。金鑰的長度可以使用128位、192位或256位。金鑰的長度不同,推薦加密輪數也不同。如AES-128,也就是金鑰的長度為128位,加密輪數為10輪。關於AES加密,詳細可參考部落格:https://blog.csdn.net/gulang03/article/details/81175854

  • 中秋節和大豐收的關聯?
  • cf手遊有哪些生化神器?