Java-web中利用RSA进行加密解密操作的方法示例
前言
最近在看,网络安全方面的问题,我们可以使用RSA进行非对称加密防止,获取用户信息。首先我们看下java下操作RSA进行加密解密算法,代码如下:
package com.jb.test; import java.security.InvalidKeyException; import java.security.KeyPair; import java.security.KeyPairGenerator; import java.security.NoSuchAlgorithmException; import java.security.PrivateKey; import java.security.PublicKey; import java.security.SecureRandom; import javax.crypto.BadPaddingException; import javax.crypto.Cipher; import javax.crypto.IllegalBlockSizeException; import javax.crypto.NoSuchPaddingException; import org.apache.commons.codec.binary.Hex; public class RSAEntry { /** * @Title: main * @Description: RSA加密算法,解密算法 * @param args * void * @throws NoSuchAlgorithmException * @throws NoSuchPaddingException * @throws InvalidKeyException * @throws BadPaddingException * @throws IllegalBlockSizeException * * @throws */ public static void main(String[] args) throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException, IllegalBlockSizeException, BadPaddingException { // Security.getProviders();//获取所有支持的加密算法 //采用非对称加密解密算法 //生成密钥实例 KeyPairGenerator keygen = KeyPairGenerator.getInstance("RSA"); SecureRandom random = new SecureRandom(); random.setSeed(System.currentTimeMillis());//设置随机种子 keygen.initialize(512, random);//设置密钥长度,应为64的整数倍 //生成密钥公钥对 KeyPair keyPair = keygen.generateKeyPair(); //获取公钥 PublicKey pubkey = keyPair.getPublic(); //获取私钥 PrivateKey prikey = keyPair.getPrivate(); //测试数据 String data = "测试数据"; //使用公钥进行加密 //构建加密解密类 Cipher cipher = Cipher.getInstance("RSA"); cipher.init(Cipher.ENCRYPT_MODE, pubkey);//设置为加密模式 byte[] jmdata = cipher.doFinal(data.getBytes()); //打印加密后数据 System.out.println(new String(Hex.encodeHex(jmdata))); //改为解密模式进行解密 cipher.init(Cipher.DECRYPT_MODE, prikey);//会用私钥解密 jmdata = cipher.doFinal(jmdata); System.out.println(new String(jmdata)); } }
在web应用中,我们可以通过js进行前端加密,java进行后台解密,已达到我们的目的。这里需要注意的是,要想实现正确的加密解密算法,需要使用bcprov-ext-jdk15on-147.jar。
首先创建系统的密钥提供者:
package com.jb.test; import java.security.KeyPair; import java.security.KeyPairGenerator; import java.security.PrivateKey; import java.security.PublicKey; import java.security.SecureRandom; import org.apache.commons.codec.binary.Hex; import org.bouncycastle.jcajce.provider.asymmetric.rsa.BCRSAPublicKey; import org.bouncycastle.jce.provider.BouncyCastleProvider; /** * RSA初始化类 * @author nmm * 结合前台的js使用的话,主要需要指定密钥提供者,即引入bcprov-ext-jdk15on-147.jar并使用其中的提供者 */ public class RsaInitUtil { private static KeyPair keyPair; private static RsaInitUtil util; private RsaInitUtil(){ try { if(keyPair == null) { //如果想要能够解密js的加密文件,使用此提供者是必须的 KeyPairGenerator keygen = KeyPairGenerator.getInstance("RSA", new BouncyCastleProvider()); SecureRandom random = new SecureRandom(); random.setSeed(System.currentTimeMillis()); keygen.initialize(512, random);//设置512位长度 keyPair = keygen.generateKeyPair(); } } catch (Exception e) { e.printStackTrace(); } } public static RsaInitUtil getInstance(){ synchronized ("rsa") { if(util == null) { util = new RsaInitUtil(); } } return util; } /** * * 功能说明:[获取公钥] * @return * 创建者:Nmm, Aug 19, 2013 */ public PublicKey getPublicKey(){ return keyPair.getPublic(); } public PrivateKey getPrivateKey(){ return keyPair.getPrivate(); } /** * * 功能说明:[获取公钥字符串] * @return * 创建者:Nmm, Aug 19, 2013 */ public String getPublicKeyStr(){ //根据我们的提供者,这里获取的是该类型公钥 BCRSAPublicKey pk = (BCRSAPublicKey) getPublicKey(); String str = new String(Hex.encodeHex(pk.getModulus().toByteArray())); System.out.println(str); //获取入口10001一般都为这个 String ss = new String(Hex.encodeHex(pk.getPublicExponent().toByteArray())); //获取转换字符串 System.out.println(b2Hex(pk.getModulus().toByteArray())); return ss + str; } /** * * 功能说明:[手动转换] * @param byteArray * @return * 创建者:Nmm, Aug 19, 2013 */ private String b2Hex(byte[] byteArray) { StringBuilder sb = new StringBuilder(); for(int i = 0; i < byteArray.length; i++ ) { int zhz = byteArray[i]; if(zhz < 0) { zhz += 256; } if(zhz < 16) { sb.append("0"); } sb.append(Integer.toHexString(zhz)); } return sb.toString(); } }
前台引入RSA.js,BigInt.js和Barrett.js并采用如下方法加密:
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%> <%@page import="com.jb.test.RsaInitUtil"%> <% RsaInitUtil rsa = RsaInitUtil.getInstance(); String my = rsa.getPublicKeyStr(); String exp = my.substring(0,6); String mou = my.substring(6); %> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <html> <head> <title>RSA测试</title> <script type="text/javascript" src="RSA.js"></script> <script type="text/javascript" src="BigInt.js"></script> <script type="text/javascript" src="Barrett.js"></script> </head> <body> </body> </html> <script type="text/javascript"> var m = '<%=mou%>'; var e = '<%=exp%>'; var key = ''; setMaxDigits(128); alert(e); key = new RSAKeyPair(e,'',m); var res = encryptedString(key,encodeURIComponent('测试数据')); window.location.href = 'rsaDecTry.do?res=' + res; </script>
后台解密算法为:
package com.jb.test; import java.net.URLDecoder; import java.security.NoSuchAlgorithmException; import javax.crypto.Cipher; import javax.crypto.NoSuchPaddingException; import org.apache.commons.codec.binary.Hex; import org.bouncycastle.jce.provider.BouncyCastleProvider; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; /** * Rsa加密的控制层 * @author nmm * */ @Controller("rsaController") public class RsaController { private RsaInitUtil rsaUtil = RsaInitUtil.getInstance(); /** * * 功能说明:[解密方法] * @param res * 创建者:Nmm, Aug 19, 2013 * @throws NoSuchPaddingException * @throws NoSuchAlgorithmException */ @RequestMapping("rsaDecTry.do") public void decodeTry(String res) throws Exception { Cipher cipher = Cipher.getInstance("RSA",new BouncyCastleProvider());//必须指定此提供者 cipher.init(Cipher.DECRYPT_MODE, rsaUtil.getPrivateKey()); System.out.println(res); byte[] buff = cipher.doFinal(Hex.decodeHex(res.toCharArray())); //将字符串转为字符 StringBuilder sb = new StringBuilder(new String(buff,"UTF-8")); //解密后的内容是倒叙的 sb.reverse(); //进行URL解密,主要是为了中文乱码问题 String result = URLDecoder.decode(sb.toString(), "UTF-8"); System.out.println(result); } }
至此可完成,整个加密解密过程,下面大家可以把rsa相关的内容全部整合到一个工具类中,不用想这里处理。
下面为RSA加密解密工具类:
package com.jb.framework.filter; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import java.math.BigInteger; import java.net.URLDecoder; import java.security.KeyFactory; import java.security.KeyPair; import java.security.KeyPairGenerator; import java.security.NoSuchAlgorithmException; import java.security.PrivateKey; import java.security.PublicKey; import java.security.SecureRandom; import java.security.spec.RSAPrivateKeySpec; import java.security.spec.RSAPublicKeySpec; import java.util.Calendar; import javax.crypto.Cipher; import org.apache.commons.codec.binary.Hex; import org.bouncycastle.jcajce.provider.asymmetric.rsa.BCRSAPublicKey; import org.bouncycastle.jce.provider.BouncyCastleProvider; /** * * @Package: com.jb.framework.filter<br> * @ClassName: RSAUtil<br> * @Description: RSA加密工具类,这里我们是每次系统启动时声称一套公钥,私钥,因此不能将加密串存入数据库中,如果要这么做可以预先生成密钥队写入到文件中<br> */ public class RSAUtil { private RSAUtil(){} public static final String keyPubFile = "rsaPubKey.bin"; public static final String keyPriFile = "rsaPriKey.bin"; private static RSAUtil rsa; //密钥生成器 private PublicKey publicKey; //密钥队 private PrivateKey privateKey; public static RSAUtil getInstance(){ synchronized ("rsa") { if(rsa == null) { rsa = new RSAUtil(); rsa.init(); } } return rsa; } /** * * @Title: init * @Description: 初始化方法 * void * @throws */ private void init() { //构建RSA算法 try { KeyPairGenerator kengen = KeyPairGenerator.getInstance("RSA",new BouncyCastleProvider()); //构建随机种子 SecureRandom random = new SecureRandom(); random.setSeed(Calendar.getInstance().getTimeInMillis()); kengen.initialize(512, random);//采用512位加密 KeyPair keyPair = kengen.generateKeyPair(); publicKey = keyPair.getPublic(); privateKey = keyPair.getPrivate(); } catch (NoSuchAlgorithmException e) { e.printStackTrace(); } } /** * * @Title: getPublicKey * @Description: 获取公钥 * @return * PublicKey * @throws */ public PublicKey getPublicKey(){ return this.publicKey; } /** * * @Title: getPrivateKey * @Description: 获取私钥 * @return * PrivateKey * @throws */ public PrivateKey getPrivateKey(){ return this.privateKey; } /** * * @Title: getPublicKeyStr * @Description: 获取系统公钥字符串,前6位为exponentk,后面为modlus * @return * String * @throws */ public String getPublicKeyStr(){ BCRSAPublicKey pk = (BCRSAPublicKey) getPublicKey(); String pubStr = ""; pubStr += b2hex(pk.getPublicExponent().toByteArray()); pubStr += b2hex(pk.getModulus().toByteArray()); return pubStr; } /** * * @Title: entryText * @Description: 使用默认公钥进行加密 * @param text * @return * String * @throws */ public String encryText(String text) { return encryText(text,getPublicKey()); } /** * * @Title: entryText * @Description: 使用指定公钥进行加密,解决长字符串加密 * @param text * @param publicKey2 * @return * String * @throws */ public String encryText(String text, PublicKey pk) { try { Cipher cipher = Cipher.getInstance("RSA",new BouncyCastleProvider()); cipher.init(Cipher.ENCRYPT_MODE, pk); int block = cipher.getBlockSize();//获取最大加密块 int j = 0; StringBuilder sb = new StringBuilder(); byte[] targetData = text.getBytes("UTF-8"); while (targetData.length - j*block > 0) { byte[] jmdata = cipher.doFinal(targetData,j*block,Math.min(targetData.length - j*block, block)); sb.append(b2hex(jmdata)); j++; } return sb.toString(); } catch (Exception e) { e.printStackTrace(); } return null; } /** * * @Title: decryText * @Description: 使用默认的私钥进行解密解密算法 * @param text * @return * String * @throws */ public String decryText(String text) { return decryText(text,getPrivateKey()); } /** * * @Title: decryText * @Description: 指定私钥进行解密,增加对于大字符串的解密操作 * @param text * @param privateKey2 * @return * String * @throws */ public String decryText(String text, PrivateKey pk) { try { Cipher cipher = Cipher.getInstance("RSA", new BouncyCastleProvider()); cipher.init(Cipher.DECRYPT_MODE, pk); byte[] targetBuff = Hex.decodeHex(text.replace(" ", "").toCharArray()); int block = cipher.getBlockSize(); int j = 0; StringBuilder sb = new StringBuilder(); while (targetBuff.length - j * block > 0) { byte[] jmdata = cipher.doFinal(targetBuff,j*block,block); sb.append(new String(jmdata,"UTF-8")); j++; } return sb.toString(); } catch (Exception e) { e.printStackTrace(); } return null; } /** * * @Title: decryTextByUrl * @Description: 解密前台传递的加密串,为防止中文乱码,前台字符串最好使用encodeURIComponent方法进行url编码 * @param text * @return * String * @throws */ public String decryTextByUrl(String text) { try { Cipher cipher = Cipher.getInstance("RSA", new BouncyCastleProvider()); cipher.init(Cipher.DECRYPT_MODE, getPrivateKey()); byte[] targetBuff = Hex.decodeHex(text.replace(" ", "").toCharArray()); int block = cipher.getBlockSize(); int j = 0; StringBuilder sb = new StringBuilder(); while (targetBuff.length - j * block > 0) {//处理大字符串的加密解密处理 byte[] jmdata = cipher.doFinal(targetBuff,j*block,block); sb.append(new StringBuilder(new String(jmdata,"UTF-8")).reverse()); j++; } String res = URLDecoder.decode(sb.toString(), "UTF-8"); return res; } catch (Exception e) { e.printStackTrace(); } return null; } /** * * @Title: createPubKey * @Description: 根据指定的幂和模式生成公钥 * @param exponent * @param modules * @return * PublicKey * @throws */ public PublicKey createPubKey(byte[] exponent,byte[]modules) { try { KeyFactory keyFactory = KeyFactory.getInstance("RSA", new BouncyCastleProvider()); RSAPublicKeySpec rsaKs = new RSAPublicKeySpec(new BigInteger(modules),new BigInteger(exponent)); return keyFactory.generatePublic(rsaKs); } catch (Exception e) { e.printStackTrace(); } return null; } /** * * @Title: createPubKey * @Description: 根据指定的幂和模式生成公钥 * @param exponent * @param modules * @return * PublicKey * @throws */ public PrivateKey createPriKey(byte[] exponent,byte[]modules) { try { KeyFactory keyFactory = KeyFactory.getInstance("RSA", new BouncyCastleProvider()); RSAPrivateKeySpec rsaKs = new RSAPrivateKeySpec(new BigInteger(modules),new BigInteger(exponent)); return keyFactory.generatePrivate(rsaKs); } catch (Exception e) { e.printStackTrace(); } return null; } /** * * @Title: saveKeyToFile * @Description: 保存公钥和私钥到文件中 * void * @throws */ public void saveKeyToFile() { PublicKey pk = getPublicKey(); PrivateKey prik = getPrivateKey(); String path = RSAUtil.class.getClassLoader().getResource("").getPath(); ObjectOutputStream outPub = null; ObjectOutputStream outPri = null; try { System.out.println(path + keyPubFile); outPub = new ObjectOutputStream(new FileOutputStream(path + keyPubFile)); outPri = new ObjectOutputStream(new FileOutputStream(path + keyPriFile)); outPub.writeObject(pk); outPri.writeObject(prik); } catch (Exception e) { e.printStackTrace(); }finally { try { outPub.close(); outPri.close(); } catch (IOException e) { e.printStackTrace(); } } } /** * * @Title: readKey * @Description: 读取密钥 * @param isPub * @return * Object * @throws */ public Object readKey(boolean isPub) { String path = RSAUtil.class.getClassLoader().getResource("").getPath(); ObjectInputStream in = null; try { if(isPub) { path += keyPubFile; in = new ObjectInputStream(new FileInputStream(path)); PublicKey pk = (PublicKey) in.readObject(); return pk; }else { path += keyPriFile; in = new ObjectInputStream(new FileInputStream(path)); PrivateKey pk = (PrivateKey) in.readObject(); return pk; } } catch (Exception e) { e.printStackTrace(); }finally { try { in.close(); } catch (IOException e) { e.printStackTrace(); } } return null; } /** * * @Title: b2hex * @Description: 将二进制转为16进制字符串 * @param buff * @return * String * @throws */ public String b2hex(byte[] buff) { StringBuilder sb = new StringBuilder(); for(int i = 0; i < buff.length; i++) { int z = buff[i]; if(z < 0) { z+= 256; } if(z < 16) { sb.append("0"); } sb.append(Integer.toHexString(z)); } return sb.toString(); } }
下载:http://xiazai.jb51.net/201808/yuanma/rsajar_jb51.rar
总结
以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,如果有疑问大家可以留言交流,谢谢大家对脚本之家的支持。
相关文章
使用IDEA创建servlet JavaWeb 应用及使用Tomcat本地部署的实现
本文主要介绍了使用IDEA创建servlet JavaWeb 应用及使用Tomcat本地部署2022-01-01springboot项目中引入本地依赖jar包并打包到lib文件夹中
这篇文章主要介绍了springboot项目中引入本地依赖jar包,如何打包到lib文件夹中,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下2023-04-04解决SpringMVC @RequestMapping不设置value出现的问题
这篇文章主要介绍了解决SpringMVC @RequestMapping不设置value出现的问题,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教2021-08-08
最新评论