最近在看,网络安全方面的问题,我们可以使用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();
- }
- }
- <%@ 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加密解密工具类:
- 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();
- }
- }