且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

使用AES在C#中进行文件加密,使用phpseclib进行解密

更新时间:2023-02-17 17:07:15

  1. 解密时不使用初始化向量.您需要将初始化向量(IV)与数据一起发送-您的PHP代码永远不会调用 $ aes-> setIV来自phpseclib,因此它将永远无法解密文本,因为phpseclib如果未设置,将使用全零的IV. RijndaelManaged.GenerateIV ,但是从PBKDF2密钥派生IV显然是可以接受的.PBKDF2(在RFC 2898中指定)是 Rfc2898DeriveBytes 实现的密钥拉伸算法.无论如何,您都需要在PHP端重新生成IV,这是否意味着用加密的数据传输IV(完全没问题)还是在PHP端重新导出IV.

  1. No initialization vector used when decrypting. You need to send the initialization vector (IV) along with the data - your PHP code is never calling $aes->setIV from phpseclib, so it will never be able to decrypt the text because phpseclib uses an IV of all zeros if one is not set according to the docs. I would personally recommend generating a secure random IV from C# using RijndaelManaged.GenerateIV, but apparently it's considered acceptable to derive the IV from a PBKDF2 key. PBKDF2 (specified in RFC 2898) is the key-stretching algorithm Rfc2898DeriveBytes implements. Regardless, you need to re-produce the IV on the PHP side, whether that means transmitting the IV with the encrypted data (which is completely fine) or re-deriving the IV on the PHP side.

使用密码作为盐是一个非常糟糕的想法.盐必须具有足够的长度,并且必须通过密码随机生成.将密码用作盐完全可以消除含盐的问题. MSDN有一些示例代码展示了如何结合使用 Rfc2898DeriveBytes 来生成密码随机盐,但重要的部分在这里:

Using the password as the salt is a REALLY BAD IDEA. The salt needs to be of sufficient length and cryptographically randomly generated. Using the password as the salt completely defeats the point of having a salt. MSDN has some sample code that shows how to generate a cryptographically random salt in conjunction with using Rfc2898DeriveBytes, but the important part is here:

byte[] saltBytes = new byte[8];
using (RNGCryptoServiceProvider rngCsp = new RNGCryptoServiceProvider())
{
    // Fill the array with a random value.
    rngCsp.GetBytes(salt1);
}

  1. 盐必须与加密的数据一起传输.您需要将PBKDF2盐字节以及IV字节和加密数据一起发送.phpseclib将需要所有这些来正确地初始化自身并解密数据.您可能需要使用phpseclib的 setPassword 为此,就像这样:
  1. The salt must be transmitted with the encrypted data. You need to send the PBKDF2 salt bytes along with the IV bytes and encrypted data. phpseclib will need all of those to properly initialize itself and decrypt the data. You'll probably want to use phpseclib's setPassword to do this, like so:

$salt = ...; // get the salt to your PHP code somehow
$iv = ...; // get the IV to your PHP code
$pw = "this_is_my_pw";
$aes = new Crypt_AES(CRYPT_AES_MODE_CBC);
$aes->setPassword($pw, 'pbkdf2' /* key extension algorithm */,
    'sha1' /* hash algorithm */, $salt /* generated salt from C# */,
    1000 /* number of iterations, must be same as C# code */,
    256 / 8 /* key size in bytes, 256 bit key / 8 bits per byte */
);
$aes->setIV($iv);

  1. 请记住有关块大小的其他答案.标准的AES块大小是128位,因此请确保C#和phpseclib都可以在更大的块大小下正常运行,或者仅对这两个块使用AES标准
  1. Keep the other answers in mind about blocksize. 128 bits is the standard AES blocksize, so make sure both C# and phpseclib can function correctly with a larger blocksize, or just use the AES standard for both.