Java-web中利用RSA進(jìn)行加密解密操作的方法示例
前言
最近在看,網(wǎng)絡(luò)安全方面的問(wèn)題,我們可以使用RSA進(jìn)行非對(duì)稱加密防止,獲取用戶信息。首先我們看下java下操作RSA進(jìn)行加密解密算法,代碼如下:
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();//獲取所有支持的加密算法
//采用非對(duì)稱加密解密算法
//生成密鑰實(shí)例
KeyPairGenerator keygen = KeyPairGenerator.getInstance("RSA");
SecureRandom random = new SecureRandom();
random.setSeed(System.currentTimeMillis());//設(shè)置隨機(jī)種子
keygen.initialize(512, random);//設(shè)置密鑰長(zhǎng)度,應(yīng)為64的整數(shù)倍
//生成密鑰公鑰對(duì)
KeyPair keyPair = keygen.generateKeyPair();
//獲取公鑰
PublicKey pubkey = keyPair.getPublic();
//獲取私鑰
PrivateKey prikey = keyPair.getPrivate();
//測(cè)試數(shù)據(jù)
String data = "測(cè)試數(shù)據(jù)";
//使用公鑰進(jìn)行加密
//構(gòu)建加密解密類
Cipher cipher = Cipher.getInstance("RSA");
cipher.init(Cipher.ENCRYPT_MODE, pubkey);//設(shè)置為加密模式
byte[] jmdata = cipher.doFinal(data.getBytes());
//打印加密后數(shù)據(jù)
System.out.println(new String(Hex.encodeHex(jmdata)));
//改為解密模式進(jìn)行解密
cipher.init(Cipher.DECRYPT_MODE, prikey);//會(huì)用私鑰解密
jmdata = cipher.doFinal(jmdata);
System.out.println(new String(jmdata));
}
}
在web應(yīng)用中,我們可以通過(guò)js進(jìn)行前端加密,java進(jìn)行后臺(tái)解密,已達(dá)到我們的目的。這里需要注意的是,要想實(shí)現(xiàn)正確的加密解密算法,需要使用bcprov-ext-jdk15on-147.jar。
首先創(chuàng)建系統(tǒng)的密鑰提供者:
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
* 結(jié)合前臺(tái)的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);//設(shè)置512位長(zhǎng)度
keyPair = keygen.generateKeyPair();
}
} catch (Exception e) {
e.printStackTrace();
}
}
public static RsaInitUtil getInstance(){
synchronized ("rsa") {
if(util == null) {
util = new RsaInitUtil();
}
}
return util;
}
/**
*
* 功能說(shuō)明:[獲取公鑰]
* @return
* 創(chuàng)建者:Nmm, Aug 19, 2013
*/
public PublicKey getPublicKey(){
return keyPair.getPublic();
}
public PrivateKey getPrivateKey(){
return keyPair.getPrivate();
}
/**
*
* 功能說(shuō)明:[獲取公鑰字符串]
* @return
* 創(chuàng)建者:Nmm, Aug 19, 2013
*/
public String getPublicKeyStr(){
//根據(jù)我們的提供者,這里獲取的是該類型公鑰
BCRSAPublicKey pk = (BCRSAPublicKey) getPublicKey();
String str = new String(Hex.encodeHex(pk.getModulus().toByteArray()));
System.out.println(str);
//獲取入口10001一般都為這個(gè)
String ss = new String(Hex.encodeHex(pk.getPublicExponent().toByteArray()));
//獲取轉(zhuǎn)換字符串
System.out.println(b2Hex(pk.getModulus().toByteArray()));
return ss + str;
}
/**
*
* 功能說(shuō)明:[手動(dòng)轉(zhuǎn)換]
* @param byteArray
* @return
* 創(chuàng)建者: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();
}
}
前臺(tái)引入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測(cè)試</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('測(cè)試數(shù)據(jù)'));
window.location.href = 'rsaDecTry.do?res=' + res;
</script>
后臺(tái)解密算法為:
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();
/**
*
* 功能說(shuō)明:[解密方法]
* @param res
* 創(chuàng)建者: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()));
//將字符串轉(zhuǎn)為字符
StringBuilder sb = new StringBuilder(new String(buff,"UTF-8"));
//解密后的內(nèi)容是倒敘的
sb.reverse();
//進(jìn)行URL解密,主要是為了中文亂碼問(wèn)題
String result = URLDecoder.decode(sb.toString(), "UTF-8");
System.out.println(result);
}
}
至此可完成,整個(gè)加密解密過(guò)程,下面大家可以把rsa相關(guān)的內(nèi)容全部整合到一個(gè)工具類中,不用想這里處理。
下面為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加密工具類,這里我們是每次系統(tǒng)啟動(dòng)時(shí)聲稱一套公鑰,私鑰,因此不能將加密串存入數(shù)據(jù)庫(kù)中,如果要這么做可以預(yù)先生成密鑰隊(duì)寫入到文件中<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;
//密鑰隊(duì)
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() {
//構(gòu)建RSA算法
try {
KeyPairGenerator kengen = KeyPairGenerator.getInstance("RSA",new BouncyCastleProvider());
//構(gòu)建隨機(jī)種子
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: 獲取系統(tǒng)公鑰字符串,前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: 使用默認(rèn)公鑰進(jìn)行加密
* @param text
* @return
* String
* @throws
*/
public String encryText(String text) {
return encryText(text,getPublicKey());
}
/**
*
* @Title: entryText
* @Description: 使用指定公鑰進(jìn)行加密,解決長(zhǎng)字符串加密
* @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: 使用默認(rèn)的私鑰進(jìn)行解密解密算法
* @param text
* @return
* String
* @throws
*/
public String decryText(String text) {
return decryText(text,getPrivateKey());
}
/**
*
* @Title: decryText
* @Description: 指定私鑰進(jìn)行解密,增加對(duì)于大字符串的解密操作
* @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: 解密前臺(tái)傳遞的加密串,為防止中文亂碼,前臺(tái)字符串最好使用encodeURIComponent方法進(jìn)行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: 根據(jù)指定的冪和模式生成公鑰
* @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: 根據(jù)指定的冪和模式生成公鑰
* @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: 將二進(jìn)制轉(zhuǎn)為16進(jìn)制字符串
* @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
總結(jié)
以上就是這篇文章的全部?jī)?nèi)容了,希望本文的內(nèi)容對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,如果有疑問(wèn)大家可以留言交流,謝謝大家對(duì)腳本之家的支持。
相關(guān)文章
Java實(shí)現(xiàn)刪除PDF中指定頁(yè)面
這篇文章主要為大家詳細(xì)介紹了如何使用一個(gè)免費(fèi)的國(guó)產(chǎn)Java庫(kù)來(lái)刪除PDF中的指定頁(yè)面或者刪除PDF中的空白頁(yè),感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下2023-11-11
Java使用Tesseract-Ocr識(shí)別數(shù)字
這篇文章主要介紹了Java使用Tesseract-Ocr識(shí)別數(shù)字的方法,幫助大家更好的理解和學(xué)習(xí)使用Java,感興趣的朋友可以了解下2021-04-04
聊聊Java BigInteger里面的mod和remainder的區(qū)別
這篇文章主要介紹了聊聊Java BigInteger里面的mod和remainder的區(qū)別,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-08-08
SpringBoot MongoDB 索引沖突分析及解決方法
這篇文章主要介紹了SpringBoot MongoDB 索引沖突分析及解決方法,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2018-11-11

