使用 AES 在 C# 中进行文件加密,使用 phpseclib 进行解密

2024-01-10

我正在开发一个安全文件传输项目,该项目在客户端使用 C# 客户端对文件进行加密。我需要使用 php 或者 phpseclib 在服务器端解密文件。这里的代码是我从 msdn 示例中复制的。但我无法计算出 php 中的解密函数。

public static byte[] AES_Encrypt(byte[] bytesToBeEncrypted, byte[] passwordBytes)
        {
            byte[] encryptedBytes = null;
            byte[] saltBytes = passwordBytes;

            using (MemoryStream ms = new MemoryStream())
            {
                using (RijndaelManaged AES = new RijndaelManaged())
                {
                    var key = new Rfc2898DeriveBytes(passwordBytes, saltBytes, 1000);

                    AES.KeySize = 256;
                    AES.BlockSize = 256;
                    AES.Mode = CipherMode.CBC;
                    AES.Padding = PaddingMode.Zeros;
                    AES.Key = key.GetBytes(AES.KeySize / 8);
                    AES.IV = key.GetBytes(AES.BlockSize / 8);                    

                    using (CryptoStream cs = new CryptoStream(ms, AES.CreateEncryptor(), CryptoStreamMode.Write))
                    {
                        cs.Write(bytesToBeEncrypted, 0, bytesToBeEncrypted.Length);
                        cs.Close();
                    }
                    encryptedBytes = ms.ToArray();
                }
            }

            return encryptedBytes;
        }

这是不起作用的 php 代码:

        $pw = "this_is_my_pw";
        $aes = new Crypt_AES(CRYPT_AES_MODE_CBC);
        $aes->setKey($pw);
        $aes->setKeyLength(256);
        $aes->disablePadding();

        $file = "enc.txt";

        $fh = fopen($file, "r");
        $contents = trim(fread($fh, filesize($file)));
        fclose($fh);

        //echo "Encoded: \n\n" . $contents;

        $contents = $aes->decrypt($contents);
        #$block = mcrypt_get_block_size(MCRYPT_RIJNDAEL_256, MCRYPT_MODE_CBC);
        #$padding = $block - (strlen($clear) % $block);

        #$dec = mcrypt_decrypt(MCRYPT_RIJNDAEL_256, $pw, base64_decode($contents), MCRYPT_MODE_CBC, $pw);

        echo "Decoded: \n\n" . $contents;

有人可以帮我解决这个问题或提示我做错了什么吗?


  1. 解密时不使用初始化向量。您需要将初始化向量 (IV) 与数据一起发送 - 您的 PHP 代码永远不会调用$aes->setIV来自 phpseclib,因此它将永远无法解密文本,因为如果未设置 phpseclib 使用全零的 IV根据文档 http://phpseclib.sourceforge.net/crypt/examples.html。我个人建议使用 C# 生成安全随机 IVRijndaelManaged.GenerateIV https://msdn.microsoft.com/en-us/library/system.security.cryptography.rijndaelmanaged.generateiv(v=vs.110).aspx,但显然从 PBKDF2 密钥导出 IV 被认为是可以接受的。 PBKDF2(在 RFC 2898 中指定)是密钥拉伸算法Rfc2898DeriveBytes实施。无论如何,您需要在 PHP 端重新生成 IV,无论这意味着使用加密数据传输 IV(完全没问题),还是在 PHP 端重新导出 IV。

  2. 使用密码作为盐是一个非常糟糕的主意。盐需要有足够的长度并且以加密方式随机生成。使用密码作为盐完全失去了盐的意义。MSDN 有一些示例代码 https://msdn.microsoft.com/en-us/library/system.security.cryptography.rfc2898derivebytes(v=vs.110).aspx展示了如何结合使用生成加密随机盐Rfc2898DeriveBytes,但重要的部分在这里:

byte[] saltBytes = new byte[8];
using (RNGCryptoServiceProvider rngCsp = new RNGCryptoServiceProvider())
{
    // Fill the array with a random value.
    rngCsp.GetBytes(salt1);
}
  1. 盐必须与加密数据一起传输。您需要发送 PBKDF2 salt 字节以及 IV 字节和加密数据。 phpseclib 将需要所有这些来正确初始化自身并解密数据。您可能想使用 phpseclibsetPassword https://api.phpseclib.org/master/phpseclib/Crypt/Base.html#method_setPassword这样做,就像这样:
$salt = ...; // get the salt to your PHP code somehow
$iv = ...; // get the IV to your PHP code
$pw = "this_is_my_pw";
$aes = new Crypt_AES(CRYPT_AES_MODE_CBC);
$aes->setPassword($pw, 'pbkdf2' /* key extension algorithm */,
    'sha1' /* hash algorithm */, $salt /* generated salt from C# */,
    1000 /* number of iterations, must be same as C# code */,
    256 / 8 /* key size in bytes, 256 bit key / 8 bits per byte */
);
$aes->setIV($iv);
  1. 请记住有关块大小的其他答案。128 位是标准 AES 块大小,因此请确保 C# 和 phpseclib 都可以在更大的块大小下正常运行,或者仅对两者使用 AES 标准。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

使用 AES 在 C# 中进行文件加密,使用 phpseclib 进行解密 的相关文章

  • 如何理顺 Laravel Blade @extends 的执行顺序?

    In 我尝试找到一种通过引用刀片 include来传递变量的方法 https stackoverflow com questions 25437939 how to pass variables by reference to includ
  • 如何在不实例化一个类的情况下检查它是否继承了另一个类? [复制]

    这个问题在这里已经有答案了 假设我有一个如下所示的类 class Derived some inheritance stuff here 我想在我的代码中检查类似的内容 Derived is SomeType 但看起来像is运算符需要 De
  • 无法从 Web api POST 读取正文数据

    我正在尝试从新的 Asp Net Web Api 中的请求中提取一些数据 我有一个像这样的处理程序设置 public class MyTestHandler DelegatingHandler protected override Syst
  • 如何在编译C代码时禁用警告?

    我正在使用 32 位 Fedora 14 系统 我正在使用编译我的源代码gcc 有谁知道如何在编译c代码时禁用警告 EDIT 是的 我知道 最好的办法是修复这些警告以避免任何未定义 未知的行为 但目前在这里 我第一次编写了巨大的代码 并且在
  • 如何在 MySQL 中使用 INET_ATON 进行通配符搜索 IP 地址?

    我发现这个方法可以使用 INET ATON 将 IP 地址作为整数存储在 MySQL 数据库中 https stackoverflow com a 5133610 4491952 https stackoverflow com a 5133
  • C# datagridview 列转入数组

    我正在用 C 构建一个程序 并在其中包含一个 datagridview 组件 datagridview 有固定数量的列 2 我想将其保存到两个单独的数组中 但行数确实发生了变化 我怎么能这样做呢 假设一个名为 dataGridView1 的
  • Symfony 4.1 组件 - 依赖注入问题

    我正在用 PHP 重构旧应用程序 我正在尝试使用 Symfony 依赖注入组件将服务注入控制器 或其他服务 但我不知道如何实现这一点 因为 symphony 文档比框架组件更适合使用框架 我已经有了自己的内核 包含所有服务和控制器的容器 控
  • 手动将 ClientBase 集合类型从 Array[] 更改为 List<>

    我将自己的 WCF 代理与 Client Base 一起使用 我想做一些类似于 svc util 中的 ct 属性的操作 并告诉代理返回 List 集合类型 我不能使用 List 因为实体由 nhibernate 管理 所以我必须使用 IL
  • 操纵 setter 以避免 null

    通常我们有 public string code get set 如果最终有人将代码设置为 null 我需要避免空引用异常 我尝试这个想法 有什么帮助吗 public string code get set if code null cod
  • 按时间戳字段中的日期过滤结果

    我已经获得了一些帮助 但不确定为什么这不起作用 我正在尝试使用表单让用户过滤他们的活动 存储在数据库中 My code GET from 01 11 2013 GET to 25 11 2013 from DateTime createFr
  • 如何在 Api-Platform 中按链接属性过滤结果?

    我有一个User实体和一个Organisation实体 存在关系ManyToOne之间Booking and User ORM ManyToOne targetEntity App Entity User inversedBy bookin
  • 特征密集稀疏矩阵乘积是线程化的吗?

    我知道稀疏密集产品是根据文档进行线程化的 https eigen tuxfamily org dox TopicMultiThreading html https eigen tuxfamily org dox TopicMultiThre
  • dropdownlist DataTextField 由属性组成?

    有没有一种方法可以通过 C 使 asp net 中的下拉列表的 datatextfield 属性由对象的多个属性组成 public class MyObject public int Id get set public string Nam
  • 系统错误 124 - SHFileOperation 的 ERROR_INVALID_LEVEL

    我在使用时遇到问题SHFileOperation SHFileOperation SHFILEOPSTRUCT https stackoverflow com questions 9191415 shfileoperation shfile
  • 设计 Javascript 前端 <-> C++ 后端通信

    在我最近的将来 我将不得不制作一个具有 C 后端和 Web 前端的系统 要求 目前 我对此了解不多 我认为前端将触发数据传输 而不是后端 所以不需要类似 Comet 的东西 由于在该领域的经验可能很少 我非常感谢您对我所做的设计决策的评论
  • PHP strtotime返回Mysql UNIX_TIMESTAMP的不同值

    我在 stackoverflow 上搜索过帖子 发现了一些类似的帖子 但我认为这是一篇不同的帖子 我的 PHP 和 Mysql 服务器的时区全部设置为 UTC 在表中我使用时间戳字段 值为 2010 11 08 02 54 15 我使用这样
  • TPL 数据流块下游如何获取源生成的数据?

    我正在使用 TPL Dataflow 处理图像 我收到处理请求 从流中读取图像 应用多次转换 然后将生成的图像写入另一个流 Request gt Stream gt Image gt Image gt Stream 为此 我使用块 Buff
  • CodeIgniter:使用多维 POST 数据验证表单

    所以框架是CodeIgniter 2 0 2 我有一个表单 其中包含与数据库中的行相对应的字段组 字段名称的格式为 opt 0 foo opt 0 bar opt 1 foo opt 1 bar etc 索引 1 2等 并不对应于数据库中的
  • SQL查询:按字符长度排序?

    是否可以按字符总数对sql数据行进行排序 e g SELECT FROM database ORDER BY data length 我想你想用这个 http dev mysql com doc refman 5 0 en string f
  • 使用 php 变量更改 css 类

    这里需要您的帮助 正如标题所示 我正在尝试使用 PHP 变量更改 css 类 所以基本上我想创建一个回显某些代码的循环 但我希望第一个循环中的 div 类有所不同 它应该被隐藏 这是我为使问题变得清晰而编写的简化代码 我不知道错误在哪里 请

随机推荐