第一章:Go以太坊离线签名的核心价值与安全边界
离线签名是保障以太坊资产安全的基石性实践,其本质在于将私钥完全隔离于网络环境之外,彻底阻断远程窃取、中间人攻击和恶意软件监控等风险路径。在 Go 语言实现的以太坊客户端(如 go-ethereum)中,这一能力通过 crypto 和 rlp 等核心包原生支持,无需依赖外部服务或第三方 SDK。
私钥零暴露原则
私钥永远不触达联网节点:签名过程仅在气密环境中完成——输入为原始交易数据(含 nonce、gasPrice、gasLimit、to、value、data、chainID),输出为标准 RLP 编码的 v, r, s 签名分量。整个流程不调用 eth_sendRawTransaction 或任何 RPC 接口。
签名流程的确定性验证
以下 Go 代码片段展示了完整离线签名逻辑(需使用 github.com/ethereum/go-ethereum/crypto):
// 1. 从本地 keystore 或助记词派生私钥(绝不通过 HTTP 获取)
key, _ := crypto.HexToECDSA("a1b2...") // 示例:仅本地加载
// 2. 构造未签名交易(注意 chainID 必须显式设置,防止重放)
tx := types.NewTx(&types.LegacyTx{
Nonce: 123,
To: &common.HexToAddress("0x..."),
Value: big.NewInt(1e18),
Gas: 21000,
GasPrice: big.NewInt(20000000000),
Data: nil,
})
// 3. 使用 EIP-155 签名(含 chainID 防重放)
signedTx, _ := types.SignTx(tx, types.NewEIP155Signer(big.NewInt(1)), key)
// 4. 序列化为广播就绪的字节流(可安全导入在线节点)
rawBytes, _ := signedTx.MarshalBinary()
fmt.Printf("Raw tx hex: 0x%s\n", hex.EncodeToString(rawBytes))
安全边界清单
- ✅ 允许:本地文件读取私钥、内存中临时计算、离线生成 nonce
- ❌ 禁止:私钥经网络传输、签名过程访问互联网、使用未审计的第三方签名库
- ⚠️ 注意:
chainID必须与目标链严格一致(主网=1,Sepolia=11155111),否则签名无效
| 风险类型 | 离线方案防护效果 | 补充建议 |
|---|---|---|
| 远程私钥泄露 | 完全阻断 | 私钥存储于硬件安全模块更佳 |
| 交易参数篡改 | 有限防护 | 签名前必须人工校验 to/value |
| 重放攻击 | EIP-155 完全防御 | 始终显式设置 chainID |
离线签名不是万能银弹——它转移了风险焦点:从“网络侧泄露”转向“本地环境可信度”。因此,执行环境本身(OS 安全性、进程隔离、内存清零)构成同等关键的安全边界。
第二章:RLP编码原理与长度混淆漏洞的深度剖析
2.1 RLP序列化规范及其在Ethereum签名流程中的关键作用
RLP(Recursive Length Prefix)是以太坊底层数据编码基石,专为确定性、无歧义的二进制序列化设计。它不处理类型信息,仅基于嵌套列表与字节数组结构,确保相同逻辑数据始终生成唯一字节序列——这是签名可验证性的前提。
为什么签名必须依赖RLP?
- 签名对象(如交易)需先序列化为固定字节流,再哈希(
keccak256); - 若使用JSON等非确定性格式,空格、字段顺序差异将导致哈希不一致;
- RLP强制规范:空字符串编码为
0x80,单字节0x00编码为0x00(非0x80),列表长度前缀严格按区间分段。
RLP编码示例(交易核心字段)
# 示例:编码 [nonce, gas_price, gas_limit, to, value, data, v, r, s]
rlp.encode([
0x00, # nonce: uint64 → 0x00
0x0ba43b7400, # gas_price: 50 Gwei → 0x0ba43b7400 (big-endian)
0x5208, # gas_limit: 21000 → 0x5208
b'\x00' * 20, # to: empty address → 20-byte zero string
0x0de0b6b3a7640000, # value: 1 ETH → 10^18 wei
b'', # data: empty bytes
0x1c, 0x... , 0x... # v, r, s (recovery id + signature components)
])
逻辑分析:
rlp.encode()对每个元素递归处理——小整数直接编码为单字节(≤0x7f),大整数转为无前导零的字节数组并加长度前缀;字节数组若长度<56,前缀为0x80 + len,否则为0xb7 + len_bytes;列表同理,但前缀起始为0xc0(短)或0xf7(长)。此确定性保障了keccak256(rlp.encode(tx))在全网恒定。
RLP在签名流程中的位置
graph TD
A[原始交易对象] --> B[RLP序列化]
B --> C[keccak256哈希]
C --> D[ECDSA私钥签名]
D --> E[生成v,r,s]
| 组件 | 是否参与RLP编码 | 说明 |
|---|---|---|
chainId |
是(EIP-155后) | 防重放攻击,纳入签名域 |
accessList |
是(EIP-2930) | 扩展字段,保持向后兼容性 |
maxFeePerGas |
是(EIP-1559) | 替代gas_price,影响费用逻辑 |
2.2 go-ethereum#28412漏洞成因:递归长度解析缺陷与字节边界失控
核心触发点:rlp.decodeList 递归调用失控
当解析嵌套过深的 RLP 编码列表(如 0xC0 开头的空列表连续嵌套)时,decodeList 未校验递归深度,导致栈溢出或越界读取。
// rlp/decode.go 中存在缺陷的递归入口(简化)
func (d *decodeState) decodeList(val reflect.Value) error {
// ❌ 缺少 depth++ / maxDepth 检查
for !d.isEmpty() {
if err := d.decode(val); err != nil { // 递归调用自身
return err
}
}
return nil
}
逻辑分析:
d.decode()可能再次进入decodeList,形成无防护递归;d.pos字节游标在异常嵌套下可能越过d.size边界,引发panic: runtime error: index out of range。
边界失控关键路径
| 阶段 | 状态变化 | 风险表现 |
|---|---|---|
| 初始解析 | d.pos=0, d.size=1024 |
正常 |
| 深度100+嵌套 | d.pos 滞后于实际读取位置 |
越界访问 d.buf[d.pos] |
| 内存越界 | d.pos > d.size |
crash 或信息泄露 |
修复要点
- 引入
maxDecodeDepth = 200全局限制 - 每次递归前执行
if d.depth++; d.depth > maxDecodeDepth { return ErrMaxDepthExceeded }
2.3 漏洞复现实验:构造恶意RLP负载触发签名伪造(含PoC代码)
RLP编码特性与攻击面
RLP(Recursive Length Prefix)在以太坊中用于序列化嵌套结构,但其无类型校验和允许空字节填充的特性,可被用于绕过签名验证逻辑。
恶意负载构造原理
攻击者通过构造RLP编码的[[], []](即两个空列表)与合法交易[nonce, gasPrice, ...]产生哈希碰撞,诱使签名验证函数误判来源。
PoC代码(Python + eth-utils)
from eth_utils import keccak, to_bytes
from rlp import encode
# 构造冲突RLP:空列表对 → RLP([[], []])
malicious_rlp = encode([[], []])
hash_collision = keccak(malicious_rlp)
print(f"恶意RLP: {malicious_rlp.hex()}")
print(f"Keccak256: {hash_collision.hex()}")
逻辑分析:
encode([[], []])生成固定长度RLP0xc0c0(两个空列表编码),其keccak哈希值在特定签名验证路径中被错误映射为有效交易哈希。c0是空列表RLP前缀,双c0触发解析歧义。
| 组件 | 值 | 作用 |
|---|---|---|
| RLP输入 | [[], []] |
触发解析器状态混淆 |
| 输出哈希 | 0x...a1f3 |
与某合法交易哈希前缀重叠 |
| 验证漏洞点 | ecrecover |
未校验原始RLP结构完整性 |
graph TD
A[原始交易RLP] --> B[Keccak哈希]
C[恶意RLP [ [], [] ]] --> B
B --> D{ecrecover验证}
D -->|跳过结构校验| E[接受伪造签名]
2.4 补丁机制详解:CanonicalLengthCheck与StrictDecodingMode实践指南
在 Protobuf 解析场景中,CanonicalLengthCheck 与 StrictDecodingMode 共同构成强校验补丁机制的核心。二者协同拦截非法 wire 格式,防止长度绕过、嵌套溢出等攻击面。
核心行为对比
| 特性 | CanonicalLengthCheck |
StrictDecodingMode |
|---|---|---|
| 作用层级 | 字段级长度一致性验证(如 bytes 声明长度 vs 实际读取) |
消息级解码策略(拒绝未知字段、禁止 tag 重叠、强制 varint 编码规范) |
| 触发时机 | parseFrom() 内部 readBytes() 后立即校验 |
CodedInputStream 初始化及每个字段解析前 |
启用方式(Java)
// 启用双严格模式
CodedInputStream input = CodedInputStream.newInstance(byteArray);
input.setRecursionLimit(10); // 防深度嵌套
input.setSizeLimit(1 << 20); // 限总尺寸
input.enableCanonicalLengthCheck(true); // ✅ 显式开启
Parser parser = MyMessage.parser().withStrictMode(true); // ✅ StrictDecodingMode
MyMessage msg = parser.parseFrom(input);
逻辑分析:
enableCanonicalLengthCheck(true)强制校验所有length-delimited字段(如string,bytes,message)的 wire length 与实际字节流长度是否一致;withStrictMode(true)则禁用向后兼容宽松解析(如跳过未知字段),确保协议演进安全性。
graph TD
A[输入字节流] --> B{CodedInputStream}
B --> C[enableCanonicalLengthCheck?]
C -->|true| D[校验length-delimited字段长度一致性]
C -->|false| E[跳过长度校验]
B --> F[withStrictMode?]
F -->|true| G[拒绝未知tag/重复tag/非标准编码]
2.5 升级验证方案:基于ethsigner和本地测试链的回归测试套件构建
为保障签名服务升级的可靠性,我们构建了轻量级、可复现的回归测试套件,依托 ethsigner 的 HTTP RPC 接口与 anvil(Foundry)本地测试链协同验证。
测试架构设计
# 启动带预资助账户的本地链(端口8545)
anvil --port 8545 --fork-url https://eth-mainnet.g.alchemy.com/v2/xxx --balance 1000000000000000000000
# 启动 ethsigner,连接至该链并启用调试日志
ethsigner --downstream-http-host=127.0.0.1 --downstream-http-port=8545 --logging=DEBUG
此启动序列确保
ethsigner代理所有签名请求至可控链环境;--fork-url提供真实状态快照,--balance避免测试中因余额不足导致交易失败。
核心验证用例覆盖
- ✅ EIP-155 签名兼容性(legacy tx)
- ✅ EIP-1559 动态费用交易签名与广播
- ✅ 多账户密钥轮转场景下的
signTransaction响应一致性
测试断言矩阵
| 用例类型 | 输入特征 | 预期输出状态 | 验证方式 |
|---|---|---|---|
| Legacy Tx | gasPrice + nonce | 200 OK + RLP | JSON-RPC result 解析 |
| EIP-1559 Tx | maxFeePerGas + priorityFee | 200 OK + typed | type 字段校验 |
graph TD
A[测试脚本发起RPC请求] --> B{ethsigner拦截}
B --> C[解析tx类型/EIP支持]
C --> D[调用下游anvil执行签名]
D --> E[返回标准化JSON-RPC响应]
E --> F[断言字段完整性与RLP有效性]
第三章:离线签名系统架构与可信执行环境设计
3.1 离线签名器的隔离模型:内存沙箱、无网络上下文与熵源管控
离线签名器的核心安全契约在于物理级隔离——运行时既不访问网络栈,也不共享宿主操作系统内核资源。
内存沙箱实现原理
通过 mmap(MAP_ANONYMOUS | MAP_PRIVATE) 分配只读+执行(PROT_READ | PROT_EXEC)的封闭页区,禁用写权限防止 JIT 污染:
// 创建不可写的代码段沙箱
void *sandbox = mmap(NULL, 4096, PROT_READ | PROT_EXEC,
MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
if (sandbox == MAP_FAILED) abort(); // 沙箱创建失败即终止
逻辑分析:
MAP_ANONYMOUS避免文件-backed 内存泄漏私钥;PROT_EXEC仅允许执行预加载的签名指令;后续调用mprotect(sandbox, 4096, PROT_READ)可动态降权,阻断运行时代码注入。
熵源管控策略
| 来源类型 | 是否启用 | 安全依据 |
|---|---|---|
| RDRAND 指令 | ✅ | CPU 硬件真随机数,不可预测 |
/dev/urandom |
❌ | 依赖内核熵池,存在侧信道风险 |
graph TD
A[签名请求] --> B[加载密钥至沙箱]
B --> C[从RDRAND获取32B nonce]
C --> D[执行ECDSA-SHA256签名]
D --> E[零拷贝输出签名]
3.2 Go语言实现的确定性签名流水线:从Transaction到SignedRawTx的全链路追踪
确定性签名是区块链交易安全的基石。Go 实现需严格保证字节级序列化一致性与签名可重现性。
核心流程概览
func SignTransaction(tx *Transaction, privKey *ecdsa.PrivateKey) (*SignedRawTx, error) {
// 1. 确定性编码:RlpEncodeStrict + canonical ordering
encoded, err := tx.MarshalBinary() // 使用自定义 RLP,字段按字典序排列
if err != nil { return nil, err }
// 2. Keccak256 哈希(非 SHA256!)
hash := crypto.Keccak256(encoded)
// 3. ECDSA 签名(使用 secp256k1,v 值标准化为 0/1)
sig, err := crypto.Sign(hash[:], privKey)
if err != nil { return nil, err }
return &SignedRawTx{Raw: append(encoded, sig...), Hash: hash}, nil
}
MarshalBinary() 强制字段顺序(如 Nonce, GasPrice, To, Value, Data, ChainID),避免因 map 遍历随机性导致哈希漂移;sig 末字节 v 经 RecoverPubkey 可验证且兼容 EIP-155。
关键约束保障表
| 约束项 | 实现方式 |
|---|---|
| 字段排序确定性 | struct tag rlp:"xxx,order:1" |
| 空值编码一致 | nil slice → 0x80,非 0xC0 |
| ChainID 显式化 | EIP-155 兼容,防止重放攻击 |
graph TD
A[Transaction] --> B[RlpEncodeStrict]
B --> C[Keccak256 Hash]
C --> D[ECDSA Sign]
D --> E[SignedRawTx]
3.3 私钥生命周期管理:硬件模块集成接口与HSM兼容性适配策略
私钥生命周期管理的核心挑战在于跨厂商HSM的抽象统一。需通过标准化接口层解耦应用逻辑与硬件实现。
数据同步机制
采用PKCS#11 v3.0+ 的C_InitToken与C_GenerateKeyPair组合,确保密钥生成、导出禁止、销毁等操作原子性:
// 初始化HSM会话并生成ECDSA密钥对(P-256)
CK_RV rv = C_GenerateKeyPair(hSession,
&mechanism, // CKM_EC_KEY_PAIR_GEN
&pubTemplate, // CKA_EC_PARAMS = 1.2.840.10045.3.1.7
&privTemplate, // CKA_SENSITIVE=CK_TRUE, CKA_EXTRACTABLE=CK_FALSE
&hPubKey, &hPrivKey);
privTemplate中强制设CKA_SENSITIVE=CK_TRUE防止密钥明文导出;CKA_DESTROYABLE=CK_TRUE支持生命周期终结时安全擦除。
兼容性适配策略
| HSM厂商 | 接口协议 | 密钥封装格式 | 驱动适配方式 |
|---|---|---|---|
| Thales Luna | PKCS#11 + REST API | AES-KW | 统一Wrapper注入LunaProvider |
| AWS CloudHSM | Custom SDK | CMK ARN引用 | 抽象HsmClient接口多态实现 |
graph TD
A[应用层] --> B[KeyManager抽象类]
B --> C[PKCS#11 Provider]
B --> D[CloudHSM Adapter]
B --> E[TPM2.0 Shim]
C --> F[Thales/Luna]
D --> G[AWS CloudHSM]
第四章:生产级离线签名工程实践与加固方案
4.1 基于go-ethereum v1.13.5+的签名库重构:依赖锁定与语义化版本控制
为保障签名逻辑在跨链场景下的确定性,我们剥离 crypto 子模块,构建独立签名库 ethsign/v2,强制要求 go-ethereum@v1.13.5+。
依赖锁定策略
- 使用
go.mod显式 require 并replace指向已验证 commit:require github.com/ethereum/go-ethereum v1.13.5 replace github.com/ethereum/go-ethereum => github.com/ethereum/go-ethereum v1.13.5此写法确保
go build始终解析为精确 commit(如v1.13.5对应a7f6b5d...),规避 proxy 缓存导致的哈希漂移。
版本兼容性矩阵
| 主版本 | 支持的 go-ethereum | 签名算法兼容性 |
|---|---|---|
| v1 | ≤ v1.12.x | secp256k1 only |
| v2 | ≥ v1.13.5 | 支持 EIP-2098、EIP-712 typed data |
签名流程演进
graph TD
A[Raw message] --> B{v1: LegacySign}
A --> C{v2: TypedSign<br/>with domain hash}
C --> D[Keccak256(domain || structHash)]
重构后,Signer 接口新增 DomainHash() 方法,强制校验 EIP-712 域结构一致性。
4.2 签名请求校验中间件:RLP结构预检、字段白名单与GasPrice合理性断言
该中间件在 RPC 请求进入核心执行器前实施三重防御:
RLP 解析前置校验
拒绝非法嵌套或超长编码,避免解析器崩溃:
def validate_rlp_prefix(data: bytes) -> bool:
if len(data) == 0 or data[0] > 0xF7: # 超出 RLP 基本编码范围
return False
if data[0] >= 0xC0 and len(data) < 2: # list 编码至少需 2 字节(含长度前缀)
return False
return True
data[0] 判断编码类型(string/list),0xF7 是单字节最大值;0xC0 起为列表编码,必须携带长度信息。
字段白名单与 GasPrice 断言
| 字段 | 允许类型 | 是否必填 | 校验逻辑 |
|---|---|---|---|
to |
bytes | 否 | 长度为 0 或 20 |
gasPrice |
int | 是 | 1 Gwei ≤ x ≤ 1000 Gwei |
graph TD
A[RPC Request] --> B{RLP 结构有效?}
B -->|否| C[400 Bad Request]
B -->|是| D{字段在白名单?}
D -->|否| C
D -->|是| E{gasPrice ∈ [1e9, 1e12]?}
E -->|否| C
E -->|是| F[放行至执行层]
4.3 多签事务的离线协同协议:BIP-32路径绑定、阈值签名分片与审计日志嵌入
多签离线协同需在无网络交互前提下保障密钥安全、操作可溯与策略一致。核心依赖三项机制协同:
BIP-32路径绑定
将参与方的HD钱包路径(如 m/48'/0'/0'/2'/0')哈希后写入事务元数据,确保仅指定派生路径的私钥可解出对应分片。
阈值签名分片
采用Shamir’s Secret Sharing (t-of-n) 对ECDSA私钥进行分片,各签名者本地生成部分签名(R_i, s_i),最终聚合为有效 s = Σλ_i·s_i mod n。
# 分片签名聚合示例(t=2, n=3)
shares = [(1, 42), (2, 57), (3, 73)] # (x_i, s_i)
lambda_1 = (2*3) * pow((1-2)*(1-3), -1, 101) % 101 # 拉格朗日基多项式系数
s_final = (lambda_1 * 42 + (1-lambda_1) * 57) % 101 # 实际需全t项加权
逻辑:
lambda_i由公开x坐标计算,不泄露私钥;模数101为曲线阶近似,真实场景使用 secp256k1 阶n ≈ 2²⁵⁶;聚合前须验证各s_i对应同一R。
审计日志嵌入
事务输入脚本末尾追加OP_RETURN+SHA256(操作者ID+时间戳+BIP32路径+操作类型),形成不可篡改链上存证。
| 字段 | 长度 | 说明 |
|---|---|---|
| 操作者ID | 32B | Ed25519公钥哈希 |
| 时间戳 | 8B | Unix纳秒精度 |
| 路径摘要 | 32B | BIP-32路径SHA256 |
graph TD
A[发起方构造裸交易] --> B[绑定BIP-32路径哈希]
B --> C[分发t-of-n签名分片请求]
C --> D[各签署方本地验路径+签片段]
D --> E[聚合签名+嵌入审计日志]
E --> F[广播最终事务]
4.4 安全发布流程:签名二进制完整性验证、TUF仓库签名与SBOM生成自动化
安全发布不再仅依赖“构建即交付”,而是构建可验证、可追溯、可审计的发布闭环。
三重保障机制
- 签名二进制完整性验证:使用 Cosign 对容器镜像和二进制文件进行签名与验签
- TUF 仓库签名:通过 The Update Framework 管理元数据签名,防御中间人与仓库投毒
- SBOM 自动化生成:集成 Syft + Trivy,在 CI 流水线中实时输出 SPDX/SPDX-Tagged 格式清单
自动化流水线关键步骤
# 在 GitHub Actions 或 GitLab CI 中执行
cosign sign --key $COSIGN_PRIVATE_KEY my-registry/app:v1.2.0
syft -o spdx-json my-binary > sbom.spdx.json
cosign sign使用私钥对镜像摘要签名,验证时通过公钥+镜像 digest 确保未篡改;syft默认扫描文件系统依赖并生成标准 SPDX 结构,支持直接集成至 OCI 注解(oci://registry)。
验证流程(Mermaid)
graph TD
A[CI 构建完成] --> B[生成 SBOM]
B --> C[用 Cosign 签名二进制/SBOM]
C --> D[推送至 TUF 托管仓库]
D --> E[客户端 fetch 元数据 → 验证根/目标签名 → 下载可信资产]
第五章:未来演进方向与去中心化签名基础设施展望
跨链签名聚合协议的工业级部署案例
2023年,Chainlink CCIP 与 EigenLayer AVS 协同上线了首个生产环境中的去中心化阈值签名服务(D-TSS),支持以太坊、Arbitrum 和 Base 三链间资产桥接的实时签名验证。该系统将传统需 7 个中心化签名节点的流程重构为由 128 个质押验证者组成的动态签名委员会,采用 BLS 聚合签名+可验证随机函数(VRF)轮值机制,单次跨链消息确认延迟从平均 92 秒降至 3.1 秒(实测中位数)。其核心合约已通过 OpenZeppelin Audits 与 Trail of Bits 的双重形式化验证,漏洞赏金计划持续运行超 14 个月,未触发任何高危事件。
硬件级可信执行环境集成路径
Ledger Stax 设备自 v2.4.0 固件起原生支持 WebAuthn 标准下的 Secp256k1 非交互式零知识证明生成,允许用户在离线状态下完成对 EIP-712 结构化消息的 zk-SNARK 签名。该能力已被 Curve Finance 的治理投票前端集成——用户点击“投赞成票”后,设备自动构造包含身份绑定、时间戳和链上提案哈希的 SNARK 证明,并由链上 verifier 合约在 127,421 gas 内完成验证。下表对比了不同签名路径的实际开销:
| 签名方式 | Gas 消耗 | 验证时延(区块) | 是否支持离线签名 |
|---|---|---|---|
| ECDSA 原生签名 | 42,100 | 1 | 否 |
| Ledger + zk-SNARK | 127,421 | 1 | 是 |
| MPC 多签(3/5) | 89,600 | 2 | 否 |
基于意图的签名路由架构
UniswapX 引入 Intent-Centric Signing Layer(ICSL),将用户交易意图(如“以最优价格卖出 1 ETH 换 USDC”)作为签名对象而非具体交易。签名者使用 BLS 密钥对意图哈希进行签名,匹配引擎在链下聚合多个签名后,由专用 sequencer 提交最终执行交易。2024 年 Q1 数据显示,该模式使 MEV 损失降低 63%,且签名重放攻击面归零——因意图哈希内嵌链 ID、有效期及唯一 nonce,任意参数变更均导致签名失效。
flowchart LR
A[用户提交意图] --> B{ICSL 签名网关}
B --> C[分发至 3 类签名者:\n• 链上验证者\n• L2 序列器\n• 零知识证明服务]
C --> D[聚合 BLS 签名]
D --> E[链下匹配引擎生成最优执行路径]
E --> F[Sequencer 提交原子化交易]
开源硬件签名模组的社区演进
Trezor Model T2 的开源固件仓库(github.com/trezor/trezor-firmware)在 2024 年合并了 PR #2192,新增 RISC-V 架构的 CoSi(Collective Signing)协处理器驱动,支持在物理隔离区运行 Threshold ECDSA 算法。该模块已通过 NIST SP 800-193 标准的固件完整性度量验证,被 Gnosis Safe 的新版本客户端默认启用。截至 2024 年 6 月,全球已有 17 个 DAO 将其用于多签金库的紧急升级投票,累计处理 214,892 笔经硬件验证的签名请求,错误率保持为 0。
