最佳实践参考

为了帮助开发者正确和安全的使用 SMN 产品套件,Safeheron 整理了一份最佳实践参考,开发者在开发集成阶段和正式上线前需要逐一确认和检查。

1 功能集成

1.1 日志 level 推荐

推荐开发者生产环境使用以下日志等级:

组件推荐日志级别描述
smn-relayerInfo便于排查问题
smn-caInfo便于排查问题
smn-serviceInfo便于排查问题
libsmnSDK-JSOff/Error取决于开发者的技术支持策略,如果用户遇到问题,是否需要用户查看并反馈现场错误日志
libsmnSDK-AndroidOff具体的错误信息将通过错误信息或者异常抛出,开发者可以进行日志上报
libsmnSDK-iOSOff具体的错误信息将通过错误信息或者异常抛出,开发者可以进行日志上报

1.2 JS、Android、iOS 记录当前的 SDK Version

JS、Android、iOS 端在启动 MPC 协议前需要调用开发者后端服务接口,服务端根据请求判断是否调用 SMN Service。在 JS、Android、iOS 端开发者后端服务接口,需要同时将 SDK 的版本号和 SDK 类型(JS/Android/iOS)上报给后端服务,用于解决将来的兼容性问题。当将来出现不兼容升级时,后端服务可以根据 SDK 版本号和 SDK 类型将请求路由给不同的 SMN Service 集群。

1.3 记录最新的 tpk

每次 MPC 协议执行时参与方需要知道其他参与方的 tpk,在首次初始化 SMNTenantClient 时会随机创建 tpk 和对应的密钥,考虑到将来开发者的用户可能会出现更换设备等情况会重新生成 tpk 和对应的密钥,所以需要开发者处理好 tpk 的更新机制,当 tpk 发生变化时通过开发者后端服务更新 tpk。

1.4 generatePreKeygenData 杜绝重复使用

ECDSA 算法中可以通过 generatePreKeygenData 接口生成预计算数据,得到的预计算数据调用 SMNECDSAClient 实例的 addPreKeygenData 方法使用,请注意,生成的预计算数据只能使用一次,杜绝一份预计算数据在不同的SMNECDSAClient 实例中使用,以避免安全问题。

1.5 ReadyTimeout/SessionTimeout 配置注意事项

每一方 MPC Node 配置项中均存在 ReadyTimeout/SessionTimeout 配置,在执行 MPC 协议时,每一方根据本地的超时时间决定是否超时,需要开发者根据实际业务场景决定是否统一各 MPC Node 超时配置或者针对某一个 MPC Node 进行特别的配置。

比如移动端配置 sessionTimeout 为 5 分钟,服务端配置 sessionTimeout 为 1 分钟,假如由于网络问题移动端 1 分钟内没有完成计算,但是由于服务端已经达到了超时时间,服务端超时后将会结束本次计算,此时移动端剩余 4 分钟后将会出现超时异常,并且计算一定会失败,此时应该考虑服务端增加超时时间。

1.6 Recover/Refresh 使用注意事项

在执行 Recover/Refresh 协议后,各端老的 KeyID 如果存在则依旧可用。开发者服务端应当根据业务逻辑进行一些安全限制,如 Recover/Refresh 后,如果其他端请求使用老的 KeyID 进行签名,开发者后端服务应当拒绝;并且根据实际业务场景设计删除策略,比如 Recover/Refresh 后,使用新的 KeyID 完成过 1 次签名后,调用 MPC Node 删除私钥分片接口删除老的 KeyID。

1.7 开发者后端服务避免透传 SMN Service/Relayer 响应数据

开发者后端服务应当根据实际业务约定请求参数和响应数据,避免透传 SMN Service/Relayer 响应数据。当 SMN Service/Relayer 出现响应数据结构调整时,通过开发者后端服务进行适配,避免安全问题和兼容性问题。

1.8 SessionID 推荐使用 UUIDv4

在执行每个 MPC 协议时需要参与方协商 SessionID,协商 SessionID 的过程开发者务必使用后端服务生成并下发给其他参与方,避免非预期的 SessionID 输入。SessionID 会参与到 KeyID 的计算过程中,为了避免 Recover/Refresh 后 KeyID 相同,开发者需要确保 SessionID 不重复,推荐使用 UUIDv4。

1.9 内网负载均衡超时时间需要不能小于 ReadyTimeout/SessionTimeout 时间

一些云厂商的负载均衡产品可能存在目标组最大超时时间限制,请注意检查负载均衡产品中对于目标组的超时时间设定是否大于等于 SMN Servie 配置的 ReadyTimeout/SessionTimeout,并且注意需要配置内网负载均衡挂载内网 SMN Service 和 SMN CA 以及 SMN Relayer。

目前已知 Alibaba Cloud ALB 产品最大超时时间为 180 秒,可以采用 CLB 作为内网负载均衡,CLB 支持最大超时时间设置为 900 秒。

1.10 负载均衡配置健康检查

采用云厂商的负载均衡产品转发 SMN Service、SMN CA、SMN Relayer 流量时,需要配置负载均衡的健康检查,当后端服务节点故障不可用时,负载均衡器可将其自动摘除,避免将流量转发至故障节点。健康检查路径均为 /check,请求方式为 GET,SMN CA 使用 Server.Port 作为健康检查端口,SMN Service 和 SMN Relayer 使用 APIServer.Port 作为健康检查端口。

1.11 服务优雅下线

对于在线流量型服务,在版本升级、配置更新等情况下,需要重启服务,为了避免影响正在执行的任务,实现优雅下线,SMN Service 及 SMN Relayer 可先调用服务提供的 preStop 接口,此时服务不再接收新的流量,并且会排空所有执行中的任务,在 preStop 接口成功执行后,确认服务没有流量时即可下线或重启服务。

1.12 JS 端引入 SDK 时在 URL 路径中区分版本

如果开发者开发浏览器插件,不存在此问题,插件会将所有依赖构建到插件本地资源中。

如果开发者开发浏览器网页应用,在引入 JS SDK 时需要在 URL 中区分版本,防止由于缓存出现潜在问题,如使用 xxx.com/v1.0.0/safeheron-crypto-sdk-wasm.wasm 方式,将该版本下所有依赖通过 URL 中的版本号区分。

1.13 选择合适的时机调用 setRelayerTokenCallback

setRelayerTokenCallback 函数在执行时会直接调用一次开发者的回调函数获取一次 OTT 并缓存,在后续执行 MPC 协议时如果存在缓存 OTT 则直接使用,如果缓存 OTT 不存在则会调用开发者设置的回调函数获取一次 OTT。因此,开发者可以选择合适的时机提前调用 setRelayerTokenCallback,缩短用户感知的创建钱包/签名等时间。以签名为例,在进行签名操作前,可以在进入到转账页面时创建两个对象并调用 setRelayerTokenCallback 方法,当用户输入转账信息后,点击转账时调用 MPC Sign 方法,将 setRelayerTokenCallback 网络请求时间前置,以提升产品体验。

1.14 推荐使用内部 Docker 镜像仓库

开发者从 Safeheron 提供的 Gitlab 下载地址中下载/更新镜像,下载后然后上传到内部 Docker 仓库在服务器中进行使用。

推荐开发者准备自动化脚本或者类似 Jenkins 的工具,当 Safeheron 发布新的镜像后,通过工具自动化拉取最新镜像并更新到内部 Docker 镜像仓库。

2、安全集成

2.1 Relayer 接口安全

Relayer 服务端口分为 APIServer 端口(默认为 8070)和 RelayerServer 端口(默认为 9001),其中 APIServer 端口具有所有 API 权限,为了保证安全,仅在内网开放,或挂载到内网负载均衡器;RelayerServer 端口仅支持通信消息的收发,可向公网开发。

2.2 MySQL 和 Redis 使用强密码

SMN 产品套件部署时依赖 MySQL 和 Redis 等中间件,请开发者务必确认所有中间件不存在空密码或弱密码的情况,以预防潜在的安全风险。推荐使用 1Password、pwgen 等工具生成强密码。

2.3 跨域白名单需配置具体地址

当开发者自己的后端服务或者需要将 Relayer 的通信接口提供给浏览器时需要配置跨域请求策略,在配置允许访问的域时请配置具体的地址,避免使用通配符等,以预防潜在的安全风险。

2.4 生成 encryption key 安全

在 JS、Android、iOS SDK 中,初始化 SMNTenantClient 时需要设置 encryptionKey,一般业务场景而言,encryptionKey 应给为本地生成的 256 bit 随机密钥,或者根据用户钱包密码进行 PBKDF2 后得到的密钥,并且注意在开发者产品中提示用户钱包密码强度,避免简单密码和弱口令。

浏览器端可以考虑使用钱包密码派生 encryptionKey,iOS 可以将 encryptionKey 存储在 Keychain,Android 可以将 encryptionKey 使用 Keystore 相关 API 存储。

2.5 生成 TPK 和 JWT 安全

在部署 SMN Service 时需要生成租户公私钥以及 JWT 鉴权公私钥,请确保生成密钥的环境安全以及密钥管理和使用者缩小的最小人员范围,并妥善备份相应的密钥。

当密钥丢失时 SMN Service 提供了更改密钥的功能,但是开发者需要注意,如果需要更换 TPK ,开发者的产品功能是否支持更新 Embedded MPC Node 配置文件中服务端 SMN Service TPK。

2.6 CA setup 流程安全

CA setup 为敏感流程,请妥善选择管理员和门限,并且在测试环境中运维人员和管理员演练 setup 流程、unseal key 备份流程、unseal 流程后再进行生产环境的 setup。推荐在部署 SMN CA 的网络环境中,为每个管理员提供一台专用的机器来完成 setup、verify、unseal 等操作,此机器无需 Intel SGX 支持,不存储数据,操作完成释放即可。

在 setup 过程中所有的 nonce 仅可以发送给管理员。

2.7 获取 Relayer OTT 接口安全

在 JS、Android、iOS SDK 中提供了 setRelayerTokenCallback 接口,允许开发者自定义回调函数调用自己的后端服务以获取 Relayer OTT,在获取 OTT 时需要注意结合业务鉴权机制获取 OTT,避免未鉴权调用或者越权调用。

2.8 敏感操作安全

开发者后端服务在调用 SMN Service 接口进行签名、删除分片等敏感操作前,应通过业务鉴权以及确认请求的用户身份和 KeyID 存在归属关系,避免越权调用敏感接口,以预防潜在的安全风险。

2.9 内网权限安全

在部署 SMN 产品套件时,SMN CA 只需要被其他 SMN CA、SMN Service 以及管理员请求和访问,SMN Service 只需要被开发者的后端服务访问。因此推荐针对核心组件 SMN CA 和 SMN Service 在内网部署时做好访问权限控制,只开启需要访问 SMN CA 和 SMN Service 的应用的白名单访问权限,其他请求一律阻断。

2.10 区块链安全

SMN 产品解决了私钥管理安全,同时给开发者接入公链带来了一定的额外成本和难度,在开发者对接各个公链时应充分调研各公链地址生成规则、交易构造和序列化规则等,避免在钱包层面产生安全风险。

常见的安全风险,如:

2.11 产物安全

开发者在部署或集成 SMN 产物前,请验证下载的产物 sha256 哈希值与 Safeheron 发布的 sha256 哈希值是否一致,不使用未经哈希值验证的产物。

3、数据安全

3.1 数据库备份

smn-service 和 smn-ca 两个应用采用 MySQL 作为持久化存储,其中涉及到私钥分片密文、数据解密根密钥密文等数据,极其重要,因此,为保证数据在极端情况下能够恢复可用,请严格按以下说明备份数据:

💡
推荐数据备份方案:多云多地数据同步备份

3.2 SMN CA 授权密钥分片备份

在初始化 SMN CA 时,多名 CA 管理员各自获取了一片授权密钥分片,即 Unseal Key,需制定符合自身情况的备份管理规范,确保每一位管理员都严格按规范备份 Unseal Key,同时,为确保备份的有效性,可定期进行演练,检验备份机制是否正常运作、备份数据是否正确可用。

💡
Unseal Key 备份工具:U 盘、保险柜、1Password

4、部署

4.1 多可用区部署

为保证服务高可用,SMN Service、SMN Relayer 和 SMN CA 组件在部署时,每一个组件都采用集群模式,根据业务流量部署合适数量的节点,最少 2 个节点,请确保多个节点分布在不同地域的可用区中,避免云厂商区域性故障引起服务不可用。

4.2 敏感数据隔离

这里数据泛指应用程序和持久化数据,针对 SMN 套件中的数据,推荐在物理层面与其他数据隔离: