mysql java 通用AES加密

最近有個需求,須要對數據庫某些字段加密,調研發現採用AES加密的方式較多,並且反向解密速度快,符合需求,因而採用;下面是遇到的問題及相關代碼java

首先第一個問題,AES的祕鑰是16位,mysql的密碼長度aes_encrypt沒有要求:

  是由於mysql默認取祕鑰的ascii編碼前16位,至關於:mysql

  byte[] keyBytes = Arrays.copyOf(password.getBytes("ASCII"), 16);

 

第二個問題,因涉及歷史數據處理,mysql須要使用aes_encrypt加密:

可是生成的二進制數據,要把二進制數據存到原先的varchar字段中,網上搜索多數採用的HEX(aes_encrypt(name, "password")),而HEX編碼會過度增大原數據的長度(聽說是增倍),有的字段長度會變的過長;算法

因而再查詢發現,mysql5.6之後增長了to_base64的base64編碼方式。二者區別sql

  • hex也稱爲base16,意思是使用16個可見字符來表示一個二進制數組,編碼後數據大小將翻倍,由於1個字符須要用2個可見字符來表示。數據庫

  • base32,意思是使用32個可見字符來表示一個二進制數組,編碼後數據大小變成原來的8/5,也即5個字符用8個可見字符表示,可是最後若是不足8個字符,將用=來補充。apache

  • base64,意思是使用64個可見字符來表示一個二進制數組,編碼後數據大小變成原來的4/3,也即3個字符用4個可見字符來表示。數組

可見base64的字段長度比HEX少不少,db設計不是很嚴謹的甚至沒必要增長字段長度;編碼

相關sql:

加密加密

update T_USER t
set t.name=to_base64(aes_encrypt(name, "password"));spa

解密

select cast(aes_decrypt(from_base64(name) ,"password") as char) from T_USER;

java類:

import org.apache.commons.lang3.StringUtils;import sun.misc.BASE64Decoder;import sun.misc.BASE64Encoder;import javax.crypto.Cipher;import javax.crypto.spec.SecretKeySpec;import java.util.Arrays;import java.util.Base64;/** * Created by Administrator on 2018/11/8. */public class EncryptUtil {    private static final String PASS_WORD="edmund2018";    private static SecretKeySpec AES_PASSWORD;    private static final String KEY_ALGORITHM = "AES";    private static final String DEFAULT_CIPHER_ALGORITHM = "AES/ECB/PKCS5Padding";//默認的加密算法    /**     * AES 加密操做     *     * @param content 待加密內容     * @return 返回Base64轉碼後的加密數據     */    public static String encrypt(String content) {        if(StringUtils.isEmpty(content)) {            return content;        }        try {            Cipher cipher = Cipher.getInstance(DEFAULT_CIPHER_ALGORITHM);// 建立密碼器            cipher.init(Cipher.ENCRYPT_MODE, getSecretKey(PASS_WORD));// 初始化爲加密模式的密碼器            byte[] encrypted = cipher.doFinal(content.getBytes("utf-8"));            return new BASE64Encoder().encode(encrypted);        } catch (Exception ex) {            Logger.defalutLogger.error("加密失敗");        }        return content;    }    /**     * AES 解密操做     *     * @param content     * @return     */    public static String decrypt(String content) {        if(StringUtils.isEmpty(content)) {            return content;        }        try {            //實例化            Cipher cipher = Cipher.getInstance(DEFAULT_CIPHER_ALGORITHM);            //使用密鑰初始化,設置爲解密模式            cipher.init(Cipher.DECRYPT_MODE, getSecretKey(PASS_WORD));            byte[] base64Data = new BASE64Decoder().decodeBuffer(content);//先用base64解密            byte[] original = cipher.doFinal(base64Data);            String originalString = new String(original,"utf-8");            return originalString;        } catch (Exception ex) {            Logger.defalutLogger.error("解密失敗"+ex.getStackTrace());        }        return content;    }    /**     * 生成加密祕鑰     *     * @return     */    private static SecretKeySpec getSecretKey(final String password) throws Exception {        if(AES_PASSWORD !=null){            return AES_PASSWORD;        }        try {  //返回生成指定算法密鑰生成器的 KeyGenerator 對象            byte[] keyBytes = Arrays.copyOf(password.getBytes("ASCII"), 16);            AES_PASSWORD =new SecretKeySpec(keyBytes, KEY_ALGORITHM);// 轉換爲AES專用密鑰            return AES_PASSWORD;        } catch (Exception ex) {            Logger.defalutLogger.error("加密祕鑰失敗"+ex.getStackTrace());            throw new Exception("加密祕鑰失敗");        }    }}
相關文章
相關標籤/搜索