當前位置:
首頁 > 最新 > 對稱加密和Base64編碼

對稱加密和Base64編碼

http://blog.7rule.com/2018/03/09/crypto-base64.html

緣起

前陣子在用golang重構一段php邏輯,那段代碼中用到了mcrypt_encrypt和base64_encode方法,大致如下:

看起來挺簡單的php調用,使用golang重構時發現沒那麼簡單。

無論是mcrypt_encrypt還是base64_encode,在golang中都無法很簡單的用一個現成的方法調用,且看官方包文檔時很多概念都搞不懂。

網上查看了一些資料,感覺理解的還不是很清楚,最終我從這兩個方法的基本概念入手,簡單學習了下,感覺清晰了很多,完成了重構。

本篇文章就是把這次學到的關於對稱加密和base64編碼的基本概念在這裡做個簡單的講解,讓大家能從基本原理中理解這兩個方法的正確使用方式。

對稱加密

簡單說:使用相同密鑰進行加密解密叫做對稱加密。

帶著的問題

加密和解密操作是如何實現的?

DES、AES是什麼意思?AES-128、AES-256又是什麼東西?如何選擇?

加密模式是什麼?多種加密模式應當如何選擇?

初始向量是什麼?

加密和解密的運算本質(XOR)

現代加解密運算都是計算機運算,也就是0和1的位運算,對稱加密中,最重要的當屬XOR運算。

XOR也叫做異或運算,規則如下:

如果是比特序列之間的XOR運算,只需要對其中每個對應的比特進行XOR運算即可,例:

這裡就有了個有趣的地方:

即:

如果A是明文,B是密鑰,那麼 即實現了加密, 即實現了解密。

分組加密的概念

這裡用一個最簡單的示例來說明基本概念。

上面大家看到了,加密需要進行運算,這就需要運算雙方的長度相同,也就是明文和密鑰的長度是相同的。

但是,實際通常要加密的明文長度很長,密鑰通常是相對固定的,那麼如何做呢?

這就需要把明文按照密鑰的長度進行分組,即分成多個,然後對每個分別和密鑰進行迭代的運算,形成最終的密文,其中迭代的方式就稱為。

上面描述的就是最簡單的分組加密的概念,實際中的演算法會複雜很多,這些等。

階段小結

通過上面的解釋,相信大家已經了解了對稱加密的基本原理。

本質上就是一種的對稱加密演算法,但這種演算法現在已經被認為是不安全的,所以後來又出現了,它對DES具備向下兼容性。

則是為了取代DES而生的,它通過公開精選,最終選定了一個叫做的分組密碼演算法。上面提到的,即是指密鑰的長度。

模式

模式指的就是分組加密的迭代方式,主要有如下幾種:

ECB

CBC

CFB

OFB

CTR

先給個結論:

絕對不要使用 ,這個模式是非常不安全的。

現在使用最多的,就是,這也是中在使用的模式。


ECB模式將明文分組加密之後的結果直接作為密文結果,如下圖:

這個模式最大的問題,就是相同的明文分組會轉換為相同的密文分組。因為只要觀察一下密文,就可以知道明文中存在怎樣的重複組合,並可以藉此攻擊。

舉個例子,假如A要向B轉賬100元,數據由3個分組構成:

付款人A的賬號

收款人B的賬號

轉賬金額

ECB加密後的密文簡單示例如下:

59 7D DE CC

DF 49 2A 1C

CD AF D5 9E

假如攻擊者將1和2的內容進行調換,則變為:

DF 49 2A 1C

59 7D DE CC

CD AF D5 9E

這樣一來,就變為了B向A轉賬100元。

ECB模式的一大漏洞,就是攻擊者可以在不破解密文的情況下操縱明文。


CBC的全稱是(密文分組鏈接),正如其名,密文分組會像鏈條一樣相互連接起來。

CBC模式首先將明文分組與前一個密文分組進行XOR運算,然後再進行加密,就這樣一直加密完所有分組。

這裡出現了這個概念:當加密第一個明文分組時,由於不存在「前一個密文分組」,因此就需要一個長度為一個分組的比特序列來代替,這個比特序列就叫做初始化向量(IV),ECB中不需要。

CBC模式現在是使用最廣泛的對稱加密模式,TLS協議(https中使用)中即使用此模式。

使用golang重構php的mcrypt_encode

我們這裡使用AES的CBC模式,這裡會涉及到3個重要的值:、、。


key的長度,可選,這是為了對應。

的複雜度最高,所以我們最好選擇這個,這樣就需要,有個最好的辦法就是對自定義的key做md5得到的字元串值即可。


iv的長度,需要和分組大小相同,AES的分組大小是,即。我們這裡可以對自定義的iv做md5後得到的字元串值取前16個位元組即可。


明文會被自動分組,為了能讓每個分組的長度固定,就需要先對明文進行數據填充,再進行分組加密操作。這裡我們使用最常用的一種數據分組填充方式

AES代碼:https://github.com/goinbox/crypto/blob/master/aes.go

PKCS5Padding代碼:https://github.com/goinbox/crypto/blob/master/padding.go


是不是發現原本php一個方法做的事情,到了golang中需要做這麼多的事。

很多高級語言都做了很多的封裝,讓大家不必了解過多的細節即可使用,但同時我們也失去了學習更多東西的機會。

現在大家可以再回過頭看看之前自己用過的對稱加密方法,對其中的參數是不是就理解了,再想想看是否之前有使用不當的地方,筆者就發現了之前一個重要的業務中使用了ECB模式,趕緊改了,呵呵。

Base64編碼

再來說下Base64編碼。

上面加密後的密文,通常會包含很多不可見字元,這樣通常會對加密後的結果做一次編碼的工作,這樣就可以在各處使用了。

帶著的問題

這裡我遇到的一個問題,就是為什麼要用Base64進行編碼,我看還有Base32啊,為什麼不用那個呢?

有了前面的經驗,我認識到還是要去了解下Base64編碼和Base32編碼的本質是什麼,才能判斷。

詳解

Base64編碼使用64個字元來對任意數據進行編碼,同理Base32編碼會使用32個字元對任意數據進行編碼。

Base64編碼的64個字元為:

編碼的過程,先將數據轉成二進位形式,然後每計算十進位值,再在上面的對應表中轉換為對應字元,最終得到一個字元串,示例:

最後的那些0,是需要進行補齊填充的bit。另外,標準Base64會使用來替代,這是因為不在索引表中,可以作為結束符存在。

小結

使用Base64編碼後的數據長度會增加1/3,Base32因為要使用更少的字元,所以編碼後的長度要增加3/5。

有此可見,Base64在某種程度上來說兼顧了字符集大小和編碼後數據長度,所以它的應用場景也更加廣泛。


喜歡這篇文章嗎?立刻分享出去讓更多人知道吧!

本站內容充實豐富,博大精深,小編精選每日熱門資訊,隨時更新,點擊「搶先收到最新資訊」瀏覽吧!


請您繼續閱讀更多來自 7rule 的精彩文章:

TAG:7rule |