RSA加密算法

RSA加密算法java

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

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

RSA公開密鑰密碼體制安全

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

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

   根據密鑰的使用方法,能夠將密碼分爲對稱密碼和公鑰密碼工具

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

    公鑰密碼:加密和解密使用不一樣的密碼的方式,所以公鑰密碼一般也稱爲非對稱密碼。加密

RSA算法實現過程spa

RSA算法基於一個十分簡單的數論事實:將兩個大素數相乘十分容易,但那時想要對其乘積進行因式分解卻極其困難,所以能夠將乘積公開做爲加密密鑰,即公鑰,而兩個大素數組合成私鑰。

公鑰是可發佈的供任何人使用,私鑰則爲本身全部,供解密之用。

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

示例:

  以甲要把信息發給乙爲例,

    首先肯定角色:甲爲加密者,乙爲解密者。

   而後由乙隨機肯定一個KEY,稱之爲密匙,將這個KEY始終保存在機器B中而不發出來;

   接着由這個 KEY計算出另外一個KEY,稱之爲公匙。這個公鑰的特性是幾乎不可能經過它自身計算出生成它的私鑰。

   接下來經過網絡把這個公鑰傳給甲,甲收到公鑰後,利用公鑰對信息加密,並把密文經過網絡發送到乙,

   最後乙利用已知的私鑰,就對密文進行解碼了。

  以上就是RSA算法的工做流程。

  RSA算法具體實現過程以下:

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

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

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

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

    五、將p和q的記錄銷燬。

  注:(N,e)是公鑰,(N,d)是私鑰。

RSA算法的應用

RSA的公鑰和私鑰是由KeyPairGenerator生成的,獲取KeyPairGenerator的實例後還須要設置其密鑰位數。

設置密鑰位數越高,加密過程越安全,通常使用1024位。

以下代碼:

java代碼:

 KeyPairGenerator keyPairGen = KeyPairGenerator.getInstance(RSA);

 // 密鑰位數

 keyPairGen.initialize(1024);

公鑰和私鑰能夠經過KeyPairGenerator執行generateKeyPair()後生成密鑰對KeyPair,經過KeyPair.getPublic()和KeyPair.getPrivate()來獲取。

以下代碼:

java代碼:

 // 動態生成密鑰對,這是當前最耗時的操做,通常要2s以上。

 KeyPair keyPair = keyPairGen.generateKeyPair();

 // 公鑰

 PublicKey publicKey = (RSAPublicKey) keyPair.getPublic();
 // 私鑰

 PrivateKey privateKey = (RSAPrivateKey) keyPair.getPrivate();

 byte[] publicKeyData = publicKey.getEncoded();

 byte[] privateKeyData = publicKey.getEncoded();

公鑰和私鑰都有它們本身獨特的比特編碼,能夠經過getEncoded()方法獲取,返回類型爲byte[]。

經過byte[]能夠再度將公鑰或私鑰還原出來。

具體代碼以下:

java代碼:

 // 經過公鑰byte[]將公鑰還原,適用於RSA算法

 public static PublicKey getPublicKey(byte[] keyBytes) throws

 NoSuchAlgorithmException,InvalidKeySpecException {

     X509EncodedKeySpec keySpec = new X509EncodedKeySpec(keyBytes);

     KeyFactory keyFactory = KeyFactory.getInstance(「RSA」);

     PublicKey publicKey = keyFactory.generatePublic(keySpec);

     return publicKey;

 }

 // 經過私鑰byte[]將公鑰還原,適用於RSA算法

 public static PrivateKey getPrivateKey(byte[] keyBytes) throws

 NoSuchAlgorithmException,InvalidKeySpecException {

    PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(keyBytes);

     KeyFactory keyFactory = KeyFactory.getInstance(「RSA」);

     PrivateKey privateKey = keyFactory.generatePrivate(keySpec);

     return privateKey;

 }

在上面講到的RSA算法實現過程當中提到(N,e)是公鑰,(N,d)是私鑰。既然已經獲取到了PublicKey和PrivateKey了,那如何取到N、e、d這三個值呢。

要取到這三個值,首先要將PublicKey和PrivateKey強制轉換成RSAPublicKey和RSAPrivateKey。

共同的N值能夠經過getModulus()獲取。

執行RSAPublicKey.getPublicExponent()能夠獲取到公鑰中的e值,

執行RSAPrivateKey.getPrivateExponent()能夠獲取私鑰中的d值。

這三者返回類型都是BigInteger。代碼以下:

java代碼:

// 打印公鑰信息

public static void printPublicKeyInfo(PublicKey key){

RSAPublicKey rsaPublicKey = (RSAPublicKey) publicKey;

  Log.d(MainActivity.TAG, 「RSAPublicKey:」);

  Log.d(MainActivity.TAG, 「Modulus.length=」 +

  rsaPublicKey.getModulus().bitLength());

  Log.d(MainActivity.TAG, 「Modulus=」 +

  rsaPublicKey.getModulus().toString());

  Log.d(MainActivity.TAG, 「PublicExponent.length=」 +

  rsaPublicKey.getPublicExponent().bitLength());

  Log.d(MainActivity.TAG, 「PublicExponent=」 +

   rsaPublicKey.getPublicExponent().toString());

 }


// 打印私鑰信息

public static void printPublicKeyInfo(PrivateKey key){

  RSAPrivateKey rsaPublicKey = (RSAPrivateKey) privateKey;

  Log.d(MainActivity.TAG, 「RSAPrivateKey:」);

  Log.d(MainActivity.TAG, 「Modulus.length=」 +

  rsaPrivateKey.getModulus().bitLength());

  Log.d(MainActivity.TAG, 「Modulus=」 +

  rsaPrivateKey.getModulus().toString());

  Log.d(MainActivity.TAG, 「PublicExponent.length=」 +

  rsaPrivateKey.getPrivateExponent().bitLength());

  Log.d(MainActivity.TAG, 「PublicExponent=」 +

   rsaPrivateKey.getPrivateExponent().toString());

 }

因爲程序中動態生成KeyPair對明文加密後生成的密文是不可測的,因此在實際開發中一般在生成一個KeyPair後將公鑰和私鑰的N、e、d這三個特徵值記錄下來,在真實的開發中使用這三個特徵值再去將PublicKey和PrivateKey還原出來。

還原方法以下:

java代碼:

 // 使用N、e值還原公鑰

 public static PublicKey getPublicKey(String modulus, String

 publicExponent)

         throws NoSuchAlgorithmException, InvalidKeySpecException {

     BigInteger bigIntModulus = new BigInteger(modulus);

     BigInteger bigIntPrivateExponent = new BigInteger(publicExponent);

     RSAPublicKeySpec keySpec = new RSAPublicKeySpec(bigIntModulus,

 bigIntPrivateExponent);

     KeyFactory keyFactory = KeyFactory.getInstance(「RSA」);

     PublicKey publicKey = keyFactory.generatePublic(keySpec);

     return publicKey;

 }



 // 使用N、d值還原公鑰

 public static PrivateKey getPrivateKey(String modulus, String

 privateExponent)

         throws NoSuchAlgorithmException, InvalidKeySpecException {

     BigInteger bigIntModulus = new BigInteger(modulus);

     BigInteger bigIntPrivateExponent = new BigInteger(privateExponent);

     RSAPrivateKeySpec keySpec = new RSAPrivateKeySpec(bigIntModulus,

  bigIntPrivateExponent);

    KeyFactory keyFactory = KeyFactory.getInstance(「RSA」);

     PrivateKey privateKey = keyFactory.generatePrivate(keySpec);

     return privateKey;

 }

公鑰和私鑰都具有後,就可使用加解密的工具類javax.crypto.Cipher對明文和密文進行處理了。

與全部的引擎類同樣,能夠經過調用Cipher類中的getInstance(String transformation)靜態工廠方法獲得Cipher對象。

該方法中的參數描述了由指定輸入產生輸出所進行的操做或操做集合,

能夠是下列兩種形式之一:

  「algorithm/mode/padding」或「algorithm」。

例以下面的例子就是有效的transformation形式:」DES/CBC/PKCS5Padding」或」DES」。

若是沒有指定模式或填充方式,就使用特定提供者指定的默認模式或默認填充方式。

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

java代碼:

 // 編碼前設定編碼方式及密鑰

 cipher.init(mode, key);

 // 傳入編碼數據並返回編碼結果

 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[]數據編碼後顯示給開發者。

相關文章
相關標籤/搜索