一個關於國密SM4的故事
我的名字叫SM4,我還有三位兄長,分別是大哥SM1, 二哥SM2, 和三哥SM3。說起我的名字,故事要回到2006年的時候,我出生的時候並不是叫SM4的,而是叫做SMS4。只是2012年的時候我父親給我改名了。雖然我起了一個洋氣的名字,但我必須鄭重地說,我是一個中國人。名字可能只是為了與國際接軌。
我的家族
先簡單地介紹一下我的家族,我的父親是國家密碼管理局,我們幾兄弟就主要負責起國家信息安全中的加密。我由一出生起,就不斷地被家人提醒我要肩負重任。因此,我也非常努力,不斷地學習和完善提升自我。
大哥主要負責硬件的加密,不知道是不是因為大哥身為長兄,所以份外地冷酷,他的加密算法和二哥三哥和我都不同,我們的算法都是公開的,但是大哥卻埋藏得很深,我們都不知道他的算法是怎樣的。
幾兄弟里,我和二哥比較親密,可能是因為他的業務名稱和我比較像吧,他主要負責的是非對稱加密。我有什么不懂都是經常跑去請教他的。
三哥主要負責哈希算法的。而我,則是負責對稱加密。別看我現在說得頭頭是道,其實一開始我完全不理解這些名詞到底是什么意思,於是我首先就走去問二哥。
我是干啥的
我說,二哥,父親告訴我要負責對稱加密,其實我到底是要做些什么呢?
二哥耐心地告訴我,在我們這個密碼學的大家族里,加密算法主要可以分為兩種,一個是非對稱加密算法,另一個就是對稱加密算法。也就是我和你主要負責的。對稱加密簡單來說就是有一個明文,通過一個密鑰加密之后得到一個密文,這個密文可以通過相同的密要解密得出和原來相同的明文。
我聽了之后覺得有點理解了,我說,那不是很簡單嗎,比如說明文是123 ,密碼是456 ,我只要將123+456那就變成了579,別人不就看不懂了嗎?
二哥哈哈大笑,你是不是看金田一和柯南的偵探小說太多了,你說的原理是沒有錯的,但是你太少瞧黑客和攻擊者了,如此簡單的加密算法,有經驗的攻擊者不用1秒鍾就可以解開了,你肩負的是我們全國的安全啊,你必須要有一種安全的加密算法才可以。而且你這種算法必須是可以公開的,只要密鑰足夠復雜,別人就永遠也解不開,這樣才能形成一種標准,四弟,你需要像我一樣成為一種標准,而不僅僅成為一種算法。
我眉頭緊皺,心想算法也可以公開?這也太難了吧。我委屈地說,二哥,這個太難了,我不能學大哥那樣子不公開算法嗎?
二哥回答,我的算法也是公開的,不也是什么事也沒有嗎?你可以看看前人是怎么實現類似的功能,你應該在前人的基礎上不斷創新,而不是從零開始,因循守舊。
我恍然大悟,前人?有誰啊?
有非常多,早在1977年,美國就頒布了一種對稱加密算法,叫DES。雖然這種算法已經被證明是不安全的,但是你也可以去學習學習。又比如比利時有兩位密碼學家,在1998年就提出了一種著名的對稱加密算法,現在已經被全世界廣泛使用,就是鼎鼎大名的AES,我們喜歡叫做算法,但其實他已經是一種標准了。
二哥果然是博古通今,我聽后大受啟發,馬上就跑回書房躍躍欲試。
我的算法標准
我查了一下書籍,果然大有發現,對稱加密分為了塊加密和流加密,流比較偏門,於是我先跳過了,我把已經出現的塊加密算法列舉了一下。
於是我了解了一下目前公認比較安全的aes。
這個過程中,我還發現了一些秘密,原來其實大哥也是對稱加密的,還有個名字另類的兄弟叫ZUC。我好像還有一些弟弟也是對稱,叫SM7的,但是族譜里現在還沒有看見,所以我也沒有深入研究了。
研究了aes之后發現,要實現一個可靠的加密算法,效率非常重要,想像一下,要加密的明文長度比較短還可以接受,萬一非常非常長的,加密的效率就非常重要了。要提高效率,我首先想到的就是並行計算,而要並行計算,就需要對明文首先划分成相同的長度,這個過程我稱之為分組。
由於要划分成相同的長度才好實現統一的加密解密處理,那么就必然會出現分組后最后的那一組字符串會出現長度不夠的問題,那么就需要把缺失的長度補充上去,這個過程我稱之為填充。
像我剛才跟二哥說的那個例子一樣,簡單的一次加密計算,必然是很容易被破解的,所以要增加算法的安全性,就需要對明文的計算轉換進行多次,我把每一次的計算稱之為迭代。
太好了!我的加密算法主要可以切分三個:分組、填充、迭代。
迭代的算法是最為核心的部分,當然要參考最為著名的Feistel分組加密結構。
影響Feistel 結構的因素有如下5 個:
(1)塊的大小:大的塊會提高加密的安全性,但是會降低加密、解密的速度。截止至2013年,比較流行的這種方案是64 bit。而128 bit 的使用也比較廣泛。
(2)密鑰的大小:同上。現在流行的是64 bit ,而 128 bit 正逐漸成為主流。
(3)循環次數(輪次數):每多進行一輪循環,安全性就會有所提高。現階段比較流行的是16輪。
(4)子密鑰的生成算法:生成算法越復雜,則會使得密碼被破譯的難度增強,即,信息會越安全。
(5)輪函數的復雜度:輪函數越復雜,則安全性越高。
另外,還有很重要的一個迭代模式。目前也是有比較成熟的參考。
ECB模式:
CBC模式:
所有的迭代模式:
好了,我定義好自己的分組長度、填充標准、輪函數的算法,我的標准終於出來了!
我的實現
后面陸陸續續,有很多語言根據我的標准進行了實現,包括c、java、python等等。
要實現這個,還是很不容易的。首先要懂得線性代數,什么線性變換、非線性變換。對編程里的位運算也得熟悉。不過這些我都不管,讓大家去實現吧,哈哈。下面貼一下我的好朋友java實現中的關鍵輪函數。
/**
* 輪函數F。
*
* 6 Round Function 𝑭
* 6.1 Round Function Structure
* Suppose the input to round function is (𝑋0 ,𝑋1 ,𝑋2 ,𝑋3 ) ∈ (𝑍43)C and the round key is
* 𝑟𝑘 ∈ 𝑍43, then 𝐹 can be represented as: 3
* 𝐹 𝑋0,𝑋2,𝑋3,𝑋4,𝑟𝑘 = 𝑋0 ⊕ 𝑇(𝑋2 ⊕ 𝑋3 ⊕ 𝑋4 ⊕ 𝑟𝑘).
*
* @param x0
* @param x1
* @param x2
* @param x3
* @param rk
* @return
*/
private long sm4F(long x0, long x1, long x2, long x3, long rk) {
return x0 ^ sm4Lt(x1 ^ x2 ^ x3 ^ rk);
}
/**
* 組合T。
* 包括:
* (1)非線性變換𝝉(tau)
* (2)線性變換L。
*
* 6.2 Permutation 𝑻
* 𝑇: 𝑍43 → 𝑍43 is an invertible transformation, composed of a nonlinear transformation 𝜏 33
* and a linear transformation 𝐿. That is, 𝑇 ∙ = 𝐿(𝜏(∙)).
*
* (1) Nonlinear transformation 𝝉
* 𝜏 is composed of 4 S-boxes in parallel. Suppose 𝐴 = (𝑎 ,𝑎 ,𝑎 ,𝑎 ) ∈ (𝑍M)C is input to 0234 3
* 𝜏, and 𝐵 = (𝑏 ,𝑏 ,𝑏 ,𝑏 ) ∈ (𝑍M)C is the corresponding output, then 0234 3
* 𝑏0,𝑏2,𝑏3,𝑏4 = 𝜏 𝐴 = (𝑆𝑏𝑜𝑥 𝑎0 ,𝑆𝑏𝑜𝑥 𝑎2 ,𝑆𝑏𝑜𝑥 𝑎3 ,𝑆𝑏𝑜𝑥 𝑎4 ).
* The S-box is as follows:
* @see SboxTable
*
* (2) Linear transformation 𝑳
* The output from the nonlinear transformation 𝜏 is the input to the linear
* transformation 𝐿. Suppose the input to 𝐿 is 𝐵 ∈ 𝑍43, and the corresponding output is 3
* 𝐶 ∈ 𝑍43, then 3
* 𝐶=𝐿 𝐵 =𝐵⊕(𝐵<<<2)⊕(𝐵<<<10)⊕(𝐵<<<18)⊕(𝐵<<<24).
*
* @param ka
* @return
*/
private long sm4Lt(long ka) {
long bb = 0L;
long c = 0L;
byte[] a = new byte[4];
byte[] b = new byte[4];
PUT_ULONG_BE(ka, a, 0);
b[0] = sm4Sbox(a[0]);
b[1] = sm4Sbox(a[1]);
b[2] = sm4Sbox(a[2]);
b[3] = sm4Sbox(a[3]);
bb = GET_ULONG_BE(b, 0);
c = bb ^ ROTL(bb, 2) ^ ROTL(bb, 10) ^ ROTL(bb, 18) ^ ROTL(bb, 24);
return c;
}
參考資料:
中國互聯網絡信息中心
https://baike.baidu.com/item/SMS4算法/16858974
https://baike.baidu.com/item/DES
https://baike.baidu.com/item/Feistel/1985068
https://baike.baidu.com/item/線性變換/5904192?fr=aladdin
https://baike.baidu.com/item/τ/2858554?fr=aladdin
祖沖之序列密碼算法
java代碼實現
另外,csdn、cnblogs搜索有很多關於國密的博客,都可以參考。
github、gitee上也有各種語言的實現。
主要記錄一下上周的學習,寫得不好希望各位指正。