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

带弹性城堡的ECDSA标志及openssl验证

王经赋
2023-03-14

我有一个自签名证书(不是流行的X.509证书)。证书和ECDSA公钥/私钥对由java程序使用bouncy Castle生成。我需要使用OpenSSL用C程序验证这个证书。然而,java程序可以正确地验证ECDSA签名,但openssl验证失败。如果我使用相同的私钥用openssl对消息重新签名,那么使用openssl的签名验证将通过。

下面是与密钥生成相关的java代码片段(生成密钥对后,我实际上将它们保存在文件中,因此它将始终使用相同的密钥,下面的代码片段中没有显示)。

KeyPair rootCASigningKeys = cryptoManager.generateKeyPair(SignatureChoices.ecdsaNistP256Signature);

BCECPublicKey bcPub = cryptoManager.toBCECPublicKey(PublicKeyAlgorithm.ecies_nistp256, (java.security.interfaces.ECPublicKey) rootCASigningKeys.getPublic());
ECPublicKey pk = (java.security.interfaces.ECPublicKey) rootCASigningKeys.getPublic();
ECPrivateKey priv = (ECPrivateKey) rootCASigningKeys.getPrivate();

System.out.println("pubkeyX="+getHexString(pk.getW().getAffineX().toByteArray()));
System.out.println("pubkeyY="+getHexString(pk.getW().getAffineY().toByteArray()));
System.out.println("privatekey="+getHexString(priv.getS().toByteArray()));
bool v2x_ecdsa_verify(
        const uint8_t *digest,
        size_t dgstlen,
        const void *sig,
        const void *pkey)
{
 ECDSA_SIG *ecdsa_sig;
    EC_KEY *ec_key;
    EC_GROUP *grp
    int ret;

    /* debug */
    EC_POINT *ecpt;
    /* debug end */

    grp = EC_GROUP_new_by_curve_name(NID_X9_62_prime256v1); /*TODO: */
    ecpt = EC_KEY_get0_public_key((const EC_KEY *)pkey);
    struct ec_point_st *cpt = (struct ec_point_st *)ecpt;
    printf("Pubkey_x:%d=\n", BN_num_bytes(&cpt->X));
    BN_print_fp(stdout, &cpt->X);
    printf("Pubkey_y:%d=\n", BN_num_bytes(&cpt->Y));
    BN_print_fp(stdout, &cpt->Y);
    printf("\n");


    printf("digest dump\n");
    v2x_dump_hex(V2X_LOG_ERR, digest, 32);
    printf("\n");
    {
        /* DEBUG code, Use the private key outputed by Java code to re-sign the digest */
        uint8_t priv_buf[] = {
            0x00, 0xB2, 0x6C, 0x1D, 0x0C, 0x62, 0x84, 0x45, 0x31, 0x3C, 0xF3, 0x83, 0x1D, 0x4E, 0xA7, 0x4B,
            0x2C, 0x07, 0x19, 0xCF, 0x19, 0xCC, 0x3E, 0xA7, 0xE5, 0x4F, 0xA4, 0xF0, 0x91, 0xBF, 0x5B, 0x96, 0xE8};
        BIGNUM *priv_bn = BN_bin2bn(priv_buf, sizeof(priv_buf), NULL);
        printf("priv_bn=\n");
        BN_print_fp(stdout, priv_bn);
        printf("\n");
        if (!priv_bn) {
            V2X_ERR("Failed to conver privkey \n");
            return false;
        }
        EC_KEY *priv_key = EC_KEY_new();
        if (priv_key) {
            if (!EC_KEY_set_group(priv_key, grp)) {
                V2X_ERR("Failed to set group\n");
                return false;
            }
            EC_KEY_set_private_key(priv_key, priv_bn);
        }
        ecdsa_sig = v2x_ecdsa_sign(digest, dgstlen, NULL, 0, (void *)priv_key);
    /* END of DEBUG code */
    }
    //ret = ECDSA_do_verify(digest, dgstlen, (ECDSA_SIG *)sig, (EC_KEY *)pkey); /* It fail to verify original signature */
    ret =  ECDSA_do_verify(digest, dgstlen, ecdsa_sig, (EC_KEY *)pkey); /* it pass to verify the re-signed signature */

    if (ret < 0)
        V2X_ERR("ret=%d\n", ret);

    return (bool)ret;
}
provider=BC
pubkeyX=00 E4 B6 E1 50 C2 7A 85 DD BD 92 F8 14 C9 0E B0 5E 1E 28 A6 3C A3 B6 B1 69 32 39 BF 1B 1B F0 B0 03 
pubkeyY=00 ED DC 75 F0 E9 36 05 25 5F 54 08 74 E7 9D 6E BC 1B DF 97 5A E4 D2 A7 04 A7 E0 5F 21 06 54 26 1E 
privatekey=00 B2 6C 1D 0C 62 84 45 31 3C F3 83 1D 4E A7 4B 2C 07 19 CF 19 CC 3E A7 E5 4F A4 F0 91 BF 5B 96 E8 
F40D983058408C0519D7E238BEBFA5EDCAA7F3B86AD4C83847F5DD66EA1C051B
Pubkey_x:32=
E4B6E150C27A85DDBD92F814C90EB05E1E28A63CA3B6B1693239BF1B1BF0B003
Pubkey_y:32=
EDDC75F0E93605255F540874E79D6EBC1BDF975AE4D2A704A7E05F210654261E
digest dump
        f4 0d 98 30  58 40 8c 05  19 d7 e2 38  be bf a5 ed
        ca a7 f3 b8  6a d4 c8 38  47 f5 dd 66  ea 1c 05 1b


priv_bn=
B26C1D0C628445313CF3831D4EA74B2C0719CF19CC3EA7E54FA4F091BF5B96E8

我很难理解,java程序可以签名和验证给定的摘要,而C程序可以使用相同的密钥对签名和验证相同的摘要。但是C程序不能验证java程序生成的签名。我还从java中删除了生成的签名R/S部分,并与我试图在C程序中验证的结果进行了比较,它们是相同的。

我可以深入OpenSSL来添加调试,但可惜我不是java bouncy Castle方面的专家。如有任何建议,不胜感激!谢谢,也很抱歉发了这么长的帖子。

共有1个答案

马银龙
2023-03-14

我想出了问题,用于签名的摘要多走了一步,我错过了,结果用于验证的摘要与用于签名的摘要不同,所以失败了。

 类似资料:
  • 使用PEM证书,如 我的问题是,AFAIK,pemparser中没有密码的位置。 有人能给我一个如何将代码迁移到PEMParser版本的例子吗?

  • 我知道曲线名称()以及EC公钥的和坐标。 如何用它们创建? 我读过https://stackoverflow.com/a/29355749/5453873,但是那里的代码使用而不是,ECPublicKey是中的接口,而不是一个可实例化的类。

  • 我已经创建了一个小程序来使用Bouncy Castle 1.47 API生成一个DSA/El Gamal PGP钥匙环。密钥生成过程非常顺利,没有一个错误。我使用ARRAMED输出将私钥和公钥导出到一个文件,当我尝试用GPG(确切地说是KGpg)导入生成的私钥时,我得到以下错误: 单击OK后,它告诉我只处理了1个密钥。看起来它只拿了DSA键,因为在屏幕上它显示为1024/0。 **编辑**我刚刚尝

  • 我正在处理一个包含多个子项目的项目,它们都使用我创建的用于哈希、签名和加密消息的实用程序库。这个库基本上是bouncy Castle的包装器。 当我运行与库相关联的测试时,一切都通过了,一切都好了。当我将实用程序库打包到jar中时,会发生两件事: 正在使用库的子项目找不到与bouncy Castle关联的JAR。 即使将bouncy castle JAR添加到正在使用库的子项目中,项目也找不到bo

  • Ladar Levison编写了ecies_encrypt和ecies_decrypt C函数。这些功能与ECIES弹力城堡兼容吗?如果不是,有没有人知道要修复什么或者ecies的另一个C实现?

  • 长话短说:我需要使用加密来对编码的数字执行乘法运算。 我目前正在使用与配合使用,并为JCE找到了一个名为Bouncy Castle的很好的提供程序。它在标准的内提供加密。然而,我完全不知道如何对我从中得到的加密消息执行乘法运算。