java双端加密操作 vue+springboot+AES(CBC-ECB) ------------------前传后

本文详细介绍了如何在前端使用Vue实现AES-CBC和AES-ECB加密,并结合Base64编码,保护数据安全。同时,展示了后端如何使用过滤器解密这些数据,确保数据在传输过程中的安全。整个流程包括加密工具类的编写,axios请求拦截器的设置,以及后端解码过滤器的实现。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、前端vue

  1. 控制台先加载AES   

    npm install crypto-js --save-dev

     

  2.  编写AES-CBC加密解密方法
    import CryptoJS from "crypto-js";
    /**
     *
     * 第一个参数word是待加密或者解密的字符串;
     * 第二个参数keyStr是aes加密需要用到的16位字符串的key;
     * 第三个参数是初始化向量 iv。
     */
    export default {
        // 加密
        encrypt(word, keyStr, ivStr) {
            keyStr = keyStr ? keyStr : "16weizifuchuan16";
            ivStr = ivStr ? ivStr : "1suibianshurude6";
            let key = CryptoJS.enc.Utf8.parse(keyStr);
            let iv = CryptoJS.enc.Utf8.parse(ivStr);
            let srcs = CryptoJS.enc.Utf8.parse(word);
    
            let encrypted = CryptoJS.AES.encrypt(srcs, key, {
                iv,
                mode: CryptoJS.mode.CBC,
                padding: CryptoJS.pad.Pkcs7   //实测如果使用ZeroPadding后端会报bad padding错误
            });
            return encrypted.ciphertext.toString();    
        },
        // 解密
        decrypt(word, keyStr, ivStr) {
            keyStr = keyStr ? keyStr : "16weizifuchuan16";
            ivStr = ivStr ? ivStr : "1suibianshurude6";
            var key = CryptoJS.enc.Utf8.parse(keyStr);
            let iv = CryptoJS.enc.Utf8.parse(ivStr);
    
            var decrypt = CryptoJS.AES.decrypt(CryptoJS.format.Hex.parse(word), key, {
                iv,
                mode: CryptoJS.mode.CBC,
                padding: CryptoJS.pad.Pkcs7     
            });
            return CryptoJS.enc.Utf8.stringify(decrypt).toString();  
        }
    };
    

     

  3. 编写AES-ECB加密解密

    import CryptoJS from "crypto-js";
    /**
     *
     * 第一个参数word是待加密或者解密的字符串;
     * 第二个参数keyStr是aes加密需要用到的16位字符串的key;
     *
     * 如果想对一个js对象加密,需要先把该对象转成json字符串。
     */
    export default {
        // 加密
        encrypt(word, keyStr) {
            keyStr = keyStr ? keyStr : "jingbablog201130";
            let key = CryptoJS.enc.Utf8.parse(keyStr);
            let srcs = CryptoJS.enc.Utf8.parse(word);
            let encrypted = CryptoJS.AES.encrypt(srcs, key, {
                mode: CryptoJS.mode.ECB,
                padding: CryptoJS.pad.Pkcs7
            });
            return encrypted.ciphertext.toString();
        },
        // 解密
        decrypt(word, keyStr) {
            keyStr = keyStr ? keyStr : "jingbablog201130";
            var key = CryptoJS.enc.Utf8.parse(keyStr);
            var decrypt = CryptoJS.AES.decrypt(CryptoJS.format.Hex.parse(word), key, {
                mode: CryptoJS.mode.ECB,
                padding: CryptoJS.pad.Pkcs7
            });
            return CryptoJS.enc.Utf8.stringify(decrypt).toString();
        }
    };
    

     

  4. 编写base64参数

    export function Base64() {
        var BASE64 = {enKey: 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/',
    
            deKey: new Array(
                -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
                -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
                -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 62, -1, -1, -1, 63,
                52, 53, 54, 55, 56, 57, 58, 59, 60, 61, -1, -1, -1, -1, -1, -1,
                -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
                15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -1, -1, -1, -1, -1,
                -1, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
                41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, -1, -1, -1, -1, -1
            ),
    
            encode: function(src){
                //用一个数组来存放编码后的字符,效率比用字符串相加高很多。
                var str=new Array();
                var ch1, ch2, ch3;
                var pos=0;
                //每三个字符进行编码。
                while(pos+3<=src.length){
                    ch1=src.charCodeAt(pos++);
                    ch2=src.charCodeAt(pos++);
                    ch3=src.charCodeAt(pos++);
                    str.push(this.enKey.charAt(ch1>>2), this.enKey.charAt(((ch1<<4)+(ch2>>4))&0x3f));
                    str.push(this.enKey.charAt(((ch2<<2)+(ch3>>6))&0x3f), this.enKey.charAt(ch3&0x3f));
                }
                //给剩下的字符进行编码。
                if(pos<src.length){
                    ch1=src.charCodeAt(pos++);
                    str.push(this.enKey.charAt(ch1>>2));
                    if(pos<src.length){
                        ch2=src.charCodeAt(pos);
                        str.push(this.enKey.charAt(((ch1<<4)+(ch2>>4))&0x3f));
                        str.push(this.enKey.charAt(ch2<<2&0x3f), '=');
                    }else{
                        str.push(this.enKey.charAt(ch1<<4&0x3f), '==');
                    }
                }
                //组合各编码后的字符,连成一个字符串。
                return str.join('');
            },
    
            decode: function(src){
                //用一个数组来存放解码后的字符。
                var str=new Array();
                var ch1, ch2, ch3, ch4;
                var pos=0;
                //过滤非法字符,并去掉'='。
                // eslint-disable-next-line no-useless-escape
                src=src.replace(/[^A-Za-z0-9\+\/]/g, '');
                //decode the source string in partition of per four characters.
                while(pos+4<=src.length){
                    ch1=this.deKey[src.charCodeAt(pos++)];
                    ch2=this.deKey[src.charCodeAt(pos++)];
                    ch3=this.deKey[src.charCodeAt(pos++)];
                    ch4=this.deKey[src.charCodeAt(pos++)];
                    str.push(String.fromCharCode(
                        (ch1<<2&0xff)+(ch2>>4), (ch2<<4&0xff)+(ch3>>2), (ch3<<6&0xff)+ch4));
                }
                //给剩下的字符进行解码。
                if(pos+1<src.length){
                    ch1=this.deKey[src.charCodeAt(pos++)];
                    ch2=this.deKey[src.charCodeAt(pos++)];
                    if(pos<src.length){
                        ch3=this.deKey[src.charCodeAt(pos)];
                        str.push(String.fromCharCode((ch1<<2&0xff)+(ch2>>4), (ch2<<4&0xff)+(ch3>>2)));
                    }else{
                        str.push(String.fromCharCode((ch1<<2&0xff)+(ch2>>4)));
                    }
                }
                //组合各解码后的字符,连成一个字符串。
                return str.join('');
            }
        };
        return BASE64;
    }
    

    注:因为我的加密使用了两层,正常来讲最好是使用两个不同的加密方式尽心加密,但是本文只使用了AES的两种加密方式进行加密

  5. 简单使用

  • 引入加密工具类

        

  • 编写登陆按钮

        

  • 测试

        

  • 结果

        

     6.但是我们不可能在每个接口都去写一遍加密的方法,以及解密的方法,所以我们需要进行统一的处理,所以我们需要在axios.js中编写请求处理方法

import axios from 'axios';
import First from "../public/thirdTool/AES_ECB.js";
import Second from "../public/thirdTool/AES_CBC.js";
import {Base64} from "../public/thirdTool/Base64";


/**
 * 请求处理
 */
axios.interceptors.request.use(function (config) {
    console.info("-------------------------------------");
    console.info("加密前数据======config" + JSON.stringify(config));
    //先加载一个uuid参数
    // eslint-disable-next-line no-undef
    let uuid = getUUID();
    // eslint-disable-next-line no-useless-escape
    uuid = uuid.replace(/\-/g, '');

    let token = uuid;
    if (token != null) {
        config.headers.Authorization = 'Bearer ' + token;
    }

    let isEncryption = true;

    if (config.url.indexOf("login/getSession") != -1) {
        //加密数据并添加到请求中
        config.headers.token = uuid;
    } else {
        if (isEncryption == true) {
            config.headers.token = uuid;
        } else {
            config.headers.token = uuid;
        }
    }

    if (isEncryption == false) {
        return config;
    }
    let flag = false;

    if (flag) {
        return config;
    }
    let data = config.data;
    if (config.headers['Content-Type'] == 'application/x-www-form-urlencoded;charset=UTF-8') {
        var ret = "";
        for (let it in data) {
            ret += encodeURIComponent(it) + '=' + encodeURIComponent(data[it]) + '&'
        }
        if (ret != "") {
            ret = ret.substring(0, ret.length - 1);
            data = ret.replace(/\+/g, " ");
            let dataEntry = Second.encrypt(First.encrypt(Base64().encode(JSON.stringify(data))));
            config.data = {
                value: dataEntry
            };
            console.info();
        }
    } else {
        if (data != null) {
            data = JSON.stringify(data);
        }
        if (data && (typeof (data) == 'string')) {
            let dataEntry = "value=" + Second.encrypt(First.encrypt(Base64().encode(data)));
            config.headers['Content-Type'] = 'application/json';
            config.data = dataEntry;
            console.info();
        }
    }
    console.info("加密后数据======config" + JSON.stringify(config));
    return config;
}, function (error) {
    // 对请求错误做些什么
    return Promise.reject(error);
});


// eslint-disable-next-line no-unused-vars
function getUUID() {
    var s = [];
    var hexDigits = "0123456789abcdef";
    for (var i = 0; i < 36; i++) {
        s[i] = hexDigits.substr(Math.floor(Math.random() * 0x10), 1);
    }
    s[14] = "4";  // bits 12-15 of the time_hi_and_version field to 0010
    s[19] = hexDigits.substr((s[19] & 0x3) | 0x8, 1);  // bits 6-7 of the clock_seq_hi_and_reserved to 01
    s[8] = s[13] = s[18] = s[23] = "-";

    var uuid = s.join("");
    return uuid;
}

       7.需要注意的是我们必须注意在加密的时候将参数先进行base64的加密,防止数据裸奔,并且AES后端解密也需要前端进行base64的加密

        

       8.查看效果

到此为止,前端的加密方法已经写完了,之后就是写后端方法了

二、后端

  1. 在请求进来之后,我们需要添加过滤器,DeCodeFilter
    /**
     * @author xiaoli
     * @create 2020-11-25 14:42:37
     */
    @WebFilter(urlPatterns = "/*")
    public class DecodeFilter implements Filter {
        @Override
        public void init(FilterConfig filterConfig) throws ServletException {
    
        }
    
        @Override
        public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
            HttpServletRequest req = (HttpServletRequest) request;
            String uri = req.getRequestURI();
            if(uri.contains("upload")){
                chain.doFilter(request, response);  //图像上传的请求,不做处理
            }else{
                String reqMethod = req.getMethod();
                if("POST".equals(reqMethod)){
                    PrintWriter out = null;
                    HttpServletResponse res = (HttpServletResponse) response;
                    response.setCharacterEncoding("UTF-8");
                    response.setContentType("application/json; charset=utf-8");
    
                    WrapperedRequest requestWrapper = new WrapperedRequest(req);
                    String body = requestWrapper.getBody();   //获取body数据
    
                    try {
                        chain.doFilter(requestWrapper, response);
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }else{
                    //get请求直接放行
                    chain.doFilter(request, response);
                }
            }
        }
    
        @Override
        public void destroy() {
    
        }
    }

     

  2. 在使用filter过滤器的时候我们需要在application启动项中添加扫描注解
  3. 添加WrapperedRequest参数处理类
    package com.smile.jingbablog.filter;
    
    import com.smile.jingbablog.utils.AES_CBCUtils;
    import com.smile.jingbablog.utils.AES_ECBUtils;
    import com.smile.jingbablog.utils.Base64Decoder;
    import com.smile.jingbablog.utils.StrUtils;
    import net.sf.json.JSONObject;
    import org.apache.commons.lang.StringUtils;
    import org.aspectj.util.FileUtil;
    import tk.mybatis.mapper.util.StringUtil;
    
    import javax.servlet.ReadListener;
    import javax.servlet.ServletInputStream;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletRequestWrapper;
    import java.io.*;
    import java.net.URLDecoder;
    import java.nio.charset.Charset;
    import java.util.*;
    
    /**
     * @author xiaoli
     * @create 2020-11-25 14:54:40
     */
    public class WrapperedRequest extends HttpServletRequestWrapper {
    
        private static final int LOOPTIMES = 500*1024*1024;//限制为500M=500*1024Kb
        private static final int MAX_STR_LEN = Integer.MAX_VALUE;
        private String requestBody = "";
        HttpServletRequest req = null;
        private Map<String, Object> parameterMap  = new HashMap<String, Object>(); // 所有参数的Map集合
    
        public WrapperedRequest(HttpServletRequest request) throws IOException {
            super(request);
            Enumeration e = request.getHeaderNames()   ;
            while(e.hasMoreElements()){
                String name = (String) e.nextElement();
                String value = request.getHeader(name);
    //            System.out.println(name+" = "+value);
    
            }
            String bodyString = HttpHelper.getBodyString(request);
    
            if(bodyString!=null&&bodyString.contains("=")){
                bodyString = bodyString.split("=")[1];
            }
    
            //先解析外层CBC
            String params = "";
            try {
                String first = AES_CBCUtils.decrypt(bodyString);  //AES_CBC解密方法
                //解析内层ECB
                String second = null;
                second = AES_ECBUtils.decrypt(first);     //AES_ECB解密方法
                params = Base64Decoder.decode(second);
                try {
                    JSONObject json = JSONObject.fromObject(params);
                    try {
                        Set<String> set = json.keySet();
                        for(String key :set) {
                            parameterMap.put(key, json.getString(key));
                        }
                    }catch (Exception export){
                        Set<String> set = json.keySet();
                        for(String key :set) {
                            parameterMap.put(key, new String[]{json.getString(key)});
                        }
                    }
                }catch(Exception ex) {
                    String[] dataArr = params.split("&");
                    for(String str : dataArr) {
                        String[] paramArra = str.split("=");
                        parameterMap.put(paramArra[0], new String[]{URLDecoder.decode(paramArra.length>1?paramArra[1]:"", "UTF-8")});
                    }
                }
                //这一行数据可以不赋值给body,但是如果报Unrecognized token 'value': was expecting ('true', 'false' or 'null')这个错误的话,需要将body解密原controller才会接收到参数
                this.requestBody = JSONObject.fromObject(parameterMap).toString();
            } catch (Exception ex) {
                ex.printStackTrace();
            }
    
        }
    
        private String readJSONString(HttpServletRequest request)throws UnsupportedEncodingException {
            try {
                request.setCharacterEncoding("UTF-8");
            } catch (UnsupportedEncodingException e1) {
                throw new UnsupportedEncodingException("设置编码失败!");
            }
            StringBuffer json = new StringBuffer();
            String line = null;
            try {
                BufferedReader reader = request.getReader();
                while ((line = readLine(reader)) != null) {
                    json.append(line);
                }
            } catch (IOException e) {
                throw new UnsupportedEncodingException("编码转换失败!");
            }
            return json.toString();
        }
    
        /**
         * @Title: readLine
         * @Description: 读取一行
         * @param @param br
         * @param @return
         * @param @throws IOException    参数说明
         * @return String    返回类型
         * @throws IOException
         */
        public static String readLine( BufferedReader br) throws IOException{
            StringBuffer sb = new StringBuffer();
            int intC;
            int i=0;
            while ((intC = br.read()) != -1) {
                i++;
                if(i > LOOPTIMES) break;
                char c = (char) intC;
                if (c == '\n') {
                    break;
                }
                if (sb.length() >= MAX_STR_LEN) {
                    throw new RuntimeException("readLine input too long");
                }
                sb.append(c);
            }
            if(sb.toString().length()>0){
                return sb.toString().replace("\r", "");
            }else if((char) intC == '\n' && i == 1){
                return "";
            }else{
                return null;
            }
        }
    
        public String getBody() {
            return this.requestBody;
        }
    
        @Override
        public BufferedReader getReader() throws IOException {
            return new BufferedReader(new StringReader(this.requestBody));
        }
    
        @Override
        public ServletInputStream getInputStream() throws IOException {
    
            final ByteArrayInputStream bais = new ByteArrayInputStream(this.requestBody.getBytes("UTF-8"));
    
            return new ServletInputStream() {
                @Override
                public boolean isFinished() {
                    return false;
                }
    
                @Override
                public boolean isReady() {
                    return false;
                }
    
                @Override
                public void setReadListener(ReadListener listener) {
    
                }
    
                @Override
                public int read() throws IOException {
                    return bais.read();
                }
            };
        }
    
        @Override
        public String getHeader(String name) {
            return super.getHeader(name);
        }
    
        /**
         * 获取所有参数名
         * @return 返回所有参数名
         */
        @Override
        public Enumeration<String> getParameterNames() {
            Vector<String> vector = new Vector<String>(parameterMap.keySet());
            return vector.elements();
        }
    
        /**
         * 获取指定参数名的值,如果有重复的参数名,则返回第一个的值 接收一般变量 ,如text类型
         * @param name 指定参数名
         * @return 指定参数名的值
         */
        @Override
        public String getParameter(String name) {
            String results = (String) parameterMap.get(name);
            if (StringUtils.isBlank(results))
                return null;
            else {
                return results;
            }
        }
    
        /**
         * 获取指定参数名的所有值的数组,如:checkbox的所有数据
         * 接收数组变量 ,如checkobx类型
         */
        @Override
        public String[] getParameterValues(String name) {
            String[] results = ((String) parameterMap.get(name)).split(",");
            if (results == null || results.length <= 0)
                return null;
            else {
                return results;
            }
        }
    
    }
    

     

  4. HttpHelper
    /**
     * 用于将字节数组转换为字符串
     * @author lijin
     * @create 2020-11-27 11:30:06
     */
    public class HttpHelper {
    
        public static String getBodyString(ServletRequest request) {
            StringBuilder sb = new StringBuilder();
            InputStream inputStream = null;
            BufferedReader reader = null;
            try {
                inputStream = request.getInputStream();
                reader = new BufferedReader(new InputStreamReader(inputStream, Charset.forName("UTF-8")));
                String line = "";
                while ((line = reader.readLine()) != null) {
                    sb.append(line);
                }
            } catch (IOException e) {
                e.printStackTrace();
            } finally {
                if (inputStream != null) {
                    try {
                        inputStream.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
                if (reader != null) {
                    try {
                        reader.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            }
            return sb.toString();
        }
    }
    

     

  5. AES_CBCUtils
    public class AES_CBCUtils {
    
        private static Logger logger = LoggerFactory.getLogger(AES_CBCUtils.class);
    
        /**
         * 默认算法
         */
        private static final String KEY = "16weizifuchuan16"; // 长度必须是 16
        private static String iv = "1suibianshurude6";//偏移量字符串必须是16位 当模式是CBC的时候必须设置偏移量
        private static String Algorithm = "AES";
        private static String AlgorithmProvider = "AES/CBC/PKCS5Padding"; //算法/模式/补码方式
    
        public static byte[] generatorKey() throws NoSuchAlgorithmException {
            KeyGenerator keyGenerator = KeyGenerator.getInstance(Algorithm);
            keyGenerator.init(256);//默认128,获得无政策权限后可为192或256
            SecretKey secretKey = keyGenerator.generateKey();
            return secretKey.getEncoded();
        }
    
        public static IvParameterSpec getIv() throws UnsupportedEncodingException {
            IvParameterSpec ivParameterSpec = new IvParameterSpec(iv.getBytes("utf-8"));
            System.out.println("偏移量:"+byteToHexString(ivParameterSpec.getIV()));
            return ivParameterSpec;
        }
    
        public static String encrypt(String src) throws NoSuchAlgorithmException, NoSuchPaddingException,
                InvalidKeyException, IllegalBlockSizeException, BadPaddingException, UnsupportedEncodingException, InvalidAlgorithmParameterException {
            byte[] key = KEY.getBytes("utf-8");
            SecretKey secretKey = new SecretKeySpec(key, Algorithm);
            IvParameterSpec ivParameterSpec = getIv();
            Cipher cipher = Cipher.getInstance(AlgorithmProvider);
            cipher.init(Cipher.ENCRYPT_MODE, secretKey, ivParameterSpec);
            byte[] cipherBytes = cipher.doFinal(src.getBytes(Charset.forName("utf-8")));
            return byteToHexString(cipherBytes);
        }
    
        public static String decrypt(String src) throws Exception {
            byte[] key = KEY.getBytes("utf-8");
            SecretKey secretKey = new SecretKeySpec(key, Algorithm);
    
            IvParameterSpec ivParameterSpec = getIv();
            Cipher cipher = Cipher.getInstance(AlgorithmProvider);
            cipher.init(Cipher.DECRYPT_MODE, secretKey, ivParameterSpec);
            byte[] hexBytes = hexStringToBytes(src);
            byte[] plainBytes = cipher.doFinal(hexBytes);
            return new String(plainBytes);
        }
    
        /**
         * 将byte转换为16进制字符串
         * @param src
         * @return
         */
        public static String byteToHexString(byte[] src) {
            StringBuilder sb = new StringBuilder();
            for (int i = 0; i < src.length; i++) {
                int v = src[i] & 0xff;
                String hv = Integer.toHexString(v);
                if (hv.length() < 2) {
                    sb.append("0");
                }
                sb.append(hv);
            }
            return sb.toString();
        }
    
        /**
         * 将16进制字符串装换为byte数组
         * @param hexString
         * @return
         */
        public static byte[] hexStringToBytes(String hexString) {
            hexString = hexString.toUpperCase();
            int length = hexString.length() / 2;
            char[] hexChars = hexString.toCharArray();
            byte[] b = new byte[length];
            for (int i = 0; i < length; i++) {
                int pos = i * 2;
                b[i] = (byte) (charToByte(hexChars[pos]) << 4 | charToByte(hexChars[pos + 1]));
            }
            return b;
        }
    
        private static byte charToByte(char c) {
            return (byte) "0123456789ABCDEF".indexOf(c);
        }
    
    }

     

  6. AES_ECBUtils
    public class AES_ECBUtils {
    
        private static Logger logger = LoggerFactory.getLogger(AES_ECBUtils.class);
    
        private static final String KEY = "jingbablog201130";   //key必须和前端的key相同
        private static String Algorithm = "AES";
        private static String AlgorithmProvider = "AES/ECB/PKCS5Padding"; // 算法/模式/补码方式
    
        public static byte[] generatorKey() throws NoSuchAlgorithmException {
            KeyGenerator keyGenerator = KeyGenerator.getInstance(Algorithm);
            keyGenerator.init(256);//默认128,获得无政策权限后可为192或256
            SecretKey secretKey = keyGenerator.generateKey();
            return secretKey.getEncoded();
        }
    
        public static String encrypt(String src) throws NoSuchAlgorithmException, NoSuchPaddingException,
                InvalidKeyException, IllegalBlockSizeException, BadPaddingException, UnsupportedEncodingException, InvalidAlgorithmParameterException {
            byte[] key = KEY.getBytes("utf-8");
            SecretKey secretKey = new SecretKeySpec(key, Algorithm);
            //IvParameterSpec ivParameterSpec = getIv();
            Cipher cipher = Cipher.getInstance(AlgorithmProvider);
            cipher.init(Cipher.ENCRYPT_MODE, secretKey);
            byte[] cipherBytes = cipher.doFinal(src.getBytes(Charset.forName("utf-8")));
            return byteToHexString(cipherBytes);
        }
    
        public static String decrypt(String src) throws Exception {
            byte[] key = KEY.getBytes("utf-8");
            SecretKey secretKey = new SecretKeySpec(key, Algorithm);
            //IvParameterSpec ivParameterSpec = getIv();
            Cipher cipher = Cipher.getInstance(AlgorithmProvider);
            cipher.init(Cipher.DECRYPT_MODE, secretKey);
            byte[] hexBytes = hexStringToBytes(src);
            byte[] plainBytes = cipher.doFinal(hexBytes);
            return new String(plainBytes);
        }
    
        /**
         * 将byte转换为16进制字符串
         * @param src
         * @return
         */
        public static String byteToHexString(byte[] src) {
            StringBuilder sb = new StringBuilder();
            for (int i = 0; i < src.length; i++) {
                int v = src[i] & 0xff;
                String hv = Integer.toHexString(v);
                if (hv.length() < 2) {
                    sb.append("0");
                }
                sb.append(hv);
            }
            return sb.toString();
        }
    
        /**
         * 将16进制字符串装换为byte数组
         * @param hexString
         * @return
         */
        public static byte[] hexStringToBytes(String hexString) {
            hexString = hexString.toUpperCase();
            int length = hexString.length() / 2;
            char[] hexChars = hexString.toCharArray();
            byte[] b = new byte[length];
            for (int i = 0; i < length; i++) {
                int pos = i * 2;
                b[i] = (byte) (charToByte(hexChars[pos]) << 4 | charToByte(hexChars[pos + 1]));
            }
            return b;
        }
    
        private static byte charToByte(char c) {
            return (byte) "0123456789ABCDEF".indexOf(c);
        }
    }

     

  7. BASE64Decode
    package com.smile.jingbablog.utils;
    
    import java.io.*;
    
    public class Base64Decoder extends FilterInputStream {
    
        private static final char[] chars = {'A', 'B', 'C', 'D', 'E', 'F', 'G',
                'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T',
                'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f', 'g',
                'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't',
                'u', 'v', 'w', 'x', 'y', 'z', '0', '1', '2', '3', '4', '5', '6',
                '7', '8', '9', '+', '/'};
    
        // A mapping between char values and six-bit integers
        private static final int[] ints = new int[128];
    
        static {
            for (int i = 0; i < 64; i++) {
                ints[chars[i]] = i;
            }
        }
    
        private int charCount;
        private int carryOver;
    
        /**
         * Creates a <code>FilterInputStream</code>
         * by assigning the  argument <code>in</code>
         * to the field <code>this.in</code> so as
         * to remember it for later use.
         *
         * @param in the underlying input stream, or <code>null</code> if
         *           this instance is to be created without an underlying stream.
         */
        protected Base64Decoder(InputStream in) {
            super(in);
        }
    
        /***
         * Returns the next decoded character from the stream, or -1 if end of
         * stream was reached.
         *
         * @return the decoded character, or -1 if the end of the input stream is
         *         reached
         * @exception IOException
         *                if an I/O error occurs
         */
        public int read() throws IOException {
            // Read the next non-whitespace character
            int x;
            do {
                x = in.read();
                if (x == -1) {
                    return -1;
                }
            } while (Character.isWhitespace((char) x));
            charCount++;
    
            // The '=' sign is just padding
            if (x == '=') {
                return -1; // effective end of stream
            }
    
            // Convert from raw form to 6-bit form
            x = ints[x];
    
            // Calculate which character we're decoding now
            int mode = (charCount - 1) % 4;
    
            // First char save all six bits, go for another
            if (mode == 0) {
                carryOver = x & 63;
                return read();
            }
            // Second char use previous six bits and first two new bits,
            // save last four bits
            else if (mode == 1) {
                int decoded = ((carryOver << 2) + (x >> 4)) & 255;
                carryOver = x & 15;
                return decoded;
            }
            // Third char use previous four bits and first four new bits,
            // save last two bits
            else if (mode == 2) {
                int decoded = ((carryOver << 4) + (x >> 2)) & 255;
                carryOver = x & 3;
                return decoded;
            }
            // Fourth char use previous two bits and all six new bits
            else if (mode == 3) {
                int decoded = ((carryOver << 6) + x) & 255;
                return decoded;
            }
            return -1; // can't actually reach this line
        }
    
        /***
         * Reads decoded data into an array of bytes and returns the actual number
         * of bytes read, or -1 if end of stream was reached.
         *
         * @param buf
         *            the buffer into which the data is read
         * @param off
         *            the start offset of the data
         * @param len
         *            the maximum number of bytes to read
         * @return the actual number of bytes read, or -1 if the end of the input
         *         stream is reached
         * @exception IOException
         *                if an I/O error occurs
         */
        public int read(byte[] buf, int off, int len) throws IOException {
            if (buf.length < (len + off - 1)) {
                throw new IOException("The input buffer is too small: " + len
                        + " bytes requested starting at offset " + off
                        + " while the buffer " + " is only " + buf.length
                        + " bytes long.");
            }
    
            // This could of course be optimized
            int i;
            for (i = 0; i < len; i++) {
                int x = read();
                if (x == -1 && i == 0) { // an immediate -1 returns -1
                    return -1;
                } else if (x == -1) { // a later -1 returns the chars read so far
                    break;
                }
                buf[off + i] = (byte) x;
            }
            return i;
        }
    
        /***
         * Returns the decoded form of the given encoded string, as a String. Note
         * that not all binary data can be represented as a String, so this method
         * should only be used for encoded String data. Use decodeToBytes()
         * otherwise.
         *
         * @param encoded
         *            the string to decode
         * @return the decoded form of the encoded string
         */
        public static String decode(String encoded) {
            return new String(decodeToBytes(encoded));
        }
    
        /***
         * Returns the decoded form of the given encoded string, as bytes.
         *
         * @param encoded
         *            the string to decode
         * @return the decoded form of the encoded string
         */
        public static byte[] decodeToBytes(String encoded) {
            byte[] bytes = null;
            try {
                bytes = encoded.getBytes("UTF-8");
            } catch (UnsupportedEncodingException ignored) {
            }
    
            Base64Decoder in = new Base64Decoder(new ByteArrayInputStream(bytes));
    
            ByteArrayOutputStream out = new ByteArrayOutputStream(
                    (int) (bytes.length * 0.67));
    
            try {
                byte[] buf = new byte[4 * 1024]; // 4K buffer
                int bytesRead;
                while ((bytesRead = in.read(buf)) != -1) {
                    out.write(buf, 0, bytesRead);
                }
                out.close();
    
                return out.toByteArray();
            } catch (IOException ignored) {
                return null;
            }
        }
    
    }
    

     

  8. 测试效果

       

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值