資料加密:RSA 加解密
1、加解密方法
對於RSA加解密來說,在iOS的API中同樣也是提供了這兩種形式的方法。
SecKeyEncrypt(加密)
SecKeyDecrypt(解密)
複製程式碼
openssl 同樣也提供了一系列的方法:
RSA_public_encrypt
RSA_private_encrypt
RSA_public_decrypt
RSA_private_decrypt
複製程式碼
相比較而言,openssl 提供的方法更為明確,比如:公鑰解密,私鑰解密,私鑰加密,公鑰解密。雖然 iOS 原生給出的只是加密和解密的方法,但是在方法註釋中明確說了,加密用的就是公鑰,解密用的就是私鑰。
其實公鑰加密私鑰解密也是最常用的方式,私鑰加密公鑰解密用的並不多,但是私鑰加密公鑰解密有的時候也是需要的。如果真的需要私鑰加密公鑰解密,openssl 會更方便一點,但其實 iOS 也可以做私鑰加密公鑰解密。
這裡大致說一下RSA加解密的過程:
1.生成金鑰
公鑰 (E,N)
私鑰 (E,D,N)
複製程式碼
2.加解密
密文 = 明文E % N 明文 = 密文D % N
我們通過一個具體的例子來直觀體驗下,經過計算我們現在得到一對具體的金鑰對:
公鑰=(E,N) = (5,323) 私鑰=(D,N) = (29,323) B = AE mod N = pow(123, 5) % 323 = 225 A = BD mod N = pow(225, 29) % 323 = 123
如果 A(123) 為明文,那上面的過程就是 公鑰加密私鑰解密;
如果 B(225) 為明文,那上面的過程就是 私鑰加密公鑰解密;
換一下順序可能會更清除一點:
A = BD mod N = pow(225, 29) % 323 = 123 (私鑰加密) B = AE mod N = pow(123, 5) % 323 = 225 (公鑰解密)
這樣一來我們就會發現,其實加解密是同一個方法。那為什麼會有加密和解密兩個方法呢?我的理解是:
加密就是,傳入資料直接做計算(就像上面的那樣)
解密就是,傳入資料直接做計算(還是上面的那樣),不過會根據填充模式做資料處理,把填充的隨機數剔除掉。
所以從原理上來說私鑰加密公鑰解密是行的通的,只是需要自己做一些資料上的處理。具體實現可以看Demo。
2、分段加密
RSA演算法本身要求加密內容也就是明文長度 m 必須 0<m<n ,也就是說內容這個大整數不能超過 n,否則就出錯。那麼如果 m=0,RSA加密器會直接返回全0結果。所以在對較長的資料進行加密的時候要把資料分段,每一段的資料長度不能大於模數長度(金鑰長度)。
在實際的 RSA 加密中,分段的長度跟填充模式也有一定的關係:
填充方式 | 最大輸入長度 | 輸出長度 | 填充內容 |
---|---|---|---|
PKCS1 | keySize - 11 | keySize | 隨機數 |
NONE | keySize - 1 | keySize | 00 |
有的文章說 padding 為 NONE 是的最大輸入長度為 keySize,其實這樣是有風險的。如果明文長度跟金鑰長度一樣的話,明文就有可能大於模數,這樣在加密的時候就會出錯。所以這裡建議 padding 為 NONE 是明文的分段長度取 keySize - 1
。
分段加密之後就要分段解密了,在實際的RSA加密中,加密出來的密文總是等於金鑰的長度,所以在分段解密的時候密文的分段大小直接取金鑰長度。
3、填充模式
RSA在實際應用為了提高安全性防範各種攻擊,在加解密過程中都需要新增一定的隨機因素。為了讓同一明文每次加密產生的密文都不一樣,加密前先填充一部分隨機數,這個不止RSA有,DES等對稱加密也都有,稱為padding。加密標準裡有各種型別的padding標準,比如PCKS1。
對於PKCS1,這個填充格式會要求每次加密的資料比金鑰長度短至少11個位元組(keySize - 11),填充格式如下:
PS 為隨機填充數,M為明文
00 02 | PS | 00 | M (公鑰加密)
00 01 | PS | 00 | M (私鑰加密)
複製程式碼
以 00 開頭填充同時也保證了待加密資料不會大於金鑰的模數。
還有一個比較常用的就是None(不填充),如果明文比金鑰短的話會在明文的前面填充零(0)
0000 | M
複製程式碼