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 metadata提取的PDF元数据,如何转换为一个Excel
  • ¥15 关于arduino编程toCharArray()函数的使用
  • ¥100 vc++混合CEF采用CLR方式编译报错
  • ¥15 coze 的插件输入飞书多维表格 app_token 后一直显示错误,如何解决?
  • ¥15 vite+vue3+plyr播放本地public文件夹下视频无法加载
  • ¥15 c#逐行读取txt文本,但是每一行里面数据之间空格数量不同
  • ¥50 如何openEuler 22.03上安装配置drbd
  • ¥20 ING91680C BLE5.3 芯片怎么实现串口收发数据
  • ¥15 无线连接树莓派,无法执行update,如何解决?(相关搜索:软件下载)
  • ¥15 Windows11, backspace, enter, space键失灵