天天看點

密碼學系列之:blowfish對稱密鑰分組算法

簡介

blowfish是由bruce schneier在1993年發明的對稱密鑰分組加密算法,類似的des和aes都是分組加密算法,blowfish是用來替代des算法出現的,并且blowfish是沒有商用限制的,任何人都可以自由使用。

對比而言,雖然aes也是一種密碼強度很高的對稱密碼算法,但是如果需要商用的話要向nist支付授權費用。

blowfish詳解

blowfish和des一樣,使用的是feistel密碼來進行分組加密。blowfish的分組塊大小是64bits,可變密鑰長度可以從32bits到448bits不等。

blowfish需要進行16輪的feistel加密操作,我們先從下圖大緻感受一下blowfish算法的加密流程:

密碼學系列之:blowfish對稱密鑰分組算法

大概的流程就是将p(原始資料)分成左右兩部分,先拿左邊的部分和kr 做異或操作,得出的結果調用f函數,最後将f函數的輸出結果和右半部分進行異或操作。

調換左右部分的位置,繼續進行這樣的操作,總共進行16輪就得到了最終的加密結果。

大家可以看到整個加密過程中最重要的兩個變量就是kr 和 f函數。

接下來我們會詳細進行講解。

密鑰數組和s-box

從圖上我們可以看到,kr 的範圍是從k1 到 k18 。總共有18個密鑰組成的數組。 每個密鑰的長度是32位。

我們來看一下密鑰數組是怎麼生成的。

首先我們使用随機數來對密鑰數組進行初始化。怎麼才能生成一個足夠随機的32位數字呢?

一個很常用的方法就是使用常量π的小數部分,将其轉換成為16淨值,如下所示:

k1 = 0x76a301d3

k2 = 0xbc452aef

k18 = 0xd7acc4a5

還記得blowfish的可變密鑰的長度嗎?是從32bits到448bits,也就是從1到14個32位的數字。我們用pi來表示,那麼就是從p1到p14總共14個可變密鑰。

接下來我們需要使用k和p進行操作,進而生成最終的k數組。

我們使用k1和p1進行異或操作,k2和p2進行異或操作,一直到k14和p14。

因為p隻有14個值,而k有18個值,是以接下來我們需要重複使用p的值,也就是k15和p1進行異或,k16和p2進行異或,直到k18和p4。

将異或之後的值作為新的k數組的值。

現在我們獲得了一個新的k數組。

注意,這個k數組并不是最終的數組,我們接下來看。

在生成最終的p數組之前,我們還要介紹一個概念叫做s-box。

在密碼學中,s-box的全稱是substitution-box,也就是一個替換盒子,可以将輸入替換成不同的輸出。

s-box 接收 n個bits的輸入,然後将其轉換成m個bits的輸出。

這裡n和m可以是不等的。

我們看一下des中s-box的例子:

密碼學系列之:blowfish對稱密鑰分組算法

上面的s-box将6-bits的輸入轉換成為4-bits的輸出。

s-box可以是固定的,也可以是動态的。比如,在des中s-box就是靜态的,而在blowfish和twofish中s-box就是動态生成的。

blowfish算法中的f函數需要用到4個s-box,f函數的輸入是32bits,首先将32bits分成4份,也就是4個8bits。

s-box的作用就是将8bits轉換成為32bits。

我們再詳細看一下f函數的工作流程:

密碼學系列之:blowfish對稱密鑰分組算法

s-box生成的值會進行相加,然後進行異或操作。最終得到最終的32bits。

s-box的初始值也可以跟k數組一樣,使用常量π的小數部分來初始化。

在上面兩節,我們生成了初始化的k數組和s-box。

blowfish認為這樣還不夠安全,不夠随機。

我們還需要進行一些操作來生成最終的k數組。

首先我們取一個全為0的64bits,然後k數組和s-box,應用blowfish算法,生成一個64bits。

将這個64bits分成兩部分,分别作為新的k1 和 k2。

然後将這個64bits作為輸入,再次調用blowfish算法,作為新的k3 和 k4。

依次類推,最終生成所有k數組中的元素。

4個s-box的數組也按照上面的流程來進行生成。進而得到最終的s-box。

blowfish

有了最終的k數組和s-box,我們就可以真正的對要加密的檔案進行加密操作了。

用個僞代碼來表示整個流程:

blowfish的應用

從上面的流程可以看出,blowfish在生成最終的k數組和s-box需要耗費一定的時間,但是一旦生成完畢,或者說密鑰不變的情況下,blowfish還是很快速的一種分組加密方法。

每個新的密鑰都需要進行大概4 kb文本的預處理,和其他分組密碼算法相比,這個會很慢。

那麼慢有沒有好處呢?

當然有,因為對于一個正常應用來說,是不會經常更換密鑰的。是以預處理隻會生成一次。在後面使用的時候就會很快了。

而對于惡意攻擊者來說,每次嘗試新的密鑰都需要進行漫長的預處理,是以對攻擊者來說要破解blowfish算法是非常不劃算的。是以blowfish是可以抵禦字典攻擊的。

因為blowfish沒有任何專利限制,任何人都可以免費使用。這種好處促進了它在密碼軟體中的普及。

比如使用blowfish的bcrypt算法,我們會在後面的文章中進行講解。

blowfish的缺點

blowfish使用64位塊大小(與aes的128位塊大小相比)使它容易受到生日攻擊,特别是在https這樣的環境中。 2016年,sweet32攻擊示範了如何利用生日攻擊對64位塊大小的密碼執行純文字恢複(即解密密文)。

因為blowfish的塊隻有64bits,比較小,是以gnupg項目建議不要使用blowfish來加密大于4 gb的檔案。

除此之外,blowfish如果隻進行一輪加密的話,容易受到反射性弱鍵的已知明文攻擊。 但是我們的實作中使用的是16輪加密,是以不容易受到這種攻擊。但是blowfish的發明人布魯斯·施耐爾(bruce schneier)還是建議大家遷移到blowfish的繼承者twofish去。

本文已收錄于 http://www.flydean.com/blowfish/ 最通俗的解讀,最深刻的幹貨,最簡潔的教程,衆多你不知道的小技巧等你來發現!