OpenSSL:EC_POINT_set_compressed_coordinates_GFp 段错误
OpenSSL: EC_POINT_set_compressed_coordinates_GFp segfault
使用 gdb 尝试查明段错误(并没有真正帮助),但我可能传递了错误的参数。这是代码和回溯:
echd.cc
#include <node.h>
#include <nan.h>
#include <openssl/evp.h>
#include <openssl/ec.h>
using v8::Handle;
using v8::FunctionTemplate;
using v8::Object;
using v8::String;
static const size_t PRIVKEY_SIZE = 32;
static const size_t PUBKEY_SIZE = 65;
static const size_t COMPRESSED_PUBKEY_SIZE = 33;
#define CHECK(cond) do { if (!(cond)) goto error; } while (0)
int derive(const uint8_t* privkey_a, const uint8_t* pubkey_b, uint8_t* shared) {
int rc = -1;
int res;
BIGNUM* pkey_bn = NULL;
EC_KEY* pkey = NULL;
bool compressed = false;
EC_KEY* peerkey = NULL;
int compressed_y_bit = 0;
EC_POINT* peerkey_p = NULL;
const EC_GROUP* peerkey_group = NULL;
BN_CTX* peerkey_ctx = NULL;
BIGNUM* peerkey_bn = NULL;
BIGNUM* peerkey_bn_x = NULL;
BIGNUM* peerkey_bn_y = NULL;
EVP_PKEY* evp_pkey = NULL;
EVP_PKEY* evp_peerkey = NULL;
EVP_PKEY_CTX* ctx = NULL;
size_t shared_len = PRIVKEY_SIZE;
// Private key A.
CHECK((pkey_bn = BN_bin2bn(privkey_a, PRIVKEY_SIZE, NULL)) != NULL);
CHECK((pkey = EC_KEY_new_by_curve_name(NID_secp256k1)) != NULL);
CHECK(EC_KEY_set_private_key(pkey, pkey_bn) == 1);
CHECK((evp_pkey = EVP_PKEY_new()) != NULL);
CHECK(EVP_PKEY_set1_EC_KEY(evp_pkey, pkey) == 1);
// Public key B.
CHECK((peerkey = EC_KEY_new_by_curve_name(NID_secp256k1)) != NULL);
(pubkey_b[0] == 2 || pubkey_b[0] == 3) ? compressed = true : compressed = false;
if (compressed) {
(pubkey_b[0] == 2) ? compressed_y_bit = 0 : compressed_y_bit = 1;
CHECK((peerkey_group = EC_KEY_get0_group(peerkey)) != NULL);
CHECK((peerkey_ctx = BN_CTX_new()) != NULL);
CHECK((peerkey_bn = BN_bin2bn(pubkey_b+1, COMPRESSED_PUBKEY_SIZE, NULL)) != NULL);
CHECK((EC_POINT_set_compressed_coordinates_GFp(peerkey_group,
peerkey_p,
peerkey_bn,
compressed_y_bit,
NULL)) != NULL);
...
回溯
(gdb) bt
#0 0x00000000012097a3 in EC_POINT_set_compressed_coordinates_GFp ()
#1 0x00007ffff4648446 in derive (privkey_a=0x2214af0 '[=12=]4' <repeats 32 times>, " 2+[=12=]2", pubkey_b=0x2214ec0 "[=12=]3345V{2d@1]>ժ2[=12=]5e7604`H17475155\a72+[=12=]2", shared=0x222d5d0 " c,[=12=]2") at ../ecdh.cc:51
#2 0x00007ffff4648817 in Derive (info=...) at ../ecdh.cc:117
#3 0x00007ffff4647756 in Nan::imp::FunctionCallbackWrapper (info=...) at ../node_modules/nan/nan_callbacks_12_inl.h:176
#4 0x0000000000a94a43 in v8::internal::FunctionCallbackArguments::Call(void (*)(v8::FunctionCallbackInfo<v8::Value> const&)) ()
#5 0x0000000000b0bbec in v8::internal::MaybeHandle<v8::internal::Object> v8::internal::(anonymous namespace)::HandleApiCallHelper<false>(v8::internal::Isolate*, v8::internal::Handle<v8::internal::HeapObject>, v8::internal::Handle<v8::internal::HeapObject>, v8::internal::Handle<v8::internal::FunctionTemplateInfo>, v8::internal::Handle<v8::internal::Object>, v8::internal::BuiltinArguments) ()
#6 0x0000000000b0c83f in v8::internal::Builtin_HandleApiCall(int, v8::internal::Object**, v8::internal::Isolate*) ()
#7 0x00002b6f5fe042fd in ?? ()
#8 0x00002b6f5fe04241 in ?? ()
#9 0x00007fffffffc610 in ?? ()
#10 0x0000000000000006 in ?? ()
---Type <return> to continue, or q <return> to quit---q
Quit
您对 EC_POINT_set_compressed_coordinates_GFp()
的调用中的 peerkey_p
参数是 NULL
,而它应该是已初始化的 EC_POINT *
。在调用该函数之前添加类似这样的内容(为清楚起见省略检查):
peerkey_p = EC_POINT_new(peerkey_group);
这将消除段错误。
您使用 COMPRESSED_PUBKEY_SIZE
等于 33
时似乎还有另一个错误。是的,public 键的总大小是 33
字节。但是在将指针 pubkey_b
前进 1
字节后,只有 32
字节与 BN_bin2bn()
函数相关。
此外,EC_POINT_set_compressed_coordinates_GFp()
的return值是一个int,不是指针。因此,与其将其与 NULL
进行比较,不如将其与 1
.
的成功值进行比较
使用 gdb 尝试查明段错误(并没有真正帮助),但我可能传递了错误的参数。这是代码和回溯:
echd.cc
#include <node.h>
#include <nan.h>
#include <openssl/evp.h>
#include <openssl/ec.h>
using v8::Handle;
using v8::FunctionTemplate;
using v8::Object;
using v8::String;
static const size_t PRIVKEY_SIZE = 32;
static const size_t PUBKEY_SIZE = 65;
static const size_t COMPRESSED_PUBKEY_SIZE = 33;
#define CHECK(cond) do { if (!(cond)) goto error; } while (0)
int derive(const uint8_t* privkey_a, const uint8_t* pubkey_b, uint8_t* shared) {
int rc = -1;
int res;
BIGNUM* pkey_bn = NULL;
EC_KEY* pkey = NULL;
bool compressed = false;
EC_KEY* peerkey = NULL;
int compressed_y_bit = 0;
EC_POINT* peerkey_p = NULL;
const EC_GROUP* peerkey_group = NULL;
BN_CTX* peerkey_ctx = NULL;
BIGNUM* peerkey_bn = NULL;
BIGNUM* peerkey_bn_x = NULL;
BIGNUM* peerkey_bn_y = NULL;
EVP_PKEY* evp_pkey = NULL;
EVP_PKEY* evp_peerkey = NULL;
EVP_PKEY_CTX* ctx = NULL;
size_t shared_len = PRIVKEY_SIZE;
// Private key A.
CHECK((pkey_bn = BN_bin2bn(privkey_a, PRIVKEY_SIZE, NULL)) != NULL);
CHECK((pkey = EC_KEY_new_by_curve_name(NID_secp256k1)) != NULL);
CHECK(EC_KEY_set_private_key(pkey, pkey_bn) == 1);
CHECK((evp_pkey = EVP_PKEY_new()) != NULL);
CHECK(EVP_PKEY_set1_EC_KEY(evp_pkey, pkey) == 1);
// Public key B.
CHECK((peerkey = EC_KEY_new_by_curve_name(NID_secp256k1)) != NULL);
(pubkey_b[0] == 2 || pubkey_b[0] == 3) ? compressed = true : compressed = false;
if (compressed) {
(pubkey_b[0] == 2) ? compressed_y_bit = 0 : compressed_y_bit = 1;
CHECK((peerkey_group = EC_KEY_get0_group(peerkey)) != NULL);
CHECK((peerkey_ctx = BN_CTX_new()) != NULL);
CHECK((peerkey_bn = BN_bin2bn(pubkey_b+1, COMPRESSED_PUBKEY_SIZE, NULL)) != NULL);
CHECK((EC_POINT_set_compressed_coordinates_GFp(peerkey_group,
peerkey_p,
peerkey_bn,
compressed_y_bit,
NULL)) != NULL);
...
回溯
(gdb) bt
#0 0x00000000012097a3 in EC_POINT_set_compressed_coordinates_GFp ()
#1 0x00007ffff4648446 in derive (privkey_a=0x2214af0 '[=12=]4' <repeats 32 times>, " 2+[=12=]2", pubkey_b=0x2214ec0 "[=12=]3345V{2d@1]>ժ2[=12=]5e7604`H17475155\a72+[=12=]2", shared=0x222d5d0 " c,[=12=]2") at ../ecdh.cc:51
#2 0x00007ffff4648817 in Derive (info=...) at ../ecdh.cc:117
#3 0x00007ffff4647756 in Nan::imp::FunctionCallbackWrapper (info=...) at ../node_modules/nan/nan_callbacks_12_inl.h:176
#4 0x0000000000a94a43 in v8::internal::FunctionCallbackArguments::Call(void (*)(v8::FunctionCallbackInfo<v8::Value> const&)) ()
#5 0x0000000000b0bbec in v8::internal::MaybeHandle<v8::internal::Object> v8::internal::(anonymous namespace)::HandleApiCallHelper<false>(v8::internal::Isolate*, v8::internal::Handle<v8::internal::HeapObject>, v8::internal::Handle<v8::internal::HeapObject>, v8::internal::Handle<v8::internal::FunctionTemplateInfo>, v8::internal::Handle<v8::internal::Object>, v8::internal::BuiltinArguments) ()
#6 0x0000000000b0c83f in v8::internal::Builtin_HandleApiCall(int, v8::internal::Object**, v8::internal::Isolate*) ()
#7 0x00002b6f5fe042fd in ?? ()
#8 0x00002b6f5fe04241 in ?? ()
#9 0x00007fffffffc610 in ?? ()
#10 0x0000000000000006 in ?? ()
---Type <return> to continue, or q <return> to quit---q
Quit
您对 EC_POINT_set_compressed_coordinates_GFp()
的调用中的 peerkey_p
参数是 NULL
,而它应该是已初始化的 EC_POINT *
。在调用该函数之前添加类似这样的内容(为清楚起见省略检查):
peerkey_p = EC_POINT_new(peerkey_group);
这将消除段错误。
您使用 COMPRESSED_PUBKEY_SIZE
等于 33
时似乎还有另一个错误。是的,public 键的总大小是 33
字节。但是在将指针 pubkey_b
前进 1
字节后,只有 32
字节与 BN_bin2bn()
函数相关。
此外,EC_POINT_set_compressed_coordinates_GFp()
的return值是一个int,不是指针。因此,与其将其与 NULL
进行比较,不如将其与 1
.