- 在去中心化应用中,一般采用中心化+去中心化混合架构。在中心化后台服务进行业务处理时,需要使用指定合约预设的签名地址对业务数据 进行签名,然后将签名数据在去中心化的合约中进行验签
举例:在一个 NFT 抢购应用中
- 当用户发起抢购时,后台服务会根据预设的各项条件进行判断,使用指定的签名地址生成包含 NFT 属性的签名数据
- 用户支付代币并携带签名数据与合约进行交互
- 合约即可对签名数据进行验证并做相应的处理
- 交易所热钱包管理
通过在 Keeper 中生成私钥,获取对应的地址和加密之后的私钥。开发、运维、客服人员在可以不需要接触热钱包的前提下实现对热钱包地址 的配置、使用。例如,当用户提现时,需要从热钱包给用户指定的链上地址转账,只需要调用 Keeper 的签名或者转账接口即可实现
- 交易所用户钱包管理
参考 “交易所热钱包管理”
- 如果想节省硬件资源,生成瞬时地址,签名时携带加密之后的私钥去请求 Keeper 签名
- 如果想简化大量的用户钱包管理,使用 HD 方式即可
- 测试接口
/api/test/keeperPOST
测试 client 与 keeper 通信是否正常
示例请求
curl http://localhost:10000/api/test/keeper -X POST -d '{"echo":"hello"}' -s | jq
{
"error": {
"code": 0,
"msg": "ok"
},
"echo": "hello",
"time": "2025-04-15 09:11:41"
}- 生成私钥接口
/api/key/generatePOST
示例请求
curl http://localhost:10000/api/key/generate -X POST -d '{}' -s | jq
{
"error": {
"code": 0,
"msg": "ok"
},
"key_id": "5ed24411-76fc-4ea7-9887-a8f00df8f01b",
"address": "0x5Cd6476FF61e5d6792ca3b973ce33764faa871A0",
"private_key": ""
}测试模式下,可以返回生成的私钥,生产模式下不建议使用
curl http://localhost:10000/api/key/generate -X POST -d '{"show_private_key":true}' -s | jq
{
"error": {
"code": 0,
"msg": "ok"
},
"key_id": "5ed24411-76fc-4ea7-9887-a8f00df8f01b",
"address": "0x5Cd6476FF61e5d6792ca3b973ce33764faa871A0",
"private_key": "1db13f9c3a3c91c9949f26040d33504ccb08d71acff4f76782b897a9383b7dc4"
}- 添加私钥接口
/api/key/addPOST
示例请求
curl http://localhost:10000/api/key/add -X POST -d '{"key_id":"3bf2b6cb-debe-4c75-bb6e-38a35e818680","address":"0x5d1D0e4A7775BD50565af85b679E726648753bC5","private_key":"ac904c67de52249561ea562f3190a7c875346c697ad80d8b037fecf688959293"}' -s | jq
{
"error": {
"code": 0,
"msg": "ok"
}
}- 签名消息接口
/api/signPOST
示例请求
curl http://localhost:10000/api/sign -X POST -d '{"key_id": "f47ac10b-58cc-0372-8567-0e02b2c3d479", "hash": "0x1075797ba87c4cacf7bc34c658471ba6c766993fd05150d77521d5f454e9a0cd"}' -s | jq
{
"error": {
"code": 0,
"msg": "ok"
},
"signature": "5a5392e0454e4c68339d62193dc1393082ca03cdf30e856ea54e60931bb1595467879a130cbf3e0149c96ef31f4e4e654adb6daa67541b13cc263d798aa4e27a00"
}如果请求的签名私钥不存在,错误如下
curl http://localhost:10000/api/sign -X POST -d '{"key_id": "b16a2659-a332-4293-9604-a8d1b3f879a3", "hash": "0x1075797ba87c4cacf7bc34c658471ba6c766993fd05150d77521d5f454e9a0cd"}' -s | jq
{
"error": {
"code": 2,
"msg": "key id: b16a2659-a332-4293-9604-a8d1b3f879a3 not found"
},
"signature": ""
}- 设置加密种子接口
/api/key/set_encryption_seedPOST
示例请求
curl 'http://localhost:10000/api/key/set_encryption_seed' -X POST -d '{"encryption_seed":"oXuVXyjjGR5YdmNxf&Qjut2b-6s*wnU!DOqPSAUW#(5k!rrYnn)uAc_DOL-VkENJU-"}' -s | jq
{
"error": {
"code": 0,
"msg": "ok"
}
}- 生成地址接口
/api/key/generate_addressPOST
示例请求
curl 'http://localhost:10000/api/key/generate_address' -X POST -d '{"is_hd_wallet": true, "number": 2}' -s | jq
{
"error": {
"code": 0,
"msg": "ok"
},
"addresses": [
{
"key_id": "8c339fe7-d9a8-4e23-b549-83dc79957cc4",
"address": "0x041E09Ac4EDf9c8198FBedD82c89FF88D72c67e2",
"private_key": "",
"hd_wallet_index": 2
},
{
"key_id": "ee48dc2a-d187-44cf-8e10-fda9f2d5b49c",
"address": "0xc8bDCB8629C6FaD267D632c3ca358646ee8B1dCd",
"private_key": "",
"hd_wallet_index": 3
}
]
}- HTTP 响应头部包含 Request-Id,结合日志文件可以追踪业务或者排查错误
< HTTP/1.1 200 OK
< Content-Type: text/plain; charset=utf-8
< Request-Id: 4a80058c306d291
< Date: Tue, 15 Apr 2025 02:59:39 GMT
< Content-Length: 191暂无
enclave_client 可以(不使用 docker)直接在宿主机 EC2 编译、运行,注释掉脚本相关代码即可
git clone https://github.com/dudebing99/enclave_in_web3.git
cd enclave_in_web3
echo "initialize env ..."
bash init.sh
echo "deploy services ..."
bash deploy.sh预期输出参考样例
[+] Building 32.1s (16/16) FINISHED docker:default
=> [internal] load build definition from dockerfile_keeper 0.0s
=> => transferring dockerfile: 796B 0.0s
=> [internal] load metadata for docker.io/library/alpine:latest 0.1s
=> [internal] load metadata for docker.io/library/golang:1.19-alpine 0.1s
=> [internal] load .dockerignore 0.0s
=> => transferring context: 2B 0.0s
=> [builder 1/6] FROM docker.io/library/golang:1.19-alpine@sha256:0ec0646e208ea58e5d29e558e39f2e59fccf39b7bda306cb53bbaff91919eca5 0.0s
=> [stage-1 1/4] FROM docker.io/library/alpine:latest@sha256:56fa17d2a7e7f168a043a2712e63aed1f8543aeafdcee47c58dcffe38ed51099 0.0s
=> [internal] load build context 0.2s
=> => transferring context: 24.52MB 0.2s
=> CACHED [builder 2/6] RUN apk add --no-cache gcc libc-dev make 0.0s
=> CACHED [builder 3/6] WORKDIR /enclave_in_web3 0.0s
=> [builder 4/6] COPY . . 0.4s
=> [builder 5/6] RUN go mod tidy 7.4s
=> [builder 6/6] RUN go build -o bin/enclave-keeper ./cmd/keeper/main.go 23.9s
=> CACHED [stage-1 2/4] WORKDIR /enclave_in_web3 0.0s
=> CACHED [stage-1 3/4] COPY --from=builder /enclave_in_web3/bin/enclave-keeper ./ 0.0s
=> CACHED [stage-1 4/4] COPY --from=builder /enclave_in_web3/conf/application_keeper.yml ./conf/application.yml 0.0s
=> exporting to image 0.0s
=> => exporting layers 0.0s
=> => writing image sha256:e6d74e77dc4a4f4038dbd94644d9205e7f12421e3c423990655918a119617930 0.0s
=> => naming to docker.io/library/enclave_keeper:latest 0.0s
[+] Building 29.1s (16/16) FINISHED docker:default
=> [internal] load build definition from dockerfile_client 0.0s
=> => transferring dockerfile: 810B 0.0s
=> [internal] load metadata for docker.io/library/alpine:latest 0.1s
=> [internal] load metadata for docker.io/library/golang:1.19-alpine 0.1s
=> [internal] load .dockerignore 0.0s
=> => transferring context: 2B 0.0s
=> [builder 1/6] FROM docker.io/library/golang:1.19-alpine@sha256:0ec0646e208ea58e5d29e558e39f2e59fccf39b7bda306cb53bbaff91919eca5 0.0s
=> [internal] load build context 0.0s
=> => transferring context: 16.99kB 0.0s
=> [stage-1 1/4] FROM docker.io/library/alpine:latest@sha256:56fa17d2a7e7f168a043a2712e63aed1f8543aeafdcee47c58dcffe38ed51099 0.0s
=> CACHED [builder 2/6] RUN apk add --no-cache gcc libc-dev make 0.0s
=> CACHED [builder 3/6] WORKDIR /enclave_in_web3 0.0s
=> CACHED [builder 4/6] COPY . . 0.0s
=> CACHED [builder 5/6] RUN go mod tidy 0.0s
=> [builder 6/6] RUN go build -o bin/enclave-client ./cmd/client/main.go 28.8s
=> CACHED [stage-1 2/4] WORKDIR /enclave_in_web3 0.0s
=> CACHED [stage-1 3/4] COPY --from=builder /enclave_in_web3/bin/enclave-client ./ 0.0s
=> CACHED [stage-1 4/4] COPY --from=builder /enclave_in_web3/conf/application_client.yml ./conf/application.yml 0.0s
=> exporting to image 0.0s
=> => exporting layers 0.0s
=> => writing image sha256:37612af8097af3e32bab264c6113f54420dbeb4c0b1be57c2380c1abc094126c 0.0s
=> => naming to docker.io/library/enclave_client:latest 0.0s
WARNING! This will remove all dangling images.
Are you sure you want to continue? [y/N] Total reclaimed space: 0B
Start building the Enclave Image...
Using the locally available Docker image...
Enclave Image successfully created.
{
"Measurements": {
"HashAlgorithm": "Sha384 { ... }",
"PCR0": "fd27433ffcb75192ab7ee460c8c9cf25e9d13900e749381dd7c23966a3159a3f852af39a0f88ac7c35174e2a626d362c",
"PCR1": "4b4d5b3661b3efc12920900c80e126e4ce783c522de6c02a2a5bf7af3a2b9327b86776f188e4be1c1c404a129dbda493",
"PCR2": "9ea41e12380e65ec2f05a47c8a373454d19a202baa42c409c2193bf8af6823c120e27205652e5f04001f02da35a7355f"
}
}
Start allocating memory...
Started enclave with enclave-cid: 22, memory: 3000 MiB, cpu-ids: [1, 3]
{
"EnclaveName": "enclave_keeper",
"EnclaveID": "i-0a8d6cd7bed188be7-enc194d70c4c759219",
"ProcessID": 42971,
"EnclaveCID": 22,
"NumberOfCPUs": 2,
"CPUIDs": [
1,
3
],
"MemoryMiB": 3000
}- [vsock in Go] https://github.com/mdlayher/vsock
- [Installing the Nitro Enclaves CLI on Linux] https://docs.aws.amazon.com/enclaves/latest/user/nitro-enclave-cli-install.html
- [Hello enclave] https://docs.aws.amazon.com/enclaves/latest/user/getting-started.html
- [aws-nitro-enclaves-samples] https://github.com/aws/aws-nitro-enclaves-samples
- [部署一个 Nitro Enclave 示例环境,结合 KMS 实现私钥安全] https://github.com/hxhwing/Nitro-Enclave-Demo
- [基于 Nitro Enclave 构建安全的可信执行环境] https://aws.amazon.com/cn/blogs/china/build-a-secure-and-trusted-execution-environment-based-on-nitro-enclave/
- [kms tool] https://github.com/aws/aws-nitro-enclaves-sdk-c
- rlp: too few elements ... 参考
https://github.com/ethereum/go-ethereum/issues/26236