draxq02664 2017-05-05 12:07
浏览 140
已采纳

openssl等效于TripleDESCryptoServiceProvider

I have some C# code for encrypting and decrypting using TripleDES. I've reduced it to a minimal example for posting.

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);
    }
}

This works(in the sense that it can decrypt what it encrypts with the same key and iv). However, I have been failing to come up with the equivalent in openssl. Most recent thing I've tried:

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

The C# code produced a VERY different result of x9iWzVc4FfU= Likewise if I feed x9iWzVc4FfU= into the inverse openssl command it barfs.

I'm pulling my hair out on this. The c# code is unchangeable. Needs to be openssl as I'm using php.

  • 写回答

1条回答 默认 最新

  • duanba7653 2017-05-05 12:41
    关注

    There’s a few things:

    1. A typo. In your C# you are encrypting "abcdegf", in your OpenSSL you are using "abcdefg" (note the order of f and g).

    2. echo adds a newline to what it outputs. Use echo -n to get the same result as your code (check that your echo actually has the -n option, or use printf when encrypting).

    3. You want the command line option -K rather than -k. -k specifies a password which is put through a KDF function, you want to specify the key directly.

    4. Your C# code uses the ASCII bytes of the key and IV strings. The OpenSSL command line interprets them as hex encoded strings. What you want to use on the command line is 41424344454630313233343536373839 for the key (the hex encoding of the bytes making up “ABCDEF0123456789”) and 4142434445463031 for the IV (the hex encoding of “ABCDEF01”).

    5. Your key is 16 bytes long. This means that the C# code is using “2 key” 3DES. In OpenSSL you need to specify this explicitly with des-ede-cbc (note the lack of 3).

    So combining all these, to replicate what your C# code does you need something like this:

    $ echo -n abcdegf | openssl enc -e -des-ede-cbc -a -K 41424344454630313233343536373839 -iv 4142434445463031
    x9iWzVc4FfU=
    
    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

悬赏问题

  • ¥15 Mac虚拟机安装Windows,Windows中用idea跑项目,报错process finished with exit code -1073741819(0xc0000005) 如何解决?
  • ¥15 关于python爬虫返回js数据结构的处理
  • ¥15 ubuntu所用stm32标准库开发烧录没反映
  • ¥15 运维工程师(在职人员回答)
  • ¥15 Kmeans的趋势分析有会的吗
  • ¥20 R语言单细胞测序 对seurat对象进行标准化时出现问题
  • ¥15 请问如何在matlab里使用raven工具?
  • ¥100 关于ios手游充值到一定金额,再点充值提示公众号的问题。
  • ¥15 求一个stm32串口控制程序
  • ¥20 Windows 驱动开发版本疑问相关