2016-10-13 4 views
0

Я пытаюсь переопределить код C# в Ruby. Следующий код (с различными секретами) работает для расшифровки файла:C# Rijndael ключ слишком короткий в Ruby

using System.IO; 
using System.Security.Cryptography; 
using System.Text; 

public static class Decrypt { 
    private const string KEY = "FOOBARB"; 

    private static readonly byte[] IV = { 
    126, 36, 216, 236, 247, 79, 205, 111, 240, 119, 197, 10, 19, 216, 139, 91 
    }; 

    public static Stream ReadEncryptedFile(string filePath) { 
    var fs = new FileStream(
     filePath, 
     FileMode.OpenOrCreate, 
     FileAccess.ReadWrite 
    ); 

    byte[] key = new UnicodeEncoding().GetBytes(KEY); 
    byte[] vector = IV; 

    using (var rijndaelEncryption = new RijndaelManaged()) { 
     var decryptor = rijndaelEncryption.CreateDecryptor(key, vector); 
     return new CryptoStream(fs, decryptor, CryptoStreamMode.Read); 
    } 
    } 

    public static void Main() { 
    var crReader = ReadEncryptedFile(
     "/path/to/file" 
    ); 
    StreamReader reader = new StreamReader(crReader); 
    System.Console.WriteLine(reader.ReadToEnd()); 
    } 
} 

Я знаю, что CBC правильный режим шифрования, поскольку System.Console.WriteLine(rijndaelEncryption.Mode) возвращает CBC. Я знаю, что размер входного и выходного блоков составляет 256 бит, потому что decryptor.OutputBlockSize и decryptor.InputBlockSize оба возвращают 32. (Я понимаю, что размер ключа также входит и действительно определяет различие между AES и Rijndael, как обсуждалось here, - но я не уверен как это работает.)

Во всяком случае, я получаю in 'key=': key length too short (OpenSSL::Cipher::CipherError), когда запускаю следующий код Ruby (я также пробовал 128-битные и 192-разрядные версии AES/CBC, хотя это не должно меняться здесь):

require 'openssl' 

f = File.read(
    'path/to/file' 
) 

key = 'FOOBARB' 

iv = [126, 36, 216, 236, 247, 79, 205, 111, 240, 119, 197, 10, 19, 216, 139, 91] 
    .pack('c*') 

cipher = OpenSSL::Cipher.new('AES-256-CBC') 

cipher.decrypt 

cipher.key = key 
cipher.iv = iv 

puts cipher.update(f) 

Так что, я думаю, три вопроса:

  1. Как C# нанести 56-битный ключ, чтобы он работал с алгоритмом, требующим хотя бы 128-битного ключа?
  2. Являются ли различия между Rijndael и AES фатальными для моей попытки использовать библиотеку OpenSSL Ruby для этой задачи?
  3. Однажды или если я получу ключ, мне нужно будет беспокоиться о кодировке символов, как описано here?

спасибо.

+0

To 1: It * возможно * прокладки с 0x00 ('' \ 0''), пока ключ не будет иметь 16 байт. Кроме того, проверьте свою математику в этом утверждении: * «Я знаю, что размер входного и выходного блоков составляет 256 бит, потому что decryptor.OutputBlockSize и decryptor.InputBlockSize оба возвращают 16». * Он должен быть 128 бит. –

ответ

0

Если вы пытаетесь использовать AES с Rijndael, вам необходимо установить размер блока 128-битным (16-байтным), то есть единственным размером блока AES. Многие соглашения о назначении реализации Rijndael определяют размер блока с размером ключа, который определяется покупаемым ключом.

Размеры ключей AES составляют 128, 192 или 256 бит, лучше всего поставлять точно правильный размер, не полагайтесь на реализацию зависимых от клавиатуры.

+0

Чтобы немного разъяснить: код C# используется для генерации зашифрованных файлов другой стороной. Непонятно, что мы можем изменить это. Я знаю, что код C#, показанный в листинге выше, работает для его расшифровки. Я пытаюсь понять, почему работает мой C#-код - как явно слишком короткий ключ, тем не менее, расшифровывает зашифрованный файл. –

+0

Вам нужно определить размер блока, который использует другая сторона. Лучше всего использовать AES (Rijndael с размером блока 128 бит), особенно для интероперабельности. Кроме того, необходимо использовать случайный IV, обычно префикс для зашифрованных данных, фиксированный IV может утечка информации, если используется с одним и тем же ключом несколько раз. – zaph