当前位置: 首页 > 知识库问答 >
问题:

在c#和PHP之间使用AES加密/解密数据-解密数据以255254开头

房冥夜
2023-03-14

我必须从一个用C#编写的外部现有webservice请求数据。此web服务要求加密一些数据(连接使用SSL连接,一些数据是aes加密的)

在php站点上,openssl用于解密。

c# 站点上使用以下设置(这是 AesCrypto 服务提供程序的默认值):

    < li >算法:AES < li >填充:PKCS7 < li >模式:CBC < li>Keysize: 256

PKCS7的填充工作如下:01如果缺少1个字节02如果缺少2个字节,依此类推

所以这个值不是由填充添加的。

我做错了什么?

我已经用c#、php和ruby检查过了——解密的数据以255、254开头

要再现,请使用以下参数:

数据:1234567890123456关键:第一个盐(四):数据

using System;
using System.Security.Cryptography;
using System.Text;
using System.IO;

namespace crypto_test
{
    class MainClass
    {
        public static void Main(string[] args)
        {

                bool running = true;
                while (running)
                {
                    Console.WriteLine("Enter data:");
                    var data = Console.ReadLine();
                    Console.WriteLine("Enter key:");
                    var key = Console.ReadLine();
                    Console.WriteLine("Enter iv:");
                    var iv = Console.ReadLine();
                    Console.WriteLine("Enter d for decode");
                    var decode = (Console.ReadLine() == "d");

                    string encoded=Crypt(data, key, iv, decode);
                    Console.WriteLine(encoded);
                    if (!decode)
                    {
                        encoded=  Crypt(encoded, key, iv, true);
                        Console.WriteLine(encoded);
                    }

                    Console.WriteLine("quit to exit");
                    running = !(Console.ReadLine() == "quit");
                }

        }

        public static string Crypt(string value, string password, string salt, bool decrypt)
        {
            DeriveBytes rgb = new Rfc2898DeriveBytes(password, Encoding.Unicode.GetBytes(salt));
            SymmetricAlgorithm algorithm = new AesCryptoServiceProvider();
            byte[] rgbKey = rgb.GetBytes(algorithm.KeySize >> 3);
            byte[] rgbIV = rgb.GetBytes(algorithm.BlockSize >> 3);

            Console.WriteLine("rbKey: size:{0} key:{1}", (algorithm.KeySize >> 3), GetHex(rgbKey));
            Console.WriteLine("rgbIV: size:{0} key:{1}", (algorithm.BlockSize >> 3), GetHex(rgbIV));

            ICryptoTransform transform = decrypt ? algorithm.CreateDecryptor(rgbKey, rgbIV) : algorithm.CreateEncryptor(rgbKey, rgbIV);
            Console.WriteLine("Mode {0}", algorithm.Mode);
            Console.WriteLine("PAdding {0}", algorithm.Padding);

            using (MemoryStream buffer = new MemoryStream())
            {
                using (CryptoStream stream = new CryptoStream(buffer, transform, CryptoStreamMode.Write))
                {
                    try
                    {
                        if (decrypt)
                        {
                            byte[] data = Convert.FromBase64String(value);
                            stream.Write(data,0,data.Length);
                        }
                        else
                        {
                            using (StreamWriter writer = new StreamWriter(stream, Encoding.Unicode))
                            {
                                writer.Write(value);
                            }
                        }
                    }
                    catch (Exception e)
                    {
                        Console.WriteLine(e.ToString());
                    }
                }

                byte[] buff = buffer.ToArray();
                if (decrypt)
                {
                    return Encoding.Unicode.GetString(buff) + "\r\n" + GetHex(buff);
                }
                else
                    return Convert.ToBase64String(buff);
            }
        }

        public static string GetHex(byte[] data)
        {
            StringBuilder sb = new StringBuilder();
            for (int i = 0; i < data.Length; ++i)
                sb.Append(data[i].ToString("X2"));
            return sb.ToString();
        }
    }
}

到目前为止,我还没有找到Rfc2898DeriveBytes的等价物,所以我复制了key和iv

php公司

<?php

$salt='Data';
$pass='First1';
$data='1234567890123456';

$encrypted_base64='VKNd9Pi+cttaM6ne8pzAuFbH1U0gJiJ2Wlbbr1rU5z8vbIfAS6nb0/5py4p54aK7';
$encrypted=base64_decode($encrypted_base64);
$key = pack('H*', "30EE7F95F0EF4835F048A481424F2F52EE21B7CEB97F8CC437E5949DB53797D9");
$iv = pack('H*', "B29F5ECF7057065758102385509F0637");
$cipher='AES-256-CBC';
$decrypted = openssl_decrypt($encrypted,$cipher, $key,true,$iv);
for($i =0; $i<strlen($decrypted);++$i)
{
    echo "char:" . ord($decrypted[$i])."<br/>";
}
echo $decrypted
?>

红宝石:

require ('openssl')
require ('base64')

while true


enc_data='VKNd9Pi+cttaM6ne8pzAuFbH1U0gJiJ2Wlbbr1rU5z8vbIfAS6nb0/5py4p54aK7'

data = Base64.decode64(enc_data)

key_hex='30EE7F95F0EF4835F048A481424F2F52EE21B7CEB97F8CC437E5949DB53797D9'
iv_hex='B29F5ECF7057065758102385509F0637'


key = [key_hex].pack('H*')
iv = [iv_hex].pack('H*')

decipher = OpenSSL::Cipher::AES.new(256, :CBC)
decipher.decrypt
decipher.key = key
decipher.iv = iv
plain = decipher.update(data) + decipher.final

puts plain
puts plain.bytes

end

共有1个答案

万浩淼
2023-03-14

好消息,你的解密似乎工作正常。

你在解密的密文中看到的是UTF-16 LE的字节顺序标记,它被微软(错误地)表示为< code >编码。Unicode。你需要做两件事情中的任何一件:

    < li >使用搜索UTF-16 LE(包括字节顺序标记)的解码器解码文本; < li >使用更合理的UTF-8编码(在C#代码中)进行编码。

就个人而言,我会强烈偏爱(2)。

 类似资料:
  • 我正在尝试通过使用本文中描述的步骤来加密/解密一些数据get-a-illegalblock size异常数据必须不超过256字节。我应该怎么做很清楚,但即使我做错了什么。 这是我的课: 我尝试过这个方法,因为我认为问题在于AES使用的填充1,但我错了<运行了一段时间后,我得到了一些结果: [ENCRYPT]之前的数据: 之后的数据: 键之前: 之后的关键: [解密]密钥之前: 之后的关键: 之前的

  • 问题内容: 我尝试解密最初使用Java中的Objective-C加密的数据。 还有其他问题要提及,但是它们确实很混乱,许多问题还没有解决,因此我将发表自己的问题。 这是加密数据的代码: 我执行此功能,并使用以下代码将结果数据写入光盘: 在Java中,我使用以下代码来尝试实现相同的行为: 如果现在尝试解密通过Objective-C加密的文件,则会收到错误的填充异常。如果我打开两个带有加密内容的文件,

  • 前面小节介绍了如何存储密码,但是有的时候,我们想把一些敏感数据加密后存储起来,在将来的某个时候,随需将它们解密出来,此时我们应该在选用对称加密算法来满足我们的需求。 base64加解密 如果Web应用足够简单,数据的安全性没有那么严格的要求,那么可以采用一种比较简单的加解密方法是base64,这种方式实现起来比较简单,Go语言的base64包已经很好的支持了这个,请看下面的例子: package

  • 我正在尝试解密AES加密数据(在. NET中加密),但我的解密结果字符串似乎不可读,并且我没有收到任何错误。 数据加密使用: < li>Padding: PKCS7Padding < li>KeySize: 128 < li >模式:CBC, 我有InItVector、PassCode、salt和NumberOfPassword(3)次迭代。 这是我的代码: 下面是在 .NET 端加密数据的代码:

  • 问题内容: 我找到了在PHP中对字符串进行编码/解码的示例。起初它看起来非常好,但是不会起作用:-( 有人知道问题出在哪里吗? 结果是: 加密: 解密: 问题答案: 并且 在您的代码中未定义。查看有效的解决方案( 但不安全! ): 停! 这个例子是 不安全的! 不要使用它! **但是此代码中还有其他问题,使其变得不安全,尤其是使用ECB(这不是_加密_模式,只能在其上定义加密模式的构造块)。

  • 客户端(4.2.1)应用程序通过请求向(5.6)API发送公钥。此API使用符合的加密数据,然后使用OpenSSL public encryption和的客户端公钥加密AES加密的密钥。它将通过编码的数据发送回客户端android应用程序,客户端android应用程序将加密数据。我已经设置了一个基本的PHP测试脚本来测试整个过程,这是预期的工作。 目前,我正在客户端Android应用程序中实现解密