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

Posted

技术标签:

【中文标题】Ruby:使用私钥/公钥进行文件加密/解密【英文标题】:Ruby: file encryption/decryption with private/public keys 【发布时间】:2012-04-11 02:41:59 【问题描述】:

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

算法必须可靠 算法对于相当大的文件应该很快 可以通过某些参数(例如密码)生成私钥 生成的私钥必须与公钥兼容(公钥只生成一次并存储在数据库中)

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

【问题讨论】:

【参考方案1】:

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

原始来源也进入more details。

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))

然后解密:

#!/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))

来自here

【讨论】:

我实际上不是 Rubyist,但这些都是相当不错的电池。我想知道在 python 中等价物有多难...... 只是想补充一点,文件应该用例如AES-256加密,但它的密钥应该用rsa发送。 很抱歉,这确实是个糟糕的建议。 OP 谈论文件加密/解密,你不应该使用 RSA。 @emboss:见 tiktak 之前的评论。你是绝对正确的——在想回答这个问题时,我并没有真正停下来考虑更广泛的问题。我会尝试修改我的帖子以显示这一点。 @brice:太好了!没有伤害,只是不想让人们被误导:)【参考方案2】:

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

一个好的经验法则是,您最终应该使用私有 非对称 密钥进行加密的是更快的对称算法使用的 对称 密钥。但在几乎所有情况下,您甚至都不应该这样做,因为在 90% 的情况下,您真正​​想要的是 TLS (SSL) - 我刚才试图解释为什么here。

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

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

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

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

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

【讨论】:

感谢您的回答!我通过以下方式传输和存储数据解决了这个问题:1)生成对称加密密钥(sym-key)2)用sym-key加密文件3)用公共asym-key加密sym-key 4)发送文件并加密sym-key 5) 用用户的秘密令牌解密用户私有加密的 asym-key 6) 用私有 asym-key 解密收到的 sym-key 7) 用解密的 sym-key 解密文件。觉得挺正常的。 这是正确的方向!但它仍然容易受到重放攻击。您不能使用 TLS 代替发送由非对称密钥包装的密钥吗?我发现在几乎所有将数据从 A 传输到 B 的情况下,您都应该使用 TLS 而不是非对称加密 - TLS 可以保护您免受最有可能破坏自定义协议的事情的影响。【参考方案3】:

Symmetric Encryption 速度肯定很快,并且对超大文件的流式传输具有出色的支持。

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

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

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

IOStreams.writer('hello.pgp', recipient: 'receiver@example.org') do |writer|
  writer.write('Hello World')
  writer.write('and some more')
end

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

【讨论】:

【参考方案4】:

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

加密很简单:

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

和解密:

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

您可以在GitHub 或RubyGems 上查看。

【讨论】:

以上是关于Ruby:使用私钥/公钥进行文件加密/解密的主要内容,如果未能解决你的问题,请参考以下文章

openssl rsa 可以用私钥加密 公钥解密吗

java中RSA用私钥加密公钥解密问题

怎么在ios进行rsa公钥加密,java做rsa私钥解密

java rsa私钥加密

RSA 加密解密

什么是公钥和私钥?