【问题标题】:How to decode Rijndael in ruby (encoded in VB.net)如何在 ruby​​ 中解码 Rijndael(在 VB.net 中编码)
【发布时间】:2010-01-11 19:56:03
【问题描述】:

我正在使用 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

这工作正常,我可以使用 AES/CBC/PKCS5Padding 在 java 中解密。现在,我的密码和 iv 有 16 个字符长(16*16bit = 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") 进行解密,我确信必须对我的 data,key,iv 进行初步的字符串/字节转换才能正常工作。

如何使用 key = "passwordpassword" 和 iv="1234567890123456" 调用 Crypt.decrypt? 我需要对我的数据进行 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")

【问题讨论】:

  • 调用算法 Rijndael 有什么特别的原因吗?为什么不坚持只称它为 AES?

标签: ruby-on-rails ruby aes rijndaelmanaged rijndael


【解决方案1】:

解决方案。这是一个 128 位加密(错误地认为 .NET 托管的默认值是 256)。因此,此代码有效(注意“AES-128-CBC”):

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

【讨论】:

    【解决方案2】:

    因为 VB 应用程序将结果编码为 base64,看起来 ruby​​ 脚本需要先使用 Base64 模块对其进行解码。

    我相信分配给 Ruby AES 密钥的密钥必须是 256 位。因此,在这种情况下,您的密码恰好需要 32 个字节长。最好使用this之类的方案。

    【讨论】:

    • VB.NET 加密已经实现,无法修改。问题是:为什么 VB.NET 使用 16 个字符的密码/iv 进行加密,而 ruby​​ 不使用相同的密码/iv 进行解密?我认为问题在于两个系统使用多少字节/字符:VB.NET 中的 16 位和 ruby​​ 中的 8 位...因此,16 字符密码在 VB.net 中有效(16 * 16 = 256)。但是,如果它已经使用上面的 VB.NET 代码进行了编码,我该如何在 ruby​​ 中对其进行解码?
    • 我认为这不是 16 位与 8 位字符的问题。 VB 应用程序使用 ASCII 编码(因此它应该是 8 位字符)。由于默认密钥大小是 256 位并且似乎没有指定,因此似乎结论是 .NET 将给定​​密钥填充为 256 位。您应该能够相当容易地在 .NET 中对其进行测试。明显的填充值将为零。
    • 感谢您指出这一点。说得通。我只是试图用零填充我的 iv/pass(参见上面的最后一个代码)。它似乎返回了一个答案(至少,它不会崩溃)。但是,答案是加密的并且 != original :-/
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-02-11
    • 2015-05-26
    • 1970-01-01
    相关资源
    最近更新 更多