将C#加密例程转换为Ruby
我一直在尝试各种方法,但.Net代码似乎在解密之前将字符串和密钥转换为二进制,这让我大吃一惊。我反复阅读AES本质上是Rijndael,因此我一直在使用Ruby 1.9.3中内置的开放SSL库将C#加密例程转换为Ruby,c#,.net,ruby,encryption,rijndaelmanaged,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 = ASC
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();
RijndaelManaged crypto=new RijndaelManaged();
crypto.Padding=PaddingMode.PKCS7;
crypto.Key=ascienceoding.ASCII.GetBytes(secretKey);
crypto.IV=ascienceoding.ASCII.GetBytes(初始化向量);
byte[]byteArray=新字节[stringToDecrypt.Length/2];
对于(int i=0;i
下面是我当前的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
text=Base64.encode64(密码文本)
cypher=OpenSSL::Cipher::AES.new(256,:CBC)
密码解密
cypher.key=Base64.encode64(“”)
cypher.iv=Base64.encode64(“”)
cypher.padding=1
aes=cypher.update(密码文本)
aes只要密钥、IV和密文相同,Ruby代码的输出与C#代码相同
在你的C#中试试这个:
在你的红宝石中:
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#试试这个:
在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字符串“\xF8\x8B\xF1$e\x14\r\xE5%\xF1\xA4\x91EQs\x8E”。Ruby OpenSSL库希望密钥、iv和密文作为字符串。(我想您可以将编码称为8位ASCII。)
我给出的密文只是一个例子,它产生了纯文本“hello\n”。我只是需要解决同样的基本问题,我想我应该为下一个出现的人添加一点对话内容
我遇到的最大困难是C#libraries在幕后到底在做什么,模棱两可。(在下面的选项列表中,正确的选项排在第一位并以粗体显示)
具体来说,new AesManaged().CreateEncryptor()
使用的AES加密的“模式”是什么(CBC、CFB、OFB、CTR或ECB)
new SHA256Managed().ComputeHash()返回什么类型?(原始字节,十六进制编码,base64编码?)
此外,C#程序是否会自动向加密流添加最终填充?(是,否)
为了找到这些答案并与C#library的结果相匹配,我编写了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
def self.encode(数据、键、iv、选项={})
#设置默认策略并应用覆盖(如果指定)
aes_类型=选择[:aes_类型]| |:CBC
sha_方法=选择[:sha_方法]| |:摘要
最终填充=(选择[:最终填充].nil?)?正确:选项[:最终填充]
cipher=OpenSSL::cipher::AES256.new(aes_类型)
加密
cipher.key=Digest::SHA256.send(sha_方法,key)
4.iv=iv
r=密码更新(数据)
(r问题是什么?你只是在寻找这个的ruby版本吗?抱歉@Smith.h.Neil我添加了我当前的代码。我有一个操作函数,它会给我带来垃圾。我认为问题在于MemoryStream/CryptoStream。不确定从哪里开始将其翻译成ruby。字符串、密钥和iv以纯文本形式提供给我。如果它们被转换为字节数组(?),Ruby应该可以工作吗?不,你只是把它们当作字符串使用。在我的回答中,请参阅我上面的编辑。哦,好的。那么我如何将C#字节数组代码块复制到Ruby中呢?我想这是我最困惑的地方。搜索Ruby pack/unpack的信息,你会发现很多从字节到字符串再到字符串的例子。我从这里开始。
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 };
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
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