最近有個需求,須要對數據庫某些字段加密,調研發現採用AES加密的方式較多,並且反向解密速度快,符合需求,因而採用;下面是遇到的問題及相關代碼java
是由於mysql默認取祕鑰的ascii編碼前16位,至關於:mysql
byte[] keyBytes = Arrays.copyOf(password.getBytes("ASCII"), 16);
可是生成的二進制數據,要把二進制數據存到原先的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設計不是很嚴謹的甚至沒必要增長字段長度;編碼
加密加密
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("加密祕鑰失敗"); } }}