RSA 前段加密 java 后台解密 已调试通过
本人整理网上的。好多网上的调不通。在这里把调试好的贴出来。
1. 异步获取公钥(后台获取);你也可以将公钥串写在页面上;(接口看下面)
var publicKey = null; $.ajax({ url: ctx+"/userLogin.do?method=getRSAPublicKey", (请求地址) type: "post", dataType: "text", async:false, success: function(data) { if(data) publicKey = data; } });
2. 前段页面加密写这个, 记得引入这个js ( jsencrypt.min.js )
var encrypt = new JSEncrypt(); encrypt.setPublicKey(publicKey); // 设置公钥 var password11 = encrypt.encrypt(password); // 加密 password 是你页面获取的值 password11 是加密后的值 生成随机串
3. RSA java工具类 我这里引入了 commons-codec 的依赖 1.4版本的
import java.io.ByteArrayOutputStream; import java.io.UnsupportedEncodingException; import java.security.KeyFactory; import java.security.KeyPair; import java.security.KeyPairGenerator; import java.security.NoSuchAlgorithmException; import java.security.PrivateKey; import java.security.Provider; import java.security.PublicKey; import java.security.SecureRandom; import java.security.Security; import java.security.interfaces.RSAPrivateKey; import java.security.interfaces.RSAPublicKey; import java.security.spec.InvalidKeySpecException; import java.security.spec.PKCS8EncodedKeySpec; import javax.crypto.Cipher; import org.apache.commons.codec.binary.Base64; import org.apache.commons.io.IOUtils; public class RSAUtils1 { public static final String CHARSET = "UTF-8"; public static final String RSA_ALGORITHM = "RSA"; private static final KeyPair keyPair = initKey(); /** * 初始化方法,产生key pair,提供provider和random * @return KeyPair instance */ private static KeyPair initKey() { try { //添加provider Provider provider = new org.bouncycastle.jce.provider.BouncyCastleProvider(); Security.addProvider(provider); //产生用于安全加密的随机数 SecureRandom random = new SecureRandom(); KeyPairGenerator generator = KeyPairGenerator.getInstance("RSA", provider); generator.initialize(1024, random); return generator.generateKeyPair(); } catch(Exception e) { throw new RuntimeException(e); } } /** * 产生public key * @return public key字符串 */ public static String generateBase64PublicKey() { PublicKey publicKey = (RSAPublicKey)keyPair.getPublic(); //encodeBase64(): Encodes binary data using the base64 //algorithm but does not chunk the output. //getEncoded():返回key的原始编码形式 return new String(Base64.encodeBase64(publicKey.getEncoded())); } /** * 产生private key * * @return private key字符串 */ public static String generateBase64PrivateKey(){ PrivateKey privateKey = keyPair.getPrivate(); return new String(Base64.encodeBase64(privateKey.getEncoded())); } /** * 私钥解密 * @param data * @param privateKey * @return */ public static String privateDecrypt(String data){ try{ RSAPrivateKey privateKey = getPrivateKey(generateBase64PrivateKey()); Cipher cipher = Cipher.getInstance(RSA_ALGORITHM); cipher.init(Cipher.DECRYPT_MODE, privateKey); return new String(rsaSplitCodec(cipher, Cipher.DECRYPT_MODE, Base64.decodeBase64(data), privateKey.getModulus().bitLength()), CHARSET); }catch(Exception e){ throw new RuntimeException("解密字符串[" + data + "]时遇到异常", e); } } /** * 得到私钥 * @param privateKey 密钥字符串(经过base64编码) * @throws Exception */ public static RSAPrivateKey getPrivateKey(String privateKey) throws NoSuchAlgorithmException, InvalidKeySpecException { //通过PKCS#8编码的Key指令获得私钥对象 KeyFactory keyFactory = KeyFactory.getInstance(RSA_ALGORITHM); PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(Base64.decodeBase64(privateKey)); RSAPrivateKey key = (RSAPrivateKey) keyFactory.generatePrivate(pkcs8KeySpec); return key; } private static byte[] rsaSplitCodec(Cipher cipher, int opmode, byte[] datas, int keySize){ int maxBlock = 0; if(opmode == Cipher.DECRYPT_MODE){ maxBlock = keySize / 8; }else{ maxBlock = keySize / 8 - 11; } ByteArrayOutputStream out = new ByteArrayOutputStream(); int offSet = 0; byte[] buff; int i = 0; try{ while(datas.length > offSet){ if(datas.length-offSet > maxBlock){ buff = cipher.doFinal(datas, offSet, maxBlock); }else{ buff = cipher.doFinal(datas, offSet, datas.length-offSet); } out.write(buff, 0, buff.length); i++; offSet = i * maxBlock; } }catch(Exception e){ throw new RuntimeException("加解密阀值为["+maxBlock+"]的数据时发生异常", e); } byte[] resultDatas = out.toByteArray(); IOUtils.closeQuietly(out); return resultDatas; } public static void main(String[] args) { // 获得公钥 私钥对 System.out.println("公钥:"+generateBase64PublicKey()); System.out.println("秘钥:"+generateBase64PrivateKey()); } }
4. 给前台返回公钥 (文章第1步调用接口)
@RequestMapping(params = "method=getRSAPublicKey") public void getRSAPublicKey(HttpServletRequest request,HttpServletResponse response){ PrintWriter writer; try { writer = response.getWriter(); String publicKey = RSAUtils1.generateBase64PublicKey(); writer.write(publicKey); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } }
5.解密 (解密的方法)
//先对前端密码进行RSA解密 加到接收加密的方法中 password = password.replace(" ","+"); 加密的数据放在Url传递时,会将“+”变成空格,这里变回来。 System.out.println("解密前:"+password); password = RSAUtils1.privateDecrypt(password); System.out.println("解密后密码:"+password);
结束。谢谢交流评论。