C#TripleDES CBC / PKCS7 / Hex不等同于Ruby / Python TripleDES

时间:2017-05-30 15:29:16

标签: c# python ruby encryption

我需要使用3DES将C#加密/解密类移植到HEX(使用静态密钥和IV)到Ruby或Python的PKCS7填充,但似乎输出完全不同。

以下是代码的C#代码段:

public CryptoDES3()
{
  this.objCryptoProvider = new TripleDESCryptoServiceProvider();
  this.CipherMode = CipherMode.CBC;
  this.PaddingMode = PaddingMode.PKCS7;
  this.EncodingType = CryptoDES3.EncodingTypeEnum.Hex;
}

/* ----- */

public string Encrypt(string strValue, string strKey, string strIV, CryptoDES3.EncodingTypeEnum intEncodingType)
{
  string str = "";
  if (strValue.Length > 0)
  {
    this.objCryptoProvider.Mode = this.CipherMode;
    this.objCryptoProvider.Padding = this.PaddingMode;
    byte[] bytes1 = Encoding.Default.GetBytes(CryptoDES3.HexDecode(strKey));
    byte[] bytes2 = Encoding.Default.GetBytes(CryptoDES3.HexDecode(strIV));
    MemoryStream memoryStream = new MemoryStream();
    CryptoStream cryptoStream = new CryptoStream((Stream) memoryStream, this.objCryptoProvider.CreateEncryptor(bytes1, bytes2), CryptoStreamMode.Write);
    StreamWriter streamWriter = new StreamWriter((Stream) cryptoStream);
    streamWriter.Write(strValue);
    streamWriter.Flush();
    cryptoStream.FlushFinalBlock();
    string strValue1 = Encoding.Default.GetString(memoryStream.GetBuffer(), 0, checked ((int) memoryStream.Length));
    switch (intEncodingType)
    {
      case CryptoDES3.EncodingTypeEnum.Hex:
        str = CryptoDES3.HexEncode(strValue1);
        break;
      case CryptoDES3.EncodingTypeEnum.Base64:
        str = CryptoDES3.Base64Encode(strValue1);
        break;
      default:
        str = strValue1;
        break;
    }
  }
  return str;
}

public string Decrypt(string strValue, string strKey, string strIV, CryptoDES3.EncodingTypeEnum intEncodingType)
{
  string str = "";
  if (strValue.Length > 0)
  {
    this.objCryptoProvider.Mode = this.CipherMode;
    this.objCryptoProvider.Padding = this.PaddingMode;
    byte[] bytes1 = Encoding.Default.GetBytes(CryptoDES3.HexDecode(strKey));
    byte[] bytes2 = Encoding.Default.GetBytes(CryptoDES3.HexDecode(strIV));
    string s;
    switch (intEncodingType)
    {
      case CryptoDES3.EncodingTypeEnum.Hex:
        s = CryptoDES3.HexDecode(strValue);
        break;
      case CryptoDES3.EncodingTypeEnum.Base64:
        s = CryptoDES3.Base64Decode(strValue);
        break;
      default:
        s = strValue;
        break;
    }
    str = new StreamReader((Stream) new CryptoStream((Stream) new MemoryStream(Encoding.Default.GetBytes(s)), this.objCryptoProvider.CreateDecryptor(bytes1, bytes2), CryptoStreamMode.Read)).ReadToEnd();
  }
  return str;
}

/* ----- */

internal const string DES3_KEY = "A0498F07C46808173894BB976F9726477CC0913D87DE912A";
internal const string DES3_IV = "0A9B11D6FEE830A9";

这是Ruby代码,它输出到控制台:

#!/usr/bin/env ruby
require 'digest'
require 'openssl'

ALG = "DES-EDE3-CBC"
KEY = "\xA0\x49\x8F\x07\xC4\x68\x08\x17\x38\x94\xBB\x97\x6F\x97\x26\x47\x7C\xC0\x91\x3D\x87\xDE\x91\x2A"
IV = "\x0A\x9B\x11\xD6\xFE\xE8\x30\xA9"

def encode(data)
  cipher = OpenSSL::Cipher::Cipher.new(ALG)
  cipher.key = KEY
  cipher.iv = IV
  cipher.encrypt
  result = cipher.update(data)
  result << cipher.final
  result = result.unpack('H*')
end

def decode(data)
  cipher = OpenSSL::Cipher::Cipher.new(ALG)
  cipher.key = KEY
  cipher.iv = IV
  cipher.decrypt
  data = data.pack('H*')
  result = cipher.update(data)
  result << cipher.final
end

data = "test"

encoded = encode(data)
decoded = decode(encoded)

puts "Encrypted: #{encoded[0]}"
puts "Decrypted: #{decoded}"

输出:

$ ./3des.rb
Encrypted: 33fd6ee287c0f46f
Decrypted: test

Python代码:

#!/usr/bin/env python
import pyDes

k = pyDes.triple_des('A0498F07C46808173894BB976F9726477CC0913D87DE912A'.decode('hex'), mode=pyDes.CBC, IV="0A9B11D6FEE830A9".decode('hex'), pad=None, padmode=pyDes.PAD_PKCS5)
d = k.encrypt("test")

print "Encrypted: " + d.encode('hex')

print "Decrypted: " + k.decrypt(d)

输出:

$ ./3des.py
Encrypted: 33fd6ee287c0f46f
Decrypted: test

使用chilkat.CkCrypt2()在Python中输出相同的内容。

MS C#TripleDESCryptoServiceProvider()与Ruby,Python,OpenSSL有什么不同? 知道如何才能得到相同的结果?

1 个答案:

答案 0 :(得分:0)

还可以使用C#:

using Microsoft.VisualBasic;
using Microsoft.VisualBasic.CompilerServices;
using System;
using System.IO;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Security.Cryptography;
using System.Threading.Tasks;

namespace _3DES
{
    class Program
    {

        public static string Encrypt(string strValue)
        {
            const string DES3_KEY = "A0498F07C46808173894BB976F9726477CC0913D87DE912A";
            const string DES3_IV = "0A9B11D6FEE830A9";
            TripleDESCryptoServiceProvider objCryptoProvider;
            string str = "";
            if (strValue.Length > 0)
            {
                objCryptoProvider = new TripleDESCryptoServiceProvider();
                objCryptoProvider.Mode = CipherMode.CBC;
                objCryptoProvider.Padding = PaddingMode.PKCS7;
                byte[] bytes1 = Encoding.Default.GetBytes(HexDecode(DES3_KEY));
                byte[] bytes2 = Encoding.Default.GetBytes(HexDecode(DES3_IV));
                MemoryStream memoryStream = new MemoryStream();
                CryptoStream cryptoStream = new CryptoStream((Stream)memoryStream, objCryptoProvider.CreateEncryptor(bytes1, bytes2), CryptoStreamMode.Write);
                StreamWriter streamWriter = new StreamWriter((Stream)cryptoStream);
                streamWriter.Write(strValue);
                streamWriter.Flush();
                cryptoStream.FlushFinalBlock();
                string strValue1 = Encoding.Default.GetString(memoryStream.GetBuffer(), 0, checked((int)memoryStream.Length));
                str = HexEncode(strValue1);
            }
            return str;
        }

        public static string Decrypt(string strValue)
        {
            const string DES3_KEY = "A0498F07C46808173894BB976F9726477CC0913D87DE912A";
            const string DES3_IV = "0A9B11D6FEE830A9";
            TripleDESCryptoServiceProvider objCryptoProvider;
            string str = "";
            if (strValue.Length > 0)
            {
                objCryptoProvider = new TripleDESCryptoServiceProvider();
                objCryptoProvider.Mode = CipherMode.CBC;
                objCryptoProvider.Padding = PaddingMode.PKCS7;
                byte[] bytes1 = Encoding.Default.GetBytes(HexDecode(DES3_KEY));
                byte[] bytes2 = Encoding.Default.GetBytes(HexDecode(DES3_IV));
                string s;
                s = HexDecode(strValue);
                str = new StreamReader((Stream)new CryptoStream((Stream)new MemoryStream(Encoding.Default.GetBytes(s)), objCryptoProvider.CreateDecryptor(bytes1, bytes2), CryptoStreamMode.Read)).ReadToEnd();
            }
            return str;
        }

        public static string HexEncode(string strValue)
        {
            string str = "";
            if (strValue.Length > 0)
            {
                byte[] bytes = Encoding.Default.GetBytes(strValue);
                int num = 0;
                int upperBound = bytes.GetUpperBound(0);
                int index = num;
                while (index <= upperBound)
                {
                    str += Conversion.Hex(bytes[index]).PadLeft(2, '0');
                    checked { ++index; }
                }
            }
            return str;
        }

        public static string HexDecode(string strValue)
        {
            string str = "";
            if (strValue.Length > 0)
            {
                strValue = strValue.ToUpper();
                int num1 = 0;
                int num2 = checked(strValue.Length - 2);
                int startIndex = num1;
                while (startIndex <= num2)
                {
                    str += Conversions.ToString(Strings.Chr(Conversions.ToInteger("&H" + strValue.Substring(startIndex, 2))));
                    checked { startIndex += 2; }
                }
            }
            return str;
        }

        static void Main(string[] args)
        {
            String encoded = Encrypt("test");
            Console.WriteLine(encoded);
            String plain = Decrypt(encoded);
            Console.WriteLine(plain);
        }
    }
}

输出:

C:\> 3DES.exe
33FD6EE287C0F46F
test