繁体   English   中英

无法在PHP Mcrypt中使用常量IV密钥和生成的ENCRYPT_KEY

[英]Cannot use a constant IV key and a produced ENCRYPT_KEY in php mcrypt

我知道恒定的IV密钥是错误的,必须生成一个随机密钥。 但是,我需要这样做,因为我已被分配执行此操作。 我已经在网上搜索了如何处理此问题的方法,但失败了。 我的代码在下面,任何建议将不胜感激。

这是完整的代码以及功能

define('ENCRYPTION_KEY', 'ITU2NjNhI0tOc2FmZExOTQ==');    //Encryption KEY

 // Encrypt Function
 function mc_encrypt($encrypt, $key)
 {
    //Do Not Put ENCRYPTION_KEY here
    $encrypt = serialize($encrypt);
    $iv = mcrypt_create_iv(mcrypt_get_iv_size(MCRYPT_RIJNDAEL_256, MCRYPT_MODE_CBC), MCRYPT_RAND);
    //$iv = ('AAAAAAAAAAAAAAAAAAAAAA==');

    $key = pack('H*', $key);
    $mac = hash_hmac('sha256', $encrypt, substr(bin2hex($key), -32));
    $passcrypt = mcrypt_encrypt(MCRYPT_RIJNDAEL_256, $key, $encrypt.$mac, MCRYPT_MODE_CBC, $iv);
    $encoded = base64_encode($passcrypt).'|'.base64_encode($iv);

    return $encoded; //return base64_encode($encoded).':'.$iv;
 }

// Decrypt Function
function mc_decrypt($decrypt, $key)
{
    $decrypt = explode('|', $decrypt);
    $decoded = base64_decode($decrypt[0]);
    $iv = base64_decode($decrypt[1]);

if(strlen($iv) !== mcrypt_get_iv_size(MCRYPT_RIJNDAEL_256, MCRYPT_MODE_CBC))
{ 
    return false; 
}

$key = pack('H*', $key);
$decrypted = trim(mcrypt_decrypt(MCRYPT_RIJNDAEL_256, $key, $decoded, MCRYPT_MODE_CBC, $iv));
$mac = substr($decrypted, -64);
$decrypted = substr($decrypted, 0, -64);
$calcmac = hash_hmac('sha256', $decrypted, substr(bin2hex($key), -32));

if($calcmac !== $mac)
{ 
    return false; 
}

$decrypted = unserialize($decrypted);

return $decrypted;
}

echo '<h1>Sample Encryption</h1>';

$data = 'Patrick';
$encrypted_data = mc_encrypt($data, ENCRYPTION_KEY);
echo '<h2>Example #1: String Data</h2>';
echo 'Data to be Encrypted: ' . $data . '<br/>';
echo 'Encrypted Data: ' . $encrypted_data . '<br/>';
echo 'Decrypted Data: ' . mc_decrypt($encrypted_data, ENCRYPTION_KEY) . '</br>';

如果我使用该错误

警告:pack():类型H:第24行的C:\\ xampp \\ htdocs \\ sample1 \\ test.php中的非法十六进制数字I

当我使用

$iv = ('AAAAAAAAAAAAAAAAAAAAAA==');

代替这个

$iv = mcrypt_create_iv(mcrypt_get_iv_size(MCRYPT_RIJNDAEL_256, MCRYPT_MODE_CBC), MCRYPT_RAND);

虽然他们都有

define('ENCRYPTION_KEY', 'd0a7e7997b6d5fcd55f4b5c32611b87cd923e88837b63bf2941ef819dc8ca282');    //Encryption KEY

这是错误

Warning: mcrypt_encrypt(): The IV parameter must be as long as the blocksize in C:\xampp\htdocs\sample1\test.php on line 26

这是在PHP 5.3.18上正常工作和经过测试的代码。 Viper-7示范

1)它使用必需的base64编码的“ AAAAAAAAAAAAAAAAAAAAAA ==”作为IV(“盐”),将其转换回字符串时为16个字节的二进制零。 因为我们需要32个字节,所以我只是将其与自身连接起来以形成所需的长度。

2)提供了两个键:

1)base64编码:“ ITU2NjNhI0tOc2FmZExOTQ ==”,这是一个“典型的”高质量密码字符串,长度为16个字节。 这需要转换为十六进制字符串以用于加密功能。

2)十六进制文字:'d0a7e7997b'...

请注意:提供的密钥(十六进制字符串)彼此不相等

这不会影响例程,只是要注意必须使用相同的密钥进行加密/解密。

例程:

 // Encrypt Function - $key must be a Hexadecimal String
 function mc_encrypt($encrypt, $key) {
    //Do Not Put ENCRYPTION_KEY here
    $encrypt = serialize($encrypt);

    // $iv = mcrypt_create_iv(mcrypt_get_iv_size(MCRYPT_RIJNDAEL_256, MCRYPT_MODE_CBC), MCRYPT_RAND);
    $iv = base64_decode(ENCRYPTION_IV); // convert back to binary string
    $actualIV = $iv . $iv; // As it is 16 bytes of binary characters just double it

    $key = pack('H*', $key); // convert key back to binary string
    $mac = hash_hmac('sha256', $encrypt, substr(bin2hex($key), -32));
    $passcrypt = mcrypt_encrypt(MCRYPT_RIJNDAEL_256, $key, $encrypt.$mac, MCRYPT_MODE_CBC, $actualIV);
    $encoded = base64_encode($passcrypt).'|'.base64_encode($iv);
    return $encoded;
 }

请注意,'$ actualIV'只是获取所需32字节的技巧。 但是,如果使用不同的16字节IV,它将起作用。

注意事项:重要的是,加密时使用不同的(随机)IV,否则,当使用相同的密钥时,相同的消息将加密为相同的密文。 要在例程中使用16个字节的IV,我很想生成一个随机IV,而只是使用当前使用的与其自身串联的前16个字节。

即替换此代码:

$iv = base64_decode(ENCRYPTION_IV); // convert back to binary string

有:

$iv = mcrypt_create_iv(mcrypt_get_iv_size(MCRYPT_RIJNDAEL_256, MCRYPT_MODE_CBC), MCRYPT_RAND);
$iv = substr($iv, 0, 16);

CBC模式和'Padding Oracle Attacks'如果您仅使用PHP,这似乎不是问题。 在不同的系统上解密可能会出现问题。 该链接说明了这些问题: Cryptography / DES-PHP-Block-Padding-in-mcrypt.html

// Decrypt Function - - $key must be a Hexadecimal String
function mc_decrypt($decrypt, $key) {
    $decrypt = explode('|', $decrypt);
    $decoded = base64_decode($decrypt[0]);
    $iv = base64_decode($decrypt[1]);

    $actualIV = $iv . $iv; // make it long enough and match the original IV used.
    if(strlen($actualIV) !== mcrypt_get_iv_size(MCRYPT_RIJNDAEL_256, MCRYPT_MODE_CBC)){ return false; }

    $key = pack('H*', $key);
    $decrypted = trim(mcrypt_decrypt(MCRYPT_RIJNDAEL_256, $key, $decoded, MCRYPT_MODE_CBC, $actualIV));
    $mac = substr($decrypted, -64);
    $decrypted = substr($decrypted, 0, -64);
    $calcmac = hash_hmac('sha256', $decrypted, substr(bin2hex($key), -32));
    if($calcmac!==$mac) { return false; }
    $decrypted = unserialize($decrypted);
    return $decrypted;
}

请注意,'$ iv'与自身连接在一起,以获得所需的32个字节。

定义的键:

define('ENCRYPTION_B64KEY', 'ITU2NjNhI0tOc2FmZExOTQ==');    //Encryption KEY
define('ENCRYPTION_IV', 'AAAAAAAAAAAAAAAAAAAAAA==');
define('ENCRYPTION_HEXKEY', 'd0a7e7997b6d5fcd55f4b5c32611b87cd923e88837b63bf2941ef819dc8ca282');    //Encryption KEY

使用两个提供的键的示例:

echo '<h1>Sample Encryption</h1>';

$data = 'Patrick';
echo '<h2>Example #1: Using base64 encoded key (ENCRYPTION_B64KEY)</h2>';

$b64HexKey = bin2hex(base64_decode(ENCRYPTION_B64KEY));
$encrypted_data = mc_encrypt($data, $b64HexKey);
echo 'Data to be Encrypted: ' . $data . '<br/>';
echo 'Encrypted Data: ' . $encrypted_data . '<br/>';
echo 'Decrypted Data: ' . mc_decrypt($encrypted_data, $b64HexKey) . '</br>';

echo '<h2>Example #2 using Hexadecimal Key (ENCRYPTION_HEXKEY)</h2>';

$hexKey = ENCRYPTION_HEXKEY;
$encrypted_data = mc_encrypt($data, $hexKey);
echo 'Data to be Encrypted: ' . $data . '<br/>';
echo 'Encrypted Data: ' . $encrypted_data . '<br/>';
echo 'Decrypted Data: ' . mc_decrypt($encrypted_data, $hexKey) . '</br>';

以上输出:

Sample Encryption

Example #1: Using base64 encoded key (ENCRYPTION_B64KEY)

Data to be Encrypted: Patrick
Encrypted Data: /7qKjoPnNiGveTHo0NnkXfSLFIHE72De1q85QWI/d16j4BzLaqIR7jpap0J2wCdHYgK+IS4Zf1OpZorK9iGnPErkh+owjkoEo/dejHxUaVxOS03+Uqti8i13aGeB6wAU|AAAAAAAAAAAAAAAAAAAAAA==
Decrypted Data: Patrick
Example #2 using Hexadecimal Key (ENCRYPTION_HEXKEY)

Data to be Encrypted: Patrick
Encrypted Data: iAyCpfnOHUeHKHT+BIra2TZbRlLJfXKAO5pRGbmKvLyTOlzr9L6IBRI8ZuDsGVdZym26Qd89hKZxnVPbBSsOktCaztF9akZA8iPa3r0jvgISFldRDdHx8CZyd+GfR9BV|AAAAAAAAAAAAAAAAAAAAAA==
Decrypted Data: Patrick

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM