强力保险箱(Strongbox)
Strongbox是一款为ActiveRecord提供公钥加密的开源工具。利用公钥加密,敏感信息可以被安全存储,只有在输入正确的密码时才能解密取出。默认情况下,Strongbox采用两层加密策略,首先使用对称加密方式,以随机生成的密钥和初始化向量(IV)加密数据,然后再使用公钥加密这些信息。
数据库中,被加密的属性以相同的名字存储,例如,如果你告诉Strongbox要加密“secret”,那么它将在数据库中的secret
列中存储加密后的信息。如果采用了对称加密(默认),还需要额外的secret_key
和secret_iv
列来保存相关数据。
设置属性值就像平常一样:
user.secret = "Shhhhhhh..."
而解密时需要输入私钥密码:
plain_text = user.secret.decrypt 'letmein'
环境
Strongbox已在Rails 2.3和3.x环境下,与Ruby 1.8.7, 1.9.2以及1.9.3版本进行了测试。
安装
将以下代码添加到你的Gemfile中:
gem "strongbox"
如果你还在使用Rails 2.x且没有Gemfile,可以在config/environment.rb
文件中加入以下代码:
config.gem "strongbox"
快速启动
在模型中:
class User < ActiveRecord::Base
encrypt_with_public_key :secret,
:key_pair => Rails.root.join('config','keypair.pem')
end
在迁移文件中:
class AddSecretColumnsToUser < ActiveRecord::Migration
def change
add_column :users, :secret, :binary
add_column :users, :secret_key, :binary
add_column :users, :secret_iv, :binary
end
end
生成密钥对:
(选择一个强大的密码。)
openssl genrsa -des3 -out config/private.pem 2048
openssl rsa -in config/private.pem -out config/public.pem -outform PEM -pubout
cat config/private.pem config/public.pem >> config/keypair.pem
在视图和表单中,不需要进行特殊操作即可加密数据。要解密,只需调用:
user.secret.decrypt 'password'
使用
encrypt_with_public_key
方法用于设置自动加密的属性。其最简单的形式是:
class User < ActiveRecord::Base
encrypt_with_public_key :secret,
:key_pair => Rails.root.join('config','keypair.pem')
end
这会加密名为secret
的属性。属性会被使用对称加密方式加密,使用自动生成的密钥和IV,并用公钥加密。这需要三个数据库列(见下文)。选项包括:
:public_key
- 公钥。优先于:key_pair
。参考密钥格式部分。:private_key
- 私钥。优先于:key_pair
。:key_pair
- 密钥对,包含公钥和私钥。:symmetric
- 对数据进行对称加密。可以选择:always
或:never
。默认为:always
。:symmetric_cipher
- 对称加密算法。默认为aes-256-cbc
。其他支持OpenSSL的算法也可以使用。:base64
- 是否使用Base64编码将加密数据转换为文本。当无法存储二进制数据时使用。默认为false
。:padding
- 用于填充由公钥加密的数据的方法。默认为RSA_PKCS1_PADDING
。默认应该足够,除非处理的是遗留数据。:ensure_required_columns
- 确保所需的数据库列存在。默认为true
,设为false
则可以加密存储在数据库之外的数据。:deferred_encryption
- 延迟加密,直到对象保存之前进行,而不是在设置了加密属性之后。默认为false
。
例如,加密一个较短的属性,只提供公钥以增加安全性,且使用Base64编码加密数据:
class User < ActiveRecord::Base
validates_length_of :pin_code, :is => 4
encrypt_with_public_key :pin_code,
:symmetric => :never,
:base64 => true,
:public_key => Rails.root.join('config','public.pem')
end
Strongbox可以加密多个属性。encrypt_with_public_key
接受一个属性列表,假设它们将使用相同的选项:
class User < ActiveRecord::Base
encrypt_with_public_key :secret, :double_secret,
:key_pair => Rails.root.join('config','keypair.pem')
end
如果你需要不同的选项,对每个属性分别调用encrypt_with_public_key
:
class User < ActiveRecord::Base
encrypt_with_public_key :secret,
:key_pair => Rails.root.join('config','keypair.pem')
encrypt_with_public_key :double_secret,
:key_pair => Rails.root.join('config','another_key.pem')
end
密钥格式
:public_key
,:private_key
和:key_pair
可以是以下任一格式:
- 包含文件路径的字符串。这是字符串的默认解释。
- 匹配正则表达式
/-+BEGIN .* KEY-+$
的PEM格式的字符串。 - 标识调用方法的符号。返回任何其他有效密钥格式的结果。
- 已解锁的
OpenSSL::PKey::RSA
实例。作为私钥使用时需处于解锁状态。
密钥生成
在命令行
生成密钥对:
openssl genrsa -des3 -out config/private.pem 2048
Generating RSA private key, 2048 bit long modulus
......+++
.+++
e is 65537 (0x10001)
Enter pass phrase for config/private.pem:
Verifying - Enter pass phrase for config/private.pem:
并提取公钥:
openssl rsa -in config/private.pem -out config/public.pem -outform PEM -pubout
Enter pass phrase for config/private.pem:
writing RSA key
如果计划将私钥安装在本地,最简单的方式是创建一个单一的密钥对文件:
cat config/private.pem config/public.pem >> config/keypair.pem
或者,为了增加安全性,可以将私钥文件存放在其他地方,仅保留公钥。
在代码中
require 'openssl'
rsa_key = OpenSSL::PKey::RSA.new(2048)
cipher = OpenSSL::Cipher.new('des3')
private_key = rsa_key.to_pem(cipher,'password')
public_key = rsa_key.public_key.to_pem
key_pair = private_key + public_key
private_key
,public_key
和 key_pair
是字符串,按需存储。
表格创建
在默认配置下,Strongbox需要三列,一列存储加密数据,一列存储加密的对称密钥,还有一列存储加密的对称IV。如果不启用对称加密,则只需要存储数据的列。
如果底层数据库允许,使用binary类型的列。如果必须以文本格式存储数据,请确保启用Base64编码,并使用text类型的列。如果使用string类型的列并且加密超过186字节(如果未启用Base64编码则是245字节)的数据,数据将会丢失。
Nil和Blank属性
默认情况下,设置为nil的属性将保持加密状态,以保护所有关于该属性的信息。然而,可以通过显式设置将其恢复为真实的nil:
# 外部模型
@object[:secret] = nil # 或 ''
# 内部模型
self[:secret] = '' # 或 nil
将来会有一个设置,允许默认情况下接受nil和空属性。
安全注意事项
如果不加密数据,攻击者只需窃取数据就可以得到你的秘密。
如果使用对称加密和存储的密钥,攻击者需要数据和服务器上存储的密钥。
如果使用公钥加密,攻击者需要数据,私钥和密码。这意味着攻击者必须以某种方式捕获密码,因此这就是你需要防范的。
作者
Spike Ilacqua
感谢
Strongbox的实现受到了Thoughtbot的Paperclip gem的启发。
感谢所有做出贡献的人!
使用这个强大的开源项目,你可以更好地保护你的应用程序中的敏感数据,实现更高级别的安全性和隐私性。无论是小型还是大型应用,Strongbox都能轻松集成,让加密变得更加简便。现在就开始使用,让你的项目更加安全吧!