Transit
Transit 机密引擎对数据进行加密并不会持久化保存(所以它们被称为传输中的数据)。Vault 不会存储引擎接收到的数据。它也可以被视为“加密即服务”。Transit 机密引擎还可以对数据进行签名和验证;生成数据的散列和 HMAC;并充当随机数据的来源。
transit
主要用途是帮助加密应用程序发来的数据,然后应用程序在其主要数据存储中保存经过加密的数据。该机密引擎将正确加解密数据的重担从应用程序的开发者身上转移到了 Vault 的管理员这里。
该引擎支持派生密钥,这允许通过基于用户提供的上下文值派生新密钥来将相同的密钥用于多种目的。在这种模式下,可以选择支持收敛加密,它允许相同的输入值产生相同的密文。
生成数据密钥功能允许应用程序请求将给定位长度的高熵密钥返回给它们,并使用命名密钥进行加密。通常也可以以明文形式返回密钥使得请求方可以立即使用,但可以禁用此功能以适应审计要求。
工作集合(Working Set)管理
Transit 机密引擎支持密钥的版本化管理。早于 min_decryption_version
参数限制的老版本密钥将被归档,其余版本的密钥则属于工作集合。这是出于保持密钥快速加载的性能考虑,也是安全考虑:通过禁止解密旧版本的密钥,可以通过由于无法被大多数用户解密来发现哪些数据对应的密钥已经过期,但在紧急情况下 min_decryption_version
可以回拨以允许合法解密。
目前,这些被归档的老密钥被存储在单个存储条目中。对于一些存储后端,尤其是那些使用 Raft 或 Paxos 来实现高可用功能的后端,频繁轮换密钥可能会导致归档的存储条目大小大于存储后端可以处理的大小。对于频繁的轮换需求,使用与时间限制相对应的命名键(例如,五分钟为一个周期,计算出处于哪个周期数)可能会提供一个很好的选择,允许同时使用多个密钥以及什么时候使用哪个密钥。
NIST(美国国家标准技术研究所) 密钥轮换指引
推荐定期轮换加密密钥。如果使用的是 AES-GCM 密钥,每个密钥在执行了大约 232 次加密前需要根据 NIST 出版物 800-38D 进行轮换。建议管理员评估密钥的加密频率,并根据该频率来确定一个可以防止达到指导限制的轮换频率。例如,如果评估的速率是每天 4000 万次操作,那么每三个月轮换一次密钥就足够了。
密钥类型
目前 Transit 机密引擎支持以下密钥类型(所有这些密钥类型都支持生成独立的 HMAC 密钥):
aes128-gcm96
: 使用 128 位 AES 密钥以及 96 位随机数的 AES-GCM;支持加密、解密、密钥派生以及收敛加密aes256-gcm96
: 具有 256 位 AES 密钥和 96 位随机数的 AES-GCM;支持加密、解密、密钥派生和收敛加密(默认)chacha20-poly1305
: 具有 256 位密钥的 ChaCha20-Poly1305;支持加密、解密、密钥派生和收敛加密ed25519
: Ed25519;支持签名、签名验证和密钥派生ecdsa-p256
: 使用 P-256 椭圆曲线的ECDSA;支持签名和签名验证ecdsa-p384
: 使用 P-384 椭圆曲线的ECDSA;支持签名和签名验证ecdsa-p521
: 使用 P-521 椭圆曲线的ECDSA;支持签名和签名验证rsa-2048
: 2048 位 RSA 密钥;支持加密、解密、签名和签名验证rsa-3072
: 3072 位 RSA 密钥;支持加密、解密、签名和签名验证rsa-4096
: 4096 位 RSA 密钥;支持加密、解密、签名和签名验证
收敛加密
收敛加密是一种相同的明文+上下文集合总是产生相同密文的模式。它通过使用密钥派生函数派生密钥以及确定性地派生随机数来做到这一点。因为在 2256 大小的密钥空间上,明文和密文的任何组合的这些属性都不同,所以随机数重用的风险接近于零。
该功能有很多实际用途。一种常见的使用模式是允许将值加密存储在数据库中,同时提供了有限的查找和查询的支持,以便可以从查询中返回特定字段为特定值的行。
为了适应任何对算法升级的需求,历史上存在过不同版本的收敛加密:
- Version 1 要求客户提供他们自己的随机数,使用起来非常灵活,但如果做得不正确可能会很危险。这仅在 Vault 0.6.1 中存在,使用此版本的密钥无法升级。
- Version 2 使用算法来派生参数。但是,所使用的算法容易受到离线已知明文攻击,如果明文太短,攻击者可能会暴力破解。使用 Version 2 的密钥可以通过简单地执行轮换操作升级到新的密钥版本;然后可以根据新的密钥版本使用 Version 3 算法重新加密现有值。
- Version 3 使用了专门用以抵御离线已知明文攻击的不同算法。该算法类似于 AES-SIV ,使用一个 PRF 以从明文中生成随机数。
配置
大部分机密引擎在工作之前必须要先进行配置。这些步骤通常是由系统管理员或是配置管理工具来完成。
- 启用 Transit 机密引擎
$ vault secrets enable transit
Success! Enabled the transit secrets engine at: transit/
默认情况下,机密引擎会挂载到名字对应的路径上。要在不同路径上启用机密引擎,请使用 -path
参数。
- 创建一个命名的加密密钥:
$ vault write -f transit/keys/my-key
Success! Data written to: transit/keys/my-key
一般来说每个应用程序都有其自己的加密密钥。
用法
配置了机密引擎后,一个拥有搭配了合适权限的 Vault 令牌的用户或是机器使用该机密引擎。
- 使用
/encrypt
端点搭配一个命名密钥加密一段明文数据:
注意:所有明文必须进行 base64 编码,这是因为 Vault 并不要求明文数据必须是文本,它也可以是一个二进制文件,例如一个 PDF 或是图片。把这种数据作为 JSON 载荷的一部分的最简单的安全传输机制是对其进行 base64 编码。
$ vault write transit/encrypt/my-key plaintext=$(base64 <<< "my secret data")
Key Value
--- -----
ciphertext vault:v1:8SDd3WHDOjf7mq69CyCqYjBXAiQQAVZRkFM13ok481zoCmHnSeDX9vyf7w==
返回的密文以 vault:v1
开头。前缀 vault
表示该密文由 Vault 加密。v1
表示使用的是密钥的 version 1 进行加密的,这样当我们要轮换密钥时,Vault 就知道使用哪个版本的密钥来解密。剩下的部分就是初始化向量(IV)以及密文的 base64 编码的拼接值。
要注意 Vault 不会存储这些数据。调用者有责任存储加密的密文。如果调用者希望获得明文,必须将密文传回 Vault 进行解密。
要注意 Vault HTTP API 限制请求最大的尺寸为 32MB 来防范拒绝服务攻击。我们可以通过调整 Vault 配置中的 listener
块来修改该限制。
- 使用
/decrypt
端点搭配一个命名密钥解密这段密文:
$ vault write transit/decrypt/my-key ciphertext=vault:v1:8SDd3WHDOjf7mq69CyCqYjBXAiQQAVZRkFM13ok481zoCmHnSeDX9vyf7w==
Key Value
--- -----
plaintext bXkgc2VjcmV0IGRhdGEK
返回结果也是经过 base64 编码的(原因前文已述)。将其解码为文本:
$ base64 --decode <<< "bXkgc2VjcmV0IGRhdGEK"
my secret data
通过使用 ACL,可以限制使用 Transit 机密引擎,以便受信任的管理员可以管理命名密钥,并且应用程序只能使用他们需要访问的命名密钥进行加密或解密。
- 轮换使用的密钥。这将生成一个新密钥并将其添加至命名密钥的密钥环中:
$ vault write -f transit/keys/my-key/rotate
Success! Data written to: transit/keys/my-key/rotate
- 使用新密钥更新已经加密的密文。Vault 会使用密钥环中对应的密钥解密密文,再使用密钥环中最新的密钥重新加密:
$ vault write transit/rewrap/my-key ciphertext=vault:v1:8SDd3WHDOjf7mq69CyCqYjBXAiQQAVZRkFM13ok481zoCmHnSeDX9vyf7w==
Key Value
--- -----
ciphertext vault:v2:0VHTTBb2EyyNYHsa3XiXsvXOQSLKulH+NqS4eRZdtc2TwQCxqJ7PUipvqQ==
该过程不会暴露明文数据。因此,Vault 策略可以授予几乎不受信任的进程“重新加密”密文数据的权限,因为该过程中无法访问明文数据。