AES 256加密PHP与填充


AES 256 encryption PHP with Padding

我对我当前试图访问的API的加密有以下要求:

  • PKCS7填充方法
  • CBC加密模式
  • AES密钥大小256,块大小128

每次我向API提交加密时,API似乎都有问题(不幸的是,没有产生错误)。

$Data = "GOOD!";
$aesKey = "1234567812345678";
$EncryptedData = encrypt($aesKey,$Data);
$DecryptedData = decrypt($aesKey,$EncryptedData);
echo "Orignal Data : ". $Data;
echo "<br/>";
echo "After encryption = ". $EncryptedData;
echo "<br/>";
echo "After decryption = " .$DecryptedData;
function encrypt($aesKey, $dataToEncrypt) {
    $output = false;
    $iv = '{{{{{{{{{{{{{{{{';
    $output = openssl_encrypt($dataToEncrypt, 'AES-128-CBC', $aesKey,
    OPENSSL_RAW_DATA, $iv);
    $output = base64_encode($output);
    return $output;
}
function decrypt($aesKey, $dataTodecrypt) {
    $output = false;
    $iv = '{{{{{{{{{{{{{{{{';
    $dataTodecrypt = base64_decode ($dataTodecrypt);
    $dataTodecrypt = $output = openssl_decrypt($dataTodecrypt, 'AES-128-CBC',
    $aesKey, OPENSSL_RAW_DATA, $iv);
    return $output;
}

问题:

  • PKCS7填充方法到底是什么,可以用php实现
  • AES 256很好,但块大小究竟意味着什么
  • 静脉注射到底是干什么的

AES 256很好,但块大小究竟意味着什么?

AES具有128位的固定块大小。块密码只适用于特定大小的一个块。模式操作扩展了块密码,使其能够在多个块上工作,而填充使其能够处理不是块大小倍数的明文。

AES-128-CBC表示密钥大小为128位的AES和CBC操作模式。如果你想使用AES-256,那么你需要告诉OpenSSL:AES-256-CBC。此外,您需要使用一个实际长度为256位的密钥。您当前的密钥只有128位长。

PKCS7填充方法到底是什么,可以用php实现?

openssl_encrypt()已经为您做了PKCS#7填充,openssl_decrypt()为您删除了它。

静脉注射到底是干什么的?

随机IV将密文随机化,这意味着用相同的密钥加密相同的明文,但不同的IV会产生不同的密文,这与随机噪声或其他使用不同IV的相同加密无法区分。维基百科很好地描述了这一点的实际作用。

请记住,每次迭代都必须随机生成IV。否则,只观察密文的攻击者可能会发现您对同一明文进行了多次加密。


请记住,AES密钥应该是具有高熵的噪声较大的密钥。"12345…"看起来更像是一个密码。如果您想使用密码,那么您需要从该密码派生密钥。PBKDF2是一个好主意,它有一个随机的salt和大量的迭代。

PKCS7填充方法到底是什么,可以用php实现?

我真的不确定"填充"是你在这里指的短语。虽然PKCS#7格式确实依赖于填充,但您提供的示例与非对称加密和上面提到的PKCS#7消息语法的ASN.1格式完全无关。

AES 256很好,但块大小究竟意味着什么?

块大小是加密密码(如AES-256)在每个排列中操作的比特大小。

静脉注射到底是干什么的?

IV是初始化向量的缩写,或者对于一些对称加密密码实现,它也可以被称为nonce。

两者都用于帮助增强生成的密文。你可以把它们想象成类似于不可逆哈希算法的盐。

你应该避免重复使用相同的IV.

就你的例子而言;openssl_encrypt()的文档说明了以下函数的用法:

string openssl_encrypt ( string $data , string $method , string $password [, int $options = 0 [, string $iv = "" ]] )

你对纯文本的加密看起来很准确(而我会选择AES-256-GCM与AES-128-CBC作为算法,块大小和模式):

$output = openssl_encrypt($dataToEncrypt, 'AES-128-CBC', $aesKey,
    OPENSSL_RAW_DATA, $iv);

在没有测试的情况下,我假设您得到了一个有效的base64编码值。

openssl_decrypt()方法的手册说明了以下用法:

string openssl_decrypt ( string $data , string $method , string $password [, int $options = 0 [, string $iv = "" ]] )

虽然从技术上讲,您的实施是正确的;我建议如下(注意$dataTodecryt=$output=openssl_decrypt()的双重赋值):

$output = openssl_decrypt(base64_decode($dataTodecrypt), 'AES-128-CBC', $aesKey, OPENSSL_RAW_DATA, $iv);