Как шифровать файлы с помощью Ruby?

Мне нужно написать простой инструмент, который шифрует/расшифровывает файлы.

Я думаю, лучший способ - использовать OpenSSL:

Сгенерируйте ключ:

openssl rand -base64 2048 > secret_key

Зашифровать файл:

openssl aes-256-cbc -a -e -in file -out file.enc -k secret_key

Расшифровать файл:

openssl aes-256-cbc -d -in file.enc -out file -k secret_key

Есть ли простой способ реализовать это в Ruby? Есть ли лучший способ сделать это? Использование PGP возможно?

Ответ 1

Ruby OpenSSL - это тонкая оболочка вокруг самого OpenSSL и обеспечивает почти все функции, которые сама OpenSSL делает, так что да, есть однозначное сопоставление для всех ваших примеров:

openssl rand -base64 2048 > secret_key

На самом деле вы преувеличиваете, вы используете AES-256, поэтому вам нужен только 256-битный ключ, здесь вы не используете RSA. Ruby OpenSSL принимает это решение с ваших плеч, он автоматически определит правильный размер ключа с учетом алгоритма, который вы хотите использовать.

Вы также совершаете ошибку при использовании детерминированного IV во время вашего шифрования. Зачем? Поскольку вы вообще не указываете IV, OpenSSL сам по умолчанию будет равен нулю всех нулевых байтов. Это не очень хорошо, поэтому я покажу вам правильный способ сделать это, для получения дополнительной информации см. Документацию Cipher.

require 'openssl'

# encryption
cipher = OpenSSL::Cipher.new('aes-256-cbc')
cipher.encrypt
key = cipher.random_key
iv = cipher.random_iv

buf = ""
File.open("file.enc", "wb") do |outf|
  File.open("file", "rb") do |inf|
    while inf.read(4096, buf)
      outf << cipher.update(buf)
    end
    outf << cipher.final
  end
end

# decryption
cipher = OpenSSL::Cipher.new('aes-256-cbc')
cipher.decrypt
cipher.key = key
cipher.iv = iv # key and iv are the ones from above

buf = ""
File.open("file.dec", "wb") do |outf|
  File.open("file.enc", "rb") do |inf|
    while inf.read(4096, buf)
      outf << cipher.update(buf)
    end
    outf << cipher.final
  end
end

Как вы можете видеть, шифрование и дешифрование довольно схожи, поэтому вы можете объединить потоковое чтение/запись в один общий метод и просто передать ему правильно настроенный Cipher плюс соответствующие имена файлов, я просто указал их явно для ясности.

Если вы хотите кодировать ключ Base64 (и, вероятно, IV), вы можете использовать модуль Base64:

base64_key = Base64.encode64(key)

Ответ 2

Ruby имеет библиотеку OpenSSL, которая должна заботиться о тяжелом подъеме.