03 May 2021
注意 MySQL 5.7 的 AES 加密演算法預設值是 AES-128-ECB

注意 MySQL 5.7 的 AES 加密演算法預設值是 AES-128-ECB

要先修改成 AES-256-CBC

單次修改

SET block_encryption_mode = 'aes-256-cbc';

全域修改

SET global block_encryption_mode = 'AES-256-CBC';

查看

SHOW VARIABLES LIKE '%block%';

不過正式時,要直接修改 my.cnf,確定編碼規則在每一次資料載重啟時都一致,不然會有問題

https://dev.mysql.com/doc/mysql-secure-deployment-guide/5.7/en/secure-deployment-block-encryption-mode.html

第 1 點:原本主 key 有使用 hash 256 取得一個 64 字元

https://stackoverflow.com/questions/2240973/how-long-is-the-sha256-hash/2241014

第 2 點:然後再用這個加密後的 key 再做一次 hash 但只取 16 個字元 ( Initialization Vector ) ( iv ) 向量初始化

第 3 點:是告訴 PHP 使用 openssl_encrypt 時,要返回 Raw 格式資料

第 4 點:自己做 Base 64 編碼

⚠️ 如果透過 openssl_encrypt 處理,會得到預期外的結果,所以自己用 PHP 或 MySQL 的 Base 64 處理

透過加密後的 key 和 iv 加密儲存的值,但發現雙方不一致

主 Key 不做 hash 試試

雙方加密後的值一致了

⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️ 重要注意事項

所以目前知道一個狀況

就是 key 太長,會造成 PHP 和 MySQL 做 AES 的結果不一致

這是 Google 到的資訊

密鑰長度:AES-128-ECB 密鑰長度為 128bits (As of MySQL 5.6.17, key lengths of 196 or 256 bits can be used),但使用 AES_ENCRYPT()、AES_DECRYPT() 時,如果輸入太短或太長的密鑰,MySQL 會自動處理成 128bits

https://security.stackexchange.com/questions/190611/mysql-aes-encrypt-string-key-length

解決方法就是減少主 key 的字串長度

然後 Initialization Vector 也是一樣,要注意是否符合演算法的規範

https://dev.mysql.com/doc/refman/8.0/en/encryption-functions.html

For modes that require the optional init_vector argument, it must be 16 bytes or longer (bytes in excess of 16 are ignored). An error occurs if init_vector is missing.

做 Equal 比對

做 LIKE 搜尋

⚠️ 注意事項

因為用 PHP 程式或 MySQL 的 AES 解編碼後會得到二進位資料

如果資料欄位不是用二位進檔案形式儲存的話 ( BINARY, VARBINARY, TINYBLOB, BLOB, MEDIUMBLOB, LONGBLOG )

就要另外做一次 BASE 64 的解編碼

像下圖就是欄位是一般的 VARCHAR,不過儲存時送進去是二進位,所以造成亂碼,此外也不一定能再取出解碼 AES 復原成原本的字串

Tags: #MySQL

回上一頁