有人看到我的钥匙吗?一种机架级安全的密钥分层策略
Has anybody seen my keys? A key-hierarchy strategy for rack-level security

原始链接: https://rfd.shared.oxide.computer/rfd/0301

该系统使用从 $K$ 个密钥份额派生出的机架密钥来管理集群安全。为了平衡安全性和可用性,该设计同时采用了**密钥派生**(旨在提高效率且无需存储)和**密钥封装**(旨在允许在不重新加密大型数据集的情况下进行密钥轮换)。 核心安全目标是在信任仲裁重新配置期间轮换机架密钥,以限制潜在损害的影响。然而,这带来了一个技术挑战:当在不同机架密钥之间转换时,即使在配置可能不会立即提交的分布式环境中,节点(sleds)也必须能够重新封装特定于驱动器的加密密钥。 该解决方案在两阶段提交协议中采用了一种“分发者”(dealer)机制。当准备新纪元(epoch)时,分发者会提供新机架密钥以及由新密钥派生出的加密旧机架密钥。一旦新纪元提交,节点即可使用新密钥解密旧密钥,从而能够派生出新旧驱动器密钥。这不仅实现了 ZFS 加密密钥的无缝、安全轮换,确保了前向安全性,而且在面对分布式系统故障时依然保持稳健。

抱歉。
相关文章

原文

Assuming a static cluster, we now have a rack secret that can be computed from K key shares and used to derive child keys. In the following example, K = 2, just so we can keep the diagrams small.

The rack secret protects every key in the system that is used after rack unlock. There are two mechanisms to get the next keys in the hierachy:

Key Derivation we already use to derive any primary child keys from the rack secret. But it can also be used to derive keys from keys. Key wrapping is just taking a key and encrypting it. Each has their benefits and drawbacks.

Key derivation is nice because you never have to store the derived keys on disk. You can just regenerate them. The problem with it is that if the derived key changes any downstream derived keys will now change also change.

Key wrapping is nice because if the wrapper key is rotated, the downstream keys do not have to change. This is particularly useful for encrypting large amounts of data on storage. You don’t want to be forced to decrypt and then re-encrypt just because a parent key was rotated. The downside of key wrapping is that you now have to store the wrapped (encrypted) key on disk somewhere. If the same key is used in multiple places you have to replicate it.

For trust quorum, we have the particular problem that when nodes are added or removed we generate new shares. While it’s possible to maintain the same rack secret and key derivation with new shares, it is less secure over time because any single malicious node who retrieved the rack secret at one time and saved it can now recover any data on any existing drives or any data produced in the future. While this is always an issue, we prefer to allow the rotation of the rack secret in the case of a known compromise. We therefore always generate a new rack secret on every change of the trust quorum (reconfiguration), or other key-share rotation. This way, even if all existing data on the rack is compromised, at least no new new data will be compromised if the compromised sled is removed.

Right now what do we know about our security goals? We want to:

  • Derive keys from the rack secret as much as possible to limit the need to store wrapped keys

  • Allow rotation of the rack secret so that a compromised rack secret can be mitigated

  • Use unique encryption keys per U.2 drive so that in case one key is compromised, the others are not compromized.

  • Ensure that new (empty) sleds cannot access any at rest data from old sleds that is not shared with them once a reconfiguration occurs.

And what are our constraints given these goals? We must:

  1. Be able to change the ZFS wrapper keys per U.2 drive when the rack secret is rotated. This requires knowing the old and new wrapper key at the same time.

  2. Allow for the fact that not all sleds will know at the same time when a new reconfiguration has been committed, and when to change the wrapper key, given the distributed nature of key rotation.

  3. Recognize that commitment of the new configuration and hence new rack secret may occur after multiple "false starts", where a new reconfiguration is distributed to multiple sleds but not committed.

The first constraint is a given from our use of disk encryption in general. The latter two constraints come from the distributed nature of the reconfiguration problem and are elaborated upon in [RFD 238]. The second constraint makes it impossible to distribute the new key share during the committment, because after a sled commits to a new epoch it should only utilize the new rack secret, and thus it may have to request the new key shares from a sled that has not yet learned that it has committed. There are other security reasons for not distributing key shares during commit that are further fleshed out in [RFD 238]. Therefore, given a 2-phase commit protocol ([RFD 238]), we must distributed the new shares in the prepare message. The third constraint makes it impossible to change the ZFS encryption wrapper keys immediately when learned, since the new rack secret from which those keys are derived may never be committed. Without a committed rack secret, it will be impossible to retrieve the shares necessary to recompute the secret and rederive the ZFS encryption wrapper keys.

Given these goals and constraints, we re-iterate that any sleds that are members of both the old and the new group must have access to the old and new committed rack secrets at the same time. This is necessary to allow them to derive the ZFS encryption wrapper keys for each U.2 device so that they can change the keys. For simplicity of the reconfiguration protocol, and to limit the exposure of the old rack secret we also only want to allow sleds to distribute key shares for the currently committed configuration. The requirement and desires above are in tension, and so we must get creative about how we handle this situation.

The most straightforward way to solve this predicament is via the dealer during a reconfiguration. As described in [RFD 238] we number each configuration with a monotonically increasing epoch. At epoch 1, each sled gets a single share and recomputes the rack secret to derive the original ZFS encryption wrapper keys for the U.2 devices. When a reconfiguration occurs, the dealer retrieves enough shares to recompute the rack secret for the current committed epoch (1 in our example). The dealer generates a new rack secret for epoch 2, and splits it into key shares. The dealer also derives an old-rack-secret encryption key associated with epoch 1 from the epoch 2 rack secret and encrypts the epoch 1 rack secret with the old-rack-secret key. It sends this encrypted secret to sleds that are members of the new group along with the rest of the trust quorum prepare message. Until the new configuration at epoch 2 is committed, the encrypted epoch-1 rack secret cannot be decrypted, because no members will send shares for epoch-2 required to recompute the epoch-2 rack secret and the derived key necessary to decrypt the epoch 1 rack secret. If epoch 2 is never committed this will remain the case.

As soon as a sled sees that a configuration has been committed for a new epoch, it retrieves enough shares to unlock the new epoch rack secret, derives the old-rack-secret encryption key, decrypts the old rack secret protected by this key, derives the old and new U.2 encryption keys from the old and new rack secret respectively and re-configures the ZFS encryption for each U.2 drive. Once the encryption keys have been changed for all the U.2 drives, the encrypted rack secret for the old epoch is securely deleted, along with any other encrypted rack secrets for the old epoch that were prepared but never committed. There is some nuance here around failure modes, but that is not relevant to this RFD and is further fleshed out in [RFD 238].

Our key hierarchy has now been roughly described in prose, and it tolerates failures of sleds during reconfiguration, and allows the changing of encryption wrapper keys used for ZFS encryption on U.2 drives. It also deals with compromise of the rack secret and limits exposure of individual derived key compromise. With this in mind, we can now draw a diagram of the key-hierarchy.

联系我们 contact @ memedata.com