本文介紹RSA加解密中必須考慮到的密鑰長度、明文長度和密文長度問題,對第一次接觸RSA的開發人員來說,RSA算是比較復雜的算法,天緣以后還會補充幾篇RSA基礎知識專題文章,用最簡單最通俗的語言描述RSA,讓各位了解RSA算法本身其實也很簡單,RSA的復雜度是因為數學家把效率和安全也考慮進去的緣故。
本文先只談密鑰長度、明文長度和密文長度的概念知識,RSA的理論及示例等以后再談。提到密鑰,我們不得不提到RSA的三個重要大數:公鑰指數e、私鑰指數d和模值n。這三個大數是我們使用RSA時需要直接接觸的,理解了本文的基礎概念,即使未接觸過RSA的開發人員也能應對自如的使用RSA相關函數庫,無需深入了解e、d、n是如何生成的,只需要知道我該如何用、要注意什么。
一、密鑰長度
1、密鑰是指誰?
首先我們說的“密鑰”是指誰?由於RSA密鑰是(公鑰+模值)、(私鑰+模值)分組分發的,單獨給對方一個公鑰或私鑰是沒有任何用處,所以我們說的“密鑰”其實是它們兩者中的其中一組。但我們說的“密鑰長度”一般只是指模值的位長度。目前主流可選值:1024、2048、3072、4096...
2、模值主流長度是多少?
目前主流密鑰長度至少都是1024bits以上,低於1024bit的密鑰已經不建議使用(安全問題)。那么上限在哪里?沒有上限,多大都可以使用。所以,主流的模值是1024位,實際運算結果可能會略小於1024bits,注意,這個值不是絕對的,跟素數的生成算法有關系,只是告訴素數生成器“幫我生成一個接近1024位的素數而已”,然后生成器“好,給您一個,這個差不多1024位”。
素數生成器這么厲害?說生成1024位就會出個1024位的大整數?真實的情況是素數生成器也只是在1024bits對應的整數附近進行“摸索”而已,大家其實都不容易,又要快又要准確又要隨機性,那么素數生成器也只能應付一下,找到1024位的算是好運,沒找到1024位,1023位也照樣送出來:)。
3、公鑰指數如何確定?
公鑰指數是隨意選的,但目前行業上公鑰指數普遍選的都是65537(0x10001,5bits),該值是除了1、3、5、17、257之外的最小素數,為什么不選的大一點?當然可以,只是考慮到既要滿足相對安全、又想運算的快一點(加密時),PKCS#1的一個建議值而已。
有意的把公鑰指數選的小一點,但是對應私鑰指數肯定很大,意圖也很明確,大家都要用公鑰加密,所以大家時間很寶貴,需要快一點,您一個人私鑰解密,時間長一點就多擔待,少數服從多數的典型應用。
4、私鑰指數如何確定?
公鑰指數隨意選,那么私鑰就不能再隨意選了,只能根據算法公式(ed%k=1,k=(p-1)(q-1))進行運算出來。那么私鑰指數會是多少位?根據ed關系,私鑰d=(x*k+1)/e,所以單看這個公式,私鑰指數似乎也不是唯一結果,可能大於也可能小於1024bits的,但我們習慣上也是指某個小於1024bits的大整數。
包括前文的公鑰指數,在實際運算和存儲時為方便一般都是按照標准位長進行使用,前面不足部分補0填充,所以,使用保存和轉換這些密鑰需要注意統一緩沖區的長度。
二、明文長度
網上有說明文長度小於等於密鑰長度(Bytes)-11,這說法本身不太准確,會給人感覺RSA 1024只能加密117字節長度明文。實際上,RSA算法本身要求加密內容也就是明文長度m必須0<m<n,也就是說內容這個大整數不能超過n,否則就出錯。那么如果m=0是什么結果?普遍RSA加密器會直接返回全0結果。如果m>n,運算就會出錯?!那怎么辦?且聽下文分解。
所以,RSA實際可加密的明文長度最大也是1024bits,但問題就來了:
如果小於這個長度怎么辦?就需要進行padding,因為如果沒有padding,用戶無法確分解密后內容的真實長度,字符串之類的內容問題還不大,以0作為結束符,但對二進制數據就很難理解,因為不確定后面的0是內容還是內容結束符。
只要用到padding,那么就要占用實際的明文長度,於是才有117字節的說法。我們一般使用的padding標准有NoPPadding、OAEPPadding、PKCS1Padding等,其中PKCS#1建議的padding就占用了11個字節。
如果大於這個長度怎么辦?很多算法的padding往往是在后邊的,但PKCS的padding則是在前面的,此為有意設計,有意的把第一個字節置0以確保m的值小於n。
這樣,128字節(1024bits)-減去11字節正好是117字節,但對於RSA加密來講,padding也是參與加密的,所以,依然按照1024bits去理解,但實際的明文只有117字節了。
關於PKCS#1 padding規范可參考:RFC2313 chapter 8.1,我們在把明文送給RSA加密器前,要確認這個值是不是大於n,也就是如果接近n位長,那么需要先padding再分段加密。除非我們是“定長定量自己可控可理解”的加密不需要padding。
三、密文長度
密文長度就是給定符合條件的明文加密出來的結果位長,這個可以確定,加密后的密文位長跟密鑰的位長度是相同的,因為加密公式:
C=(P^e)%n
所以,C最大值就是n-1,所以不可能超過n的位數。盡管可能小於n的位數,但從傳輸和存儲角度,仍然是按照標准位長來進行的,所以,即使我們加密一字節的明文,運算出來的結果也要按照標准位長來使用(當然了,除非我們能再采取措施區分真實的位長,一般不在考慮)。
至於明文分片多次加密,自然密文長度成倍增長,但已不屬於一次加密的問題,不能放到一起考慮。