rsa加密算法的加解密所踩過的坑

RSA加解密遇到的問題。

1首先是私鑰和公鑰的讀取

項目組使用的是.key格式的公私鑰。已有讀取代碼,但是讀取不到。百度說是pem格式,又去百度pem的讀取,沒有成功,很多博客裏的好多都試過了,沒有成功。先貼全部代碼。

package cn.com.yusys.yusp.uaa.security;

/**
 * @項目名稱: yusp-commons
 * @類名稱: RSAUtil
 * @類描述: 
 * @功能描述: 
 * @創建人: [email protected]
 * @創建時間: 2018-02-05 13:13
 * @修改備註: 
 * @修改記錄: 修改時間    修改人員    修改原因
 * -------------------------------------------------------------
 * @version 1.0.0
 * @Copyright (c) 201
 */
import java.io.ObjectInputStream;
import java.security.Key;
import java.security.KeyFactory;
import java.security.PublicKey;
import java.security.Security;
import java.security.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPublicKey;
import java.security.spec.X509EncodedKeySpec;

import javax.crypto.Cipher;

import org.apache.commons.codec.binary.Base64;
import org.springframework.util.Base64Utils;

import cn.com.yusys.yusp.commons.util.Base64Tools;

public class BCRSAUtil {

	private static RSAPublicKey pubKey = null;
	private static RSAPrivateKey priKey = null;
	private static String filePath = "C:\\private.key";
	private static String filePath2 = "C:\\public.key";

	static {
		try {
			Security.addProvider(new org.bouncycastle.jce.provider.BouncyCastleProvider());

			priKey = (RSAPrivateKey) readKey("private.key");
			pubKey = (RSAPublicKey) readKey("public.key");

		} catch (Exception err) {
			err.printStackTrace();
		}
	}

	private static Key readKey(String keyName) throws Exception {
		
		ObjectInputStream keyIn = new ObjectInputStream(BCRSAUtil.class.getClassLoader().getResourceAsStream(keyName));
		Key key = (Key) keyIn.readObject();
		keyIn.close();
		return key;
	}

	public static String decrypt(String rawStr) throws Exception {
		byte rst[] = decrypt(priKey,Base64.decodeBase64(rawStr));
		return new String(rst);
	}

	public static byte[] decrypt(Key key, byte[] raw) throws Exception {
		Cipher cipher = Cipher.getInstance("RSA/None/PKCS1Padding", "BC");
		cipher.init(Cipher.DECRYPT_MODE, key);
		return cipher.doFinal(raw);
	}
	
	/**
	  * 使用RSA公鑰加密數據
	  * 
	  * @param pubKeyInByte
	  *            打包的byte[]形式公鑰
	  * @param data
	  *            要加密的數據
	  * @return 加密數據
	  */
	public static byte[] encryptByRSA(byte[] pubKeyInByte, byte[] data) {
	  try {
	   KeyFactory mykeyFactory = KeyFactory.getInstance("RSA");
	   X509EncodedKeySpec pub_spec = new X509EncodedKeySpec(pubKeyInByte);
	   PublicKey pubKey = mykeyFactory.generatePublic(pub_spec);
	   Cipher cipher = Cipher.getInstance("RSA/None/PKCS1Padding", "BC");
	   cipher.init(Cipher.ENCRYPT_MODE, pubKey);
	   return cipher.doFinal(data);
	  } catch (Exception e) {
	   return null;
	  }
	}
	
	/**
	 * @方法名稱:encryptByPublicKey
	 * @方法描述:公鑰加密
	 * @參數與返回說明:加密結果
	 * @算法描述:
	 */
	public static byte[] encryptByPublicKey(byte[] data, String publicKey) throws Exception {
		byte[] keyBytes = Base64Utils.decodeFromString(publicKey);
		X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec(keyBytes);
		KeyFactory keyFactory = KeyFactory.getInstance("RSA");
		Key publicK = keyFactory.generatePublic(x509KeySpec);
		Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
		cipher.init(Cipher.ENCRYPT_MODE, publicK);

		return cipher.doFinal(data);
	}
	public static void main(String[] args) {

		String orgString = "159753";

		String encryptString = "";
		String decryptString = "";

		RSAPublicKey pubKey = null;
		RSAPrivateKey priKey = null;
		try {
			// 3- 服務端私鑰
			priKey = (RSAPrivateKey) readKey("private.key");
			// 4- 服務端公鑰
			pubKey = (RSAPublicKey) readKey("public.key");

			System.out.println("priKey:\n" + priKey + "\n");
			System.out.println("pubKey:\n" + pubKey + "\n");
		} catch (Exception e) {
			e.printStackTrace();
		}

		System.out.println("\n=============================== Step-1:服務端公鑰加密-服務端私鑰解密\n");

		// 服務端公鑰加密-服務端私鑰解密
		try {
			byte[] data = orgString.getBytes();

			// 加密數據
			byte[] encodedData = BCRSAUtil.encryptByPublicKey(data,Base64Tools.encodeToString(pubKey.getEncoded(), false));
			encryptString = new String(encodedData);
			String base64decryptString = Base64Tools.encodeToString(encodedData, false);
			String base64decrypt = new String(Base64Tools.decode(base64decryptString));

			

			System.out.println("orginalString:" + orgString+"\n");
			System.out.println("encrypString:" + encryptString+"\n");
			System.out.println("base64decryptString:" + base64decryptString+"\n");
			System.out.println("base64decrypt:" + base64decrypt+"\n");
			decryptString = BCRSAUtil.decrypt(base64decryptString);
			System.out.println("decryptString:" + decryptString);
		} catch (Exception e) {
			System.err.println(e.getMessage());
			System.err.println("Step-5  解密失敗!");
		}
	}

}

讀取不到的解決方案:

private static Key readKey(String keyName) throws Exception {
		
		ObjectInputStream keyIn = new ObjectInputStream(BCRSAUtil.class.getClassLoader().getResourceAsStream(keyName));
		Key key = (Key) keyIn.readObject();
		keyIn.close();
		return key;
	}

該代碼需要讀取classpath裏面的數據,百度上說的classpath就行,確保方法是打開工作空間


在這裏我選的是紅框中的,網上說有lib,經過嘗試,沒有用,其他的沒試過。

2自己的寫的main方法測試加密解密算是否可用,但是總是報錯unknown block type

解決方式是解密的時候傳的參數不正確(我自己不明白要什麼參數的情況下,不知道怎麼寫的那個值。)

這裏的Base64Tool和java8中的Base64是一樣的。
第一個base64decryptString 是將加密生成的字節數組轉換成base64的String,而下一個測試對該字符串進行解碼,剛好有點相反,所以解密傳的應該是轉換成base64的字符串。具體形式是這樣嬸的:
base64decryptString:AY4wLplP9P0ji4Pqb1OdQHGyvanucM3AxdylPkXG5hR7jI4xe4fCJKojnKdYmK+cHg0Y5KX4crQE6FRw2LY/I5bBAKX6CnD2vX1sSjR1uHKXX34ox8IzxWHQuBMzaHmcXfUgMJz1EiDA+iSiVTys2Cg7n+LLgkQLu+bt+O4+I+w=


base64decrypt:�0.�O��#���oS�@q����p���ܥ>E��{��1{��$�#��X���
��r��Tpض?#��
base64decryptString:AY4wLplP9P0ji4Pqb1OdQHGyvanucM3AxdylPkXG5hR7jI4xe4fCJKojnKdYmK+cHg0Y5KX4crQE6FRw2LY/I5bBAKX6CnD2vX1sSjR1uHKXX34ox8IzxWHQuBMzaHmcXfUgMJz1EiDA+iSiVTys2Cg7n+LLgkQLu+bt+O4+I+w=

base64decrypt:�0.�O��#���oS�@q����p���ܥ>E��{��1{��$�#��X���
��r��Tpض?#��


你沒有看錯,也不是亂碼。一個是加密後的密文,另一個是什麼鬼嗎,所以傳遞一個解密就好了

priKey:
sun.security.rsa.RSAPrivateCrtKeyImpl@6e011

pubKey:
Sun RSA public key, 1024 bits
  modulus: 120116649152897472271287104872754798782213527672210743190671068774033441576736874540459779045286436916557147705789905620298384842729176215679538256569937324132675099830357252207268698583851266014533841920315045715095657984432900945166150291536668788342133045718998663816167262065309549976473478652006862280889
  public exponent: 65537


=============================== Step-1:服務端公鑰加密-服務端私鑰解密

orginalString:159753

encrypString:�0.�O��#���oS�@q����p���ܥ>E��{��1{��$�#��X���
��r��Tpض?#��
上邊是輸出結果,該代碼真實可用。


發佈了32 篇原創文章 · 獲贊 10 · 訪問量 5萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章