RSA的JAVA實現 及javax.crypto.IllegalBlockSizeException


  

一、背景

  最近工作中涉及到RSA加密的相關需求任務,之前對加密算法了解不多,開發過程中遇到了一些坑記錄一下。

 

二、RSA原理

      RSA加密是非對稱加密,公開私鑰,保留私鑰。通信時數據通過公開的公鑰加密,接收方用私鑰解密,達到安全傳輸的目的。RSA算法原理在這就不詳述了,放個鏈接                     https://blog.csdn.net/raalghul/article/details/51883354

三、JAVA實現

    公鑰和私鑰 都是由 兩個數的組合構成,這樣儲存不太方便。 用base64將PublicKey 和PrivateKey對象  轉為公鑰、私鑰 字符串。

    KeyPairGenerator generator = KeyPairGenerator.getInstance("RSA", new BouncyCastleProvider());
    generator.initialize(2048, new SecureRandom());
    KeyPair keyPair = generator.generateKeyPair();
    PublicKey publicKey = keyPair.getPublic();
    String pubKey = new String(Base64.encodeBase64(publicKey.getEncoded()));
    System.out.println("公鑰:"+pubKey);
    PrivateKey privateKey = keyPair.getPrivate();
    String priKey = new String(Base64.encodeBase64(privateKey.getEncoded()));
    System.out.println("私鑰:"+priKey);

    在加密解密的過程中需要的仍是 PublicKey 和PrivateKey對象, 需要將 公鑰、私鑰字符串轉換為 PublicKey 和PrivateKey對象 來實現加密 解密。

    //公鑰string 轉publicKey對象
    public static PublicKey getPublicKey(String key) throws Exception {
      byte[] keyBytes;
      keyBytes = (new sun.misc.BASE64Decoder()).decodeBuffer(key);
      X509EncodedKeySpec keySpec = new X509EncodedKeySpec(keyBytes);
      KeyFactory keyFactory = KeyFactory.getInstance("RSA");
      PublicKey publicKey = keyFactory.generatePublic(keySpec);
      return publicKey;
      }


    //公鑰string 轉publicKey對象
    public static PublicKey getPublicKey(String key) throws Exception {
      byte[] keyBytes;
      keyBytes = (new sun.misc.BASE64Decoder()).decodeBuffer(key);
      X509EncodedKeySpec keySpec = new X509EncodedKeySpec(keyBytes);
      KeyFactory keyFactory = KeyFactory.getInstance("RSA");
      PublicKey publicKey = keyFactory.generatePublic(keySpec);
      return publicKey;
      }  

 

    其他部分代碼貼出,如果不注意編碼問題會拋出javax.crypto.IllegalBlockSizeException,在代碼中標出


public static PrivateKey getPrivateKey(String key) throws Exception{
byte[] keyBytes;
keyBytes = (new sun.misc.BASE64Decoder()).decodeBuffer(key);
PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(keyBytes);
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
PrivateKey privateKey = keyFactory.generatePrivate(keySpec);
return privateKey;
}

//加密
public static byte[] encrypt(byte[] content, PublicKey publicKey) throws Exception {
Cipher cipher = Cipher.getInstance("RSA");
cipher.init(Cipher.ENCRYPT_MODE, publicKey);
return cipher.doFinal(content);
}

/**
* byte[] b1 byte[] b2 byte[] b1 String
* String data----getBytes(默認編碼)-----公鑰加密(ISO字符集,使用其他字符集數據丟失)---------私鑰解密----------new String(默認編碼)----String data
*
*
* @param args
* @throws Exception
*/
public static void main(String[] args) throws Exception {
KeyPairGenerator generator = KeyPairGenerator.getInstance("RSA", new BouncyCastleProvider());
generator.initialize(2048, new SecureRandom());
KeyPair keyPair = generator.generateKeyPair();
PublicKey publicKey = keyPair.getPublic();
String pubKey = new String(Base64.encodeBase64(publicKey.getEncoded()));
System.out.println("公鑰:"+pubKey);
PrivateKey privateKey = keyPair.getPrivate();
String priKey = new String(Base64.encodeBase64(privateKey.getEncoded()));
System.out.println("私鑰:"+priKey);
//公鑰加密 此時的getBytes() 的編碼 為默認 應該和最后的 new String() 的編碼一樣
byte[] encryptedBytes = encrypt(data.getBytes(), publicKey);
//將密文字節數組轉String時 不使用ISO編碼 可能導致數據丟失 解密失敗

//如果下面兩句 沒有指明編碼,或者使用其他編碼,會導致數據的錯誤,導致字節數組b1長度超出限制, 報出異常javax.crypto.IllegalBlockSizeException,具體原因可能是因為在公鑰加密時使用的字符集問題。
String s1 = new String(encryptedBytes,"ISO8859-1");
byte[] b1 = s1.getBytes("ISO8859-1");
//解密
byte[] decryptedByte = decrypt(b1, privateKey);
System.out.println("解密后:"+new String(decryptedByte));

}

public static byte[] decrypt(byte[] content, PrivateKey privateKey) throws Exception{
Cipher cipher = Cipher.getInstance("RSA");
cipher.init(Cipher.DECRYPT_MODE, privateKey);
return cipher.doFinal(content);

}
}

運行結果:

 

 

 

歡迎大家關注我的個人微信訂閱號:Java從零單排   分享學習資料,交流學習經驗~

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM