You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用JavaScript库验证Azure KeyVault签名出现间歇性失败如何解决

问题解决方案

认知确认

你提到的「Azure 采用的非确定性签名可正常通过区块链验证」的认知是正确的。ECDSA 签名验证仅校验 r、s 值与公钥、原始哈希的匹配性,与签名生成时使用的随机数k是随机(非确定性签名)还是固定生成(确定性签名)无关,只要签名符合规范均可通过验证。

偶现验证失败根因

你当前遇到的偶现失败是由于Azure Key Vault 返回的 Secp256k1 签名为 ASN.1 DER 可变长度编码格式,而区块链普遍要求固定 64 字节的 r+s 拼接格式:

  • DER 编码的 ECDSA 签名长度会随 r、s 值的大小在 70~72 字节区间波动
  • 当编码后的长度刚好能被错误转换为符合要求的格式时验证成功,否则失败,因此出现偶现通不过的情况

修复步骤

1. 接口参数校验

调用 Azure Key Vault 签名接口时,签名算法必须指定为 ES256K,避免算法不匹配导致的签名错误。

2. DER 签名格式转换

将 Key Vault 返回的 RawURL 解码后的字节,先解析 ASN.1 DER 结构提取 r、s 大整数,再转换为链上要求的 64 字节拼接格式,同时可兼容处理区块链普遍要求的低S值规则(避免签名延展性问题),Golang 参考代码如下:

import (
	"encoding/asn1"
	"math/big"
)

// DER格式ECDSA签名结构定义
type ecdsaSig struct {
	R *big.Int
	S *big.Int
}

// Secp256k1曲线阶常量
var secp256k1N, _ = new(big.Int).SetString("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141", 16)
var halfN = new(big.Int).Rsh(secp256k1N, 1)

func convertAzureSigToChainSig(rawSig []byte) ([]byte, error) {
	var sig ecdsaSig
	_, err := asn1.Unmarshal(rawSig, &sig)
	if err != nil {
		return nil, err
	}
	// 处理低S值规则
	if sig.S.Cmp(halfN) > 0 {
		sig.S.Sub(secp256k1N, sig.S)
	}
	// R、S补前导0到32字节
	rBytes := sig.R.Bytes()
	sBytes := sig.S.Bytes()
	rPadded := make([]byte, 32)
	copy(rPadded[32-len(rBytes):], rBytes)
	sPadded := make([]byte, 32)
	copy(sPadded[32-len(sBytes):], sBytes)
	// 拼接为64字节签名
	return append(rPadded, sPadded...), nil
}

3. 上游逻辑校验

确认步骤1的十六进制转字节逻辑正确,没有误处理0x前缀、大小写等问题;步骤2的SHA256哈希运算结果为标准32字节,无额外填充或截断。

修复后流程调整

原流程的第5步之后,新增上述DER签名转换逻辑,再执行第6步转十六进制即可解决偶现验证失败问题。


内容的提问来源于stack exchange,提问作者Jaswinder Singh

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.24 09:12:08