如何在near_sdk_rs智能合约中实现消息签名的链上验证?
在NEAR智能合约(near_sdk_rs)中实现消息签名与验证
NEAR基于Ed25519加密算法处理签名验证,在near_sdk_rs中可直接利用SDK提供的工具类实现消息签名的链上验证,核心是校验签名、消息与公钥的匹配关系,甚至可关联到具体NEAR账号。
核心实现步骤
1. 基础签名验证(仅校验签名与公钥、消息的匹配)
通过解析传入的公钥、签名,调用SDK内置方法确认签名有效性:
use near_sdk::{near_bindgen, PublicKey, crypto::Signature}; #[near_bindgen] #[derive(Default)] pub struct Contract; #[near_bindgen] impl Contract { /// 验证消息签名是否匹配指定公钥 pub fn verify_signature(&self, message: Vec<u8>, signature: Vec<u8>, public_key: Vec<u8>) -> bool { // 解析公钥,失败则返回false let pk = match PublicKey::from_bytes(&public_key) { Ok(pk) => pk, Err(_) => return false, }; // 解析签名,失败则返回false let sig = match Signature::from_bytes(&signature) { Ok(sig) => sig, Err(_) => return false, }; // 核心验证:签名是否由该公钥对目标消息生成 sig.verify(&message, &pk) } }
2. 进阶:验证签名者为指定NEAR账号
若需确认签名者是具体账号,可先获取该账号的所有关联公钥,再逐一验证签名是否匹配:
use near_sdk::{near_bindgen, crypto::Signature, env}; #[near_bindgen] impl Contract { /// 验证签名是否来自指定NEAR账号 pub fn verify_signature_for_account(&self, message: Vec<u8>, signature: Vec<u8>, account_id: String) -> bool { // 查询目标账号的绑定公钥列表 let account = match env::view_account(&account_id) { Ok(account) => account, Err(_) => return false, }; // 遍历公钥逐一验证 for pk in account.public_keys { match Signature::from_bytes(&signature) { Ok(sig) => { if sig.verify(&message, &pk) { return true; } }, Err(_) => continue, } } // 所有公钥均不匹配则返回false false } }
关键注意事项
- 消息一致性:前端签名的消息与合约接收的消息必须完全一致(包括编码格式,如字符串转字节需用UTF-8),否则验证会失败。
- 签名生成规范:前端需使用NEAR官方工具生成签名,比如
near-api-js的signMessage方法,确保签名符合Ed25519标准。 - 公钥获取方式:前端可通过NEAR钱包API获取用户公钥(如
window.nearConnection.signer.getPublicKey(accountId, networkId)),再传递给合约。 - 权限补充校验:针对敏感操作,除签名验证外,还可结合
env::predecessor_account_id()确认调用者身份,实现多重安全校验。
内容的提问来源于stack exchange,提问作者marethyu
相关产品推荐
相关产品推荐

