Ruby:使用私钥/公钥进行文件加密/解密

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/9891708/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-03 03:07:43  来源:igfitidea点击:

Ruby: file encryption/decryption with private/public keys

ruby-on-railsrubyencryptionpublic-key-encryptionencryption-asymmetric

提问by tiktak

I am searching for an algorithm for file encryption/decryption which satisfies the following requirements:

我正在寻找一种满足以下要求的文件加密/解密算法:

  • Algorithm must be reliable
  • Algorithm should be fast for rather big files
  • Private key can be generated by some parameter (for example, password)
  • Generated private key must be compatible with public key (public key is generated only once and stored in database)
  • 算法必须可靠
  • 对于相当大的文件,算法应该很快
  • 私钥可以通过一些参数(例如密码)生成
  • 生成的私钥必须与公钥兼容(公钥只生成一次并存储在数据库中)

Is there any Ruby implementation of suggested algorithms?

是否有建议算法的 Ruby 实现?

回答by brice

Note Well:As emboss mentions in the comments, this answer is a poor fit for an actual system. Firstly, file encryption should not be carried out using this method (The lib provides AES, for example.). Secondly, this answer does not address any of the wider issues that will also affect how you engineer your solution.

The original source also goes into more details.

注意:正如 emboss 在评论中提到的,这个答案不适合实际系统。首先,不应该使用这种方法进行文件加密(例如,lib 提供了 AES。)。其次,这个答案没有解决任何更广泛的问题,这些问题也会影响您设计解决方案的方式。

原始来源也有更多细节

Ruby can use openssl to do this:

Ruby 可以使用 openssl 来做到这一点:

#!/usr/bin/env ruby

# ENCRYPT

require 'openssl'
require 'base64'

public_key_file = 'public.pem';
string = 'Hello World!';

public_key = OpenSSL::PKey::RSA.new(File.read(public_key_file))
encrypted_string = Base64.encode64(public_key.public_encrypt(string))

And decrypt:

并解密:

#!/usr/bin/env ruby

# DECRYPT

require 'openssl'
require 'base64'

private_key_file = 'private.pem';
password = 'boost facile'

encrypted_string = %Q{
...
}

private_key = OpenSSL::PKey::RSA.new(File.read(private_key_file),password)
string = private_key.private_decrypt(Base64.decode64(encrypted_string))

from here

这里

回答by emboss

I'm afraid you are mixing two concepts here, authentication/authorization and confidentiality, trying to cover both aspects in one single step, and that won't work. You should never encrypt "real data" with asymmetric algorithms. a) they are way too slow for that, b) there are subtle issues that, if not done right, will severely weaken the security of your solution.

恐怕您在这里混淆了两个概念,身份验证/授权和机密性,试图在一个步骤中涵盖这两个方面,这是行不通的。您永远不应该使用非对称算法加密“真实数据”。a) 他们为此太慢了,b) 有一些微妙的问题,如果处理不当,将严重削弱您的解决方案的安全性。

A good rule of thumb is that the only thing you should end up encrypting with private asymmetrickeys is symmetrickeys used by a much faster symmetric algorithm. But in almost all cases you shouldn't even be doing that, because in 90% of the cases what you actually want is TLS (SSL) in those cases - I tried to explain why herea while ago.

一个好的经验法则是,您最终应该使用私有对称密钥加密的唯一东西是由更快的对称算法使用的对称密钥。但在几乎所有情况下,您甚至都不应该这样做,因为在 90% 的情况下,您真正​​想要的是 TLS (SSL) - 我前段时间试图在这里解释原因。

In your case, I assume the requirements are:

在您的情况下,我假设要求是:

  • confidentiality of the data that is to be stored in the database: the general public shouldn't be able to read it (or even access it)

  • a selected few (probably just one person) should be able to access and read that data

  • 要存储在数据库中的数据的机密性:一般公众不应该能够读取(甚至访问它)

  • 选定的少数人(可能只有一个人)应该能够访问和读取该数据

The first goal is generally achieved by using symmetric encryption. The second goal is, albeit related, realized by quite different means. You want the user accessing the file to be authenticated (i.e. establish the identity) and on top of that you also want them to be authorized (i.e. check whether the established identity has the right to do what they intend to). This is where asymmetric cryptography mayenter the stage, but not necessarily. Since your question is tagged with Rails I assume we are talking about a Rails application. You typically already have some means to authenticate and authorize users there (most likely involving the afore-mentioned TLS), you may simply reuse them in order to establish a symmetric key for actual file encryption/decryption. Password-based encryptionwould fit for this purpose, if you want to avoid asymmetric crypto at all. Things get even more complicated if you also want to ensure integrity of the already confidential data, that is, you want to give a kind of guarantee to the authenticated and authorized user in the sense that what they finally access has not been altered in any way in the meantime.

第一个目标通常是通过使用对称加密来实现的。第二个目标虽然相关,但通过完全不同的方式实现。您希望对访问文件的用户进行身份验证(即建立身份),最重要的是您还希望他们获得授权(即检查建立的身份是否有权做他们打算做的事情)。这是非对称密码学可能进入舞台的地方,但不一定。由于您的问题是用 Rails 标记的,因此我假设我们正在讨论 Rails 应用程序。您通常已经有一些方法可以在那里对用户进行身份验证和授权(很可能涉及上述 TLS),您可以简单地重用它们以建立用于实际文件加密/解密的对称密钥。如果您想完全避免非对称加密,则基于密码的加密将适合此目的。如果您还想确保已经保密的数据的完整性,事情会变得更加复杂,也就是说,您想向经过身份验证和授权的用户提供某种保证,即他们最终访问的内容没有以任何方式被更改同时。

Developing a solution for this will be no trivial task and depend to a large extent on your given requirements, so I'm afraid there's no "golden way" that suits everyone. I would suggest to do some research, get a clearer picture of what you are trying to achieve and how, then try to get additional advice on subjects that you still feel uncertain/uncomfortable with.

为此开发解决方案绝非易事,并且在很大程度上取决于您给定的要求,因此恐怕没有适合所有人的“黄金方式”。我建议做一些研究,更清楚地了解您要实现的目标以及如何实现,然后尝试就您仍然感到不确定/不舒服的主题获得更多建议。

回答by Reid

Symmetric Encryptionis definitely fast and has excellent support for streaming of very large files.

对称加密绝对是快速的,并且对非常大的文件流具有出色的支持。

SymmetricEncryption::Writer.open('my_file.enc') do |file|
  file.write "Hello World\n"
  file.write "Keep this secret"
end

Symmetric Encryption is designed for encrypting data and large files within an organization.

对称加密旨在加密组织内的数据和大文件。

When it comes to sharing files with other organizations then the best option is PGP. For streaming of very large files with PGP consider: IOStreams

在与其他组织共享文件时,最好的选择是 PGP。对于使用 PGP 流式传输非常大的文件,请考虑:IOStreams

IOStreams.writer('hello.pgp', recipient: '[email protected]') do |writer|
  writer.write('Hello World')
  writer.write('and some more')
end

Look at the file iostreams/lib/io_streams/pgp.rb for more PGP examples. It also supports PGP key management directly from Ruby.

查看文件 iostreams/lib/io_streams/pgp.rb 以获取更多 PGP 示例。它还支持直接从 Ruby 进行 PGP 密钥管理。

回答by user6713635

I made a gem to help with this. It's called cryptosystem. Simply configure the path and password to your private key as well as the path to your public key, and it does the rest.

我做了一个宝石来帮助解决这个问题。它被称为cryptosystem。只需配置私钥的路径和密码以及公钥的路径,剩下的就交给它了。

Encrypting is as simple as:

加密很简单:

rsa = Cryptosystem::RSA.new
rsa.encrypt('secret') # => "JxpuhTpEqRtMLmaSfaq/X6XONkBnMe..."

And decrypting:

并解密:

encrypted_value = rsa.encrypt('secret') # => "Y8DWJc2/+7TIxdLEolV99XI2sclHuK..."
rsa.decrypt(encrypted_value) # => "secret"

You can check it out on GitHubor RubyGems.

您可以在GitHubRubyGems上查看。