【问题标题】:Encrypt plaintext with DES algorithm [closed]使用 DES 算法加密明文 [关闭]
【发布时间】:2019-09-21 23:25:22
【问题描述】:

我正在尝试在 PHP 中使用 DES 算法加密明文。
我设法用 C# 编写了一个工作示例:

String plaintext = "1y7wpc4iddseyrwez1lor8ow3297t.pd0bfl";
String pass = "rpsxi.t.rjsmklexarygfqyrrkhwdjh";
byte[] bytesPlain = Encoding.UTF8.GetBytes(plaintext);
byte[] bytesPass = Encoding.UTF8.GetBytes(pass).Take(8).ToArray();
DESCryptoServiceProvider p = new DESCryptoServiceProvider();
p.Mode = CipherMode.ECB;
ICryptoTransform t = p.CreateEncryptor(bytesPass, bytesPass);
CryptoStreamMode m = CryptoStreamMode.Write;
MemoryStream stream = new MemoryStream();
CryptoStream cryptoStream = new CryptoStream(stream, t, m);
cryptoStream.Write(bytesPlain, 0, bytesPlain.Length);
cryptoStream.FlushFinalBlock();
byte[] encBytesPlain = new byte[stream.Length];
stream.Position = 0;
stream.Read(encBytesPlain, 0, encBytesPlain.Length);
string encrypted = Convert.ToBase64String(encBytesPlain);
System.Diagnostics.Debug.WriteLine(encrypted);

明文 = 1y7wpc4iddseyrwez1lor8ow3297t.pd0bfl
密码 = rpsxi.t.rjsmklexarygfqyrrkhwdjh
(仅密码的前 8 个字节用于加密消息)。

无论如何,当我尝试使用 crypt 函数或我在 github https://github.com/phpseclib/phpseclib-php5/blob/master/phpseclib/Crypt/DES.php 上找到的这个类来编写 PHP 版本时,我得到的结果与 C# 不同。

我完全确定 C# 代码可以正常工作,但我真的不知道如何在 PHP 中制作工作版本以在 Base64 中获得相同的结果。

Edit1:我已经知道 DES 不再安全,但我需要在网页中使用它只是为了学习目的,而且 C# 代码的编写方式是完全正确的,因为我需要遵循一些说明并获取这正是结果。

【问题讨论】:

  • 有什么理由使用 DES?
  • 如果您将 DES 用于除学习之外的任何其他用途,我强烈建议您选择其他算法。
  • C# 代码绝对正确。您正在使用 48 位密钥,但 DES 使用 56 位密钥。您决不能为同一个密钥重复使用 IV。考虑使用 3DES 而不是 DES。 56 位现在被认为是一个太小的密钥空间。它可以在数小时内被暴力破解。最后,ECB 是您可以选择的最差的区块模式。
  • 顺便说一句,你为什么不使用openssl?它已经内置在 PHP 中,它支持 DES 没有任何问题,而且我觉得它很容易使用。
  • 如果您想学习,请阅读 PKCS#5:基于密码的加密 (PBE) - 但请注意,即使该标准也在老化。

标签: c# php encryption des


【解决方案1】:

请不要再使用 DES,因为它不再被认为是安全的。而是尝试使用 AES。

还要注意php crypt函数默认不加密,只是使用DES创建一个hash值,和加密不一样。

来源:https://www.w3schools.com/php/func_string_crypt.asp

【讨论】:

    【解决方案2】:

    DES 是一种已弃用的加密标准,您不应将其用于学习目的之外的任何其他用途。如果您打算使用它来加密敏感数据,AES 可能是更好的选择。

    除此之外,由于我有一段时间没有编写 PHP,但仍想贡献,我稍微修复了您现有的 C# 代码:

    var plainText = "1y7wpc4iddseyrwez1lor8ow3297t.pd0bfl";
    var password = "rpsxi.t.rjsmklexarygfqyrrkhwdjh";
    var plainTextBytes = Encoding.UTF8.GetBytes(plainText);
    var passwordBytes = Encoding.UTF8.GetBytes(password).Take(8).ToArray();
    
    var des = new DESCryptoServiceProvider
    {
        Mode = CipherMode.CBC, // don't use ECB as your CipherMode
        Padding = PaddingMode.PKCS7,
        Key = passwordBytes
    };
    
    des.GenerateIV(); // work with a unique IV for each operation
    
    string encrypted = null;
    using (var desEncryptor = des.CreateEncryptor())
    {
        var resultStream = new MemoryStream();
        using (var cryptoStream = new CryptoStream(resultStream, desEncryptor, CryptoStreamMode.Write))
        {
            cryptoStream.Write(plainTextBytes, 0, plainTextBytes.Length);
        }
    
        encrypted = Convert.ToBase64String(resultStream.ToArray());
    }
    

    这仍然不安全,正如我在开始时所说,如果安全性对您正在构建的应用程序至关重要,那么您不应该使用它。此答案应该使您的代码安全,只是为了指出您在使用 C# Streams 和一般编码准则时存在的一些缺陷。

    对于 PHP 部分 this 答案可以与我发布的更新代码一起使用。您只需通过des.IVdes 对象中提取IV 并在您的PHP 脚本中使用它来实现相同的功能。

    还值得注意的是,使用的函数mcrypt_encrypt 在较新版本的 PHP 中已被弃用,这让我回到了我回答的第一句话:您可能应该完全停止使用 DES!

    【讨论】:

    • 您正在解释如何将 ECB 模式与 IV 一起使用,而密码仍然被削减为 8 个字节。代码看起来更好,但加密没有进步。
    • @MaartenBodewes 我更新了我的代码并添加了一条通知。
    猜你喜欢
    • 2016-05-12
    • 1970-01-01
    • 1970-01-01
    • 2011-08-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多