1. 程式人生 > >AES/CBC/PKCS7加密 以及PKCS5加密簡單實用

AES/CBC/PKCS7加密 以及PKCS5加密簡單實用

高階加密標準(英語:Advanced Encryption Standard,縮寫:AES),在密碼學中又稱Rijndael加密法,是美國聯邦政府採用的一種區塊加密標準。這個標準用來替代原先的DES,已經被多方分析且廣為全世界所使用。經過五年的甄選流程,高階加密標準由美國國家標準與技術研究院(NIST)於2001年11月26日釋出於FIPS PUB 197,並在2002年5月26日成為有效的標準。2006年,高階加密標準已然成為對稱金鑰加密中最流行的演算法之一。

高階加密標準(AES,Advanced Encryption Standard)為最常見的對稱加密演算法(微信小程式加密傳輸就是用這個加密演算法的)。對稱加密演算法也就是加密和解密用相同的金鑰 

在這裡簡單介紹下對稱加密演算法與非對稱加密演算法的區別。

對稱加密演算法

加密和解密用到的金鑰是相同的,這種加密方式加密速度非常快,適合經常傳送資料的場合。缺點是金鑰的傳輸比較麻煩。

非對稱加密演算法

加密和解密用的金鑰是不同的,這種加密方式是用數學上的難解問題構造的,通常加密解密的速度比較慢,適合偶爾傳送資料的場合。優點是金鑰傳輸方便。常見的非對稱加密演算法為RSA、ECC和EIGamal。

實際中,一般是通過RSA加密AES的金鑰,傳輸到接收方,接收方解密得到AES金鑰,然後傳送方和接收方用AES金鑰來通訊。

 

PKCS7 的工具類,加密之前用十六進位制編過碼

package com.example.administrator.standardOA.utils;

import javax.crypto.Cipher;
import javax.crypto.spec.SecretKeySpec;
import javax.crypto.spec.IvParameterSpec;

import java.io.UnsupportedEncodingException;


/**
 * Created by Duqianlong on 2018/11/15.
 */


public class AESPKCS7PaddingUtils {
    /**
     * 演算法/模式/填充
     **/
    private static final String CipherMode = "AES/CBC/PKCS7Padding";

    // 建立金鑰, 長度為128位(16bytes), 且轉成位元組格式
    private static SecretKeySpec createKey(String key) {

        byte[] data = null;

        if (key == null) {
            key = "";
        }
        StringBuffer sb = new StringBuffer(16);
        sb.append(key);
        while (sb.length() < 16) {
            sb.append("0");
        }
        if (sb.length() > 16) {
            sb.setLength(16);
        }

        try {
            data = sb.toString().getBytes("UTF-8");
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }

        return new SecretKeySpec(data, "AES");
    }

    // 建立初始化向量, 長度為16bytes, 向量的作用其實就是salt
    private static IvParameterSpec createIV(String iv) {

        byte[] data = null;

        if (iv == null) {
            iv = "";
        }
        StringBuffer sb = new StringBuffer(16);
        sb.append(iv);
        while (sb.length() < 16) {
            sb.append("0");
        }
        if (sb.length() > 16) {
            sb.setLength(16);
        }

        try {
            data = sb.toString().getBytes("UTF-8");
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }

        return new IvParameterSpec(data);
    }

    /****************************************************************************/

    // 加密位元組資料, 被加密的資料需要提前轉化成位元組格式
    private static byte[] encrypt(byte[] content, String key, String iv) {

        try {
            SecretKeySpec secretKeySpec = createKey(key);
            IvParameterSpec ivParameterSpec = createIV(iv);
            Cipher cipher = Cipher.getInstance(CipherMode);
            cipher.init(Cipher.ENCRYPT_MODE, secretKeySpec, ivParameterSpec);
            byte[] result = cipher.doFinal(content); // 加密
            return result;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }


    // 加密字串資料, 返回的位元組資料還需轉化成16進位制字串
    public static String encrypt(String content, String key) {

        byte[] data = null;
        try {
            data = content.getBytes("UTF-8");
        } catch (Exception e) {
            e.printStackTrace();
        }

        data = encrypt(data, key, "text1234");
        return byte2hex(data);
    }


    /****************************************************************************/

    // 解密位元組陣列
    private static byte[] decrypt(byte[] content, String key) {

        try {
            SecretKeySpec secretKeySpec = createKey(key);
            IvParameterSpec ivParameterSpec = createIV("text1234");
            Cipher cipher = Cipher.getInstance(CipherMode);
            cipher.init(Cipher.DECRYPT_MODE, secretKeySpec, ivParameterSpec);
            byte[] result = cipher.doFinal(content);
            return result;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    // 解密(輸出結果為字串), 密文為16進位制的字串
    public static String decrypt(String content, String password) {

        byte[] data = null;
        try {
            data = hex2byte(content);
        } catch (Exception e) {
            e.printStackTrace();
        }

        data = decrypt(data, password);
        if (data == null) return null;

        String result = null;
        try {
            result = new String(data, "UTF-8");
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }

        return result;
    }

    /****************************************************************************/

    // 位元組陣列轉成16進位制大寫字串
    private static String byte2hex(byte[] b) {

        String tmp = "";
        StringBuffer sb = new StringBuffer(b.length * 2);
        for (int n = 0; n < b.length; n++) {
            tmp = (Integer.toHexString(b[n] & 0XFF));
            if (tmp.length() == 1) {
                sb.append("0");
            }
            sb.append(tmp);
        }
        return sb.toString().toUpperCase();
    }

    // 將16進位制字串轉換成位元組陣列
    private static byte[] hex2byte(String inputString) {

        if (inputString == null || inputString.length() < 2) {
            return new byte[0];
        }
        inputString = inputString.toLowerCase();
        int l = inputString.length() / 2;
        byte[] result = new byte[l];
        for (int i = 0; i < l; ++i) {
            String tmp = inputString.substring(2 * i, 2 * i + 2);
            result[i] = (byte) (Integer.parseInt(tmp, 16) & 0xFF);
        }
        return result;
    }

}

 PKCS5 的工具類,加密之前用Base64編過碼

package com.example.administrator.standardOA.utils;

import android.util.Base64;

import com.alibaba.fastjson.JSONObject;


import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.spec.SecretKeySpec;
import java.util.HashMap;
import java.util.Map;

/**
 * Created by Duqianlong on 2018/11/15.
 */

public class AesEncryptUtils {

    //可配置到Constant中,並讀取配置檔案注入,16位,自己定義
    private static final String KEY = "xxxxxxxxxxxxxxxx";

    //引數分別代表 演算法名稱/加密模式/資料填充方式
    private static final String ALGORITHMSTR = "AES/ECB/PKCS5Padding";

    /**
     * 加密
     * @param content 加密的字串
     * @param encryptKey key值
     * @return
     * @throws Exception
     */
    public static String encrypt(String content, String encryptKey) throws Exception {
        KeyGenerator kgen = KeyGenerator.getInstance("AES");
        kgen.init(128);
        Cipher cipher = Cipher.getInstance(ALGORITHMSTR);
        cipher.init(Cipher.ENCRYPT_MODE, new SecretKeySpec(encryptKey.getBytes(), "AES"));
        byte[] b = cipher.doFinal(content.getBytes("utf-8"));
        // 採用base64演算法進行轉碼,避免出現中文亂碼
//        return Base64.encodeBase64String(b);
        String strBase64 = Base64.encodeToString(b , Base64.DEFAULT);
        return strBase64;

    }

    /**
     * 解密
     * @param encryptStr 解密的字串
     * @param decryptKey 解密的key值
     * @return
     * @throws Exception
     */
    public static String decrypt(String encryptStr, String decryptKey) throws Exception {
        KeyGenerator kgen = KeyGenerator.getInstance("AES");
        kgen.init(128);
        Cipher cipher = Cipher.getInstance(ALGORITHMSTR);
        cipher.init(Cipher.DECRYPT_MODE, new SecretKeySpec(decryptKey.getBytes(), "AES"));
        // 採用base64演算法進行轉碼,避免出現中文亂碼
//        byte[] encryptBytes = Base64.decodeBase64(encryptStr);
        byte[] encryptBytes = Base64.decode(encryptStr,Base64.DEFAULT);
        byte[] decryptBytes = cipher.doFinal(encryptBytes);
        return new String(decryptBytes);
    }

    public static String encrypt(String content) throws Exception {
        return encrypt(content, KEY);
    }
    public static String decrypt(String encryptStr) throws Exception {
        return decrypt(encryptStr, KEY);
    }


    public static void main(String[] args) throws Exception {
        Map map=new HashMap<String,String>();
        map.put("loginName","jtliyajuan");
        String content = JSONObject.toJSONString(map);
        System.out.println("加密前:" + content);

        String encrypt = encrypt(content, KEY);
        System.out.println("加密後:" + encrypt);

        String decrypt = decrypt(encrypt, KEY);
        System.out.println("解密後:" + decrypt);
    }

}

使用規則

//加密 pkcs5
    public static String encryption(Map<String, String> map) {
        String encrypt = "";
        Gson gson = new Gson();
        try {
            encrypt = AesEncryptUtils.encrypt(gson.toJson(map));
        } catch (Exception e) {
            e.printStackTrace();
        }
        return encrypt;
    }

    //解密 pkcs5
    public static String decryption(String string) {
        String decrypt = "";
        try {
            decrypt = AesEncryptUtils.decrypt(string);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return decrypt;
    }


    //加密
    public static String pkcs7encryption(String string) {
        if (!TextUtils.isEmpty(string)) {
            String text1 = AESPKCS7PaddingUtils.encrypt(string, UrlConstant.AESkey);//UrlConstant.AESkey:密匙
            return text1;
        } else {
            return "";
        }
    }

    //解密
    public static String kpcs7decryption(String string) {
        if (!TextUtils.isEmpty(string)) {
            String text2 = AESPKCS7PaddingUtils.decrypt(string, UrlConstant.AESkey);//UrlConstant.AESkey:密匙
            return text2;
        } else {
            return "";
        }
    }