java使用RSA与AES加密解密

2019-08-09 00:00:00 rsa java 加密解密
  • 首先了解下,什么是堆成加密,什么是非对称加密?

  对称加密:加密与解密的密钥是相同的,加解密速度很快,比如AES

  非对称加密:加密与解密的秘钥是不同的,速度较慢,比如RSA

 

  • 先看代码(先会用在研究) 

  相关依赖:

     <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); // 初始化密钥长度 KeyPair keyPair = keyPairGenerator.generateKeyPair();// 生成密钥对 return keyPair; } catch (Exception e) { logger.error("获取RSA秘钥对异常",e); throw new Exception("获取RSA秘钥对异常",e); } } //利用公钥进行加密 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进行转换成16进制 String result = CommonUtils.parseByte2HexStr(bytes); return result; } catch (Exception e) { logger.error("使用RSA公钥进行加密异常",e); throw new Exception("使用RSA公钥进行加密异常",e); } } //利用私钥进行解密 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对象 //16进制转换成2进制 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私钥进行解密异常",e); throw new Exception("使用RSA私钥进行解密异常",e); } } //通过cipher获取字节数组 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) { // 将二进制数据分块写入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; } //保存秘钥对到文件 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); //对象序列号 oos.writeObject(keyPair); } catch (Exception e) { logger.error("RSA秘钥对保存到文件异常[{}]",fileName,e); throw new Exception("RSA秘钥对保存到文件异常",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";

    //字符补全
    private static final String[] consult = new String[]{"0","1","2","3","4","5","6","7","8","9","A","B","C","D","E","F","G"};

    //关流
    public static void closeReaderandWriter(Reader reader, Writer writer){
        if(writer!=null){
            try {
                writer.close();
            } catch (IOException e) {
                logger.error("关闭输出流失败",e);
            }
        }
        if(reader!=null){
            try {
                reader.close();
            } catch (IOException e) {
                logger.error("关闭输出流失败",e);
            }
        }
    }

    //将16进制转换为二进制
    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;
    }

    //将二进制转换成16进制
    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();
    }

    //补全字符
    public static String completionCodeFor16Bytes(String str) throws Exception {
        try{
            int num = str.getBytes(CODE_TYPE).length;
            int index = num%16;
            //进行加密内容补全操作, 加密内容应该为 16字节的倍数, 当不足16*n字节是进行补全, 差一位时 补全16+1位
            //补全字符 以 $ 开始,$后一位代表$后补全字符位数,之后全部以0进行补全;
            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加密前补全字符异常",e);
            throw new Exception("使用AES加密前补全字符异常",e);
        }
    }

    //追加字符
    public static String addStr(int num){
        StringBuffer sbBuffer = new StringBuffer("");
        for (int i = 0; i < num; i++) {
            sbBuffer.append("0");
        }
        return sbBuffer.toString();
    }

    //还原字符(进行字符判断)
    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位

    //对字符串加密
    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);
            //字符补全
            String content16Str = CommonUtils.completionCodeFor16Bytes(content);
            byte[] encryptedData = cipher.doFinal(content16Str.getBytes(CommonUtils.CODE_TYPE));
            //2进制转换成16进制
            String hexStr = CommonUtils.parseByte2HexStr(encryptedData);
            return hexStr;
        } catch (Exception e) {
            logger.error("使用AES对字符串加密异常",e);
            throw new Exception("使用AES对字符串加密异常",e);
        }

    }
    //对字符串解密
    public static String  decryptStr(String content,String aesKey) throws Exception {
        try {
            //16进制转换成2进制
            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对字符串解密异常",e);
            throw new Exception("使用AES对字符串解密异常",e);
        }
    }

    //对文件加密
    public static File encryptFile(File orgFile, File encryptFile, Map<String,Object> context) throws Exception {
        logger.info("使用AES对文件加密开始,源文件地址[{}]加密后文件地址[{}]",orgFile.getPath(),encryptFile.getPath());
        BufferedReader br=null;
        BufferedWriter bw=null;
        try{
            //获取AESKEY ,如果没有为默认
            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对文件加密结束,源文件地址[{}]加密后文件地址[{}]",orgFile.getPath(),encryptFile.getPath());
            return encryptFile;
        }catch (Exception e){
            logger.error("使用AES对文件加密异常,源文件地址[{}]加密后文件地址[{}]",orgFile.getPath(),encryptFile.getPath(),e);
            throw new Exception("使用AES对文件加密异常",e);
        }finally {
            CommonUtils.closeReaderandWriter(br,bw);
        }
    }

    //对文本解密,返回解密文件后的文件
    public static File decryptFile(File decryptfile,  File encryptFile,Map<String,Object> context) throws Exception {
        logger.info("使用AES对文件解密开始,源加密文件地址[{}]解密后文件地址[{}]",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对文件解密结束,源加密文件地址[{}]解密后文件地址[{}]",encryptFile.getPath(),decryptfile.getPath());
            return decryptfile;
        }catch (Exception e){
            logger.error("使用AES对文件解密异常,源加密文件地址[{}]解密后文件地址[{}]",encryptFile.getPath(),decryptfile.getPath(),e);
            throw new Exception("使用AES对文件解密异常",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"; //是为了在原始文件中进行补充加密

    //返回码
    public final static String SUCCESSCODE="000000";
    public final static String FAILEDCODE="999999";

    //加密文件所放的目录
    public final static String BASELOCALDIR="XXX"; //基本目录路径
    public final static String ENCRYPTLOCALDIR="encrypt"; //加密文件目录


}

 

 

  • AES的介绍

   详情请参考:https://blog.csdn.net/qq_28205153/article/details/55798628

  • RSA的介绍

        详情请参考:https://www.cnblogs.com/jiftle/p/7903762.html

相关文章