【问题标题】:How to use Ruby to decrypt plaintext that was encrypted with the openssl command line utility using a password and no salt?如何使用 Ruby 解密使用密码且不加盐的 openssl 命令行实用程序加密的明文?
【发布时间】:2020-07-10 11:29:50
【问题描述】:

我使用openssl 命令行实用程序使用密码加密了一些明文:

echo -n "foo" | openssl enc -e -base64 -rc4 -nosalt -pass pass:secretkey

这会返回:

ryW2

如何使用 Ruby 解密这个值?

【问题讨论】:

    标签: ruby openssl


    【解决方案1】:

    最后在Ruby中参考了Above

    编码

    def encrypt(str, key)
      cipher = OpenSSL::Cipher.new('RC4')
      cipher.key = OpenSSL::Digest.digest('md5', key)
      cipher.decrypt
      Base64.encode64(cipher.update(str) + cipher.final)
    end
    
    encrypt('This is Test', 'Test')
    => "JGmpM+ewGA79qaZH\n"
    

    解码

    def decrypt(encrypted_string, key)
      decipher = OpenSSL::Cipher.new('RC4')
      decipher.key = OpenSSL::Digest.digest('md5', key)
      decipher.decrypt
      decipher.update(Base64.decode64(encrypted_string)) + decipher.final
    end
    
    decrypt("JGmpM+ewGA79qaZH\n", "Test")
    => "This is Test"
    

    【讨论】:

      【解决方案2】:

      这是您需要输入的命令,将字符串foo 加密为密文:

      echo -n "foo" | openssl enc -e -base64 -rc4 -nosalt -pass pass:secretkey -p
      

      这会返回:

      key=610A2EE688CDA9E724885E23CD2CFDEE
      ryW2
      

      ryW2 是您的 base64 编码密文。

      我们添加了-p,因此我们可以看到用于加密的密钥。

      -p 是必需的,因为 OpenSSL 使用内部函数 EVP_BytesToKey 将密码短语转换为密钥,并且没有等效的 Ruby 方法来执行此操作。因此,在 Ruby 中加密或解密时,您必须直接使用此键值,而不是密码。

      解密同样简单:

      echo "ryW2" | openssl enc -d -base64 -rc4 -nosalt -pass pass:secretkey
      

      这会返回:

      foo
      

      考虑到这一切,下面是使用 Ruby 加密此字符串以获得相同值的方法:

      require 'openssl'
      require 'base64'
      
      plaintext = 'foo'
      cipher = OpenSSL::Cipher.new('rc4')
      cipher.encrypt
      # Use the key that was generated by EVP_BytesToKey
      key = '610A2EE688CDA9E724885E23CD2CFDEE'
      # Convert the key to a byte string
      key_bytes = key.scan(/../).map { |x| x.hex.chr }.join
      cipher.key = key_bytes
      ciphertext = cipher.update(plaintext) + cipher.final
      base64 = Base64.strict_encode64(ciphertext)
      

      这会在命令行上返回与 OpenSSL 相同的值:

      ryW2
      

      解密相当简单:

      decipher = OpenSSL::Cipher.new('rc4')
      decipher.decrypt
      decipher.key = key_bytes
      decrypted = decipher.update(ciphertext) + decipher.final
      

      这将返回原始明文:

      foo
      

      最终,只要您知道EVP_BytesToKey 将为给定的pass 返回什么内容,加密和解密就相当简单。您可以在此处阅读有关EVP_BytesToKey 的更多信息:

      【讨论】:

      • 谢谢 实际上它有效,我对 key_bytes 的一部分感到困惑
      【解决方案3】:

      我很不高兴在 Ruby 中没有内置的方法来做到这一点。 My other answer 这个问题是一个功能性的解决方法,但它需要一些我不喜欢的耗时步骤。所以我写了一个名为 evp_bytes_to_key 的 gem,它会为你做的!

      首先安装gem:

      gem install evp_bytes_to_key
      

      然后生成你的密文:

      echo -n "foo" | openssl enc -e -base64 -rc4 -nosalt -pass pass:secretkey
      

      这会返回:

      ryW2
      

      然后用 Ruby 解密:

      require 'evp_bytes_to_key'
      require 'openssl'
      require 'base64'
      
      decipher = OpenSSL::Cipher.new('rc4')
      decipher.decrypt
      decipher.key = EvpBytesToKey::Key.new('secretkey', nil, 128, 0).key
      ciphertext = Base64.strict_decode64('ryW2')
      plaintext = decipher.update(ciphertext) + decipher.final
      

      这将返回原始明文:

      foo
      

      更多使用这个 gem 的例子可以在README找到。

      【讨论】:

        猜你喜欢
        • 2015-11-27
        • 2016-04-22
        • 2012-07-31
        • 2017-10-23
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多