将C#加密例程转换为Ruby

时间:2014-09-02 21:44:21

标签: c# .net ruby encryption rijndaelmanaged

我一直在尝试各种方法,但.Net代码似乎是在解密之前将字符串和键转换为二进制文件并且让我感到沮丧。我一遍又一遍地读到AES本质上就是Rijndael,所以我一直在使用Ruby 1.9.3中内置的开放SSL库。

RijndaelManaged crypto = new RijndaelManaged();
crypto.Padding = PaddingMode.PKCS7;
crypto.Key = ASCIIEncoding.ASCII.GetBytes(secretKey);
crypto.IV = ASCIIEncoding.ASCII.GetBytes(initializationVector);

byte[] byteArray = new byte[stringToDecrypt.Length / 2];
for (int i = 0; i < stringToDecrypt.Length / 2; i++)
{
  int index = (Convert.ToInt32(stringToDecrypt.Substring(i * 2, 2), 16));
  byteArray[i] = (byte)index;
}

MemoryStream memStream = new MemoryStream();
CryptoStream cryStream = new CryptoStream(memStream, crypto.CreateDecryptor(), CryptoStreamMode.Write);
cryStream.Write(byteArray, 0, byteArray.Length);
cryStream.FlushFinalBlock();

StringBuilder stringBuilder = new StringBuilder();

foreach (byte dByte in memStream.ToArray())
{
  stringBuilder.Append((char)dByte);
}

return stringBuilder.ToString();

这是我当前的Ruby代码,它没有做到这一点。它运行(除了最后一行)但是给了我垃圾。

我非常肯定问题在于MemoryStream / CryptoStream函数,但我不知道从哪里开始使用Ruby

text = Base64.encode64(cipher_text)
cypher = OpenSSL::Cipher::AES.new(256, :CBC)
cypher.decrypt
cypher.key = Base64.encode64("<cypher key>")
cypher.iv = Base64.encode64("<cypher iv>")
cypher.padding = 1
aes = cypher.update(cipher_text)
aes << cypher.final

我也尝试过这个。我想如果这不起作用,加密不仅仅是Rijndael与PKCS7填充,而是其他混淆。

cypher = OpenSSL::Cipher::AES.new(256, :CBC)
cypher.decrypt
cypher.key = "<cypher key>"
cypher.iv = "<cypher iv>"
cypher.padding = 1
cypher.update(cipher_text)

2 个答案:

答案 0 :(得分:1)

只要密钥,IV和密文相同,您的Ruby代码就会输出与C#代码相同的代码。

在C#中试试这个:

crypto.Key = new byte[32];
crypto.IV = new byte[16];
byteArray = new byte[] { 0x7d, 0x7f, 0x06, 0x32, 0xd6, 0x43, 0x03, 0x64, 0x85, 0x64, 0xcc, 0x81, 0xae, 0xfa, 0x29, 0xf5 };

这在Ruby中:

cypher.key = "\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0"
cypher.iv = "\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0"
text = "\x7d\x7f\x06\x32\xd6\x43\x03\x64\x85\x64\xcc\x81\xae\xfa\x29\xf5"

你会发现它运作正常。

无论你的C#字节数组是什么,你都希望Ruby字符串中的字节为字节,用于这些值。这就是你遇到问题的地方 - 你没有使用相同的值。

编辑:

这是一个更好的例子。在C#中尝试这个:

crypto.Key = ASCIIEncoding.ASCII.GetBytes("the quick brown fox jumps over t");
crypto.IV = ASCIIEncoding.ASCII.GetBytes("the quick brown ");
byteArray = new byte[] { 0xf8, 0x8b, 0xf1, 0x24, 0x65, 0x14, 0x0d, 0xe5, 0x25, 0xf1, 0xa4, 0x91, 0x45, 0x51, 0x73, 0x8e };

这在Ruby中:

cypher.key = "the quick brown fox jumps over t"
cypher.iv = "the quick brown "
text = [0xf8, 0x8b, 0xf1, 0x24, 0x65, 0x14, 0x0d, 0xe5, 0x25, 0xf1, 0xa4, 0x91, 0x45, 0x51, 0x73, 0x8e].map {|x| x.chr }.join

最后一行将密文转换为ASCII字符串&#34; \ xF8 \ x8B \ xF1 $ e \ x14 \ r \ xE5%\ xF1 \ xA4 \ x91EQs \ x8E&#34;。 Ruby OpenSSL库需要key,iv和ciphertext作为字符串。 (我猜你可以把编码称为8位ASCII。)

我给出的那个密文只是一个例子,并产生明文&#34;你好\ n&#34;。

答案 1 :(得分:0)

我只需要处理同样的基本问题,并且认为我会在对话中添加一些内容,以便混合中出现下一个人。

对我来说,最大的困难是C#库在幕后正在做什么的含糊不清。 (正确的选项在下面的选项列表中是第一个和粗体)

具体来说,&#39;模式&#39; AES加密是new AesManaged().CreateEncryptor()使用( CBC ,CFB,OFB,CTR还是ECB)?

new SHA256Managed().ComputeHash()返回什么类型? (原始字节,十六进制编码,base64编码?)

此外,C#程序是否会自动将最终填充添加到加密流中? (,否)

为了找到这些答案并与C#库的结果相匹配,我编写了Ruby代码来枚举所有这些可能性(30)并吐出输出。也许有一天这会对某人有所帮助......

def self.encode(data, key, iv, opts={})
    # Setup our default strategies and apply overrides if specified
    aes_type = opts[:aes_type] || :CBC
    sha_method = opts[:sha_method] || :digest
    final_padded = (opts[:final_padded].nil?) ? true : opts[:final_padded]
    cipher = OpenSSL::Cipher::AES256.new(aes_type)
    cipher.encrypt
    cipher.key = Digest::SHA256.send(sha_method, key)
    cipher.iv = iv
    r = cipher.update(data) 
    (r << cipher.final) if final_padded
    Base64.encode64(r)
end

# Try all the different ways that AES-256 encryption might be interpreted
def self.encode_possibilities(data, key, iv)
    results = {}
    [:CBC, :CFB, :OFB, :CTR, :ECB].each do |type|
        [:digest, :base64digest, :hexdigest].each do |sha_type|
            [true, false].each do |final_padded|
                r = encode(data, key, iv, 
                                        aes_type: type, 
                                        sha_method: sha_type, 
                                        final_padded: final_padded)
                results["AES(#{type})-SHA-ENCODING(#{sha_type})-FINAL(#{final_padded})"] = r
            end
        end
    end
    puts "\n"
    results.each{|k,v| puts "#{k}  ==>  #{v}"}
    puts "\n"
end