java rsa 加密_Java-web中利用RSA进行加密解密操作的方法示例

这篇博客详细介绍了在Java环境下如何使用RSA算法进行加密和解密操作,包括生成密钥对、前端JS加密、后台Java解密的流程。同时,强调了在Web应用中结合前端和后端进行加密解密的重要性,并提到了必须使用bcprov-ext-jdk15on-147.jar库来确保正确解密。此外,还提供了具体的代码示例和关键类的实现,如RsaInitUtil和RSAUtil工具类。
摘要由CSDN通过智能技术生成

前言

最近在看,网络安全方面的问题,我们可以使用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并采用如下方法加密:

RsaInitUtil rsa = RsaInitUtil.getInstance();

String my = rsa.getPublicKeyStr();

String exp = my.substring(0,6);

String mou = my.substring(6);

%>

RSA测试

var m = '';

var e = '';

var key = '';

setMaxDigits(128);

alert(e);

key = new RSAKeyPair(e,'',m);

var res = encryptedString(key,encodeURIComponent('测试数据'));

window.location.href = 'rsaDecTry.do?res=' + res;

后台解密算法为:

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

* @ClassName: RSAUtil

* @Description: RSA加密工具类,这里我们是每次系统启动时声称一套公钥,私钥,因此不能将加密串存入数据库中,如果要这么做可以预先生成密钥队写入到文件中

*/

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();

}

}

总结

以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,如果有疑问大家可以留言交流,谢谢大家对脚本之家的支持。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值