【问题标题】:Encrypt file with Ruby OpenSSL and decrypt with command line使用 Ruby OpenSSL 加密文件并使用命令行解密
【发布时间】:2015-11-27 13:36:24
【问题描述】:

我正在使用 Ruby 自动执行 OpenSSL 文件加密过程。以这种方式加密的文件需要能够在 linux 命令行上使用 OpenSSL 进行解密。

我可以使用以下 Ruby 方法加密文件:

  def encrypt_file
    cipher = OpenSSL::Cipher.new('aes-256-cbc')
    cipher.encrypt
    cipher.key = "somelongkeystring"

    buf = ""
    File.open("file.enc", "wb") do |outf|
      File.open("file.zip", "rb") do |inf|

        while inf.read(4096, buf)
          outf << cipher.update(buf)
        end
        outf << cipher.final
      end
    end
  end

我需要能够使用以下命令解密文件 (file.enc):

$ openssl aes-256-cbc -d -in file.enc -out file.zip

但是,当我运行它时,在我从上方键入密钥后,bad magic number 出现错误。

由于我无法更改解密方法(这意味着它仅使用密码并在 linux 命令行上输入)我如何更改我的 Ruby 方法来加密文件以便可以通过这种方式解密?

【问题讨论】:

  • @MarcoSandrini 我的问题与那个问题相似。但是,给出的解决方案是更改我说我不能做的 openssl 命令。我只能修改Ruby方法。
  • 然后您应该更改您的代码,以便它使用与命令行版本的 openssl 用于从密码短语派生密钥和 IV 相同的派生算法。但是引用问题security.stackexchange.com/questions/29106/…的答案“使用带有一些重复散列的自定义密钥派生函数。这是一个非标准且未经严格审查的构造(!),它依赖于可疑声誉的MD5散列函数(!!) ;"
  • 鉴于我之前评论中引用的答案中的信息,我将开始考虑替代路线,例如将对 openssl 命令行工具的调用包装到 system/exec/spawn 调用中
  • @MarcoSandrini 从系统或 exec 或 open3 调用 openssl 仅接受来自键盘或 tty 的输入。它不接受标准输入来提供密钥。

标签: ruby openssl


【解决方案1】:

借助 stackoverflow 中类似问题的帮助,我能够在 ruby​​ 中实现它。

首先你必须在你的密码对象中添加一个iv 东西,像这样

cipher = OpenSSL::Cipher.new('aes-256-cbc')
cipher.encrypt
cipher.iv = "0"*16
cipher.key = "somelongkeystring"

解密时你必须传递-K-iv

openssl aes-256-cbc -d -in file.enc -out file.zip -K <key_hex_code> -iv <iv_hex_code>

你可以像"string".unpack('H*')这样在ruby中生成hex代码。也必须有某种方法可以在 cli 中生成十六进制代码。

【讨论】:

    【解决方案2】:

    基于 Sumit 回答的解决方案:

    require 'openssl'
    
    class Crypto
      def initialize(key, iv, data, cipher='aes-256-cbc')
        @key = key 
        @iv = iv
        @cipher = cipher
        @data = data
      end 
    
      def encrypt
        c = OpenSSL::Cipher.new(@cipher).encrypt
        c.iv = @iv 
        c.key = @key
        c.update(@data) + c.final    
      end 
    
      def decrypt
        c = OpenSSL::Cipher.new(@cipher).decrypt
        c.iv = @iv 
        c.key = @key
        c.update(@data) + c.final    
      end 
    end
    
    iv = '0'*16
    key = '1'*32
    message = 'My Message' 
    encrypted = Crypto.new(key,iv,message).encrypt
    puts Crypto.new(key,iv,encrypted).decrypt
    puts `echo -n '#{encrypted}' | openssl aes-256-cbc -d -K #{key.unpack('H*').first} -iv #{iv.unpack('H*').first}`
    # My Message
    # My Message
    

    此解决方案适用于字符串,可以轻松适应文件。

    【讨论】:

      【解决方案3】:

      虽然没有使用 Ruby OpenSSL 实现(我更喜欢),但我还是让它工作了。如果你使用 -k 标志,你可以指定一个密码作为下一个参数,那么你不需要传递任何东西并且可以使用 system 来调用它。

        system("openssl aes-256-cbc -k '#{key}' -in file.zip -out file.enc")
      

      如果有人有使用 Ruby OpenSSL 实现的方法,我将不胜感激。

      【讨论】:

        猜你喜欢
        • 2012-07-31
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2016-09-25
        • 2016-04-22
        • 1970-01-01
        相关资源
        最近更新 更多