Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/entity-framework/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C#和PHP之间的对称加密_C#_Php_Encryption - Fatal编程技术网

C#和PHP之间的对称加密

C#和PHP之间的对称加密,c#,php,encryption,C#,Php,Encryption,目前,我对PHP和C#之间的对称加密很感兴趣,无论我如何重写我的脚本,我总是会收到一条错误消息,或者加密的文本更加加密。3天来,我一直在尝试互联网上提供的所有建议,但都没有成功,我希望有人能帮助我完成加密和解密过程。您可以在下面找到我的脚本示例 这是我构建和发送包含密钥、IV和加密文本的消息的方式: function alphaNumeric () : string { $number = rand(32, 127); return $number >= 48 &

目前,我对PHP和C#之间的对称加密很感兴趣,无论我如何重写我的脚本,我总是会收到一条错误消息,或者加密的文本更加加密。3天来,我一直在尝试互联网上提供的所有建议,但都没有成功,我希望有人能帮助我完成加密和解密过程。您可以在下面找到我的脚本示例

这是我构建和发送包含密钥、IV和加密文本的消息的方式:

function alphaNumeric () : string {

    $number = rand(32, 127);
    return $number >= 48 && $number <= 57 
        || $number >= 65 && $number <= 90 
        || $number >= 97 && $number <= 122
        ? chr($number)
        : alphaNumeric();
}

function randomBytes (int $length, string $byteString = '') : string {

    return $length > 0
        ? randomBytes($length - 1, $byteString.alphaNumeric())
        : $byteString;
}

$key        = randomBytes(16);
$iv         = randomBytes(16);
$data       = 'This text should be encrypted in PHP and decrypted in C#!';
$encrypted  = openssl_encrypt($data, 'aes-128-cbc', $key, 1, $iv);
$message    = $key.$iv.$encrypted;

file_put_contents('message.txt', $message);
echo $message;
die;
最后是c#代码,它应该解密消息:

    public static void Main()
    {
        var client = new HttpClient();
        var requestUri = "http://localhost/message.php";

        while (Console.ReadLine() == string.Empty)
        {
            var response = client.GetAsync(requestUri).Result;

            if (!response.IsSuccessStatusCode)
            {
                continue;
            }

            var content = response.Content.ReadAsStringAsync().Result;

            if (string.IsNullOrWhiteSpace(content) || content.Length < 48)
            {
                continue;
            }

            File.WriteAllText("../../../message.txt", content);

            var keyString = content.Substring(0, 16);
            var keyBytes = Encoding.UTF8.GetBytes(keyString);

            var ivString = content.Substring(16, 16);
            var ivBytes = Encoding.UTF8.GetBytes(ivString);

            var encString = content.Substring(32);
            var encBytes = Encoding.UTF8.GetBytes(encString);

            Console.WriteLine($"{keyBytes.Length}: {keyString}");
            Console.WriteLine($"{ivBytes.Length}: {ivString}");
            Console.WriteLine($"{encBytes.Length}: {encString}");

            try
            {
                var plainText = Decrypt(encBytes, keyBytes, ivBytes);

                Console.WriteLine(plainText);
            }
            catch (Exception e)
            {
                Console.WriteLine($"Error: {e.Message}");
            }
        }
    }

    static string Decrypt(byte[] encrypted, byte[] key, byte[] iv)
    {
        using var alg = AesCryptoServiceProvider.Create();

        //alg.IV = iv;
        //alg.Key = key;
        //alg.KeySize = 128;
        //alg.BlockSize = 256;
        //alg.Mode = CipherMode.CBC;
        alg.Padding = PaddingMode.PKCS7;

        var decryptor = alg.CreateDecryptor(key, iv);
        using var ms = new MemoryStream(encrypted);
        using var cs = new CryptoStream(ms, decryptor, CryptoStreamMode.Read);
        using var sr = new StreamReader(cs);

        return sr.ReadToEnd();
    }
publicstaticvoidmain()
{
var client=新的HttpClient();
var requestUri=”http://localhost/message.php";
while(Console.ReadLine()==string.Empty)
{
var response=client.GetAsync(requestUri).Result;
如果(!response.issucessStatusCode)
{
继续;
}
var content=response.content.ReadAsStringAsync().Result;
if(string.IsNullOrWhiteSpace(content)| | content.Length<48)
{
继续;
}
File.writealText(“../../../message.txt”,content);
var-keyString=content.Substring(0,16);
var keyBytes=Encoding.UTF8.GetBytes(keyString);
var ivString=content.Substring(16,16);
var ivBytes=Encoding.UTF8.GetBytes(ivString);
var encString=content.Substring(32);
var encBytes=Encoding.UTF8.GetBytes(encString);
WriteLine($“{keyBytes.Length}:{keyString}”);
WriteLine($“{ivBytes.Length}:{ivString}”);
WriteLine($“{encBytes.Length}:{encString}”);
尝试
{
var plainText=解密(encBytes、keyBytes、ivBytes);
Console.WriteLine(纯文本);
}
捕获(例外e)
{
WriteLine($“错误:{e.Message}”);
}
}
}
静态字符串解密(字节[]加密,字节[]密钥,字节[]iv)
{
使用var alg=aescyptoserviceprovider.Create();
//alg.IV=IV;
//alg.Key=Key;
//alg.KeySize=128;
//alg.BlockSize=256;
//alg.Mode=CipherMode.CBC;
alg.Padding=PaddingMode.PKCS7;
var decryptor=alg.CreateDecryptor(密钥,iv);
使用var ms=新内存流(加密);
使用var cs=新的加密流(ms、解密器、CryptoStreamMode.Read);
使用var sr=新的StreamReader(cs);
返回sr.ReadToEnd();
}
这是我目前收到的信息:
提前感谢。

C代码中有以下问题:

  • 在PHP代码中会生成一个32字节的密钥,但由于指定了AES-128(
    AES-128-cbc
    ),因此只考虑前16个字节。因此,在C#代码中,只考虑密钥的前16个字节,而不是完整的32个字节(参见第一条注释)
  • 在PHP代码中,openssl#u encrypt返回默认编码的密文Base64,因此这部分密文必须在C#代码中进行Base64解码,而不是UTF8编码(参见第二条注释)
  • AESCryptServiceProvider
    默认情况下使用CBC模式和PKCS7填充,因此无需在C代码中明确指定这两种模式
以下C#代码对使用PHP代码加密的密文进行解密:

string content = "UeWeXUAnu98RKTkMiBGLWpMNy4CRKJErOqTTUfJWrtXziFTELGG+647lw/XT846dj8tlNMITLVBg2cKS3dFINeKot4zlb+gVpfq4oIb/M3a8n3a9XWaeIOrHpNedZmMrYiZoCQ=="; var keyString = content.Substring(0, 16); var keyBytes = Encoding.UTF8.GetBytes(keyString); var ivString = content.Substring(32, 16); var ivBytes = Encoding.UTF8.GetBytes(ivString); var encString = content.Substring(48); var encBytes = Convert.FromBase64String(encString); using var alg = AesCryptoServiceProvider.Create(); alg.IV = ivBytes; alg.Key = keyBytes; var decryptor = alg.CreateDecryptor(keyBytes, ivBytes); using var ms = new MemoryStream(encBytes); using var cs = new CryptoStream(ms, decryptor, CryptoStreamMode.Read); using var sr = new StreamReader(cs); string decrypted = sr.ReadToEnd(); Console.WriteLine(decrypted); string content=“UEWEXANU98RKTKMIBGLWPMNY4CRKJEROQTTUFJWRTXZIFTELGG+647lw/XT846dj8tlNMITLVBg2cKS3dFINeKot4zlb+gVpfq4oIb/M3a8n3a9XWaeIOrHpNedZmMrYiZoCQ=”; var-keyString=content.Substring(0,16); var keyBytes=Encoding.UTF8.GetBytes(keyString); var ivString=content.Substring(32,16); var ivBytes=Encoding.UTF8.GetBytes(ivString); var encString=content.Substring(48); var encBytes=Convert.FromBase64String(encString); 使用var alg=aescyptoserviceprovider.Create(); alg.IV=ivBytes; alg.Key=keyBytes; var decryptor=alg.CreateDecryptor(keyBytes,ivBytes); 使用var ms=新内存流(encBytes); 使用var cs=新的加密流(ms、解密器、CryptoStreamMode.Read); 使用var sr=新的StreamReader(cs); 已解密字符串=sr.ReadToEnd(); Console.WriteLine(已解密);

请考虑PHP代码,当为AES-128生成32字节密钥时,它是不一致的。相反,应该生成一个16字节的密钥。或者,您可以切换到AES-256(

AES-256-cbc
)。还要记住第一条注释中的提示:密钥通常不能与密文一起发送,因为任何攻击者都可以轻松解密数据。

两个“快速截图”:在PHP端,您为加密函数“aes-128-cbc”提供一个32个字符长的密钥。当使用“128”键时,任何更长的键都会被截断16个字符,因此您应该在PHP和C#端截断该键[将子字符串参数缩短为16]。第二:PHP默认使用PKCS7Padding,所以在C端也需要它[不知道默认值]。顺便说一句:将密钥和iv与加密消息一起发送意味着发送明文,是不安全的。此外:
openssl\u encrypt
默认使用Base64编码数据,即数据的第三部分(实际密文)必须是Base64解码:
var encBytes=Convert.FromBase64String(encString)
AesCryptoServiceProvider
默认情况下使用PKCS7,即填充正常。我将两边的密钥长度减少到16字节,但得到的消息相同,当我使用Base64解码时,它抛出一个异常,表示:输入不是有效的Base-64字符串,因为它包含一个非Base 64字符,多于两个填充字符,或者是填充字符中的非法字符。我得到了它,所以我使用16字节作为密钥和向量,并对以base64编码的加密消息进行了编码,然后对base64消息进行了解码 string content = "UeWeXUAnu98RKTkMiBGLWpMNy4CRKJErOqTTUfJWrtXziFTELGG+647lw/XT846dj8tlNMITLVBg2cKS3dFINeKot4zlb+gVpfq4oIb/M3a8n3a9XWaeIOrHpNedZmMrYiZoCQ=="; var keyString = content.Substring(0, 16); var keyBytes = Encoding.UTF8.GetBytes(keyString); var ivString = content.Substring(32, 16); var ivBytes = Encoding.UTF8.GetBytes(ivString); var encString = content.Substring(48); var encBytes = Convert.FromBase64String(encString); using var alg = AesCryptoServiceProvider.Create(); alg.IV = ivBytes; alg.Key = keyBytes; var decryptor = alg.CreateDecryptor(keyBytes, ivBytes); using var ms = new MemoryStream(encBytes); using var cs = new CryptoStream(ms, decryptor, CryptoStreamMode.Read); using var sr = new StreamReader(cs); string decrypted = sr.ReadToEnd(); Console.WriteLine(decrypted);