php - 我需要哪种数据格式来解密存储在 MySQL DB 中的数据?
问题描述
我正在使用 PHP 7.1,研究加密/解密主题。我使用这个函数来编码/解码(基于 PHP 的官方文档):
$key = openssl_random_pseudo_bytes(16);
function encryptName($plaintext) {
global $key;
// $plaintext - string which must be encrypted
$ivlen = openssl_cipher_iv_length($cipher="AES-128-CBC");
$iv = openssl_random_pseudo_bytes($ivlen);
$ciphertext_raw = openssl_encrypt($plaintext, $cipher, $key, $options=OPENSSL_RAW_DATA, $iv);
$hmac = hash_hmac('sha256', $ciphertext_raw, $key, $as_binary=true);
$ciphertext = base64_encode( $iv.$hmac.$ciphertext_raw );
return $ciphertext;
}
function decryptName($ciphertext) {
global $key;
// $ciphertext - encrypted string
$c = base64_decode($ciphertext);
$ivlen = openssl_cipher_iv_length($cipher="AES-128-CBC");
$iv = substr($c, 0, $ivlen);
$hmac = substr($c, $ivlen, $sha2len=32);
$ciphertext_raw = substr($c, $ivlen+$sha2len);
$original_plaintext = openssl_decrypt($ciphertext_raw, $cipher, $key,
$options=OPENSSL_RAW_DATA, $iv); // | OPENSSL_ZERO_PADDING
$calcmac = hash_hmac('sha256', $ciphertext_raw, $key, $as_binary=true);
if (hash_equals($hmac, $calcmac)) {
//echo $original_plaintext."\n";
}
echo openssl_error_string();
return $original_plaintext;
}
当我 enc/dec strig "MyTestPhrase" 时,这两个函数都运行良好。但是当我加密数据然后将其写入 MySQL 表时,解密失败并出现以下错误代码:
error:0606506D:digital envelope routines:EVP_DecryptFinal_ex:wrong final block length
和我的$original_plaintext
平等bool(false)
。
我是这样想的。AES 适用于块。解密的字符串必须适合块长度:解密数据的大小必须是 16 的倍数。如果不是,我们必须激活 PHP 选项,用 0es 填充它。
猜猜这个问题可能与 MySQL 数据格式和加密字符串长度有关,但无法捕捉到它。
请帮我解决上面发布的问题。
解决方案
因此,在我的示例中,我使用 pseudo_bytes 创建了一个 base64_encoded 字符串。这样你的密钥是不变的。您可以创建自己的密钥,但对于这个 ex,我们将使用这个。LoPCPKd8iDxHvb8mATzhhg==
接下来我们将键定义为常量。这可以在脚本顶部或 conf.php 文件中完成。
接下来,我们将在需要密钥的任何地方使用常量值。
像这样:
define("MYKEY_", base64_decode('LoPCPKd8iDxHvb8mATzhhg=='));
function encryptName($plaintext) {
$ivlen = openssl_cipher_iv_length($cipher="AES-128-CBC");
$iv = openssl_random_pseudo_bytes($ivlen);
$ciphertext_raw = openssl_encrypt($plaintext, $cipher, MYKEY_, $options=OPENSSL_RAW_DATA, $iv);
$hmac = hash_hmac('sha256', $ciphertext_raw, MYKEY_, $as_binary=true);
$ciphertext = base64_encode( $iv.$hmac.$ciphertext_raw );
return $ciphertext;
}
function decryptName($ciphertext) {
$c = base64_decode($ciphertext);
$ivlen = openssl_cipher_iv_length($cipher="AES-128-CBC");
$iv = substr($c, 0, $ivlen);
$hmac = substr($c, $ivlen, $sha2len=32);
$ciphertext_raw = substr($c, $ivlen+$sha2len);
$original_plaintext = openssl_decrypt($ciphertext_raw, $cipher, MYKEY_,
$options=OPENSSL_RAW_DATA, $iv); // | OPENSSL_ZERO_PADDING
$calcmac = hash_hmac('sha256', $ciphertext_raw, MYKEY_, $as_binary=true);
if (hash_equals($hmac, $calcmac)) {
//echo $original_plaintext."\n";
}
echo openssl_error_string();
return $original_plaintext;
}
推荐阅读
- android - Android studio Framelayout - 上半部分下的Listview
- python - 使用 h2o 实现决策树
- c - 如何使用签名“__ASM volatile rbit(x)”抑制解析、预处理代码
- angular - 总结Angular 6的总价
- r - R RefClass 使用包含具有停止条件的初始化的字段/避免调用初始化
- php - Laravel 将出发次数限制为 1
- javascript - MVC - 加密 ajax 调用参数
- php - php 无法在 mysql 上为登录页面选择数据库
- java - 在拉格纳图上设置文本
- java - 尝试删除请求 ajax 时出现 405 错误 - java