1. 程式人生 > >資料加密:RSA 加解密

資料加密: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
複製程式碼

Demo傳送門