【问题标题】:ECDSA DER signatureECDSA DER 签名
【发布时间】:2021-12-01 08:26:58
【问题描述】:

我在 Java 中生成了一个 ECDSA 签名,我想从中获取 R 和 S 值,以便获得 COSE 编码的签名。据我了解,我生成的签名是 DER 编码的(默认使用 bouncyCastle)。当我使用 P-256 曲线 (SHA256withECDSA) 时,我正确检索了 R 和 S 值。

当我使用其他曲线(P-521、P-384)时,我在将签名从一种编码解析到另一种编码时遇到了一些问题。

下面是我的解析方式:

public static byte[] extractRandSToCose(byte[] signature) {

    if (signature[0] == 0x30) {
        //parse R
        int rSize = signature[3];
        BigInteger rBigInt = new BigInteger(Arrays.copyOfRange(signature, 4, rSize+4));
        //strip out sign byte 0x00
        byte[] r = toByteArrayUnsigned(rBigInt);

        //parse S
        int sSize = signature[5 + rSize];
        int index = rSize + 6;
        BigInteger sBigInt = new BigInteger(Arrays.copyOfRange(signature, index, index+sSize));
        //strip out sign byte 0x00
        byte[] s = toByteArrayUnsigned(sBigInt);

        return Bytes.concat(r,s);
    }
    return null;
}


public static byte[] toByteArrayUnsigned(BigInteger bigInteger) {
    byte[] extractedBytes = bigInteger.toByteArray();
    int skipped = 0;
    boolean skip = true;
    for (byte b : extractedBytes) {
        boolean signByte = b == 0x00;

        if (skip && signByte) {
            skipped++;
            continue;
        } else if (skip){
            skip = false;
        }
    }
    extractedBytes = Arrays.copyOfRange(extractedBytes, skipped, extractedBytes.length);
    return extractedBytes;
}

我不明白我做错了什么。

PS:这些方法有时会起作用。它每次都适用于 P-256(DER 签名是 70 71 还是 72 字节长,并且正确地给了我 64 字节长的 Cose 签名),P-384(对于 102、103 104 字节长并且正确地给了我 96 字节)长 cose 签名),但只在 P-521 的一半时间内工作(138、139、140 字节长,即使它这样做,cose 签名也只有 31 字节长......)

【问题讨论】:

  • 将 ASN.1/DER 签名转换为 IEEE P1363 (r|s) 签名的替代方法是直接以 IEEE P1363 (r|s) 格式生成签名。较新的 BC 版本使用算法 SHA256withPlain-ECDSA(或 SHA384withPlain-ECDSASHA512withPlain-ECDSA)支持此格式。
  • 关于转换,使用 ASN.1 解析器(例如来自 BouncyCastle)可能更有效,参见例如DER Decode ECDSA Signature in Java.
  • @Topaco+ Bouncy 自 2014 年 1.51 起 - 或 SunEC 自 2017 年 9 起使用不同(且更笨拙)的命名 {hash}withECDSAinP1363Format。 OP:您的代码虽然很笨拙,但应该大部分适用于高达 488 位的任何曲线,包括 P-384; P-521/secp521r1 和 brainpool512 是上面唯一常见的,但是一些恰好具有算术上小的 r 和/或 s 的签名是错误的。
  • @dave_thompson_085 - 谢谢。我依稀记得后来添加了对 r|s 的支持,但不完全是什么时候。然后我想 BC 版本的 OP 应该可以工作 ;-)
  • 谢谢两位的回答,我去看看。为什么它不能在 488 位之后使用任何曲线?

标签: java bouncycastle signature ecdsa


【解决方案1】:

{hash}withECDSAinP1363Format 成功了!谢谢 !我什至不需要阅读所有这些规范来了解如何解析它......

【讨论】:

    猜你喜欢
    • 2017-01-16
    • 2015-10-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-11-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多