.Net和PHP Rijndael加密不匹配 [英] .Net and PHP Rijndael encryption not matching

查看:169
本文介绍了.Net和PHP Rijndael加密不匹配的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

起初我以为这是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 the md5() 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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆