2015-11-24 3 views
3

Привет, у меня есть алгоритм шифрования в C#, и мне нужно его перенести в 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; 
} 

Как я понимаю alghorithm генерирует ключ AES, а также внутривенно и шифровать и возвращают в качестве базы 64 строки.

Я не нашел точной альтернативы для Rfc2898DeriveBytes, и я использовал PBKDF2 Gem. И вот мой рубиновый метод:

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, и если я использую его как статическое значение, возвращаемые значения не совпадают.

У меня слишком много опыта C#. Что мне не хватает?

+1

MSDN говорит, что функция getBytes меняет размеры ключей для каждого вызова. Я имею в виду, если вы дважды вызываете GetBytes (10), это то же самое, что и вызов GetBytes (10 + 10) или непосредственно GetBytes (20). Существует несколько способов решения этой проблемы, и вы можете генерировать более длинный ключ при первом вызове, а затем разрезать его как на производный ключ, так и на IV. –

+0

Если у вас мало опыта работы с C#, я бы предложил вам не «переводить» код, а просто написать его в Ruby с нуля. Если вы более знакомы с Ruby, это может быть проще, чем пытаться расшифровать неизвестный язык. – onebree

ответ

2

Похоже, ваш алгоритм генерации PBKDF2 имеет фиксированный вход, поэтому полученные Key и IV всегда должны быть одинаковыми.

Я только что запустил код C# на моей машине, модифицированный для вывода значений Key и IV. Это дало мне:

takKsX7IBXq3R0Q5GWgJo/XhhEHDNfRFxSVru12vtU4= 
y/lm9eKzBJTMdU+uA6GlXA== 

как Base64 закодированных значений Key и IV соответственно. Вы можете просто использовать эти значения в своем Ruby-коде, что избавит вас от необходимости генерировать их, используя жемчуг PBKDF2.

Так что этот рубин код

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")

+0

Чем вы очень. когда я устанавливаю ключи, поскольку проблема с базовыми 64 строками решена. – htkaya

0

Для начала, у вас есть различные ключи шифрования

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 

Если вы действительно используете тот же «все» вы, возможно, потребуется, чтобы убедиться, что ваша ключевая фраза является одинаковой до KDF-ки его :)

Кроме того, не забудьте pack your IV in with your ciphertext, так как вы не хотите, что (или ваша соль), чтобы быть статичным, зашифровать, затем MAC, все, что нужно хорошо :)

Смежные вопросы