RSA加解密遇到的问题。
1首先是私钥和公钥的读取
项目组使用的是.key格式的公私钥。已有读取代码,但是读取不到。百度说是pem格式,又去百度pem的读取,没有成功,很多博客里的好多都试过了,没有成功。先贴全部代码。
package cn.com.yusys.yusp.uaa.security;
/**
* @项目名称: yusp-commons
* @类名称: RSAUtil
* @类描述:
* @功能描述:
* @创建人: ????@yusys.com.cn
* @创建时间: 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ض?#��
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ض?#��
上边是输出结果,该代码真实可用。