.Net 和 PHP Rijndael 加密不匹配
起初我以为这是填充,因为 mcrypt 使用零填充,但我更改了 php 以使用 PKCS7 并得到相同的精确结果
有人可以帮忙吗?我认为这与 .Net 的 php 测试输出中的填充有关
:
Key: d88f92e4fa27f6d45b49446c7fc76976
Text: Testing123
Encrypted: /DMkj7BL9Eu2LMxKhdGT+A==
Encrypted after base64 decode: ?3$??K?K?,?J???
Decrypted: Testing123
PHP 的测试输出:
Key: d88f92e4fa27f6d45b49446c7fc76976
Text: Testing123
Encrypted: K+ke5FNI5T6F6B/XvDF494+S8538Ze83cFz6v1FE89U=
Encrypted after base64 decode: +éäSHå>…è×¼1x÷’óüeï7p\ú¿QDóÕ
Decrypted: Testing123����������������������
PHP:
class rijndael{
var $mcrypt_cipher = MCRYPT_RIJNDAEL_256;
var $mcrypt_mode = MCRYPT_MODE_CBC;
function decrypt($pass, $encrypted)
{
$encrypted = base64_decode($encrypted);
$key = $this->getkey($pass);
$iv = $this->getiv($pass);
$decrypted = mcrypt_decrypt($this->mcrypt_cipher, $key, $encrypted, $this->mcrypt_mode, $iv);
$block = mcrypt_get_block_size($this->mcrypt_cipher, $this->mcrypt_mode);
$pad = ord($decrypted[($len = strlen($decrypted)) - 1]);
return substr($decrypted, 0, strlen($decrypted) - $pad);
}
function encrypt($pass, $decrypted)
{
$key = $this->getkey($pass);
$iv = $this->getiv($pass);
$block = mcrypt_get_block_size($this->mcrypt_cipher, $this->mcrypt_mode);
$pad = $block - (strlen($str) % $block);
$str .= str_repeat(chr($pad), $pad);
$encrypted = mcrypt_encrypt($this->mcrypt_cipher, $key, $decrypted, $this->mcrypt_mode, $iv);
return base64_encode($encrypted);
}
function getkey($passphrase)
{
$L1 = base64_encode(hash("sha256", $passphrase, true));
$L2 = $passphrase.$L1;
return hash("sha256", $L2, true);
}
function getiv($passphrase)
{
$L1 = base64_encode(md5($passphrase));
$L2 = $passphrase.$L1;
return md5($L2);
}
}
VB .Net:
Public Class RijnDael
Public Shared Function Decrypt(ByVal sData As String, ByVal sKey As String)
Dim bytData() As Byte = Encoding.UTF8.GetBytes(sData)
Return Decrypt(bytData, sKey)
End Function
Public Shared Function Decrypt(ByVal bytData As Byte(), ByVal strPass As String) As Byte()
Dim bytResult As Byte()
Using oRM As New System.Security.Cryptography.RijndaelManaged
oRM.KeySize = 256
oRM.Key = GeKey(strPass)
oRM.IV = GetIV(strPass)
oRM.Mode = CipherMode.CBC
oRM.Padding = PaddingMode.PKCS7
Using oMS As New MemoryStream(bytData)
Using oCS As New Cryptography.CryptoStream(oMS, oRM.CreateDecryptor, Security.Cryptography.CryptoStreamMode.Read)
Dim TempDecryptArr As Byte()
ReDim TempDecryptArr(bytData.Length)
Dim decryptedByteCount As Integer
decryptedByteCount = oCS.Read(TempDecryptArr, 0, bytData.Length)
'
ReDim bytResult(decryptedByteCount)
Array.Copy(TempDecryptArr, bytResult, decryptedByteCount)
'
oCS.Close()
End Using
oMS.Close()
End Using
End Using
Return bytResult
End Function
Public Shared Function Encrypt(ByVal sData As String, ByVal sKey As String)
Dim bytData() As Byte = Encoding.UTF8.GetBytes(sData)
Return Encrypt(bytData, sKey)
End Function
Public Shared Function Encrypt(ByVal bytData As Byte(), ByVal strPass As String) As Byte()
Dim bytResult As Byte()
Using oRM As New Cryptography.RijndaelManaged
oRM.KeySize = 256
oRM.Key = GeKey(strPass)
oRM.IV = GetIV(strPass)
oRM.Mode = CipherMode.CBC
oRM.Padding = PaddingMode.PKCS7
Using oMS As New MemoryStream
Using oCS As New Cryptography.CryptoStream(oMS, oRM.CreateEncryptor, Cryptography.CryptoStreamMode.Write)
oCS.Write(bytData, 0, bytData.Length)
oCS.FlushFinalBlock()
bytResult = oMS.ToArray()
oCS.Close()
End Using
oMS.Close()
End Using
End Using
Return bytResult
End Function
Private Shared Function GeKey(ByVal strPass As String) As Byte()
Dim bytResult As Byte()
'Generate a byte array of required length as the encryption key.
'A SHA256 hash of the passphrase has just the required length. It is used twice in a manner of self-salting.
Using oSHA256 As New Cryptography.SHA256Managed
Dim L1 As String = System.Convert.ToBase64String(oSHA256.ComputeHash(Encoding.UTF8.GetBytes(strPass)))
Dim L2 As String = strPass & L1
bytResult = oSHA256.ComputeHash(System.Text.Encoding.UTF8.GetBytes(L2))
oSHA256.Clear()
End Using
Return bytResult
End Function
Private Shared Function GetIV(ByVal strPass As String) As Byte()
Dim bytResult As Byte()
'Generate a byte array of required length as the iv.
'A MD5 hash of the passphrase has just the required length. It is used twice in a manner of self-salting.
Using oMD5 As New Cryptography.MD5CryptoServiceProvider
Dim L1 As String = System.Convert.ToBase64String(oMD5.ComputeHash(Encoding.UTF8.GetBytes(strPass)))
Dim L2 As String = strPass & L1
bytResult = oMD5.ComputeHash(System.Text.Encoding.UTF8.GetBytes(L2))
oMD5.Clear()
End Using
Return bytResult
End Function
End Class
At first i thought it was the padding since mcrypt uses zero padding but i changed the php to use PKCS7 and get the same exact results
Can anyone help? I think it has something to do with the padding in the php
Test output from .Net:
Key: d88f92e4fa27f6d45b49446c7fc76976
Text: Testing123
Encrypted: /DMkj7BL9Eu2LMxKhdGT+A==
Encrypted after base64 decode: ?3$??K?K?,?J???
Decrypted: Testing123
Test output from PHP:
Key: d88f92e4fa27f6d45b49446c7fc76976
Text: Testing123
Encrypted: K+ke5FNI5T6F6B/XvDF494+S8538Ze83cFz6v1FE89U=
Encrypted after base64 decode: +éäSHå>…è×¼1x÷’óüeï7p\ú¿QDóÕ
Decrypted: Testing123����������������������
PHP:
class rijndael{
var $mcrypt_cipher = MCRYPT_RIJNDAEL_256;
var $mcrypt_mode = MCRYPT_MODE_CBC;
function decrypt($pass, $encrypted)
{
$encrypted = base64_decode($encrypted);
$key = $this->getkey($pass);
$iv = $this->getiv($pass);
$decrypted = mcrypt_decrypt($this->mcrypt_cipher, $key, $encrypted, $this->mcrypt_mode, $iv);
$block = mcrypt_get_block_size($this->mcrypt_cipher, $this->mcrypt_mode);
$pad = ord($decrypted[($len = strlen($decrypted)) - 1]);
return substr($decrypted, 0, strlen($decrypted) - $pad);
}
function encrypt($pass, $decrypted)
{
$key = $this->getkey($pass);
$iv = $this->getiv($pass);
$block = mcrypt_get_block_size($this->mcrypt_cipher, $this->mcrypt_mode);
$pad = $block - (strlen($str) % $block);
$str .= str_repeat(chr($pad), $pad);
$encrypted = mcrypt_encrypt($this->mcrypt_cipher, $key, $decrypted, $this->mcrypt_mode, $iv);
return base64_encode($encrypted);
}
function getkey($passphrase)
{
$L1 = base64_encode(hash("sha256", $passphrase, true));
$L2 = $passphrase.$L1;
return hash("sha256", $L2, true);
}
function getiv($passphrase)
{
$L1 = base64_encode(md5($passphrase));
$L2 = $passphrase.$L1;
return md5($L2);
}
}
VB .Net:
Public Class RijnDael
Public Shared Function Decrypt(ByVal sData As String, ByVal sKey As String)
Dim bytData() As Byte = Encoding.UTF8.GetBytes(sData)
Return Decrypt(bytData, sKey)
End Function
Public Shared Function Decrypt(ByVal bytData As Byte(), ByVal strPass As String) As Byte()
Dim bytResult As Byte()
Using oRM As New System.Security.Cryptography.RijndaelManaged
oRM.KeySize = 256
oRM.Key = GeKey(strPass)
oRM.IV = GetIV(strPass)
oRM.Mode = CipherMode.CBC
oRM.Padding = PaddingMode.PKCS7
Using oMS As New MemoryStream(bytData)
Using oCS As New Cryptography.CryptoStream(oMS, oRM.CreateDecryptor, Security.Cryptography.CryptoStreamMode.Read)
Dim TempDecryptArr As Byte()
ReDim TempDecryptArr(bytData.Length)
Dim decryptedByteCount As Integer
decryptedByteCount = oCS.Read(TempDecryptArr, 0, bytData.Length)
'
ReDim bytResult(decryptedByteCount)
Array.Copy(TempDecryptArr, bytResult, decryptedByteCount)
'
oCS.Close()
End Using
oMS.Close()
End Using
End Using
Return bytResult
End Function
Public Shared Function Encrypt(ByVal sData As String, ByVal sKey As String)
Dim bytData() As Byte = Encoding.UTF8.GetBytes(sData)
Return Encrypt(bytData, sKey)
End Function
Public Shared Function Encrypt(ByVal bytData As Byte(), ByVal strPass As String) As Byte()
Dim bytResult As Byte()
Using oRM As New Cryptography.RijndaelManaged
oRM.KeySize = 256
oRM.Key = GeKey(strPass)
oRM.IV = GetIV(strPass)
oRM.Mode = CipherMode.CBC
oRM.Padding = PaddingMode.PKCS7
Using oMS As New MemoryStream
Using oCS As New Cryptography.CryptoStream(oMS, oRM.CreateEncryptor, Cryptography.CryptoStreamMode.Write)
oCS.Write(bytData, 0, bytData.Length)
oCS.FlushFinalBlock()
bytResult = oMS.ToArray()
oCS.Close()
End Using
oMS.Close()
End Using
End Using
Return bytResult
End Function
Private Shared Function GeKey(ByVal strPass As String) As Byte()
Dim bytResult As Byte()
'Generate a byte array of required length as the encryption key.
'A SHA256 hash of the passphrase has just the required length. It is used twice in a manner of self-salting.
Using oSHA256 As New Cryptography.SHA256Managed
Dim L1 As String = System.Convert.ToBase64String(oSHA256.ComputeHash(Encoding.UTF8.GetBytes(strPass)))
Dim L2 As String = strPass & L1
bytResult = oSHA256.ComputeHash(System.Text.Encoding.UTF8.GetBytes(L2))
oSHA256.Clear()
End Using
Return bytResult
End Function
Private Shared Function GetIV(ByVal strPass As String) As Byte()
Dim bytResult As Byte()
'Generate a byte array of required length as the iv.
'A MD5 hash of the passphrase has just the required length. It is used twice in a manner of self-salting.
Using oMD5 As New Cryptography.MD5CryptoServiceProvider
Dim L1 As String = System.Convert.ToBase64String(oMD5.ComputeHash(Encoding.UTF8.GetBytes(strPass)))
Dim L2 As String = strPass & L1
bytResult = oMD5.ComputeHash(System.Text.Encoding.UTF8.GetBytes(L2))
oMD5.Clear()
End Using
Return bytResult
End Function
End Class
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
两段代码中的问题是:
在 .NET 和 PHP 代码中使用密钥和块大小均为 16 字节/128 位的 Rijndael-128。对于 Rijndael-256,您的代码生成长度错误的 IV。我不知道如何在 PHP 中使用 AES-256(密钥长度为 32 字节/256 位,块大小为 16 字节/128 位)。
MD5 的使用:在 PHP 代码中,将第二个参数
true
添加到md5()
函数(在两个位置),以便结果是二进制数据,而不是十六进制字符串。在 PHP 代码的 encrypt() 函数中,将变量
$str
替换为$decrypted
(在两个位置)。$str
从未被赋值且从未使用过,因此填充不起作用。如果你解决了这些问题,那么两个程序都会返回结果:
我还没有尝试解密它。
The problems in your two pieces of code are:
Use Rijndael-128 with a key and block size of 16 bytes / 128 bit in both the .NET and the PHP code. For Rijndael-256, your code generates an IV with the wrong length. And I don't know how to use AES-256 in PHP (key length of 32 bytes / 256 bits, block size of 16 bytes / 128 bit).
Use of MD5: In the PHP code, add a second parameter
true
to themd5()
function (in two places) so the result is binary data and not a hexadecimal string.In the encrypt() function in your PHP code, replace the variable
$str
with$decrypted
(in two places).$str
is never assigned a value and never used, so the padding has no effect.If you fix these problems, then both programs will return the result:
I haven't tried to decrypt it.
对于初学者来说,2 位代码将创建不同的初始化向量(PHP 使用 sha256 和 .net md5)。并且您不会通过第一个空字符来截断 PHP 输出。代码中也存在几个潜在的字符集问题。
For starters the 2 bits of code will create different initialization vectors (PHP is using sha256, and .net md5). And you're not truncating the PHP output by then first null char. There are several potential char set issues in the code too.