且构网

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

如何将此 C# Rijndael 加密转换为 PHP?

更新时间:2023-02-17 16:57:21

我认为 PHP 版本实际上可能会在键和 IV 中添加 00h 值字节.它们都有一个无效的大小:每个 8 个字节.对于 AES-128,它们需要扩展到 16 个字节.在您的 C# 代码中,您使用 32 个字节作为密钥,因此将使用具有 密钥大小 256 位的 AES.

I think that the PHP version may actually add 00h valued bytes to the key and IV. They both have an invalid size : 8 bytes for each. They need to be extended to 16 bytes for AES-128. In your C# code you use 32 bytes for the key, which will therefore use AES with a key size of 256 bits.

此外,您没有在 PasswordDeriveBytes 中指定迭代次数,您应该指定它,因为该类没有指定默认的迭代次数 - 根据您的评论,这将是 100,让我们假设它是.

Futhermore, you don't specify the number of iterations in PasswordDeriveBytes, you should specify it as the class does not specify the default number of iterations - according to your comments, this would be 100, lets assume it is.

哦,您使用了不正确的加密方法.MCRYPT_RIJNDAEL_256 指定使用 blocksize 256 位的 Rijndael 算法,而不是 256 位的 密钥.据推测,密钥的位大小只是密钥的字节数乘以 8.

Oh, and you use the incorrect encryption method. MCRYPT_RIJNDAEL_256 specifies the Rijndael algorithm using a blocksize of 256 bits, not keys of 256 bits. Presumably, the bitsize of the keys is simply the number of bytes of the key times 8.

你能用这个替换你的加密功能然后再试一次吗?

Could you replace your Encrypt function with this and try again?

function Encrypt($pass, $salt)
{
     $derived = PBKDF1($pass, $salt, 100, 48);
     $key = bin2hex(substr($derived, 0, 32));
     $iv = bin2hex(substr($derived, 32, 16));
     return mcrypt_encrypt(MCRYPT_RIJNDAEL_128, $key, $pass, MCRYPT_MODE_CBC, $iv);
}

最后,请在进行加密或解密之前检查生成的IV和密钥是否与PHP中的IV和密钥匹配.你确定那个 PHP PBKDF1 函数是正确的?

Finally, please check if the generated IV and key match with the ones in PHP before performing encryption or decryption. Are you sure that that PHP PBKDF1 function is correct?

更新:这里是关于 M$ PBKDF1 例程的更多信息在 PasswordDeriveBytes 中(包括您可以尝试转换的 Java 代码):

UPDATE: Here is some more information on the M$ PBKDF1 routines in PasswordDeriveBytes (including Java code which you may try and convert):

哈,我明白你的意思.

有趣的是,使用.NET:调用48时结果不同或调用 32 然后调用 16:

Interestingly, using .NET: the results are different when calling 48 or calling 32 followed by 16:

.NET GetBytes( 32 +16 ):04DD9D139DCB9DE889946D3662B319682159FF9C9B47FA15ED205C7CAF890922655D8DD89AE1CAAC60A8041FCD7E8DA4

.NET GetBytes( 32 +16 ): 04DD9D139DCB9DE889946D3662B319682159FF9C9B47FA15ED205C7CAF890922655D8DD89AE1CAAC60A8041FCD7E8DA4

.NET GetBytes(32)04DD9D139DCB9DE889946D3662B319682159FF9C9B47FA15ED205C7CAF890922其次是 GetBytes( 16 ) 89946D3662B3196860A8041FCD7E8DA4

.NET GetBytes( 32 ) 04DD9D139DCB9DE889946D3662B319682159FF9C9B47FA15ED205C7CAF890922 Followed by GetBytes( 16 ) 89946D3662B3196860A8041FCD7E8DA4

真正的 Microsoft 代码,他们无法更改它,因为它可能会破坏该领域的应用程序.请注意,当使用 16 字节和 8 字节或直接使用 24 字节设计调用它时,它们也会返回不同的结果.您***升级到 PBKDF2,并将 PBKDF1 限制为最大 20 个字节,如标准中所定义.

True Microsoft code, and they cannot change it because it could break applications in the field. Note that they also would return different results when calling it with 16 and then 8 bytes or directly by 24 bytes by design. You'd better upgrade to PBKDF2, and keep PBKDF1 limited to 20 bytes max, as defined in the standards.