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

.NET中ECDSA签名从DER格式转换为RS格式的实现方案

AWS KMS DER格式签名转JWT兼容的RS格式(.NET实现)

JWT要求的RSASSA-PKCS1-v1_5签名是PKCS#1 raw格式(即直接拼接签名的R、S整数分量,无ASN.1编码结构),而AWS KMS返回的签名是DER编码的ASN.1结构,需要提取R、S分量后重新拼接。以下是两种可行的实现方式:

1. 使用.NET内置API手动转换

无需额外NuGet包,利用System.Formats.Asn1命名空间解析DER结构:

using System.Formats.Asn1;

public static byte[] ConvertDerToRawRSASignature(byte[] derSignature)
{
    // 解析ASN.1 DER格式的签名序列
    var reader = new AsnReader(derSignature, AsnEncodingRules.DER);
    var sequenceReader = reader.ReadSequence();
    
    // 读取R和S两个整数的字节数组
    byte[] r = sequenceReader.ReadIntegerBytes();
    byte[] s = sequenceReader.ReadIntegerBytes();
    
    // 根据密钥长度调整R、S为固定字节数(2048位密钥对应256字节,3072位对应384字节)
    int keySizeBytes = 256;
    r = PadToFixedLength(r, keySizeBytes);
    s = PadToFixedLength(s, keySizeBytes);
    
    // 拼接R和S得到JWT所需的raw签名
    byte[] rawSignature = new byte[keySizeBytes * 2];
    Buffer.BlockCopy(r, 0, rawSignature, 0, keySizeBytes);
    Buffer.BlockCopy(s, 0, rawSignature, keySizeBytes, keySizeBytes);
    
    return rawSignature;
}

private static byte[] PadToFixedLength(byte[] data, int targetLength)
{
    if (data.Length == targetLength)
        return data;
    
    byte[] padded = new byte[targetLength];
    // 处理ASN.1整数可能带的前导0,确保最终是固定长度的无符号整数字节
    int copyStart = data.Length > targetLength ? data.Length - targetLength : 0;
    int copyLength = Math.Min(data.Length, targetLength);
    Buffer.BlockCopy(data, copyStart, padded, targetLength - copyLength, copyLength);
    
    return padded;
}

转换后的raw签名可直接用于JWT的Base64Url编码(Convert.ToBase64String(rawSignature).Replace('+', '-').Replace('/', '_').TrimEnd('=')),或传入JwtSecurityTokenHandler完成JWT生成。

2. 使用BouncyCastle NuGet包简化操作

如果不想手动处理ASN.1解析,可引入BouncyCastle.Cryptography NuGet包:

using Org.BouncyCastle.Asn1.Pkcs;

public static byte[] ConvertDerToRawRSASignature(byte[] derSignature)
{
    var rsaSig = RsaSignature.FromDerEncoded(derSignature);
    int keySizeBytes = (rsaSig.ModulusBitLength + 7) / 8;
    
    byte[] r = rsaSig.R.ToByteArrayUnsigned();
    byte[] s = rsaSig.S.ToByteArrayUnsigned();
    
    r = PadToFixedLength(r, keySizeBytes);
    s = PadToFixedLength(s, keySizeBytes);
    
    byte[] rawSignature = new byte[keySizeBytes * 2];
    Buffer.BlockCopy(r, 0, rawSignature, 0, keySizeBytes);
    Buffer.BlockCopy(s, 0, rawSignature, keySizeBytes, keySizeBytes);
    
    return rawSignature;
}

// 复用前面的PadToFixedLength方法

关键注意事项

  • 需根据实际使用的KMS密钥长度调整keySizeBytes值,避免签名长度不匹配导致JWT验证失败。
  • 若直接生成JWT,可自定义ISecurityTokenSigningKeyProvider,在签名逻辑中调用上述转换方法,替代本地私钥签名流程。

内容的提问来源于stack exchange,提问作者busch-dk

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.10 02:01:11