Как расшифровать Rijndael в ruby ​​(закодировано в VB.net)

Я использую Rinjael для кодирования в VB.NET, и мне нужно декодировать в Ruby. Мой класс шифрования VB.NET выглядит так:

Private Class Encryptor
        Private symmetricKey As System.Security.Cryptography.RijndaelManaged
        Private iVector As Byte()
        Private Key As Byte()
        Public Function encrypt(ByVal data As String) As String
            Try
                Dim plainTextBytes As Byte() = System.Text.Encoding.ASCII.GetBytes(data)
                Dim encryptor As System.Security.Cryptography.ICryptoTransform = symmetricKey.CreateEncryptor(Key, iVector)
                Dim memoryStream As New System.IO.MemoryStream
                Dim cryptoStream As System.Security.Cryptography.CryptoStream = New System.Security.Cryptography.CryptoStream(memoryStream, encryptor, System.Security.Cryptography.CryptoStreamMode.Write)
                cryptoStream.Write(plainTextBytes, 0, plainTextBytes.Length)
                cryptoStream.FlushFinalBlock()
                Dim cipherTextBytes As Byte() = memoryStream.ToArray()
                memoryStream.Close()
                cryptoStream.Close()
                Return Convert.ToBase64String(cipherTextBytes)
            Catch
                Return ""
            End Try
        End Function
        Public Function decrypt(ByVal data As String) As String
            Try
                Dim crypted As Byte() = Convert.FromBase64String(data)
                Dim decryptor As System.Security.Cryptography.ICryptoTransform = symmetricKey.CreateDecryptor(Key, iVector)
                Dim memoryStream As New System.IO.MemoryStream(crypted)
                Dim cryptoStream As System.Security.Cryptography.CryptoStream = New System.Security.Cryptography.CryptoStream(memoryStream, decryptor, System.Security.Cryptography.CryptoStreamMode.Read)
                Dim plain(crypted.Length) As Byte
                Dim count As Integer = cryptoStream.Read(plain, 0, plain.Length)
                memoryStream.Close()
                cryptoStream.Close()
                Return System.Text.Encoding.UTF8.GetString(plain, 0, count)
            Catch
                Return ""
            End Try
        End Function

        Public Sub New(ByVal clientkey As String)
            iVector = System.Text.Encoding.ASCII.GetBytes("1234567890123456")
            Key = System.Text.Encoding.ASCII.GetBytes(clientkey)
            symmetricKey = New System.Security.Cryptography.RijndaelManaged
            symmetricKey.Mode = System.Security.Cryptography.CipherMode.CBC
        End Sub
    End Class

это работает нормально, и я могу расшифровать в java, используя AES/CBC/PKCS5Padding. Теперь мой пароль и iv имеют длину 16 символов (16 * 16 бит = 256). Когда я пытаюсь расшифровать в Ruby, он жалуется, что мой пароль слишком короткий... Я предполагаю, что он использует 8-битные символы. Я использую этот класс для расшифровки в ruby:

    require 'openssl'

module Crypt
  # Decrypts a block of data (encrypted_data) given an encryption key
  # and an initialization vector (iv).  Keys, iv's, and the data 
  # returned are all binary strings.  Cipher_type should be
  # "AES-256-CBC", "AES-256-ECB", or any of the cipher types
  # supported by OpenSSL.  Pass nil for the iv if the encryption type
  # doesn't use iv's (like ECB).
  #:return: => String
  #:arg: encrypted_data => String 
  #:arg: key => String
  #:arg: iv => String
  #:arg: cipher_type => String
  def Crypt.decrypt(encrypted_data, key, iv, cipher_type)
    aes = OpenSSL::Cipher::Cipher.new(cipher_type)
    aes.decrypt
    aes.key = key
    aes.iv = iv if iv != nil
    aes.update(encrypted_data) + aes.final  
  end

  # Encrypts a block of data given an encryption key and an 
  # initialization vector (iv).  Keys, iv's, and the data returned 
  # are all binary strings.  Cipher_type should be "AES-256-CBC",
  # "AES-256-ECB", or any of the cipher types supported by OpenSSL.  
  # Pass nil for the iv if the encryption type doesn't use iv's (like
  # ECB).
  #:return: => String
  #:arg: data => String 
  #:arg: key => String
  #:arg: iv => String
  #:arg: cipher_type => String  
  def Crypt.encrypt(data, key, iv, cipher_type)
    aes = OpenSSL::Cipher::Cipher.new(cipher_type)
    aes.encrypt
    aes.key = key
    aes.iv = iv if iv != nil
    aes.update(data) + aes.final      
  end
end

В настоящее время. Пытаясь расшифровать с помощью Crypt.decrypt(data,key,iv, "AES-CBC-256"), я уверен, что для правильной работы необходимо выполнить предварительные преобразования строки/байта для моих данных, ключа,iv.

Как мне вызвать Crypt.decrypt, используя key = «passwordpassword» и iv = «1234567890123456»? Нужно ли мне base64 декодировать мои данные?

Вот мой вызов расшифровки, который, похоже, не работает (пытаюсь заполнить нулями):

   text = Base64.decode64(text)
   pass = Digest::SHA1.hexdigest("#{@pass}0000000000000000").unpack('a2'*32).map{|x| x.hex}.pack('c'*32)
   iv = Digest::SHA1.hexdigest("12345678901234560000000000000000").unpack('a2'*32).map{|x| x.hex}.pack('c'*32)
   return Crypt.decrypt(text,pass,iv,"AES-256-CBC")

person Sparky    schedule 11.01.2010    source источник
comment
Есть ли какая-то конкретная причина называть алгоритм Rijndael? Почему бы не называть это только AES?   -  person Magnus Hoff    schedule 11.01.2010


Ответы (2)


Решение. Это было 128-битное шифрование (ошибочно полагая, что по умолчанию в управляемом .NET было 256). Следовательно, этот код работает (обратите внимание на «AES-128-CBC»):

   text = Base64.decode64(text)
   pass = "passwordpassword"
   iv = "1234567890123456"
   return Crypt.decrypt(text,pass,iv,"AES-128-CBC")
person Sparky    schedule 12.01.2010

Поскольку приложение VB кодирует результат как base64, похоже, что скрипт ruby ​​должен будет использовать модуль Base64 для его декодирования в первую очередь.

Я считаю, что ключ, указанный для ключа Ruby AES, должен быть 256-битным. Таким образом, ваш пароль должен быть длиной 32 байта именно в этом случае. Лучше использовать такую ​​схему, как эта.

person Mark Wilkins    schedule 11.01.2010
comment
Шифрование VB.NET уже реализовано и не может быть изменено. Проблема в следующем: почему VB.NET шифрует с помощью 16-символьного пароля /iv, а ruby ​​не расшифровывает с использованием того же пароля /iv? Я думаю, проблема заключается в том, сколько байтов/символов используют обе системы: 16 бит в VB.NET и 8 бит в ruby... Следовательно, 16-символьный пароль работает в VB.net (16*16=256). Но как мне декодировать его в ruby, если он уже закодирован с использованием приведенного выше кода VB.NET? - person Sparky; 12.01.2010
comment
Я не думаю, что это проблема 16-битных и 8-битных символов. Приложение VB использует кодировку ASCII (поэтому это должны быть 8-битные символы). Поскольку размер ключа по умолчанию составляет 256 бит и, по-видимому, не указан, можно сделать вывод, что .NET дополняет данный ключ до 256 бит. Вы сможете довольно легко проверить это в .NET. Очевидным значением заполнения будут нули. - person Mark Wilkins; 12.01.2010
comment
Спасибо за указание на это. Имеет смысл. Я только что попытался дополнить свой iv/pass нулями (см. последний код выше). И, кажется, возвращает ответ (по крайней мере, он не падает). Однако ответ зашифрован и != оригинал :-/ - person Sparky; 12.01.2010