【问题标题】:openssl equivalent for TripleDESCryptoServiceProviderTripleDESCryptoServiceProvider 的 openssl 等效项
【发布时间】:2017-10-03 21:54:03
【问题描述】:

我有一些 C# 代码用于使用 TripleDES 进行加密和解密。我已将其简化为发布的最小示例。

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

class TDes
{
    static void Main() {
        string key = "ABCDEF0123456789";
        string iv = "ABCDEF01";

        TDes tdes = new TDes(key, iv);

        string dataToDecrypt = "x9iWzVc4FfU=";
        string decrypted = tdes.Decrypt(dataToDecrypt,key);
        Console.WriteLine(decrypted);

        string dataToEncrypt = "abcdegf";
        string encrypted = tdes.Encrypt(dataToEncrypt, key);
        Console.WriteLine(encrypted);
    }

    public TripleDESCryptoServiceProvider TdesProvider;

    public TDes(string Key, string IV)
    {
        TdesProvider = new TripleDESCryptoServiceProvider();
        TdesProvider.Key = System.Text.ASCIIEncoding.ASCII.GetBytes(Key);
        TdesProvider.IV = System.Text.ASCIIEncoding.ASCII.GetBytes(IV);
    }

    public string Decrypt(string Source, string Key)
    {
        long lLen;
        int nRead, nReadTotal;
        byte[] buf = new byte[3];
        byte[] decData;
        byte[] encData;
        System.IO.MemoryStream sin;
        System.IO.MemoryStream sout;
        CryptoStream decStream;

        encData = System.Convert.FromBase64String(Source);
        sin = new MemoryStream(encData);
        sout = new MemoryStream();

        decStream = new CryptoStream(sin,
            TdesProvider.CreateDecryptor(),
            CryptoStreamMode.Read);

        lLen = sin.Length;
        nReadTotal = 0;
        while (nReadTotal < lLen)
        {
            nRead = decStream.Read(buf, 0, buf.Length);
            if (0 == nRead) break;

            sout.Write(buf, 0, nRead);
            nReadTotal += nRead;
        }
        decStream.Close();

        decData = sout.ToArray();

        ASCIIEncoding ascEnc = new ASCIIEncoding();
        return ascEnc.GetString(decData);
    }

    public string Encrypt(string Source, string Key)
    {
        long lLen;
        int nRead, nReadTotal;
        byte[] buf = new byte[3];
        byte[] srcData;
        byte[] encData;
        System.IO.MemoryStream sin;
        System.IO.MemoryStream sout;
        CryptoStream encStream;

        srcData = System.Text.ASCIIEncoding.ASCII.GetBytes(Source);
        sin = new MemoryStream();
        sin.Write(srcData,0,srcData.Length);
        sin.Position = 0;
        sout = new MemoryStream();

        encStream = new CryptoStream(sout,
            TdesProvider.CreateEncryptor(),
            CryptoStreamMode.Write);
        lLen = sin.Length;
        nReadTotal = 0;
        while (nReadTotal < lLen)
        {
            nRead = sin.Read(buf, 0, buf.Length);
            encStream.Write(buf, 0, nRead);
            nReadTotal += nRead;
        }
        encStream.Close();

        encData = sout.ToArray();
        return System.Convert.ToBase64String(encData);
    }
}

这是可行的(从某种意义上说,它可以解密使用相同的密钥和 iv 加密的内容)。但是,我一直未能在 openssl 中提出等价物。我最近尝试过的事情:

echo abcdefg | openssl enc -e -des-ede3-cbc -a -k ABCDEF0123456789 -iv ABCDEF01
U2FsdGVkX1+o9K0itpYTEqGfyMjN8gARTYIDB2ZHg1U=

C# 代码产生了一个非常不同的结果 x9iWzVc4FfU= 同样,如果我将 x9iWzVc4FfU= 输入到反向 openssl 命令它 barfs。

我正在为此而烦恼。 c# 代码是不可更改的。需要openssl,因为我使用的是php。

【问题讨论】:

  • 请勿将 3DES 用于新工作,它已被 AES 取代。此外,在这个问题中,正在使用双密钥 3DES,它非常不安全,只有 112 位密钥,并且仅比 DES 强四倍。对于现有工作,最好努力更新到 AES。
  • 我知道这个@zaph。谢谢,但我无法控制它。在这一点上只需要拔出它来适应它。
  • 请出示您的基于 C 的 OpenSSL 代码。否则,这个问题只是要求提供所有代码或教程。
  • 是的,安全并不是那么重要,通常似乎有理由忽略它,对吧?到 2050 年我们还会有 2-key 3DES,可能仍然有同样的借口。为什么这段代码可能会被引用为不更新对方代码的原因,一个永无止境的循环!解决方案,只需添加一个版本标签,同时添加旧版本和安全版本,然后双方可以分别及时更新,最终会有安全加密。它只需要一个 1 字节的版本指示符。它是允许 HTTP/SSL/TLS 更新和向后兼容的版本控制。
  • @zaph 你误读了我的评论吗?我说过我没有可以控制它。

标签: c# php encryption openssl 3des


【解决方案1】:

有几点:

  1. 一个错字。在您的 C# 中,您正在加密“abcdegf”,在您的 OpenSSL 中,您正在使用“abcdefg”(注意 fg 的顺序)。

  2. echo 在其输出内容中添加换行符。使用echo -n 获得与您的代码相同的结果(检查您的echo 是否确实具有-n 选项,或者在加密时使用printf)。

  3. 你想要command line option -K rather than -k-k 指定一个密码,它是通过 KDF 函数输入的,你想直接指定密钥。

  4. 您的 C# 代码使用密钥和 IV 字符串的 ASCII 字节。 OpenSSL 命令行将它们解释为十六进制编码的字符串。您要在命令行上使用的内容是 41424344454630313233343536373839 用于键(构成“ABCDEF0123456789”的字节的十六进制编码)和4142434445463031 用于 IV(“ABCDEF01”的十六进制编码)。

  5. 您的密钥长度为 16 个字节。这意味着C# code is using “2 key” 3DES.在 OpenSSL 中,您需要使用 des-ede-cbc 明确指定这一点(注意缺少 3)。

所以结合所有这些,要复制你的 C# 代码,你需要这样的东西:

$ echo -n abcdegf | openssl enc -e -des-ede-cbc -a -K 41424344454630313233343536373839 -iv 4142434445463031
x9iWzVc4FfU=

【讨论】:

  • 天哪,谢谢。我现在正在运输途中,但我会在使用计算机后立即尝试一下
  • 而且大声笑,当然我在整理问题时尝试的最后一件事会出现拼写错误......我确实尝试过很多次没有拼写错误
  • 我在 php 中得到了这个工作。我实际上必须做的唯一改变是算法名称。再次感谢
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2013-03-28
  • 2015-04-30
  • 1970-01-01
  • 2013-02-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多