当前位置: 首页 > 知识库问答 >
问题:

如何在由ECDSA[r,s]值组成的openssl中验证签名?

许华清
2023-03-14

我使用Bouncy Castle/Java生成签名,因为它给出了两个带有R,S值的大整数。现在的要求是使用OpenSSL命令来验证。

public static String[] generateSignature(String message) {
    final ECDSASigner ecdsaSigner = new ECDSASigner();

    try {

        // Get private key

        BCECPrivateKey ecPrivateKey = (BCECPrivateKey) JKSUtil.getPrivateKey();
        if(ecPrivateKey != null) {
            // Get parameter spec from private key
            ECParameterSpec ecSpec = ecPrivateKey.getParameters();

            // Create ECDomain object
            ECDomainParameters params = new ECDomainParameters(ecSpec.getCurve(), ecSpec.getG(), // G
                    ecSpec.getN()); // n

            // Create private key parameters
            ECPrivateKeyParameters priKey = new ECPrivateKeyParameters(ecPrivateKey.getD(), // d
                    params);

            ecdsaSigner.init(true, priKey);

            // Create digest message (hash) for the actual message. 
            SHA256Digest keyDigest = new SHA256Digest();
            keyDigest.update(message.getBytes(), 0, message.getBytes().length);
            byte[] digestMessage = new byte[keyDigest.getDigestSize()];
            keyDigest.doFinal(digestMessage, 0);
            BigInteger[] sig = ecdsaSigner.generateSignature(digestMessage);

            // Convert signature to base64
            String[] base64Sig = new String[2];
            base64Sig[0] = new String(Base64.encodeBase64(sig[0].toByteArray()));
            base64Sig[1] = new String(Base64.encodeBase64(sig[1].toByteArray()));
            String signature = base64Sig[0]+"|"+base64Sig[1];

            System.out.println(signature);

            return base64Sig;
        }
    } catch (Exception e) {

    }

    return null;
}

例如:我要签名的消息是“name is rs”,运行上面的实用程序将返回R和S值,分隔符为'',在base64中编码为

ALk8VQP5XLmCIe0Kh3IE74fS55huvzv0jw==|Hj+UsStEbDYOqX98EszSET2ULE3D9kCV

现在在openssl端:

openssl enc  -base64 -d -in signature.txt -out signatureToVerify.bin -A
openssl dgst -sha256 -verify eckey.pub -signature signatureToVerify.bin message.txt

它无法验证,我被困住了--在openssl端不断得到“验证失败”的错误。

共有1个答案

习华灿
2023-03-14

OpenSSL需要X9.62签名。这包括两个整数值R和s的DER编码。如果查看provider类Signaturespi的Bouncy Castle源代码,您会发现:

ASN1EncodableVector v = new ASN1EncodableVector();
v.add(new ASN1Integer(r));
v.add(new ASN1Integer(s));
byte[] derEncodedSignature = new DERSequence(v).getEncoded(ASN1Encoding.DER);

这是您应该使用弹跳城堡来编码签名的。这里RS应该是您在两个元素结果数组中获得的BigInteger值。

正如您可能已经猜到的,您也可以使用Java JCAsignatural类,这将产生相同的签名编码。如果需要或需要,您可以通过注册/指示提供者来使用BouncyCastle实现作为底层提供者。有趣的是,Bouncy Castle库现在有了一个相当快的EC实现,它胜过了Oracle提供的实现,即使是在本机代码中。

二进制输出与OpenSSL的签名输入直接兼容。要创建文本字符串,可以将字节数组编码为基本的64字符串(最好没有行尾,例如base64.encode(DerencodedSignatura)),然后必须通过openSSL enc-base64-a-d-in signature.txt-out signaturetoverify.bin对其进行解码

 类似资料:
  • 我正在写一段代码来检查签名 如果r和s是正的,我下面的代码可以工作,否则验证失败。 我的代码是 我的签名是从原始的r和s开始,以der格式创建的。请记住,如果r或s是负数,要在der格式中添加“00 ”,我还使用了BouncyCastle ANS1类 但是我仍然能够验证r和s是否为正,如果其中一个为负,我就不能验证(初始字节大于0x80) 我错过了什么? -----编辑----- 我已经创建了一个

  • 我尝试使用java客户端对内容进行签名,然后在服务器(nodejs)上进行验证。我的客户端签名函数使用ECDSA并返回一个< code>byte[]。我可以访问服务器上包含< code>publicKey的< code>x和< code>y坐标值。 是否可以找到构成签名的和?如何将从上面获得的<code>字节〔〕对或<code>DER编码的签名 编辑: 谢谢戴夫的评论,我正在使用这个SO答案中指示

  • 我想创建一个签名并使用openssl验证它。我想有我的签名的十六进制输出。 这是我的密码 我得到这个错误: 如果我在创建签名的过程中删除了-hex,它就可以工作了。

  • 我正在尝试使用公钥验证散列的ECDSA签名。我写了一个小的围棋程序,成功地做到了这一点,但是我不能把它移植到C语言中。 这是我的输入数据: < li >公钥:< code > mfkwewyhkozizj 0 caqyikozij0 dackcdqgaedd 9 vxm phjv 4 vofo 0 zofplr r5 iczxquxsr 9 eka ouo 9 b 7 wl 1 daggi 0 e

  • 我传入以下内容(摘要/哈希是SHA1): 到此功能: 但我无法在OpenSSL中验证签名(verify_success为0),即使完全相同的数据在C#中验证成功。 关于我为什么或做错了什么的任何想法? C#中的公钥是: 我假设4543533120000000是。NET特定的东西,所以我只是把04前置到它的其余部分。 这是用于验证签名的C#代码,它成功地做到了(dataBytes的SHA1在两个程序

  • 我使用OpenSSL(在C中)对文本进行签名,但是我的Java程序并不总是验证签名的消息(只有大约1/5得到验证)。有趣的是,https://kjur.github.io/jsrsasign/sample/sample-ecdsa.html没有证实其中任何一个: 曲线名称:secp256k1签名算法:SHA256with ECDSA 私钥 密钥 失败: 成功: 爪哇 C.