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

Java解析ECDSA DER签名提取R/S生成COSE签名异常问题咨询

问题原因及修复方案

根因分析

  • 硬编码DER结构偏移:你当前代码默认DER SEQUENCE的长度字段为1字节(短编码形式),仅适用于总长度<=127的DER签名。P-256、P-384的最长DER签名长度分别为72、104,都小于127,所以运行正常;P-521的最长DER签名长度可达140,超过127时会使用长编码形式的长度字段(占2字节),此时硬编码的rSize = signature[3]实际读到的是R字段的tag值0x02,直接导致长度读取错误,解析出来的R、S长度异常,刚好符合你提到的「仅半数场景可运行、输出长度过短」的表现。
  • 缺少固定长度补全逻辑:COSE规范要求ECDSA签名的R、S值必须为和曲线阶匹配的固定大端长度:P-256各32字节、P-384各48字节、P-521各66字节,你提取完无符号字节后没有补前导0对齐长度,也会导致最终拼接的签名长度不符合要求。

修复方案

推荐使用BouncyCastle内置的DER解析能力,避免自己手写偏移解析逻辑出错,修复后代码如下:

import org.bouncycastle.asn1.ASN1Integer;
import org.bouncycastle.asn1.ASN1Sequence;
import java.math.BigInteger;
import java.util.Arrays;

// 各曲线对应的R/S固定长度常量
public static final int P256_RS_LEN = 32;
public static final int P384_RS_LEN = 48;
public static final int P521_RS_LEN = 66;

public static byte[] extractRandSToCose(byte[] derSignature, int rsFixedLength) throws Exception {
    if (derSignature == null || derSignature[0] != 0x30) {
        return null;
    }
    // 自动处理DER长短编码,无需手动计算偏移
    ASN1Sequence seq = ASN1Sequence.getInstance(derSignature);
    BigInteger r = ((ASN1Integer) seq.getObjectAt(0)).getValue();
    BigInteger s = ((ASN1Integer) seq.getObjectAt(1)).getValue();
    
    // 转无符号大端字节并补前导0到固定长度
    byte[] rBytes = toFixedLengthUnsigned(r, rsFixedLength);
    byte[] sBytes = toFixedLengthUnsigned(s, rsFixedLength);
    
    // 拼接为COSE要求的格式
    byte[] coseSig = new byte[rsFixedLength * 2];
    System.arraycopy(rBytes, 0, coseSig, 0, rsFixedLength);
    System.arraycopy(sBytes, 0, coseSig, rsFixedLength, rsFixedLength);
    return coseSig;
}

private static byte[] toFixedLengthUnsigned(BigInteger value, int length) {
    byte[] unsigned = value.toByteArray();
    // 去掉BigInteger默认带的前导符号位0x00
    if (unsigned[0] == 0x00) {
        unsigned = Arrays.copyOfRange(unsigned, 1, unsigned.length);
    }
    // 长度不足时补前导0对齐要求长度
    if (unsigned.length < length) {
        byte[] padded = new byte[length];
        System.arraycopy(unsigned, 0, padded, length - unsigned.length, unsigned.length);
        return padded;
    }
    return unsigned;
}

使用示例

  • P-256场景调用:extractRandSToCose(derSig, P256_RS_LEN) 返回64字节COSE签名
  • P-384场景调用:extractRandSToCose(derSig, P384_RS_LEN) 返回96字节COSE签名
  • P-521场景调用:extractRandSToCose(derSig, P521_RS_LEN) 返回132字节COSE签名

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.30 03:06:00