常見的加密演算法之RSA加密演算法

RSA加密演算法 RSA公鑰加密演算法是1977年由Ron Rivest, Adi Shamir 和Leonard Adleman一起提出,RSA就是他們三人姓氏開頭字母拼在一起組成的。RSA是目前最有影響力和最常用的公鑰加密演算法,它能夠抵抗到目前為止已知的絕大多數密碼攻擊,至今未被完全攻破。目前已被ISO推薦為公鑰數據加密標準。

RSA演算法是第一個能同時用於加密和數字簽名的演算法,也易於理解和操作。RSA是被研究得最廣泛的公鑰演算法,從提出到現今的三十多年裡,經歷了各種攻擊的考驗,逐漸為人們接受,截止2017年被普遍認為是最優秀的公鑰方案之一。

RSA公開密鑰密碼體制 所謂的公開密鑰密碼體制就是使用不同的加密密鑰與解密密鑰,是一種「由已知加密密鑰推導出解密密鑰在計算上是不可行的」密碼體制。

Advertisements

在公開密鑰密碼體制中,加密密鑰(即公開密鑰)PK是公開信息,而解密密鑰(即秘密密鑰)SK是需要保密的。加密演算法E和解密演算法D也都是公開的。雖然解密密鑰SK是由公開密鑰PK決定的,但卻不能根據PK計算出SK。

根據密鑰的使用方法,可以將密碼分為對稱密碼和公鑰密碼

對稱密碼:加密和解密使用同一種密鑰的方式

公鑰密碼:加密和解密使用不同的密碼的方式,因此公鑰密碼通常也稱為非對稱密碼。

RSA演算法實現過程 RSA演算法基於一個十分簡單的數論事實:將兩個大素數相乘十分容易,但那時想要對其乘積進行因式分解卻極其困難,因此可以將乘積公開作為加密密鑰,即公鑰,而兩個大素數組合成私鑰。公鑰是可發布的供任何人使用,私鑰則為自己所有,供解密之用。

Advertisements

解密者擁有私鑰,並且將由私鑰計算生成的公鑰發布給加密者。加密都使用公鑰進行加密,並將密文發送到解密者,解密者用私鑰解密將密文解碼為明文。

以甲要把信息發給乙為例,首先確定角色:甲為加密者,乙為解密者。首先由乙隨機確定一個KEY,稱之為密匙,將這個KEY始終保存在機器B中而不發出來;然後,由這個 KEY計算出另一個KEY,稱之為公匙。這個公鑰的特性是幾乎不可能通過它自身計算出生成它的私鑰。接下來通過網路把這個公鑰傳給甲,甲收到公鑰后,利用公鑰對信息加密,並把密文通過網路發送到乙,最後乙利用已知的私鑰,就對密文進行解碼了。以上就是RSA演算法的工作流程。

RSA演算法實現過程為:

1、隨意選擇兩個大的質數p和q,p不等於q,計算N=pq。

2、根據歐拉函數,不大於N且與N互質的整數個數為(p-1)(q-1)。

3、選擇一個整數e與(p-1)(q-1)互質,並且e小於(p-1)(q-1)。

4、用以下這個公式計算d:d× e ≡ 1 (mod (p-1)(q-1))。

5、將p和q的記錄銷毀。

以上內容中,(N,e)是公鑰,(N,d)是私鑰。

RSA演算法的應用 RSA的公鑰和私鑰是由KeyPairGenerator生成的,獲取KeyPairGenerator的實例后還需要設置其密鑰位數。設置密鑰位數越高,加密過程越安全,一般使用1024位。如下代碼:

[代碼]java代碼:

1 KeyPairGenerator keyPairGen = KeyPairGenerator.getInstance(RSA);
2 // 密鑰位數
3 keyPairGen.initialize(1024);

公鑰和私鑰可以通過KeyPairGenerator執行generateKeyPair()後生成密鑰對KeyPair,通過KeyPair.getPublic()和KeyPair.getPrivate()來獲取。如下代碼:

[代碼]java代碼:

1 // 動態生成密鑰對,這是當前最耗時的操作,一般要2s以上。
2 KeyPair keyPair = keyPairGen.generateKeyPair();
3 // 公鑰
4 PublicKey publicKey = (RSAPublicKey) keyPair.getPublic();
5 // 私鑰
6 PrivateKey privateKey = (RSAPrivateKey) keyPair.getPrivate();
7 byte[] publicKeyData = publicKey.getEncoded();
8 byte[] privateKeyData = publicKey.getEncoded();

公鑰和私鑰都有它們自己獨特的比特編碼,可以通過getEncoded()方法獲取,返回類型為byte[]。通過byte[]可以再度將公鑰或私鑰還原出來。具體代碼如下:

[代碼]java代碼:

01 // 通過公鑰byte[]將公鑰還原,適用於RSA演算法
02 public static PublicKey getPublicKey(byte[] keyBytes) throws
03 NoSuchAlgorithmException,InvalidKeySpecException {
04 X509EncodedKeySpec keySpec = new X509EncodedKeySpec(keyBytes);
05 KeyFactory keyFactory = KeyFactory.getInstance(「RSA」);
06 PublicKey publicKey = keyFactory.generatePublic(keySpec);
07 return publicKey;
08 }
09 // 通過私鑰byte[]將公鑰還原,適用於RSA演算法
10 public static PrivateKey getPrivateKey(byte[] keyBytes) throws
11 NoSuchAlgorithmException,InvalidKeySpecException {
12 PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(keyBytes);
13 KeyFactory keyFactory = KeyFactory.getInstance(「RSA」);
14 PrivateKey privateKey = keyFactory.generatePrivate(keySpec);
15 return privateKey;
16 }

在上文講到的RSA演算法實現過程中提到(N,e)是公鑰,(N,d)是私鑰。既然已經獲取到了PublicKey和PrivateKey了,那如何取到N、e、d這三個值呢。要取到這三個值,首先要將PublicKey和PrivateKey強制轉換成RSAPublicKey和RSAPrivateKey。共同的N值可以通過getModulus()獲取。執行RSAPublicKey.getPublicExponent()可以獲取到公鑰中的e值,執行RSAPrivateKey.getPrivateExponent()可以獲取私鑰中的d值。這三者返回類型都是BigInteger。代碼如下:

[代碼]java代碼:01 // 列印公鑰信息
02 public static void printPublicKeyInfo(PublicKey key){
03 RSAPublicKey rsaPublicKey = (RSAPublicKey) publicKey;
04 Log.d(MainActivity.TAG, 「RSAPublicKey:」);
05 Log.d(MainActivity.TAG, 「Modulus.length=」 +
06 rsaPublicKey.getModulus().bitLength());
07 Log.d(MainActivity.TAG, 「Modulus=」 +
08 rsaPublicKey.getModulus().toString());
09 Log.d(MainActivity.TAG, 「PublicExponent.length=」 +
10 rsaPublicKey.getPublicExponent().bitLength());
11 Log.d(MainActivity.TAG, 「PublicExponent=」 +
12 rsaPublicKey.getPublicExponent().toString());
13 }
14
15 // 列印私鑰信息
16 public static void printPublicKeyInfo(PrivateKey key){
17 RSAPrivateKey rsaPublicKey = (RSAPrivateKey) privateKey;
18 Log.d(MainActivity.TAG, 「RSAPrivateKey:」);
19 Log.d(MainActivity.TAG, 「Modulus.length=」 +
20 rsaPrivateKey.getModulus().bitLength());
21 Log.d(MainActivity.TAG, 「Modulus=」 +
22 rsaPrivateKey.getModulus().toString());
23 Log.d(MainActivity.TAG, 「PublicExponent.length=」 +
24 rsaPrivateKey.getPrivateExponent().bitLength());
25 Log.d(MainActivity.TAG, 「PublicExponent=」 +
26 rsaPrivateKey.getPrivateExponent().toString());
27 }

由於程序中動態生成KeyPair對明文加密後生成的密文是不可測的,所以在實際開發中通常在生成一個KeyPair后將公鑰和私鑰的N、e、d這三個特徵值記錄下來,在真實的開發中使用這三個特徵值再去將PublicKey和PrivateKey還原出來。還原方法如下:

[代碼]java代碼: 01 // 使用N、e值還原公鑰
02 public static PublicKey getPublicKey(String modulus, String
03 publicExponent)
04 throws NoSuchAlgorithmException, InvalidKeySpecException {
05 BigInteger bigIntModulus = new BigInteger(modulus);
06 BigInteger bigIntPrivateExponent = new BigInteger(publicExponent);
07 RSAPublicKeySpec keySpec = new RSAPublicKeySpec(bigIntModulus,
08 bigIntPrivateExponent);
09 KeyFactory keyFactory = KeyFactory.getInstance(「RSA」);
10 PublicKey publicKey = keyFactory.generatePublic(keySpec);
11 return publicKey;
12 }
13
14 // 使用N、d值還原公鑰
15 public static PrivateKey getPrivateKey(String modulus, String
16 privateExponent)
17 throws NoSuchAlgorithmException, InvalidKeySpecException {
18 BigInteger bigIntModulus = new BigInteger(modulus);
19 BigInteger bigIntPrivateExponent = new BigInteger(privateExponent);
20 RSAPrivateKeySpec keySpec = new RSAPrivateKeySpec(bigIntModulus,
21 bigIntPrivateExponent);
22 KeyFactory keyFactory = KeyFactory.getInstance(「RSA」);
23 PrivateKey privateKey = keyFactory.generatePrivate(keySpec);
24 return privateKey;
25 }

公鑰和私鑰都具備后,就可以使用加解密的工具類javax.crypto.Cipher對明文和密文進行處理了。與所有的引擎類一樣,可以通過調用Cipher類中的getInstance(String transformation)靜態工廠方法得到Cipher對象。該方法中的參數描述了由指定輸入產生輸出所進行的操作或操作集合,可以是下列兩種形式之一:「algorithm/mode/padding」或「algorithm」。例如下面的例子就是有效的transformation形式:」DES/CBC/PKCS5Padding」或」DES」。如果沒有指定模式或填充方式,就使用特定提供者指定的默認模式或默認填充方式。

Cipher的加密和解密方式所調用的方法和過程都一樣,只是傳參不同的區別。如下代碼:

[代碼]java代碼:

1 // 編碼前設定編碼方式及密鑰
2 cipher.init(mode, key);
3 // 傳入編碼數據並返回編碼結果
4 byte[] dataResult = cipher.doFinal(input);

Cipher.init(mode, key)方法中MODE指加密或解密模式,值為Cipher.ENCRYPT_MODE或Cipher.DECRYPT_MODE,參數key在加密時傳入PublicKey,在解密時以PrivateKey傳入。Cipher.doFinal(byte[] data)則是將待編碼數據傳入后並返回編碼結果。為了將編碼結果轉為可讀字元串,通常最後還使用BASE 64演算法對最終的byte[]數據編碼后顯示給開發者。

SSL證書是HTTP明文協議升級HTTPS加密協議的重要渠道,是網路安全傳輸的加密通道。關於更多SSL證書的資訊,請關注數安時代(GDCA)。GDCA致力於網路信息安全,已通過WebTrust 的國際認證,是全球可信任的證書籤發機構。GDCA專業技術團隊將根據用戶具體情況為其提供最優的產品選擇建議,並針對不同的應用或伺服器要求提供專業對應的HTTPS解決方案。

文章來源於https://www.trustauth.cn/baike/24298.html

Advertisements

你可能會喜歡