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ض?#��
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ض?#��上边是输出结果,该代码真实可用。