signalapp/SecureValueRecovery2
GitHub: signalapp/SecureValueRecovery2
Signal 的安全密钥恢复服务,利用可信执行环境(SGX/Nitro/SEV-SNP)与 Raft 共识在服务端安全存储受 PIN 码保护的客户端密钥,抵御暴力破解并防止密钥泄漏。
Stars: 60 | Forks: 24
# Secure Value Recovery Service v2/3
SecureValueRecovery2 (SVR2) 项目旨在存储客户端密钥,
这些密钥在服务器端受到人类记忆的(因此是低熵的)pin 码保护。
它通过将恢复此类密钥的尝试次数限制在极少的猜测次数内来实现这一点,
以防止暴力破解攻击,否则这类攻击将轻易恢复出密钥。为了限制恢复尝试次数,
SVR2 将猜测次数的持久状态以及密钥本身,保存在一个基于
内存 Raft 的多副本、强共识共享存储机制中。
SVR3 项目对此方法进行了扩展,实现了跨多个受硬件保护的后端(SGX、Nitro、SEV-SNP)的密钥共享,
要求必须破坏所有底层硬件安全模型才能提取所需的密钥。
SVR2/3 的首要设计原则是不泄漏密钥材料,其次是向客户端提供密钥材料。鉴于
这一点,如果要在“永久丢失密钥材料”和“存储密钥材料但可能泄漏它”之间做出选择,我们将选择前者。
这意味着,在某些情况下,我们选择允许系统丢失_活性_(即对外提供任何服务的能力),以维持
系统的安全属性。我们宁愿丢弃系统中的所有密钥,
也不愿让其中一个密钥面临泄漏的风险。
## 历史
SVR2 是 Signal 已经用于上述目的的
[SecureValueRecovery](https://github.com/signalapp/SecureValueRecovery)
项目的继任者。我们构建了该系统的第二个版本,以解决以下几个具体问题:
- 更新至 SGX DCAP 功能
- 通过自我修复提供更好的崩溃/故障运维处理
- 简化为单一副本组模型,因为现在的 SGX CPU 具有数百 GB 的 EPC 大小
作为 SGX DCAP 更新的一部分,与原始版本中使用的 SGX MEE 内存所提供的
不同的安全保证相比,该项目还尽可能确保在 SGX TME 内存上运行时的安全性。
SVR3 构建于已实现的 SVR2 数据模型之上,公开了不同的客户端
请求/响应协议,该协议公开了基于 Ristretto 的不经意伪随机函数 (OPRF),而不是直接的存储/检索数据库。
## 构建
为了构建和测试此存储库中的所有内容,您只需
在顶层目录运行 `make` 即可。您必须在本地安装有效的 `docker`
才能执行此操作。在顶层目录运行此命令将:
- 创建一个用于构建内容的 docker 镜像
- 构建 `enclave/enclave.test`(用于模拟/测试的 debug enclave)和
`enclave/enclave.signed`(生产 enclave)
- 构建并测试 `host/` 中的宿主机端进程
如果您想增量构建和修改内容,可以通过
运行 `make dockersh` 来实现。这将构建上述 docker 镜像,
然后让您进入其中的 `bash` shell。接着您可以运行以下任何命令
```
make all # Make everything
make enclave # Make all of the enclave stuff
make host # Make all of the host stuff
(cd enclave && make $SOMETARGET) # Make just a specific target in enclave
(cd host && make $SOMETARGET) # Make just a specific target in host
```
## 代码结构
顶层目录的代码分为几个主要目录
* `docker` - 包含用于构建所有其他内容的 docker 镜像的规范。
* `shared` - 包含必须在宿主机端和 enclave 之间共享的所有代码/配置。
这包括宿主机端和 enclave 之间通信所使用的所有 proto,以及 ocalls/ecalls 的定义(`*.edl` 文件)。
* `enclave` - 包含用于构建 enclave 内二进制文件的所有代码和构建规则。
这是一个 C++ 代码库。
* `host` - 包含用于构建宿主机端二进制文件的所有代码和构建规则,该二进制文件
会启动一个 enclave,然后与其进行通信。这是一个 Go 代码库。
* `docs` - 包含超出宿主机端/enclave `README.md` 文档之外的特定主题的额外文档。
* `trustedimage` - 基于当前的 enclave 代码构建可信的 VM 磁盘镜像,
用于 AMD SEV-SNP 以及其他可信单元是 VM 而非二进制文件的环境。
## 验证构建度量
SVR2/3 客户端可以校验服务器是否正在运行特定的应用程序版本。这些版本
被硬编码到客户端中,并与此存储库中发布的构件相对应。
根据服务器应用程序运行所在的受信计算平台,您可以
验证带有版本号的构件是否基于此存储库的源代码构建,或者至少
验证有关远程软件正在运行的内容的某些细节。
### 验证 SVR2 度量
SVR2 仅支持 SGX。客户端会校验服务器是否正在运行由特定的 MRENCLAVE 表示的 enclave 二进制文件。SGX enclave 的构建是确定可复现的。要进行验证,请自行从源代码构建 enclave 二进制文件并检查生成的 MRENCLAVE 值。
假设您的客户端校验远程 enclave 具有 MRENCLAVE [a6622ad4656e1abcd0bc0ff17c229477747d2ded0495c4ebee7ed35c1789fa97](https://github.com/signalapp/Signal-Android/blob/4b8546a1510bbc6e54be5aeadd02aac2934ccee1/app/build.gradle.kts#L199)
```
# Checkout 引入 enclave 的 commit
git checkout $(git log --diff-filter=A --pretty=format:"%h" -- enclave/releases/sgx/default.a6622ad4656e1abcd0bc0ff17c229477747d2ded0495c4ebee7ed35c1789fa97) && git submodule update
# 进入 build environment
make dockersh
# Build the enclave
make enclave
# 应该匹配 a6622ad4656e1abcd0bc0ff17c229477747d2ded0495c4ebee7ed35c1789fa97
/opt/openenclave/bin/oesign dump -e enclave/build/enclave.signed | fgrep mrenclave
```
### 验证 SVR3 度量
SVR3 支持多种受信计算平台。验证的具体细节取决于平台。
#### 验证 SGX 度量
请参阅 SVR2 验证部分。对于 SVR3,您可以在 [libsignal](https://github.com/signalapp/libsignal/blob/a4a0663528dadc38215e46c6f94484b435f5fe02/rust/attest/src/constants.rs#L21) 中找到客户端校验的 MRENCLAVE。
#### 验证 Nitro 度量
Nitro 的构建也是确定性的,因此您可以通过自行构建 eif 镜像并比较生成的 PCR 度量,来验证校验过的服务器是否对应于提交的源代码。
假设您的客户端校验的 nitro 版本为 [ffe631d7.52b91975.a4544fb5](https://github.com/signalapp/libsignal/blob/a4a0663528dadc38215e46c6f94484b435f5fe02/rust/attest/src/constants.rs#L21) 及 [这些 PCR](https://github.com/signalapp/libsignal/blob/a4a0663528dadc38215e46c6f94484b435f5fe02/rust/attest/src/constants.rs#L29)。
```
# Checkout 引入 nitro image 的 commit
git checkout $(git log --diff-filter=A --pretty=format:"%h" -- enclave/releases/nitro/nitro.ffe631d7.52b91975.a4544fb5.eif) && git submodule update
# 进入 build environment
make dockersh
# Build the nitro images
make enclave_release
# 你应该已经 build 了 `ffe631d7.52b91975.a4544fb5`
ls -lrth enclave/releases/nitro
# 检查与你 build 的 eif 关联的 PCR 是否与你 attested 的相匹配
docker run -v "$(pwd)/enclave/releases/nitro:/enclaves" \
--rm -it --entrypoint nitro-cli svr2_nsmeif \
describe-eif \
--eif-path /enclaves/nitro.5582bdc0.52b91975.612eb43d.eif | grep PCR
```
### 验证 amd-sev-snp 度量
AMD-SEV-SNP 平台会校验整个 VM,而不是单个二进制文件或容器。VM 镜像不是可复现构建的,因此整个镜像被直接提交到此存储库中。因此,验证需要两个步骤:
1. 检查提交的镜像是否与校验过的度量相匹配。如果它们匹配,您就知道
经过校验的远程服务器正在运行提交到此存储库的 VM 镜像。
2. 检查提交的镜像是否将运行您期望的内容。
发布版本存储在 `enclave/releases/gcpsnp/$RELEASE.tar.gz` 和 `enclave/releases/gcpsnp/$RELEASE.eventlog` 中。
#### 检查度量
假设您的客户端校验远程 AMD-SEV-SNP 镜像具有与[版本]()关联的 [PCR 值]()
我们首先必须查看这些度量是什么。这可以通过解析 `$RELEASE.eventlog`
文件来完成。
```
sudo apt-get install tpm2-tools yq
tpm2_eventlog enclave/releases/gcpsnp/$RELEASE.eventlog | yq .pcrs.sha256
```
上述命令将输出该发布版本的 SHA256 PCR。这些是编译到
Signal 客户端(在 libsignal 中)的值,可以进行比对检查。其中一些会被忽略,因此
Signal 客户端中只会显示其一个子集。
#### 运行验证脚本
运行以下脚本以执行多项自动化检查:
```
sudo apt-get install tpm2-tools yq
cd enclave/releases/gcpsnp
./verify_gcpsnp.sh $RELEASE
```
该脚本将解压 `$RELEASE` 的磁盘镜像,将
root 和 boot 分区挂载到一个可访问的位置,并运行一组初始的
自动化检查,以确保它与 `$RELEASE.eventlog` 中找到的 PCR 相匹配。
如果您有本地预构建的镜像(通过在 trustedimage 目录中运行 `make build/debian2.out`
创建),它还将比较发布版本和
该镜像之间的文件,并报告哪些文件存在差异。
然后,它将为您提供保持分区挂载的选项,以便
您可以进行任何您认为合适的进一步调查(与已知文件核对、
检查 systemd 配置等)。
## 许可证
版权所有 2023 Signal Messenger, LLC
基于 [AGPLv3](LICENSE) 许可
标签:Raft共识, 分布式系统, 可信执行环境, 响应大小分析, 大语言模型安全, 密码学, 手动系统调用, 日志审计, 机密管理, 请求拦截, 防暴力破解