.Net和PHP Rijndael加密不匹配 [英] .Net and PHP Rijndael encryption not matching
问题描述
起初我以为这是padding,因为mcrypt使用零填充,但是我改变了PHP使用PKCS7并得到相同的确切结果
任何人都可以帮助?我认为它与php中的填充有关
从.Net测试输出:
键:d88f92e4fa27f6d45b49446c7fc76976
文本:Testing123
加密:/ DMkj7BL9Eu2LMxKhdGT + A ==
在base64解码后加密:?3 $ ?? K?K? Ĵ???
解密:Testing123
从PHP测试输出:
密钥:d88f92e4fa27f6d45b49446c7fc76976
文本:Testing123
加密:K + ke5FNI5T6F6B / XvDF494 + S8538Ze83cFz6v1FE89U =
加密后base64解码:+éäSHå> ; ...è×¼1x÷'óüeï7p\ú¿QDóÕ
解密:Testing123
PHP:
class rijndael {
var $ mcrypt_cipher = MCRYPT_RIJNDAEL_256;
var $ mcrypt_mode = MCRYPT_MODE_CBC;
函数解密($ pass,$ encrypted)
{
$ encrypted = base64_decode($ encrypted);
$ key = $ this-> getkey($ pass);
$ iv = $ this-> getiv($ pass);
$ decryptpted = mcrypt_decrypt($ this-> mcrypt_cipher,$ key,$ encrypted,$ this-> mcrypt_mode,$ iv);
$ block = mcrypt_get_block_size($ this-> mcrypt_cipher,$ this-> mcrypt_mode);
$ pad = ord($ decryptpted [($ len = strlen($ decryptpted)) - 1]);
return substr($ decryptpted,0,strlen($ decryptpted) - $ pad);
}
函数加密($ pass,$ decryptpted)
{
$ 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,$ decryptpted,$ this-> mcrypt_mode,$ iv);
返回base64_encode($ encrypted);
}
函数getkey($ passphrase)
{
$ L1 = base64_encode(hash(sha256,$ passphrase,true));
$ L2 = $ passphrase $ L1;
return hash(sha256,$ L2,true);
}
函数getiv($ passphrase)
{
$ L1 = base64_encode(md5($ passphrase));
$ L2 = $ passphrase $ L1;
返回md5($ L2);
}
}
VB .Net:
公共类RijnDael
公共共享函数解密(ByVal sData As String,ByVal sKey As String)
Dim bytData )By Byte = Encoding.UTF8.GetBytes(sData)
返回解密(bytData,sKey)
结束函数
公共共享函数解密(ByVal bytData As Byte(),ByVal strPass As String)作为Byte()
Dim bytResult As Byte()
使用oRM作为新的System.Security.Cryptography.RijndaelManaged
oRM.KeySize = 256
oRM.Key = GeKey(strPass)
oRM.IV = GetIV(strPass)
oRM.Mode = CipherMode.CBC
oRM.Padding = PaddingMode.PKCS7
使用oMS作为新的MemoryStream(bytData)
使用oCS作为新的Cryptography.CryptoStream(oMS,oRM.CreateDecryptor,Security.Cryptography.CryptoStreamMode.Read)
Dim TempDecryptArr As Byte()
ReDim TempDecryptArr(bytData.Length)
Dim decryptptedByteCount As Integer
decryptptedByteCount = oCS.Read(TempDecryptArr,0,bytData.Length)
'
ReDim bytResult(decryptptedByteCount)
Array.Copy(TempDecryptArr,bytResult,decryptptedByteCount)
'
oCS.Close()
结束使用
oMS.Close()
结束使用
结束使用
返回bytResult
结束函数
公共共享函数加密(ByVal sData As String,ByVal sKey As String)
Dim bytData()As Byte = Encoding。 UTF8.GetBytes(sData)
返回加密(bytData,sKey)
结束函数
公共共享函数加密(ByVal bytData As Byte(),ByVal strPass As String)As Byte()
Dim bytResult As Byte()
使用oRM作为Ne w Cryptography.RijndaelManaged
oRM.KeySize = 256
oRM.Key = GeKey(strPass)
oRM.IV = GetIV(strPass)
oRM.Mode = CipherMode.CBC
oRM.Padding = PaddingMode.PKCS7
使用oMS作为新的MemoryStream
使用oCS作为新的Cryptography.CryptoStream(oMS,oRM.CreateEncryptor,Cryptography.CryptoStreamMode.Write)
oCS.Write( bytData,0,bytData.Length)
oCS.FlushFinalBlock()
bytResult = oMS.ToArray()
oCS.Close()
结束使用
oMS.Close ()
结束使用
结束使用
返回bytResult
结束函数
私有共享函数GeKey(ByVal strPass As String)As Byte()
Dim bytResult As Byte()
'生成所需长度的字节数组作为加密密钥。
'密码短语的SHA256哈希只有所需的长度。以自我盐化的方式使用两次。
使用oSHA256作为新密码.SHA256管理
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()
结束使用
返回bytResult
结束函数
私有共享函数GetIV(ByVal strPass As String)As Byte()
Dim bytResult As Byte()
'生成所需长度的字节数组作为iv。
'密码短语的MD5哈希只有所需的长度。以自我盐化的方式使用两次。
使用oMD5作为新的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()
结束使用
返回bytResult
结束函数
结束类
您的两段代码中的问题是:
-
使用Rijndael-128 键和在.NET和PHP代码中,块大小为16字节/ 128位。对于Rijndael-256,您的代码会生成长度不正确的IV。我不知道如何在PHP中使用AES-256(密钥长度为32字节/ 256位,块大小为16字节/ 128位)。
- <使用MD5 :在PHP代码中,添加第二个参数
true
到md5()
function(在两个地方),所以结果是二进制数据而不是十六进制字符串。 -
在PHP代码中的encrypt()函数,用
$解密
(两个地方)替换变量$ str
。$ str
从未分配过值,从未使用过,所以填充没有任何效果。
如果您修复这些问题,则两个程序都将返回结果:
加密:/ DMkj7BL9Eu2LMxKhdGT + A ==
我没有尝试解密它。
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
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:
Encrypted: /DMkj7BL9Eu2LMxKhdGT+A==
I haven't tried to decrypt it.
这篇关于.Net和PHP Rijndael加密不匹配的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!