如何获得 openssl_decrypt 二进制输出?
How to get an openssl_decrypt binary output?
我正在尝试使用 openssl_encrypt/openssl_decrypt encrypt/decrypt 一些数据。目的如下:用户在 GUI 中输入一些数据,这些数据被加密并存储在数据库中。稍后将仅针对特定用户配置文件对其进行检索和解密。
加密部分工作正常,因为我听从了同事的建议,即将输出包装到 bin2hex 函数中。
关键是我在解密数据时似乎无法获得二进制输出,即使我尝试使用 hex2bin 转换输出也是如此。我总是得到类似“� �Ps�1�_G�5�OUT”的输出。
我 运行 没有想法,实际上我现在真的不知道该怎么做。
这是我为测试此功能而编写的示例代码:
PHP
function encrypt($string) {
$cypher = 'aes-256-cbc';
$key = 's7aBkf4Ypn59bWviQziPDXyPasdaYlhQ';
$ivsize = openssl_cipher_iv_length($cypher);
$iv = openssl_random_pseudo_bytes($ivsize);
$encripted = openssl_encrypt(
$string, $cypher, $key, OPENSSL_RAW_DATA | OPENSSL_ZERO_PADDING, $iv
);
return $iv . $encripted;
}
function decrypt($string) {
$cypher = 'aes-256-cbc';
$key = 's7aBkf4Ypn59bWviQziPDXyPasdaYlhQ';
$ivsize = openssl_cipher_iv_length($cypher);
$iv = mb_substr($string, 0, $ivsize, '8bit');
$decrypted = mb_substr($string, $ivsize, null, '8bit');
$output = openssl_decrypt(
$decrypted, $cifrado, $key, OPENSSL_RAW_DATA | OPENSSL_ZERO_PADDING, $iv
);
return $output;
}
HTML:
<!doctype html>
<html>
<head><title>TEST</title></head>
<body>
<div style='margin-left:250px;'>
<form action="test.php" method="POST">
Encrypt
<input type="text" name="encrypt" value=''/>
<input type="submit" name="send" value='Send'/>
<br/><br/>
<?php
if (isset($_POST['encrypt']) && !empty($_POST['encrypt'])) {
echo 'encrypted string: ' . bin2hex(encrypt($_POST['encrypt']));
}
?>
<br/>
<br/>
Decrypt
<input type="text" name="decrypt" value=''/>
<input type="submit" name="send" value='Send'/>
<br/><br/>
<?php
if (isset($_POST['decrypt']) && !empty($_POST['decrypt'])) {
echo 'decrypted string: ' . decrypt($_POST['decrypt']);
var_dump(decrypt($_POST['decrypt']));
}
?>
</form>
</body>
如有任何想法或帮助,我们将不胜感激。
我的PHP版本是5.4.45-0+deb7u2.
提前致谢。
根据@Zaph 的评论更新。
有一个小的语法错误。然而,代码的问题在于,在加密例程中,您只能使用以下之一:OPENSSL_RAW_DATA 或 OPENSSL_ZERO_PADDING。文档中有提到。
@Zaph 的评论:应该使用 PKCS#7 填充,它是一般填充。事实证明,PHP OpenSSL 的默认设置是 PKCS#7。所以,不要添加任何填充选项,你会得到正确的结果。
Openssl_encrypt()
在使用 CBC 或 ECB 模式的块密码加密之前,将 PKCS7 填充添加到明文。 Openssl_decrypt()
解密后去除填充。
我正在使用 PHP 5.4.4.
因此,唯一需要的选项是:OPENSSL_RAW_DATA。
请注意,IV(初始化向量)每次都会更改并存储在输出字符串中。为什么?如果您提供相同的字符串和密码,那么每次输出的字符串肯定不同。
使加密的字符串可以安全地存储在任何地方。我有 base64_encoded
它。
演示地点:ideone.com
###加密:
/**
* 加密字符串
*
*
* @Param 字符串 $数据
* @Param 字符串 $key
*
* @return 字符串 - base64_encoded
*/
函数加密($data,$key){
$cypher = 'aes-256-cbc';
$ivSize = openssl_cipher_iv_length($cypher);
$ivData = openssl_random_pseudo_bytes($ivSize);
$encripted = openssl_encrypt($data,
$cypher,
$key,
OPENSSL_RAW_DATA,
$ivData);
return base64_encode($ivData . $encripted);
}
###解密:
/**
* Decrypt a string
*
* @Param string $data
* @Param string $key
*
* @return string - original text
*/
function decrypt($data, $key) {
$cypher = 'aes-256-cbc';
$ivSize = openssl_cipher_iv_length($cypher);
$data = base64_decode($data);
$ivData = substr($data, 0, $ivSize);
$encData = substr($data, $ivSize);
$output = openssl_decrypt($encData,
$cypher,
$key,
OPENSSL_RAW_DATA,
$ivData);
return $output;
}
运行它:
$srcText = "Hello World! - " . uniqid();
$key = 's7aBkf4Ypn59bWviQziPDXyPasdaYlhQ';
$srcEncrypted = '';
$srcDecrypted = '';
$srcEncrypted = encrypt($srcText, $key);
$srcDecrypted = decrypt($srcEncrypted, $key);
var_dump($srcText,
$srcEncrypted,
$srcDecrypted,
$srcDecrypted == $srcText);
###示例输出:
string 'Hello World! - 5776adf944c52' (length=28)
string 'NOjIIMM0visDbJPmBsAMgH+OQbYiReLBSvzg5JVZTMUOCAtk3CO7FBNs/Dn/vE9s' (length=64)
string 'Hello World! - 5776adf944c52' (length=28)
boolean true
我正在尝试使用 openssl_encrypt/openssl_decrypt encrypt/decrypt 一些数据。目的如下:用户在 GUI 中输入一些数据,这些数据被加密并存储在数据库中。稍后将仅针对特定用户配置文件对其进行检索和解密。
加密部分工作正常,因为我听从了同事的建议,即将输出包装到 bin2hex 函数中。
关键是我在解密数据时似乎无法获得二进制输出,即使我尝试使用 hex2bin 转换输出也是如此。我总是得到类似“� �Ps�1�_G�5�OUT”的输出。
我 运行 没有想法,实际上我现在真的不知道该怎么做。
这是我为测试此功能而编写的示例代码:
PHP
function encrypt($string) {
$cypher = 'aes-256-cbc';
$key = 's7aBkf4Ypn59bWviQziPDXyPasdaYlhQ';
$ivsize = openssl_cipher_iv_length($cypher);
$iv = openssl_random_pseudo_bytes($ivsize);
$encripted = openssl_encrypt(
$string, $cypher, $key, OPENSSL_RAW_DATA | OPENSSL_ZERO_PADDING, $iv
);
return $iv . $encripted;
}
function decrypt($string) {
$cypher = 'aes-256-cbc';
$key = 's7aBkf4Ypn59bWviQziPDXyPasdaYlhQ';
$ivsize = openssl_cipher_iv_length($cypher);
$iv = mb_substr($string, 0, $ivsize, '8bit');
$decrypted = mb_substr($string, $ivsize, null, '8bit');
$output = openssl_decrypt(
$decrypted, $cifrado, $key, OPENSSL_RAW_DATA | OPENSSL_ZERO_PADDING, $iv
);
return $output;
}
HTML:
<!doctype html>
<html>
<head><title>TEST</title></head>
<body>
<div style='margin-left:250px;'>
<form action="test.php" method="POST">
Encrypt
<input type="text" name="encrypt" value=''/>
<input type="submit" name="send" value='Send'/>
<br/><br/>
<?php
if (isset($_POST['encrypt']) && !empty($_POST['encrypt'])) {
echo 'encrypted string: ' . bin2hex(encrypt($_POST['encrypt']));
}
?>
<br/>
<br/>
Decrypt
<input type="text" name="decrypt" value=''/>
<input type="submit" name="send" value='Send'/>
<br/><br/>
<?php
if (isset($_POST['decrypt']) && !empty($_POST['decrypt'])) {
echo 'decrypted string: ' . decrypt($_POST['decrypt']);
var_dump(decrypt($_POST['decrypt']));
}
?>
</form>
</body>
如有任何想法或帮助,我们将不胜感激。
我的PHP版本是5.4.45-0+deb7u2.
提前致谢。
根据@Zaph 的评论更新。
有一个小的语法错误。然而,代码的问题在于,在加密例程中,您只能使用以下之一:OPENSSL_RAW_DATA 或 OPENSSL_ZERO_PADDING。文档中有提到。
@Zaph 的评论:应该使用 PKCS#7 填充,它是一般填充。事实证明,PHP OpenSSL 的默认设置是 PKCS#7。所以,不要添加任何填充选项,你会得到正确的结果。
Openssl_encrypt()
在使用 CBC 或 ECB 模式的块密码加密之前,将 PKCS7 填充添加到明文。 Openssl_decrypt()
解密后去除填充。
我正在使用 PHP 5.4.4.
因此,唯一需要的选项是:OPENSSL_RAW_DATA。
请注意,IV(初始化向量)每次都会更改并存储在输出字符串中。为什么?如果您提供相同的字符串和密码,那么每次输出的字符串肯定不同。
使加密的字符串可以安全地存储在任何地方。我有 base64_encoded
它。
演示地点:ideone.com
###加密:
/**
* 加密字符串
*
*
* @Param 字符串 $数据
* @Param 字符串 $key
*
* @return 字符串 - base64_encoded
*/
函数加密($data,$key){
$cypher = 'aes-256-cbc';
$ivSize = openssl_cipher_iv_length($cypher);
$ivData = openssl_random_pseudo_bytes($ivSize);
$encripted = openssl_encrypt($data,
$cypher,
$key,
OPENSSL_RAW_DATA,
$ivData);
return base64_encode($ivData . $encripted);
}
###解密:
/**
* Decrypt a string
*
* @Param string $data
* @Param string $key
*
* @return string - original text
*/
function decrypt($data, $key) {
$cypher = 'aes-256-cbc';
$ivSize = openssl_cipher_iv_length($cypher);
$data = base64_decode($data);
$ivData = substr($data, 0, $ivSize);
$encData = substr($data, $ivSize);
$output = openssl_decrypt($encData,
$cypher,
$key,
OPENSSL_RAW_DATA,
$ivData);
return $output;
}
运行它:
$srcText = "Hello World! - " . uniqid();
$key = 's7aBkf4Ypn59bWviQziPDXyPasdaYlhQ';
$srcEncrypted = '';
$srcDecrypted = '';
$srcEncrypted = encrypt($srcText, $key);
$srcDecrypted = decrypt($srcEncrypted, $key);
var_dump($srcText,
$srcEncrypted,
$srcDecrypted,
$srcDecrypted == $srcText);
###示例输出:
string 'Hello World! - 5776adf944c52' (length=28)
string 'NOjIIMM0visDbJPmBsAMgH+OQbYiReLBSvzg5JVZTMUOCAtk3CO7FBNs/Dn/vE9s' (length=64)
string 'Hello World! - 5776adf944c52' (length=28)
boolean true