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

Azure Key Vault P-256 EC密钥本地签名验证失败求助

问题分析与解决方案

你的验证失败核心有两个错误:

  1. 错误将签名按UTF8字节解析,实际需要对签名做Base64URL解码
  2. Azure Key Vault返回的签名是ASN.1/DER编码格式,而.NET的ECDsa.VerifyData默认期望原始的r-s拼接格式

修正后的代码

// x and y points from JWK
string x = "melmeVA/KKt+kTRGljKubiohqcwD9A65dyX3nxqxUg8=";
string y = "wSOw9N8jkoeMgdNMCeAAKop4kR9f8jrvDOZnpkc9Fw0=";

ECDsa key = ECDsa.Create(new ECParameters
{
    Curve = ECCurve.NamedCurves.nistP256,
    Q = new ECPoint
    {
        X = Base64UrlEncoder.DecodeBytes(x),
        Y = Base64UrlEncoder.DecodeBytes(y)
    }
});

var header = "{\"alg\":\"ES256\"}";
var body = "{\"key\":\"value\"}";
var toBeSigned = Base64UrlEncoder.Encode(header) + "." + Base64UrlEncoder.Encode(body);

// Sign API response (using the digest from above)
var signature = "ZBPn3jJpccDPasbasOfocjSkHpRA0bmn2963IMzraa50H5v5ovtavtilwpu7zf_8McwfR9qCrkXMiXBOf4W8BQ";

// 修正1:对签名做Base64URL解码,而非UTF8解析
byte[] signatureBytes = Base64UrlEncoder.DecodeBytes(signature);

// 修正2:指定签名格式为ASN.1 DER(.NET Core 3.0+/.NET 5+支持)
bool result = key.VerifyData(
    Encoding.UTF8.GetBytes(toBeSigned),
    signatureBytes,
    HashAlgorithmName.SHA256,
    DSASignatureFormat.Rfc3279DerSequence);

Console.WriteLine(result);

兼容旧版.NET的方案

如果你的项目使用不支持DSASignatureFormat的.NET版本,可以手动将ASN.1格式签名转换为r-s拼接格式:

private static byte[] ConvertDerToRs(byte[] derSignature)
{
    // ASN.1 DER结构:SEQUENCE { r INTEGER, s INTEGER }
    using (var ms = new MemoryStream(derSignature))
    using (var reader = new BinaryReader(ms))
    {
        if (reader.ReadByte() != 0x30) throw new InvalidDataException("无效签名格式");
        int length = reader.ReadByte();
        if (length == 0x81) length = reader.ReadByte();
        
        if (reader.ReadByte() != 0x02) throw new InvalidDataException("无效r字段");
        int rLength = reader.ReadByte();
        byte[] r = reader.ReadBytes(rLength).TrimLeadingZero();
        
        if (reader.ReadByte() != 0x02) throw new InvalidDataException("无效s字段");
        int sLength = reader.ReadByte();
        byte[] s = reader.ReadBytes(sLength).TrimLeadingZero();

        // P-256要求r/s均为32字节,补全长度
        r = r.PadLeft(32);
        s = s.PadLeft(32);

        return r.Concat(s).ToArray();
    }
}

private static byte[] TrimLeadingZero(this byte[] data)
{
    int startIndex = 0;
    while (startIndex < data.Length && data[startIndex] == 0) startIndex++;
    return startIndex == 0 ? data : data[startIndex..];
}

private static byte[] PadLeft(this byte[] data, int length)
{
    if (data.Length >= length) return data;
    byte[] padded = new byte[length];
    Array.Copy(data, 0, padded, length - data.Length, data.Length);
    return padded;
}

使用时替换验证逻辑:

byte[] rsSignature = ConvertDerToRs(signatureBytes);
bool result = key.VerifyData(Encoding.UTF8.GetBytes(toBeSigned), rsSignature, HashAlgorithmName.SHA256);

额外验证点

  • 确认JWK的x/y值是从Azure Key Vault密钥属性中正确提取的(必须是Base64URL编码,而非标准Base64)
  • 确认调用Sign API时使用的算法是ES256,与代码中签名算法保持一致

内容的提问来源于stack exchange,提问作者Brânica

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.22 05:02:02