java - ECC ASN1 签名验证失败

标签 java cryptography digital-signature bouncycastle elliptic-curve

我有 48 字节 ECC secp192r1 签名,可以在其他环境中工作:

byte[] signature = new byte[]{(byte)0x08, (byte)0x33, (byte)0x6B, (byte)0x27, (byte)0xBC, (byte)0x29, (byte)0x64, (byte)0x36, (byte)0x70, (byte)0x08, (byte)0x97, (byte)0x4F, (byte)0xA8, (byte)0xD7, (byte)0x1F, (byte)0x4D, (byte)0x05, (byte)0xF5, (byte)0xB2, (byte)0x0F, (byte)0x15, (byte)0x5D, (byte)0x68, (byte)0x61, (byte)0xB3, (byte)0x2B, (byte)0x0E, (byte)0xA9, (byte)0xFB, (byte)0x37, (byte)0xF1, (byte)0xD4, (byte)0x70, (byte)0xEA, (byte)0x2B, (byte)0xCA, (byte)0x53, (byte)0x9D, (byte)0x11, (byte)0xE7, (byte)0x26, (byte)0x37, (byte)0x92, (byte)0x73, (byte)0xDE, (byte)0x95, (byte)0x6C, (byte)0x4A};

它被编码为 ASN1 格式 ~54 字节长度:

    byte[] sig1 = Arrays.copyOfRange(signature, 0, 24);
    byte[] sig2 = Arrays.copyOfRange(signature, 24, 48);

    ASN1EncodableVector v = new ASN1EncodableVector();
    v.add(new ASN1Integer(new BigInteger(sig1)));
    v.add(new ASN1Integer(new BigInteger(sig2)));

    byte[] javaSig = new DERSequence(v).getEncoded();

但是,当我尝试验证数据时,它失败了。将签名编码为 ASN1 是否正确?

从 ASN1 到 48 字节格式的签名解码也存在同样的问题:

    ASN1InputStream input = new ASN1InputStream(signed);
    ASN1Primitive item = input.readObject();

    ASN1Sequence s = (ASN1Sequence)item;
    BigInteger[] items = new BigInteger[2];

    items[0] = ((ASN1Integer)s.getObjectAt(0)).getValue();
    items[1] = ((ASN1Integer)s.getObjectAt(1)).getValue();

    byte[] itBytes0 = items[0].toByteArray();
    byte[] itBytes1 = items[1].toByteArray();

最佳答案

byte[] 创建 BigInteger 时的一个常见问题是,在 Java 上默认情况下所有数字都被解释为单数:

BigInteger(byte[] val)

Translates a byte array containing the two's-complement binary representation of a BigInteger into a BigInteger.

我不知道您使用的算法是否需要有符号数或无符号数,但是显式强制 Java 将字节数组解释为无符号数是值得的:

v.add(new ASN1Integer(new BigInteger(1, sig1)));
v.add(new ASN1Integer(new BigInteger(1, sig2)));

关于java - ECC ASN1 签名验证失败,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37613566/

相关文章:

java - 下载文件之前通过套接字在客户端和服务器之间交换字符串

java - 如何应用onClick函数打开它的URL

ios - iOS 的简化加密库

c# - RSA解密公式的问题

java - 使用 Java keytool 生成 ECDSA key 对时选择曲线

c# - 对 PDF 文件进行数字签名

java - 我们可以在 lookbehind 表达式中使用量词吗?

java - 用 Jersey SSE : Detect closed connection 广播

c# - 密码学.NET,避免定时攻击

java - Android - 更改应用程序签名( keystore + key )