iT邦幫忙

1

MySQL AES 256 加密與解密

之前介紹過MD5加密, 有以下兩種方式

Java MD5

MySQL MD5

但MD5屬於不可逆, 我們仍有些資料需要能被解密

例如: 電話, 電子郵件, 住址...等等可被修改的個資

這時候就可以用AES 256來做加解密, 以下我們用Email欄位來做示範

首先把加解密方法做成Function, 要使用時就可直接呼叫

新增encrypt_email_function

CREATE FUNCTION `encrypt_email_function`(email VARCHAR(100)) 
RETURNS varchar(100) CHARSET utf8
BEGIN
	SET block_encryption_mode = 'aes-256-cbc';
	SET @key_str = SHA2('MySecretKey', 512);
	SET @init_vector = '1,2,3,4,5,6,7,8,9,0,a,b,c,d,e,f';
	RETURN CONVERT(HEX(AES_ENCRYPT(email, @key_str, @init_vector)), CHAR CHARACTER SET utf8);
END

新增decrypt_email_function

CREATE FUNCTION `decrypt_email_function`(email VARCHAR(100)) 
RETURNS varchar(100) CHARSET utf8
BEGIN
	SET block_encryption_mode = 'aes-256-cbc';
	SET @key_str = SHA2('MySecretKey', 512);
	SET @init_vector = '1,2,3,4,5,6,7,8,9,0,a,b,c,d,e,f';
	RETURN CAST(AES_DECRYPT(UNHEX(email), @key_str, @init_vector) AS CHAR CHARACTER SET utf8);
END

block_encryption_mode: 加密的方式

key_str: 加密所使用的key, 官方建議使用SHA2做雜湊, 因為SHA1已在2017年被Google攻破

init_vector: 初始向量, 官方文件上註明must be 16 bytes or longer

加密跟解密必須用同一組key跟vector, 若其中一組不一樣, 則會解不出來。

例: 將init_vector換成RANDOM_BYTES(16), 會發現每次的向量都不同, 而不同向量是解不開的。

我們在加密時會HEX, 解密時會UNHEX

這是因為AES_ENCRYPT與AES_DECRYPT加解密完回來的格式是二進制

二進制直接存到VARCHAR欄位, 寫入時會有warning, 雖然能寫入但實際上取出時會出錯

解法有兩種

  1. 將欄位型別改為以下其中一種binary / varbinary / blob
  2. 寫入前先做HEX

HEX()可以將二進制轉為十六進制, 如此就能順利存到VARCHAR欄位

取出時先使用UNHEX()轉回二進制, 再進行解密

如果你的資料不止英數, 會有中文字出現, 那可能取出時會變亂碼

這時可以在最外層加CAST(), 轉為CHAR, 並指定為UTF8格式。


1 則留言

1
黃彥儒
iT邦高手 1 級 ‧ 2019-12-12 19:19:24

可以不要混用雜湊加密兩個不同的概念嗎?
另外如果你有提到『官方文件說……』建議附上連結

我要留言

立即登入留言