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万+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章