使用php openssl_encrypt的正确方法

时间:2017-12-29 05:32:43

标签: php encryption cryptography aes php-openssl

我正在项目中使用加密技术,我需要一些关于如何使用openssl_encryptopenssl_decrypt的帮助,我只想知道最基本和最正确的方法它。这是我到目前为止所得到的:

// To encrypt a string

$dataToEncrypt = 'Hello World';

$cypherMethod = 'AES-256-CBC';
$key = random_bytes(32);
$iv = openssl_random_pseudo_bytes(openssl_cipher_iv_length($cypherMethod));

$encryptedData = openssl_encrypt($dataToEncrypt, $cypherMethod, $key, $options=0, $iv);

然后我存储$cypherMethod$key$iv,以便在解密$encryptedData时使用。 (我们不详细说明如何存储值,谢谢!)

// To decrypt an encrypted string

$decryptedData = openssl_decrypt($encryptedData, $cypherMethod, $key, $options=0, $iv);

首先,上面的示例代码是如何使用php openssl_encrypt

的正确示例

其次,我的方法是生成$key$iv正确且安全吗?因为我一直在阅读,所以密钥应该是加密安全的。

最后,32-byte不需要AES-256-CBC值吗?如果是,那么为什么openssl_cipher_iv_length()仅返回int(16)作为长度?不应该是int(32)吗?

3 个答案:

答案 0 :(得分:4)

  

首先,上面的示例代码是如何使用php openssl_encrypt的正确示例?

您对该功能的使用看起来是正确的,但您可能需要考虑CBC以外的操作模式。 CBC很难做到正确,因为在这种模式下加密数据会产生已知的攻击,例如臭名昭​​着的CBC bit-flipping attack,它允许攻击者通过修改密文对明文进行有意义的更改。如果可能,我会使用像GCM这样经过身份验证的加密模式(看起来像it's supported in PHP 7.1+ (Example #1))。

如果您使用CBC模式,请查看Example #2 in the docs。注意,在加密之后,通过密文计算MAC(消息认证码)并存储。在解密密文之前应重新计算此MAC,如果它与存储的MAC不匹配,则密文已被修改且无效。

  

其次,我的方法是生成$ key和$ iv是否正确且安全?因为我一直在阅读,所以密钥应该是加密安全的。

需要使用加密安全随机数生成器生成密钥。幸运的是,大多数操作系统都通过/dev/urandom提供了一个开箱即用的系统。 This answer很好地解释了如何在PHP中读取/dev/urandomopenssl_random_pseudo_bytes 也应该是加密安全的,但有times when this is not the case

初始化向量(IV)需要是随机的,不应该使用相同的密钥重复使用。

  

最后,AES-256-CBC不是32字节值?如果是,那么为什么openssl_cipher_iv_length()只返回int(16)作为长度?不应该是int(32)吗?

AES是一种块密码,无论密钥大小如何,都可以在128位(16字节)块上运行。

答案 1 :(得分:4)

这是使用openssl_encrypt和openssl_decrypt的最基本方法。确保创建32字节secret_key和16字节secret_iv

General

答案 2 :(得分:2)

// --- Encrypt --- //
$key = openssl_digest("passkey", 'SHA256', TRUE);
$plaintext = "Data to be encrypted";
$ivlen = openssl_cipher_iv_length($cipher="AES-128-CBC");
$iv = openssl_random_pseudo_bytes($ivlen);
// binary cipher
$ciphertext_raw = openssl_encrypt($plaintext, $cipher, $key, OPENSSL_RAW_DATA, $iv);
// or replace OPENSSL_RAW_DATA & $iv with 0 & bin2hex($iv) for hex cipher (eg. for transmission over internet)

// or increase security with hashed cipher; (hex or base64 printable eg. for transmission over internet)
$hmac = hash_hmac('sha256', $ciphertext_raw, $key, true);
$ciphertext = base64_encode( $iv.$hmac.$ciphertext_raw );

// --- Decrypt --- //
$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, OPENSSL_RAW_DATA, $iv);
$calcmac = hash_hmac('sha256', $ciphertext_raw, $key, true);
if (hash_equals($hmac, $calcmac))
    echo $original_plaintext."\n";