Flutter eth_sig_util 在鸿蒙上的签名实践
eth_sig_util 是一个专门为以太坊签名习惯优化的 Dart 库,覆盖了 personal_sign、signTypedData、公钥恢复这些核心操作。因为纯 Dart 实现,它在鸿蒙(OpenHarmony)上可以直接跑,不用折腾原生桥接,集成成本很低。
它能做什么
本质就是基于 Secp256k1 椭圆曲线的消息哈希与签名构造。下边这几个场景在 Web3 应用里几乎必用:
- 个人消息签名,自动拼接
\x19Ethereum Signed Message:\n前缀,签出来的结果能直接被 EVM 兼容链识别。 - EIP-712 结构化数据签名,对分层数据进行递归哈希,让用户在确认弹窗里看到资产、授权等可读字段,而不是一段十六进制乱码。
- 从签名和消息中逆向恢复签发者的以太坊地址,适合做'免私钥参与'的身份验证。
流程大致是这样:消息格式化并加盐 → 私钥 Secp256k1 签名 → 打包输出签名三元组 V, R, S → 需要时再从签名恢复地址。整个计算链路在 Dart 侧完成,不依赖额外原生模块。
鸿蒙适配情况
因为库只依赖底层的加密数学运算(纯 Dart),所以对 OpenHarmony 是全量支持的。需要留意的是,批量验签或高频签名时,BigInt 运算会产生不少临时对象,对 CPU 和内存有压力,建议分批异步处理,避免一次性扫全量历史数据导致主线程卡顿。
私钥管理上,理想的方式是借助鸿蒙的 HUKS 硬件安全存储:把资产私钥锁在安全网关里,签名动作先由 eth_sig_util 构造好待签名哈希,再调硬件接口完成计算。这样哈希在应用层,签名在安全区,能平衡好性能和安全。
基本用法:用签名做身份登录
pubspec.yaml 里加上:
dependencies:
eth_sig_util: ^0.0.9+ # 建议选最新稳定版
下面是一个典型的去中心化登录流程——用私钥签名一段消息,再恢复地址核验身份:
import 'package:eth_sig_util/eth_sig_util.dart';
String generateLoginSignature(String privateKey, String message) {
// signPersonalMessage 会自动处理以太坊签名前缀
final signature = EthSigUtil.signPersonalMessage(
privateKey: privateKey,
message: message.codeUnits,
);
print('签名结果:$signature');
return signature;
}
void verifySignature(String signature, String message) {
final recoveredAddress = EthSigUtil.recoverPersonalSignature(
signature: signature,
message: message.codeUnits,
);
print('恢复到的地址:$recoveredAddress');
}
结构化数据签名(EIP-712)
比如 NFT 挂单授权,呼出 signTypedData 并传入定好域和结构的 JSON,用户就能看见具体的金额、有效期等字段。签出来的结果符合 ERC-712 规范,钱包、合约间互认没障碍。
常见坑与处理
- 批处理性能:大批量验证签名时,底层 BigInt 运算容易产生内存峰值。我通常的做法是分页 + 异步,每次处理一小批,间隔释放。
- 十六进制字符串格式:有些输入的私钥或消息哈希可能带
0x前缀,或者长度没补零,跟库内部预期不一致就会直接报错。建议在调用前统一做一次清洗,去掉可选前缀,固定长度。
附一个简单的签名状态面板
非必要,但可以在开发调试时直观显示当前签名层配置:
import 'package:flutter/material.dart';
class SignaturePanel extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Container(
padding: EdgeInsets.all(16),
decoration: BoxDecoration(
color: Colors.blueGrey[900],
borderRadius: BorderRadius.circular(12),
),
child: Column(
children: [
Icon(Icons.lock_person, color: Colors.cyanAccent, size: 48),
Text(
'签名层:V3 (Secp256k1)',
style: TextStyle(color: Colors.white, fontSize: 16),
),
Divider(color: Colors.cyan),
Text(
'哈希引擎:Keccak-256',
style: TextStyle(color: Colors.white70),
),
Text(
'EIP-712 支持:已开启',
style: TextStyle(color: Colors.greenAccent),
),
],
),
);
}
}


