java使用RSA與AES加密解密的實(shí)例代碼詳解
首先了解下,什么是堆成加密,什么是非對(duì)稱加密?
對(duì)稱加密:加密與解密的密鑰是相同的,加解密速度很快,比如AES
非對(duì)稱加密:加密與解密的秘鑰是不同的,速度較慢,比如RSA
•先看代碼(先會(huì)用在研究)
相關(guān)依賴:
<dependency> <groupId>org.bouncycastle</groupId> <artifactId>bcprov-jdk15on</artifactId> <version>1.58</version> </dependency>
1,RSA工具類:
package cn.wangtao.utils;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.crypto.Cipher;
import java.io.ByteArrayOutputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectOutputStream;
import java.security.*;
import java.security.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPublicKey;
/**
* @ClassName RSAUtils
* @Auth 桃子
* @Date 2019-6-25 15:15
* @Version 1.0
* @Description
**/
public class RSAUtils {
private static final String RSA = "RSA"; // 加密方式
private static final Logger logger= LoggerFactory.getLogger(RSAUtils.class);
//獲取密鑰
public static KeyPair getKey() throws Exception {
try {
KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance(RSA, new BouncyCastleProvider());
keyPairGenerator.initialize(2048); // 初始化密鑰長(zhǎng)度
KeyPair keyPair = keyPairGenerator.generateKeyPair();// 生成密鑰對(duì)
return keyPair;
} catch (Exception e) {
logger.error("獲取RSA秘鑰對(duì)異常",e);
throw new Exception("獲取RSA秘鑰對(duì)異常",e);
}
}
//利用公鑰進(jìn)行加密
public static String encryptStr(RSAPublicKey publicKey, String str) throws Exception {
try {
Cipher cipher = Cipher.getInstance(RSA, new BouncyCastleProvider());
cipher.init(Cipher.ENCRYPT_MODE, publicKey);
//加密
byte[] bytes = getBytes(str.getBytes(), cipher);
//2進(jìn)行轉(zhuǎn)換成16進(jìn)制
String result = CommonUtils.parseByte2HexStr(bytes);
return result;
} catch (Exception e) {
logger.error("使用RSA公鑰進(jìn)行加密異常",e);
throw new Exception("使用RSA公鑰進(jìn)行加密異常",e);
}
}
//利用私鑰進(jìn)行解密
public static String decryptStr(RSAPrivateKey privateKey, String str) throws Exception {
try {
Cipher cipher = Cipher.getInstance(RSA, new BouncyCastleProvider());
cipher.init(Cipher.DECRYPT_MODE, privateKey); // 用密鑰初始化此Cipher對(duì)象
//16進(jìn)制轉(zhuǎn)換成2進(jìn)制
byte[] bytes = CommonUtils.parseHexStr2Byte(str);
//解密
byte[] bs = getBytes(bytes, cipher);
String content=new String(bs,"utf-8");
return content;
} catch (Exception e) {
logger.error("使用RSA私鑰進(jìn)行解密異常",e);
throw new Exception("使用RSA私鑰進(jìn)行解密異常",e);
}
}
//通過cipher獲取字節(jié)數(shù)組
public static byte[] getBytes(byte[] bytes,Cipher cipher) throws Exception {
int blockSize = cipher.getBlockSize(); // 返回塊的大小
int j = 0;
ByteArrayOutputStream baos = new ByteArrayOutputStream();
while (bytes.length - j * blockSize > 0) { // 將二進(jìn)制數(shù)據(jù)分塊寫入ByteArrayOutputStream中
if(bytes.length-j*blockSize>blockSize){
baos.write(cipher.doFinal(bytes, j * blockSize, blockSize));
}else{
baos.write(cipher.doFinal(bytes, j * blockSize,bytes.length-j*blockSize));
}
j++;
}
baos.close();
byte[] byteArray = baos.toByteArray();
return byteArray;
}
//保存秘鑰對(duì)到文件
public void saveRSAKey(String fileName) throws Exception {
FileOutputStream fos=null;
ObjectOutputStream oos=null;
try {
KeyPair keyPair = getKey();
fos=new FileOutputStream(fileName);
oos=new ObjectOutputStream(fos); //對(duì)象序列號(hào)
oos.writeObject(keyPair);
} catch (Exception e) {
logger.error("RSA秘鑰對(duì)保存到文件異常[{}]",fileName,e);
throw new Exception("RSA秘鑰對(duì)保存到文件異常",e);
}finally {
if(oos!=null){
try {
oos.close();
} catch (IOException e1) {
e1.printStackTrace();
}
}
if(fos!=null){
try {
fos.close();
} catch (IOException e1) {
e1.printStackTrace();
}
}
}
}
}
2,CommonUtils通用工具類:
package cn.wangtao.utils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.IOException;
import java.io.Reader;
import java.io.Writer;
/**
* @ClassName CommonUtils
* @Auth 桃子
* @Date 2019-6-27 12:51
* @Version 1.0
* @Description
**/
public class CommonUtils {
private static final Logger logger= LoggerFactory.getLogger(CommonUtils.class);
//編碼方式
public static final String CODE_TYPE = "UTF-8";
//字符補(bǔ)全
private static final String[] consult = new String[]{"0","1","2","3","4","5","6","7","8","9","A","B","C","D","E","F","G"};
//關(guān)流
public static void closeReaderandWriter(Reader reader, Writer writer){
if(writer!=null){
try {
writer.close();
} catch (IOException e) {
logger.error("關(guān)閉輸出流失敗",e);
}
}
if(reader!=null){
try {
reader.close();
} catch (IOException e) {
logger.error("關(guān)閉輸出流失敗",e);
}
}
}
//將16進(jìn)制轉(zhuǎn)換為二進(jìn)制
public static byte[] parseHexStr2Byte(String hexStr) {
if (hexStr.length() < 1)
return null;
byte[] result = new byte[hexStr.length()/2];
for (int i = 0;i< hexStr.length()/2; i++) {
int high = Integer.parseInt(hexStr.substring(i*2, i*2+1), 16);
int low = Integer.parseInt(hexStr.substring(i*2+1, i*2+2), 16);
result[i] = (byte) (high * 16 + low);
}
return result;
}
//將二進(jìn)制轉(zhuǎn)換成16進(jìn)制
public static String parseByte2HexStr(byte buf[]) {
StringBuffer sb = new StringBuffer();
for (int i = 0; i < buf.length; i++) {
String hex = Integer.toHexString(buf[i] & 0xFF);
if (hex.length() == 1) {
hex = '0' + hex;
}
sb.append(hex.toUpperCase());
}
return sb.toString();
}
//補(bǔ)全字符
public static String completionCodeFor16Bytes(String str) throws Exception {
try{
int num = str.getBytes(CODE_TYPE).length;
int index = num%16;
//進(jìn)行加密內(nèi)容補(bǔ)全操作, 加密內(nèi)容應(yīng)該為 16字節(jié)的倍數(shù), 當(dāng)不足16*n字節(jié)是進(jìn)行補(bǔ)全, 差一位時(shí) 補(bǔ)全16+1位
//補(bǔ)全字符 以 $ 開始,$后一位代表$后補(bǔ)全字符位數(shù),之后全部以0進(jìn)行補(bǔ)全;
if(index != 0){
StringBuffer sbBuffer = new StringBuffer(str);
if(16-index == 1){
sbBuffer.append("$" + consult[16-1] + addStr(16-1-1));
}else{
sbBuffer.append("$" + consult[16-index-1] + addStr(16-index-1-1));
}
str = sbBuffer.toString();
}
return str;
}catch (Exception e){
logger.error("使用AES加密前補(bǔ)全字符異常",e);
throw new Exception("使用AES加密前補(bǔ)全字符異常",e);
}
}
//追加字符
public static String addStr(int num){
StringBuffer sbBuffer = new StringBuffer("");
for (int i = 0; i < num; i++) {
sbBuffer.append("0");
}
return sbBuffer.toString();
}
//還原字符(進(jìn)行字符判斷)
public static String resumeCodeOf16Bytes(String str) throws Exception{
int indexOf = str.lastIndexOf("$");
if(indexOf == -1){
return str;
}
String trim = str.substring(indexOf+1,indexOf+2).trim();
int num = 0;
for (int i = 0; i < consult.length; i++) {
if(trim.equals(consult[i])){
num = i;
}
}
if(num == 0){
return str;
}
return str.substring(0,indexOf).trim();
}
}
3,AESUtils通用工具類:
package cn.wangtao.utils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.crypto.Cipher;
import javax.crypto.spec.SecretKeySpec;
import java.io.*;
import java.security.interfaces.RSAPrivateKey;
import java.util.Map;
/**
* @ClassName AESUtils
* @Auth 桃子
* @Date 2019-6-27 12:05
* @Version 1.0
* @Description
**/
public class AESUtils {
private static final Logger logger= LoggerFactory.getLogger(AESUtils.class);
//填充類型
public static final String AES_TYPE = "AES/ECB/PKCS5Padding";
private static final String AES = "AES"; // 加密方式
public static final String DES_TYPE = "DES/ECB/PKCS5Padding";
private static final String DES = "DES"; // 加密方式
private final String defaultDesKey="11112222";//8位
//對(duì)字符串加密
public static String encryptStr(String content,String aesKey) throws Exception {
try {
SecretKeySpec key = new SecretKeySpec(aesKey.getBytes(),AES );
Cipher cipher = Cipher.getInstance(AES_TYPE);
cipher.init(Cipher.ENCRYPT_MODE, key);
//字符補(bǔ)全
String content16Str = CommonUtils.completionCodeFor16Bytes(content);
byte[] encryptedData = cipher.doFinal(content16Str.getBytes(CommonUtils.CODE_TYPE));
//2進(jìn)制轉(zhuǎn)換成16進(jìn)制
String hexStr = CommonUtils.parseByte2HexStr(encryptedData);
return hexStr;
} catch (Exception e) {
logger.error("使用AES對(duì)字符串加密異常",e);
throw new Exception("使用AES對(duì)字符串加密異常",e);
}
}
//對(duì)字符串解密
public static String decryptStr(String content,String aesKey) throws Exception {
try {
//16進(jìn)制轉(zhuǎn)換成2進(jìn)制
byte[] bytes = CommonUtils.parseHexStr2Byte(content);
SecretKeySpec key = new SecretKeySpec(
aesKey.getBytes(), AES);
Cipher cipher = Cipher.getInstance(AES_TYPE);
cipher.init(Cipher.DECRYPT_MODE, key);
byte[] decryptedData = cipher.doFinal(bytes);
String result=new String(decryptedData, CommonUtils.CODE_TYPE);
//還原字符
String orgResult = CommonUtils.resumeCodeOf16Bytes(result);
return orgResult;
} catch (Exception e) {
logger.error("使用AES對(duì)字符串解密異常",e);
throw new Exception("使用AES對(duì)字符串解密異常",e);
}
}
//對(duì)文件加密
public static File encryptFile(File orgFile, File encryptFile, Map<String,Object> context) throws Exception {
logger.info("使用AES對(duì)文件加密開始,源文件地址[{}]加密后文件地址[{}]",orgFile.getPath(),encryptFile.getPath());
BufferedReader br=null;
BufferedWriter bw=null;
try{
//獲取AESKEY ,如果沒有為默認(rèn)
String aesKey = (String) context.get(Dirt.AES_KEY);
br=new BufferedReader(new FileReader(orgFile));
bw=(BufferedWriter)context.get(Dirt.BUFFEREDWRITER);
if(null==bw){
bw=new BufferedWriter(new FileWriter(encryptFile));
}
String len=null;
while (null!=(len=br.readLine())){
String encrypt= encryptStr(len,aesKey);
bw.write(encrypt);
bw.newLine();
bw.flush();
}
logger.info("使用AES對(duì)文件加密結(jié)束,源文件地址[{}]加密后文件地址[{}]",orgFile.getPath(),encryptFile.getPath());
return encryptFile;
}catch (Exception e){
logger.error("使用AES對(duì)文件加密異常,源文件地址[{}]加密后文件地址[{}]",orgFile.getPath(),encryptFile.getPath(),e);
throw new Exception("使用AES對(duì)文件加密異常",e);
}finally {
CommonUtils.closeReaderandWriter(br,bw);
}
}
//對(duì)文本解密,返回解密文件后的文件
public static File decryptFile(File decryptfile, File encryptFile,Map<String,Object> context) throws Exception {
logger.info("使用AES對(duì)文件解密開始,源加密文件地址[{}]解密后文件地址[{}]",encryptFile.getPath(),decryptfile.getPath());
BufferedReader br=null;
BufferedWriter bw=null;
try{
if(decryptfile.exists()){
decryptfile.delete();
}
//邊讀邊加密邊寫
br=new BufferedReader(new FileReader(encryptFile));
bw=new BufferedWriter(new FileWriter(decryptfile));
String len=null;
String aesKey=null;
//判斷是否加密
RSAPrivateKey privateKey= (RSAPrivateKey) context.get(Dirt.RSAPRIVATEKEY);
if(null!=privateKey){
StringBuffer sb=new StringBuffer();
while ((len=br.readLine())!=null){
sb.append(len);
if(len.equals("\n")||len.equals("")||len.equals("\r\n")||len.equals("\r")){
aesKey=RSAUtils.decryptStr(privateKey,sb.toString());
break;
}
}
}
if(null==aesKey){
aesKey=(String) context.get(Dirt.AES_KEY);
}
logger.info("aesKey[{}]",aesKey);
if(aesKey!=null){
while ((len=br.readLine())!=null){
String decrypt= decryptStr(len,aesKey);
bw.write(decrypt);
bw.flush();
bw.newLine();
}
}
logger.info("使用AES對(duì)文件解密結(jié)束,源加密文件地址[{}]解密后文件地址[{}]",encryptFile.getPath(),decryptfile.getPath());
return decryptfile;
}catch (Exception e){
logger.error("使用AES對(duì)文件解密異常,源加密文件地址[{}]解密后文件地址[{}]",encryptFile.getPath(),decryptfile.getPath(),e);
throw new Exception("使用AES對(duì)文件解密異常",e);
}finally {
CommonUtils.closeReaderandWriter(br,bw);
}
}
}
4,Dirt常量
package cn.wangtao.utils;
import java.security.interfaces.RSAPublicKey;
/**
* @ClassName Dirt
* @Auth 桃子
* @Date 2019-6-27 14:20
* @Version 1.0
* @Description
**/
public class Dirt {
public static final String UPLOADFILEURL="uploadFileUrl";
public static final String AES_KEY="aesKey";
public static final String RSAPUBLICKEY="rsaPublicKey";
public static final String RSAPRIVATEKEY="rsaPrivateKey";
public final static String RETURNCODE="returnCode";
public final static String RETURNMSG="returnMsg";
public final static String FILENAME="fileName";
public final static String ORGFILENAME="orgFileName";
public final static String ENCRYPTFILE="encryptFile";
public static final String BUFFEREDWRITER="bufferedWriter"; //是為了在原始文件中進(jìn)行補(bǔ)充加密
//返回碼
public final static String SUCCESSCODE="000000";
public final static String FAILEDCODE="999999";
//加密文件所放的目錄
public final static String BASELOCALDIR="XXX"; //基本目錄路徑
public final static String ENCRYPTLOCALDIR="encrypt"; //加密文件目錄
總結(jié)
以上所述是小編給大家介紹的java使用RSA與AES加密解密的實(shí)例代碼詳解 ,希望對(duì)大家有所幫助,如果大家有任何疑問請(qǐng)給我留言,小編會(huì)及時(shí)回復(fù)大家的。在此也非常感謝大家對(duì)腳本之家網(wǎng)站的支持!
如果你覺得本文對(duì)你有幫助,歡迎轉(zhuǎn)載,煩請(qǐng)注明出處,謝謝!
相關(guān)文章
詳解Java編程中final,finalize,finally的區(qū)別
這篇文章主要介紹了詳解Java編程中final,finalize,finally的區(qū)別,這個(gè)在Java面試題中簡(jiǎn)直是太常見了...需要的朋友可以參考下2015-11-11
Springboot中Instant時(shí)間傳參及序列化詳解
這篇文章主要介紹了Springboot中Instant時(shí)間傳參及序列化詳解,Instant是Java8引入的一個(gè)精度極高的時(shí)間類型,可以精確到納秒,但實(shí)際使用的時(shí)候不需要這么高的精確度,通常到毫秒就可以了,需要的朋友可以參考下2023-11-11
SpringBoot通過@MatrixVariable進(jìn)行傳參詳解
這篇文章主要介紹了SpringBoot使用@MatrixVariable傳參,文章圍繞@MatrixVariable展開詳細(xì)的內(nèi)容介紹,具有一定的參考價(jià)值,需要的小伙伴可以參考一下2022-06-06
Mybatis-Plus支持GBase8s分頁查詢的實(shí)現(xiàn)示例
本文主要介紹了使?Mybatis-Plus?支持?GBase8s?的分頁查詢,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2023-01-01
springboot打印接口調(diào)用日志的實(shí)例
這篇文章主要介紹了springboot打印接口調(diào)用日志的實(shí)例,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-09-09
java網(wǎng)絡(luò)編程基礎(chǔ)知識(shí)介紹
這篇文章主要介紹了java網(wǎng)絡(luò)編程基礎(chǔ)知識(shí)介紹,涉及OSI分層模型和TCP/IP分層模型的對(duì)應(yīng)關(guān)系、IP地址、端口號(hào)、tcp、udp等相關(guān)內(nèi)容,還是比較不錯(cuò)的,這里分享給大家,供需要的朋友參考。2017-11-11
基于String和List<String>間的相互轉(zhuǎn)換方式
這篇文章主要介紹了基于String和List間的相互轉(zhuǎn)換方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-05-05

