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

.Net Core中ECDsa签名SXGs更新请求提示公钥签名无效

问题原因分析

你遇到的签名验证失败,核心原因是**.NET Core生成的签名格式与OpenSSL dgst -sign输出的格式不一致**:

  • OpenSSL的dgst -sign默认输出ASN.1 DER格式的ECDSA签名(包含SEQUENCE包裹的r和s整数)
  • .NET Core的ECDsa.SignData默认输出IEEE P1363格式的签名(直接拼接r和s的字节数组)

缓存服务器期望的是OpenSSL兼容的ASN.1 DER格式签名,所以需要对.NET生成的签名做格式转换。

解决方案

修改你的.NET代码,将P1363格式的签名转换为ASN.1 DER格式,具体步骤如下:

1. 添加签名格式转换方法

新增一个方法,将P1363格式的签名字节数组转换为ASN.1 DER格式:

private static byte[] ConvertP1363ToDer(byte[] p1363Signature)
{
    // 对于prime256v1,r和s各32字节
    int halfLength = p1363Signature.Length / 2;
    byte[] r = p1363Signature.Take(halfLength).ToArray();
    byte[] s = p1363Signature.Skip(halfLength).ToArray();

    // 处理整数的DER编码:去掉前导零,若最高位为1则加0x00前缀
    r = PrepareDerInteger(r);
    s = PrepareDerInteger(s);

    // 构建SEQUENCE:0x30 + 总长度 + r的DER编码 + s的DER编码
    int sequenceLength = 2 + r.Length + 2 + s.Length;
    using (var ms = new MemoryStream())
    {
        ms.WriteByte(0x30);
        WriteLength(ms, sequenceLength);
        ms.WriteByte(0x02);
        WriteLength(ms, r.Length);
        ms.Write(r);
        ms.WriteByte(0x02);
        WriteLength(ms, s.Length);
        ms.Write(s);
        return ms.ToArray();
    }
}

private static byte[] PrepareDerInteger(byte[] data)
{
    // 去掉前导零
    int startIndex = 0;
    while (startIndex < data.Length && data[startIndex] == 0)
    {
        startIndex++;
    }
    if (startIndex == data.Length)
    {
        return new byte[] { 0x00 }; // 表示整数0
    }
    // 如果最高位是1,添加0x00前缀避免被解析为负数
    if ((data[startIndex] & 0x80) != 0)
    {
        var result = new byte[data.Length - startIndex + 1];
        result[0] = 0x00;
        Buffer.BlockCopy(data, startIndex, result, 1, data.Length - startIndex);
        return result;
    }
    return data.Skip(startIndex).ToArray();
}

private static void WriteLength(MemoryStream ms, int length)
{
    if (length < 0x80)
    {
        ms.WriteByte((byte)length);
    }
    else
    {
        // 处理长长度(这里prime256v1的签名不会用到,仅做兼容)
        byte[] lengthBytes = BitConverter.GetBytes(length).Reverse().ToArray();
        ms.WriteByte((byte)(0x80 | lengthBytes.Length));
        ms.Write(lengthBytes);
    }
}

2. 修改签名生成逻辑

在生成签名后,调用转换方法将格式转为ASN.1 DER:

string timestamp = ((int)(DateTime.UtcNow.Subtract(new DateTime(1970, 1, 1))).TotalSeconds).ToString();
string message = url + " " + timestamp;
string signature = "";

using (ECDsa ecDsa = ECDsa.Create())
{
    string key = File.ReadAllText(ecprivkeyPath);
    ecDsa.ImportFromPem(key);
    byte[] data = Encoding.ASCII.GetBytes(message);

    byte[] p1363Signature = ecDsa.SignData(data, HashAlgorithmName.SHA256);
    // 转换为ASN.1 DER格式
    byte[] derSignature = ConvertP1363ToDer(p1363Signature);
    signature = Convert.ToBase64String(derSignature);
}

3. 其他验证点

  • 确认url变量与bash脚本中的URL完全一致(包括协议、域名、路径,无多余空格)
  • 确认私钥文件读取正确,没有额外的换行或空格
  • 确认timestamp是UTC时间戳(你的代码已经用了DateTime.UtcNow,没问题)
测试验证

可以将.NET生成的signature和bash脚本生成的signature对比:

  1. 用bash脚本生成一个固定timestamp的signature
  2. 在.NET中手动设置相同的timestamp,生成signature
  3. 对比两个base64字符串是否一致,一致则说明格式转换正确

内容的提问来源于stack exchange,提问作者Naveed Ahmed

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.24 14:17:20