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://download.csdn.net/detail/niemingming/5977395




  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值