【问题标题】:ECDSA: How to get y coordinate from uncompressing x using opensslECDSA:如何使用 openssl 从解压缩 x 中获取 y 坐标
【发布时间】:2021-10-20 02:01:52
【问题描述】:

我试图用 ECDSA 做的是从外部 ECDSA 硬件(它实际上是一个公钥)获取的值中获取一个 x“压缩”坐标和一个 y“位”,然后尝试恢复 y 坐标(未压缩) OpenSSL 函数调用。

我正在尝试以下代码,但它没有按预期工作(我的 xy[] 数组没有填充正确的数据)。有人可以帮忙吗?

我是 ECDSA 的新手,甚至是 OpenSSL 的新手,但我想我可以做到以下几点:

EC_GROUP *curve_group = EC_GROUP_new_by_curve_name(NID_X9_62_prime192v1);
EC_POINT *point;
BIGNUM *x_compressed = BN_new();
int y_chooser_bit = 1;
int results = 0;
size_t returnsize = 0;
 
unsigned char x_compressed_byte_array[25] = {0x02, 0x71, 0xc0, 0x73, 0x73, 
                                             0x9b, 0xbf, 0xc2, 0x0a, 
                                             0x81, 0xcd, 0xdd, 0xf4, 
                                             0xcf, 0xca, 0xc7, 0xb5, 
                                             0xa9, 0x99, 0x61, 0x23, 
                                             0x2c, 0x5c, 0x63, 0x7a};

unsigned char xy[49];

// create a big number from the unsigned char array
BN_bin2bn(&x_compressed_byte_array[0],200,NULL); // length is in bits?

point = EC_POINT_new(curve_group);

results = EC_POINT_set_compressed_coordinates_GFp(curve_group, point, 
                                                  x_compressed,                                                               
                                                  y_chooser_bit, NULL);

returnsize = EC_POINT_point2oct(curve_group, point, 
                                POINT_CONVERSION_UNCOMPRESSED, 
                                &xy[0], 49, NULL); // 49

// clean up allocated memory
BN_free(x_compressed);
EC_POINT_free(point);
EC_GROUP_free(curve_group);

【问题讨论】:

    标签: openssl compression point ecdsa


    【解决方案1】:

    在这行代码中

    BN_bin2bn(&x_compressed_byte_array[0],200,NULL); // length is in bits?
    

    您应该传递您创建的 BIGNUM bn_compressed 来保存转换后的结果。长度以字节为单位。

    BN_bin2bn(&x_compressed_byte_array[0],sizeof(x_compressed_byte_array),x_compressed);
    

    设置_compressed_coordinates后,您可以验证您刚刚创建的点是否在组中正确定位。

    if (!EC_POINT_is_on_curve(curve_group,point,NULL)) return 0;
    

    要进一步检查点坐标 (x,y),您可以将其放入代码中。

    if (!EC_POINT_get_affine_coordinates_GFp(curve_group, point, x, y, NULL)) return 0;
    fprintf(stdout, "\point = (x,y)\n");
    fprintf(stdout, "     x = 0x");
    BN_print_fp(stdout, x);
    fprintf(stdout, "\n     y = 0x");
    BN_print_fp(stdout, y);
    fprintf(stdout, "\n");
    

    只需记住在函数的第一个/结尾处新建/释放 BIGNUM x 和 y。

    BIGNUM *x, *y;
    x = BN_new();
    y = BN_new();
    
    /* your code */
    
    if(x) BN_free(x);
    if(y) BN_free(y);
    

    它应该可以工作。我得到的结果 xy[49] 是

    0x0471C073739BBFC20A81CDDDF4CFCAC7B7A99961232C5C637C388AB06AA7E43A2B5CFE2D7F3AC2DF910D6F8D8F209CD817

    【讨论】:

    • 非常感谢 ChiaraHsieh!我能够复制您的答案(xy[49])。现在,我唯一的困惑是如何最好地处理压缩的 x 键。上面的代码使用 25 字节作为 192 位曲线的压缩密钥,但也许我应该使用 24 字节并简单地依靠传递“y_bit”?所以,我想我的问题是:OPENSSL 是否需要压缩密钥的额外字节,或者我应该使用 24 字节的 x 坐标和 y 位?再次感谢!
    • 不客气。 :) 你需要 25 个字节。第一个字节表示 x 坐标是未压缩的、混合的或压缩的形式。例如,x0x02 的第一个字节表示 x 是压缩形式。 xy 0x04 的第一个字节表示 xy 是未压缩的形式。 OPENSSL 需要这个指标,当然还有 ybit,才能正确恢复 ec_point (x,y)。如果您需要任何参考,点压缩在 X9.62 标准中定义。
    猜你喜欢
    • 2019-06-30
    • 2022-11-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-08-19
    • 1970-01-01
    • 2012-07-22
    相关资源
    最近更新 更多