OpenSSL自定义secp192r1曲线时EC_POINT_set_affine_coordinates_GFp调用报错
解决OpenSSL手动定义secp192r1时EC_POINT_set_affine_coordinates_GFp的错误
首先,我注意到你的代码里有两个关键问题导致了这个错误,咱们一步步解决:
1. 参数字节长度错误(核心问题)
secp192r1是192位椭圆曲线,所有参数(p, a, b, order, x, y)都是192位,对应24字节(192 ÷ 8 = 24),但你的代码里用了28字节的数组,并且填充了多余的0xFF前缀,这直接导致所有曲线参数的数值完全偏离了SEC2标准定义的secp192r1参数,生成的曲线根本不是你想要的,自然生成元(x,y)也不在这条错误的曲线上,所以EC_POINT_set_affine_coordinates_GFp会返回错误。
2. a参数的数值错误
即使修正了字节长度,你原来的a参数二进制值也不对:secp192r1的a参数是-3(在GF(p)中等价于p-3),而你原来的a值是p-2,同样会导致点不在曲线上。
修正后的完整代码
下面是修正了字节长度和参数值的代码,完全匹配SEC2-Ver-1.0.pdf第2.5.2节的secp192r1参数:
#include <openssl/ec.h> #include <openssl/bn.h> #include <openssl/err.h> void handleErrors(void) { ERR_print_errors_fp(stderr); abort(); } EC_GROUP *create_curve(void) { BN_CTX *ctx; EC_GROUP *curve; BIGNUM *a, *b, *p, *order, *x, *y; EC_POINT *generator; /* 修正:192位参数对应24字节数组 */ // secp192r1的p = 2^192 - 2^64 - 1 unsigned char p_bin[24] = {0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}; // a = -3 mod p unsigned char a_bin[24] = {0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFE, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFC}; // b参数(匹配SEC2标准) unsigned char b_bin[24] = {0xB4,0x05,0x0A,0x85,0x0C,0x04,0xB3,0xAB, 0xF5,0x41,0x32,0x56,0x50,0x44,0xB0,0xB7, 0xD7,0xBF,0xD8,0xBA,0x27,0x0B,0x39,0x43}; // 生成元的阶order unsigned char order_bin[24] = {0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x16,0xA2, 0xE0,0xB8,0xF0,0x3E,0x13,0xDD,0x29,0x45}; // 生成元x坐标 unsigned char x_bin[24] = {0xB7,0x0E,0x0C,0xBD,0x6B,0xB4,0xBF,0x7F, 0x32,0x13,0x90,0xB9,0x4A,0x03,0xC1,0xD3, 0x56,0xC2,0x11,0x22,0x34,0x32,0x80,0xD6}; // 生成元y坐标 unsigned char y_bin[24] = {0xBD,0x37,0x63,0x88,0xB5,0xF7,0x23,0xFB, 0x4C,0x22,0xDF,0xE6,0xCD,0x43,0x75,0xA0, 0x5A,0x07,0x47,0x64,0x44,0xD5,0x81,0x99}; /* 初始化上下文 */ if(NULL == (ctx = BN_CTX_new())) handleErrors(); /* 转换二进制到BIGNUM */ if(NULL == (a = BN_bin2bn(a_bin, sizeof(a_bin), NULL))) handleErrors(); if(NULL == (b = BN_bin2bn(b_bin, sizeof(b_bin), NULL))) handleErrors(); if(NULL == (p = BN_bin2bn(p_bin, sizeof(p_bin), NULL))) handleErrors(); if(NULL == (order = BN_bin2bn(order_bin, sizeof(order_bin), NULL))) handleErrors(); if(NULL == (x = BN_bin2bn(x_bin, sizeof(x_bin), NULL))) handleErrors(); if(NULL == (y = BN_bin2bn(y_bin, sizeof(y_bin), NULL))) handleErrors(); /* 创建GF(p)上的椭圆曲线 */ if(NULL == (curve = EC_GROUP_new_curve_GFp(p, a, b, ctx))) handleErrors(); /* 创建生成元点 */ if(NULL == (generator = EC_POINT_new(curve))) handleErrors(); // 现在设置坐标应该成功,因为点在正确的曲线上 if(1 != EC_POINT_set_affine_coordinates_GFp(curve, generator, x, y, ctx)) handleErrors(); /* 设置生成元和阶 */ if(1 != EC_GROUP_set_generator(curve, generator, order, NULL)) handleErrors(); /* 释放资源 */ EC_POINT_free(generator); BN_free(y); BN_free(x); BN_free(order); BN_free(p); BN_free(b); BN_free(a); BN_CTX_free(ctx); return curve; }
额外排查技巧
如果以后再遇到类似错误,可以:
- 在
handleErrors函数里调用ERR_print_errors_fp(stderr),打印具体的OpenSSL错误信息,这能帮你快速定位是参数错误、点不在曲线上还是其他问题。 - 手动验证生成元是否满足曲线方程:计算
y² mod p和(x³ + a*x + b) mod p,看两者是否相等,这能确认点是否在曲线上。
内容的提问来源于stack exchange,提问作者efrat
相关产品推荐
相关产品推荐

