将 C# 加密算法转换为 Ruby
Converting C# Encryption Algorithm to Ruby
您好,我有一个用 C# 编写的加密算法,我需要将它移植到 ruby。
private string Encrypt(string clearText)
{
string EncryptionKey = "ENC_KEY";
byte[] clearBytes = Encoding.Unicode.GetBytes(clearText);
using (Aes encryptor = Aes.Create())
{
Rfc2898DeriveBytes pdb = new Rfc2898DeriveBytes(EncryptionKey, new byte[] { 0x1, 0x2, 0x3, 0x4, 0x5, 0x5, 0x5, 0x6, 0x7, 0x8, 0x9, 0x10, 0x11 });
encryptor.Key = pdb.GetBytes(32);
encryptor.IV = pdb.GetBytes(16);
using (MemoryStream ms = new MemoryStream()) {
using (CryptoStream cs = new CryptoStream(ms, encryptor.CreateEncryptor(), CryptoStreamMode.Write))
{
cs.Write(clearBytes, 0, clearBytes.Length); cs.Close();
}
clearText = Convert.ToBase64String(ms.ToArray()); }
}
return clearText;
}
据我所知,算法生成 AES 密钥,iv 和加密并 return 作为 base 64 字符串。
我没有找到 Rfc2898DeriveBytes 的确切替代品,我使用了 PBKDF2 Gem。这是我的 ruby 方法:
def self.encrypt clear_text
iterations = 1000
encryption_key = 'EncryptionKey'
clearBytes = clear_text.encode( 'UTF-16LE' ).bytes.to_a
enc_bytes = [0x1, 0x2, 0x3, 0x4, 0x5, 0x5, 0x5, 0x6, 0x7, 0x8, 0x9, 0x10, 0x11]
salt = enc_bytes.pack('C*')
derived_a = PBKDF2.new do |p|
p.password = encryption_key
p.salt = salt
p.iterations = iterations
p.key_length = 32
end
derived_b = PBKDF2.new do |p|
p.password = encryption_key
p.salt = salt
p.iterations = iterations
p.key_length = 16
end
key = derived_a.bin_string
# iV = derived_b.bin_string
iV_a = iV_a = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16] # Static iV
iV = iV_a.pack('C*')
cipher = OpenSSL::Cipher::AES256.new(:CBC)
cipher.encrypt
cipher.key = key
cipher.iv = iV
encrypted = cipher.update(clear_text) + cipher.final
Base64.encode64(encrypted)
end
我的代码有 2 个问题。我无法在 iv 上获得相同的值,如果我将它用作静态值,return 值不匹配。
我没有太多的 C# 经验。我错过了什么?
看起来您的 PBKDF2 生成算法具有固定输入,因此生成的 Key
和 IV
应该始终相同。
我只是 运行 我机器上的 C# 代码修改为输出 Key
和 IV
的值。它给了我:
takKsX7IBXq3R0Q5GWgJo/XhhEHDNfRFxSVru12vtU4=
y/lm9eKzBJTMdU+uA6GlXA==
分别作为Key
和IV
的Base64编码值。您可以在 Ruby 代码中使用这些值,这将消除使用 PBKDF2 gem.
继续生成这些值的需要
所以这个Ruby代码
clear_text = 'HELLO WORLD'
cipher = OpenSSL::Cipher::AES256.new(:CBC)
cipher.encrypt
cipher.key = Base64.decode64('takKsX7IBXq3R0Q5GWgJo/XhhEHDNfRFxSVru12vtU4=')
cipher.iv = Base64.decode64('y/lm9eKzBJTMdU+uA6GlXA==')
clearBytes = clearText.encode('UTF-16LE')
encrypted = cipher.update(clearBytes)
encrypted << cipher.final
puts Base64.encode64(encrypted)
将输出与 Encrypt("HELLO WORLD")
相同的内容
首先,您有不同的加密密钥
string EncryptionKey = "ENC_KEY";
Rfc2898DeriveBytes pdb = new Rfc2898DeriveBytes(EncryptionKey, new byte[] { 0x1, 0x2, 0x3, 0x4, 0x5, 0x5, 0x5, 0x6, 0x7, 0x8, 0x9, 0x10, 0x11 });
不同于:
encryption_key = 'EncryptionKey'
...
derived_a = PBKDF2.new do |p|
p.password = encryption_key
p.salt = salt
p.iterations = iterations
p.key_length = 32
end
如果您确实使用相同的 "everything",您可能需要在 KDF-ing 之前确保您的密码相同:)
另外,不要忘记 pack your IV in with your ciphertext 因为你不希望它(或你的盐)是静态的,然后加密 MAC,所有这些好东西:)
您好,我有一个用 C# 编写的加密算法,我需要将它移植到 ruby。
private string Encrypt(string clearText)
{
string EncryptionKey = "ENC_KEY";
byte[] clearBytes = Encoding.Unicode.GetBytes(clearText);
using (Aes encryptor = Aes.Create())
{
Rfc2898DeriveBytes pdb = new Rfc2898DeriveBytes(EncryptionKey, new byte[] { 0x1, 0x2, 0x3, 0x4, 0x5, 0x5, 0x5, 0x6, 0x7, 0x8, 0x9, 0x10, 0x11 });
encryptor.Key = pdb.GetBytes(32);
encryptor.IV = pdb.GetBytes(16);
using (MemoryStream ms = new MemoryStream()) {
using (CryptoStream cs = new CryptoStream(ms, encryptor.CreateEncryptor(), CryptoStreamMode.Write))
{
cs.Write(clearBytes, 0, clearBytes.Length); cs.Close();
}
clearText = Convert.ToBase64String(ms.ToArray()); }
}
return clearText;
}
据我所知,算法生成 AES 密钥,iv 和加密并 return 作为 base 64 字符串。
我没有找到 Rfc2898DeriveBytes 的确切替代品,我使用了 PBKDF2 Gem。这是我的 ruby 方法:
def self.encrypt clear_text
iterations = 1000
encryption_key = 'EncryptionKey'
clearBytes = clear_text.encode( 'UTF-16LE' ).bytes.to_a
enc_bytes = [0x1, 0x2, 0x3, 0x4, 0x5, 0x5, 0x5, 0x6, 0x7, 0x8, 0x9, 0x10, 0x11]
salt = enc_bytes.pack('C*')
derived_a = PBKDF2.new do |p|
p.password = encryption_key
p.salt = salt
p.iterations = iterations
p.key_length = 32
end
derived_b = PBKDF2.new do |p|
p.password = encryption_key
p.salt = salt
p.iterations = iterations
p.key_length = 16
end
key = derived_a.bin_string
# iV = derived_b.bin_string
iV_a = iV_a = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16] # Static iV
iV = iV_a.pack('C*')
cipher = OpenSSL::Cipher::AES256.new(:CBC)
cipher.encrypt
cipher.key = key
cipher.iv = iV
encrypted = cipher.update(clear_text) + cipher.final
Base64.encode64(encrypted)
end
我的代码有 2 个问题。我无法在 iv 上获得相同的值,如果我将它用作静态值,return 值不匹配。
我没有太多的 C# 经验。我错过了什么?
看起来您的 PBKDF2 生成算法具有固定输入,因此生成的 Key
和 IV
应该始终相同。
我只是 运行 我机器上的 C# 代码修改为输出 Key
和 IV
的值。它给了我:
takKsX7IBXq3R0Q5GWgJo/XhhEHDNfRFxSVru12vtU4=
y/lm9eKzBJTMdU+uA6GlXA==
分别作为Key
和IV
的Base64编码值。您可以在 Ruby 代码中使用这些值,这将消除使用 PBKDF2 gem.
所以这个Ruby代码
clear_text = 'HELLO WORLD'
cipher = OpenSSL::Cipher::AES256.new(:CBC)
cipher.encrypt
cipher.key = Base64.decode64('takKsX7IBXq3R0Q5GWgJo/XhhEHDNfRFxSVru12vtU4=')
cipher.iv = Base64.decode64('y/lm9eKzBJTMdU+uA6GlXA==')
clearBytes = clearText.encode('UTF-16LE')
encrypted = cipher.update(clearBytes)
encrypted << cipher.final
puts Base64.encode64(encrypted)
将输出与 Encrypt("HELLO WORLD")
首先,您有不同的加密密钥
string EncryptionKey = "ENC_KEY";
Rfc2898DeriveBytes pdb = new Rfc2898DeriveBytes(EncryptionKey, new byte[] { 0x1, 0x2, 0x3, 0x4, 0x5, 0x5, 0x5, 0x6, 0x7, 0x8, 0x9, 0x10, 0x11 });
不同于:
encryption_key = 'EncryptionKey'
...
derived_a = PBKDF2.new do |p|
p.password = encryption_key
p.salt = salt
p.iterations = iterations
p.key_length = 32
end
如果您确实使用相同的 "everything",您可能需要在 KDF-ing 之前确保您的密码相同:)
另外,不要忘记 pack your IV in with your ciphertext 因为你不希望它(或你的盐)是静态的,然后加密 MAC,所有这些好东西:)