使用Ruby OpenSSL加密文件并使用命令行解密

使用Ruby OpenSSL加密文件并使用命令行解密,ruby,openssl,Ruby,Openssl,我正在使用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

我正在使用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
但是,当我运行此命令时,在我从上面键入密钥后,我会收到一个错误,原因是
坏幻数


既然我不能更改解密方法(这意味着它只使用一个密码,并且是在linux命令行上输入的),那么如何更改我的Ruby方法来加密文件,以便以这种方式对其进行解密呢

虽然没有使用Ruby OpenSSL实现(我更喜欢),但我还是做到了这一点。如果您使用-k标志,您可以指定密码作为下一个参数,那么您不需要传递任何东西,可以使用系统调用它

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

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

借助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>
openssl aes-256-cbc-d-in file.enc-out file.zip-K-iv

您可以在ruby中生成如下
hex
代码
“string.unpack('H*')
。还必须有某种方法在cli中生成十六进制代码

基于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

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

可能重复@MarcoSandrini我的问题与该问题类似。然而,给出的解决方案是更改openssl命令,我声明我不能这样做。我只能修改Ruby方法,然后您应该更改代码,使其使用openssl命令行版本用于从密码短语派生key和IV的相同派生算法。但引用问题的答案“使用自定义密钥派生函数和一些重复的散列。这是一个非标准且未经充分审查的构造(!),它依赖于信誉可疑的MD5散列函数(!!);”鉴于我在前面的评论中引用的答案中的信息,我会开始考虑替代路由,类似于将对openssl命令行工具的调用包装到system/exec/spawn中call@MarcoSandrini从system或exec或open3调用openssl只接受键盘或tty的输入。它不接受stdin提供密钥。
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