int main(void) { int i; secp256k1_gej groupj[EXHAUSTIVE_TEST_ORDER]; secp256k1_ge group[EXHAUSTIVE_TEST_ORDER]; /* Build context */ secp256k1_context *ctx = secp256k1_context_create(SECP256K1_CONTEXT_SIGN | SECP256K1_CONTEXT_VERIFY); /* TODO set z = 1, then do num_tests runs with random z values */ /* Generate the entire group */ secp256k1_gej_set_infinity(&groupj[0]); secp256k1_ge_set_gej(&group[0], &groupj[0]); for (i = 1; i < EXHAUSTIVE_TEST_ORDER; i++) { /* Set a different random z-value for each Jacobian point */ secp256k1_fe z; random_fe(&z); secp256k1_gej_add_ge(&groupj[i], &groupj[i - 1], &secp256k1_ge_const_g); secp256k1_ge_set_gej(&group[i], &groupj[i]); secp256k1_gej_rescale(&groupj[i], &z); /* Verify against ecmult_gen */ { secp256k1_scalar scalar_i; secp256k1_gej generatedj; secp256k1_ge generated; secp256k1_scalar_set_int(&scalar_i, i); secp256k1_ecmult_gen(&ctx->ecmult_gen_ctx, &generatedj, &scalar_i); secp256k1_ge_set_gej(&generated, &generatedj); CHECK(group[i].infinity == 0); CHECK(generated.infinity == 0); CHECK(secp256k1_fe_equal_var(&generated.x, &group[i].x)); CHECK(secp256k1_fe_equal_var(&generated.y, &group[i].y)); } } /* Run the tests */ #ifdef USE_ENDOMORPHISM test_exhaustive_endomorphism(group, EXHAUSTIVE_TEST_ORDER); #endif test_exhaustive_addition(group, groupj, EXHAUSTIVE_TEST_ORDER); test_exhaustive_ecmult(ctx, group, groupj, EXHAUSTIVE_TEST_ORDER); test_exhaustive_ecmult_multi(ctx, group, EXHAUSTIVE_TEST_ORDER); test_exhaustive_sign(ctx, group, EXHAUSTIVE_TEST_ORDER); test_exhaustive_verify(ctx, group, EXHAUSTIVE_TEST_ORDER); #ifdef ENABLE_MODULE_RECOVERY test_exhaustive_recovery_sign(ctx, group, EXHAUSTIVE_TEST_ORDER); test_exhaustive_recovery_verify(ctx, group, EXHAUSTIVE_TEST_ORDER); #endif secp256k1_context_destroy(ctx); return 0; }
int secp256k1_ecdsa_pubkey_tweak_add(unsigned char *pubkey, int pubkeylen, const unsigned char *tweak) { int ret = 1; secp256k1_num_t term; secp256k1_num_init(&term); secp256k1_num_set_bin(&term, tweak, 32); if (secp256k1_num_cmp(&term, &secp256k1_ge_consts->order) >= 0) ret = 0; secp256k1_ge_t p; if (ret) { if (!secp256k1_ecdsa_pubkey_parse(&p, pubkey, pubkeylen)) ret = 0; } if (ret) { secp256k1_gej_t pt; secp256k1_ecmult_gen(&pt, &term); secp256k1_gej_add_ge(&pt, &pt, &p); if (secp256k1_gej_is_infinity(&pt)) ret = 0; secp256k1_ge_set_gej(&p, &pt); int oldlen = pubkeylen; secp256k1_ecdsa_pubkey_serialize(&p, pubkey, &pubkeylen, oldlen <= 33); assert(pubkeylen == oldlen); } secp256k1_num_free(&term); return ret; }
void test_ecdsa_openssl(void) { secp256k1_scalar_t key, msg; unsigned char message[32]; secp256k1_rand256_test(message); secp256k1_scalar_set_b32(&msg, message, NULL); random_scalar_order_test(&key); secp256k1_gej_t qj; secp256k1_ecmult_gen(&qj, &key); secp256k1_ge_t q; secp256k1_ge_set_gej(&q, &qj); EC_KEY *ec_key = get_openssl_key(&key); CHECK(ec_key); unsigned char signature[80]; unsigned int sigsize = 80; CHECK(ECDSA_sign(0, message, sizeof(message), signature, &sigsize, ec_key)); secp256k1_ecdsa_sig_t sig; CHECK(secp256k1_ecdsa_sig_parse(&sig, signature, sigsize)); CHECK(secp256k1_ecdsa_sig_verify(&sig, &q, &msg)); secp256k1_scalar_t one; secp256k1_scalar_set_int(&one, 1); secp256k1_scalar_t msg2; secp256k1_scalar_add(&msg2, &msg, &one); CHECK(!secp256k1_ecdsa_sig_verify(&sig, &q, &msg2)); random_sign(&sig, &key, &msg, NULL); int secp_sigsize = 80; CHECK(secp256k1_ecdsa_sig_serialize(signature, &secp_sigsize, &sig)); CHECK(ECDSA_verify(0, message, sizeof(message), signature, secp_sigsize, ec_key) == 1); EC_KEY_free(ec_key); }
void test_ecdsa_openssl() { const secp256k1_ge_consts_t *c = secp256k1_ge_consts; secp256k1_num_t key, msg; secp256k1_num_init(&msg); unsigned char message[32]; secp256k1_rand256_test(message); secp256k1_num_set_bin(&msg, message, 32); secp256k1_num_init(&key); random_num_order_test(&key); secp256k1_gej_t qj; secp256k1_ecmult_gen(&qj, &key); secp256k1_ge_t q; secp256k1_ge_set_gej(&q, &qj); EC_KEY *ec_key = get_openssl_key(&key); assert(ec_key); unsigned char signature[80]; int sigsize = 80; assert(ECDSA_sign(0, message, sizeof(message), signature, &sigsize, ec_key)); secp256k1_ecdsa_sig_t sig; secp256k1_ecdsa_sig_init(&sig); assert(secp256k1_ecdsa_sig_parse(&sig, signature, sigsize)); assert(secp256k1_ecdsa_sig_verify(&sig, &q, &msg)); secp256k1_num_inc(&sig.r); assert(!secp256k1_ecdsa_sig_verify(&sig, &q, &msg)); random_sign(&sig, &key, &msg, NULL); sigsize = 80; assert(secp256k1_ecdsa_sig_serialize(signature, &sigsize, &sig)); assert(ECDSA_verify(0, message, sizeof(message), signature, sigsize, ec_key) == 1); secp256k1_ecdsa_sig_free(&sig); EC_KEY_free(ec_key); secp256k1_num_free(&key); secp256k1_num_free(&msg); }
int secp256k1_ecdsa_pubkey_tweak_add(unsigned char *pubkey, int pubkeylen, const unsigned char *tweak) { DEBUG_CHECK(secp256k1_ecmult_consts != NULL); DEBUG_CHECK(pubkey != NULL); DEBUG_CHECK(tweak != NULL); int ret = 1; secp256k1_num_t term; secp256k1_num_init(&term); secp256k1_num_set_bin(&term, tweak, 32); if (secp256k1_num_cmp(&term, &secp256k1_ge_consts->order) >= 0) ret = 0; secp256k1_ge_t p; if (ret) { if (!secp256k1_ecdsa_pubkey_parse(&p, pubkey, pubkeylen)) ret = 0; } if (ret) { secp256k1_gej_t pt; secp256k1_gej_set_ge(&pt, &p); secp256k1_num_t one; secp256k1_num_init(&one); secp256k1_num_set_int(&one, 1); secp256k1_ecmult(&pt, &pt, &one, &term); secp256k1_num_free(&one); if (secp256k1_gej_is_infinity(&pt)) ret = 0; secp256k1_ge_set_gej(&p, &pt); int oldlen = pubkeylen; secp256k1_ecdsa_pubkey_serialize(&p, pubkey, &pubkeylen, oldlen <= 33); VERIFY_CHECK(pubkeylen == oldlen); } secp256k1_num_free(&term); return ret; }
int secp256k1_ecdsa_pubkey_tweak_mul(unsigned char *pubkey, int pubkeylen, const unsigned char *tweak) { int ret = 1; secp256k1_num_t factor; secp256k1_num_init(&factor); secp256k1_num_set_bin(&factor, tweak, 32); if (secp256k1_num_is_zero(&factor)) ret = 0; if (secp256k1_num_cmp(&factor, &secp256k1_ge_consts->order) >= 0) ret = 0; secp256k1_ge_t p; if (ret) { if (!secp256k1_ecdsa_pubkey_parse(&p, pubkey, pubkeylen)) ret = 0; } if (ret) { secp256k1_num_t zero; secp256k1_num_init(&zero); secp256k1_num_set_int(&zero, 0); secp256k1_gej_t pt; secp256k1_gej_set_ge(&pt, &p); secp256k1_ecmult(&pt, &pt, &factor, &zero); secp256k1_num_free(&zero); secp256k1_ge_set_gej(&p, &pt); int oldlen = pubkeylen; secp256k1_ecdsa_pubkey_serialize(&p, pubkey, &pubkeylen, oldlen <= 33); assert(pubkeylen == oldlen); } secp256k1_num_free(&factor); return ret; }
int secp256k1_ecdsa_pubkey_create(unsigned char *pubkey, int *pubkeylen, const unsigned char *seckey, int compressed) { secp256k1_num_t sec; secp256k1_num_init(&sec); secp256k1_num_set_bin(&sec, seckey, 32); secp256k1_gej_t pj; secp256k1_ecmult_gen(&pj, &sec); secp256k1_ge_t p; secp256k1_ge_set_gej(&p, &pj); secp256k1_ecdsa_pubkey_serialize(&p, pubkey, pubkeylen, compressed); return 1; }
void test_ecdsa_sign_verify(void) { secp256k1_scalar_t msg, key; random_scalar_order_test(&msg); random_scalar_order_test(&key); secp256k1_gej_t pubj; secp256k1_ecmult_gen(&pubj, &key); secp256k1_ge_t pub; secp256k1_ge_set_gej(&pub, &pubj); secp256k1_ecdsa_sig_t sig; random_sign(&sig, &key, &msg, NULL); secp256k1_num_t msg_num; secp256k1_scalar_get_num(&msg_num, &msg); CHECK(secp256k1_ecdsa_sig_verify(&sig, &pub, &msg_num)); secp256k1_num_inc(&msg_num); CHECK(!secp256k1_ecdsa_sig_verify(&sig, &pub, &msg_num)); }
int My_secp256k1_ec_pubkey_create(secp256k1_pubkey_t *pubkey, const unsigned char *seckey, int window_size) { int ret = 0; secp256k1_gej_t pj; secp256k1_ge_t p; secp256k1_scalar_t sec; int overflow; secp256k1_scalar_set_b32(&sec, seckey, &overflow); //secp256k1_ecmult_gen(&pj, &sec); secp256k1_ecmult_gen2(&pj, seckey); secp256k1_ge_set_gej(&p, &pj); secp256k1_pubkey_save(pubkey, &p); return ret; }
void test_point_times_order(const secp256k1_gej_t *point) { /* X * (point + G) + (order-X) * (pointer + G) = 0 */ secp256k1_scalar_t x; random_scalar_order_test(&x); secp256k1_scalar_t nx; secp256k1_scalar_negate(&nx, &x); secp256k1_gej_t res1, res2; secp256k1_ecmult(&res1, point, &x, &x); /* calc res1 = x * point + x * G; */ secp256k1_ecmult(&res2, point, &nx, &nx); /* calc res2 = (order - x) * point + (order - x) * G; */ secp256k1_gej_add_var(&res1, &res1, &res2); CHECK(secp256k1_gej_is_infinity(&res1)); CHECK(secp256k1_gej_is_valid(&res1) == 0); secp256k1_ge_t res3; secp256k1_ge_set_gej(&res3, &res1); CHECK(secp256k1_ge_is_infinity(&res3)); CHECK(secp256k1_ge_is_valid(&res3) == 0); }
void test_ecdsa_sign_verify(void) { int recid; int getrec; secp256k1_scalar_t msg, key; random_scalar_order_test(&msg); random_scalar_order_test(&key); secp256k1_gej_t pubj; secp256k1_ecmult_gen(&pubj, &key); secp256k1_ge_t pub; secp256k1_ge_set_gej(&pub, &pubj); secp256k1_ecdsa_sig_t sig; getrec = secp256k1_rand32()&1; random_sign(&sig, &key, &msg, getrec?&recid:NULL); if (getrec) CHECK(recid >= 0 && recid < 4); CHECK(secp256k1_ecdsa_sig_verify(&sig, &pub, &msg)); secp256k1_scalar_t one; secp256k1_scalar_set_int(&one, 1); secp256k1_scalar_add(&msg, &msg, &one); CHECK(!secp256k1_ecdsa_sig_verify(&sig, &pub, &msg)); }
int secp256k1_ecdsa_pubkey_create(unsigned char *pubkey, int *pubkeylen, const unsigned char *seckey, int compressed) { DEBUG_CHECK(secp256k1_ecmult_gen_consts != NULL); DEBUG_CHECK(pubkey != NULL); DEBUG_CHECK(pubkeylen != NULL); DEBUG_CHECK(seckey != NULL); secp256k1_num_t sec; secp256k1_num_init(&sec); secp256k1_num_set_bin(&sec, seckey, 32); secp256k1_gej_t pj; secp256k1_ecmult_gen(&pj, &sec); secp256k1_num_clear(&sec); secp256k1_num_free(&sec); secp256k1_ge_t p; secp256k1_ge_set_gej(&p, &pj); secp256k1_ecdsa_pubkey_serialize(&p, pubkey, pubkeylen, compressed); return 1; }
int secp256k1_ec_pubkey_combine(const secp256k1_context* ctx, secp256k1_pubkey *pubnonce, const secp256k1_pubkey * const *pubnonces, size_t n) { size_t i; secp256k1_gej Qj; secp256k1_ge Q; ARG_CHECK(pubnonce != NULL); memset(pubnonce, 0, sizeof(*pubnonce)); ARG_CHECK(n >= 1); ARG_CHECK(pubnonces != NULL); secp256k1_gej_set_infinity(&Qj); for (i = 0; i < n; i++) { secp256k1_pubkey_load(ctx, &Q, pubnonces[i]); secp256k1_gej_add_ge(&Qj, &Qj, &Q); } if (secp256k1_gej_is_infinity(&Qj)) return 0; secp256k1_ge_set_gej(&Q, &Qj); secp256k1_pubkey_save(pubnonce, &Q); return 1; }
void test_ecdsa_sign_verify() { const secp256k1_ge_consts_t *c = secp256k1_ge_consts; secp256k1_num_t msg, key; secp256k1_num_init(&msg); random_num_order_test(&msg); secp256k1_num_init(&key); random_num_order_test(&key); secp256k1_gej_t pubj; secp256k1_ecmult_gen(&pubj, &key); secp256k1_ge_t pub; secp256k1_ge_set_gej(&pub, &pubj); secp256k1_ecdsa_sig_t sig; secp256k1_ecdsa_sig_init(&sig); random_sign(&sig, &key, &msg, NULL); assert(secp256k1_ecdsa_sig_verify(&sig, &pub, &msg)); secp256k1_num_inc(&msg); assert(!secp256k1_ecdsa_sig_verify(&sig, &pub, &msg)); secp256k1_ecdsa_sig_free(&sig); secp256k1_num_free(&msg); secp256k1_num_free(&key); }
int secp256k1_ec_pubkey_create(const secp256k1_context* ctx, secp256k1_pubkey *pubkey, const unsigned char *seckey) { secp256k1_gej pj; secp256k1_ge p; secp256k1_scalar sec; int overflow; int ret = 0; VERIFY_CHECK(ctx != NULL); ARG_CHECK(pubkey != NULL); memset(pubkey, 0, sizeof(*pubkey)); ARG_CHECK(secp256k1_ecmult_gen_context_is_built(&ctx->ecmult_gen_ctx)); ARG_CHECK(seckey != NULL); secp256k1_scalar_set_b32(&sec, seckey, &overflow); ret = (!overflow) & (!secp256k1_scalar_is_zero(&sec)); if (ret) { secp256k1_ecmult_gen(&ctx->ecmult_gen_ctx, &pj, &sec); secp256k1_ge_set_gej(&p, &pj); secp256k1_pubkey_save(pubkey, &p); } secp256k1_scalar_clear(&sec); return ret; }
int secp256k1_ec_pubkey_create(const secp256k1_context_t* ctx, unsigned char *pubkey, int *pubkeylen, const unsigned char *seckey, int compressed) { secp256k1_gej_t pj; secp256k1_ge_t p; secp256k1_scalar_t sec; int overflow; int ret = 0; DEBUG_CHECK(ctx != NULL); DEBUG_CHECK(secp256k1_ecmult_gen_context_is_built(&ctx->ecmult_gen_ctx)); DEBUG_CHECK(pubkey != NULL); DEBUG_CHECK(pubkeylen != NULL); DEBUG_CHECK(seckey != NULL); secp256k1_scalar_set_b32(&sec, seckey, &overflow); if (!overflow) { secp256k1_ecmult_gen(&ctx->ecmult_gen_ctx, &pj, &sec); secp256k1_scalar_clear(&sec); secp256k1_ge_set_gej(&p, &pj); ret = secp256k1_eckey_pubkey_serialize(&p, pubkey, pubkeylen, compressed); } if (!ret) { *pubkeylen = 0; } return ret; }
/* Tests several edge cases. */ void test_ecdsa_edge_cases(void) { const unsigned char msg32[32] = { 'T', 'h', 'i', 's', ' ', 'i', 's', ' ', 'a', ' ', 'v', 'e', 'r', 'y', ' ', 's', 'e', 'c', 'r', 'e', 't', ' ', 'm', 'e', 's', 's', 'a', 'g', 'e', '.', '.', '.' }; const unsigned char sig64[64] = { /* Generated by signing the above message with nonce 'This is the nonce we will use...' * and secret key 0 (which is not valid), resulting in recid 0. */ 0x67, 0xCB, 0x28, 0x5F, 0x9C, 0xD1, 0x94, 0xE8, 0x40, 0xD6, 0x29, 0x39, 0x7A, 0xF5, 0x56, 0x96, 0x62, 0xFD, 0xE4, 0x46, 0x49, 0x99, 0x59, 0x63, 0x17, 0x9A, 0x7D, 0xD1, 0x7B, 0xD2, 0x35, 0x32, 0x4B, 0x1B, 0x7D, 0xF3, 0x4C, 0xE1, 0xF6, 0x8E, 0x69, 0x4F, 0xF6, 0xF1, 0x1A, 0xC7, 0x51, 0xDD, 0x7D, 0xD7, 0x3E, 0x38, 0x7E, 0xE4, 0xFC, 0x86, 0x6E, 0x1B, 0xE8, 0xEC, 0xC7, 0xDD, 0x95, 0x57 }; unsigned char pubkey[65]; int pubkeylen = 65; CHECK(!secp256k1_ecdsa_recover_compact(msg32, 32, sig64, pubkey, &pubkeylen, 0, 0)); CHECK(secp256k1_ecdsa_recover_compact(msg32, 32, sig64, pubkey, &pubkeylen, 0, 1)); CHECK(!secp256k1_ecdsa_recover_compact(msg32, 32, sig64, pubkey, &pubkeylen, 0, 2)); CHECK(!secp256k1_ecdsa_recover_compact(msg32, 32, sig64, pubkey, &pubkeylen, 0, 3)); /* signature (r,s) = (4,4), which can be recovered with all 4 recids. */ const unsigned char sigb64[64] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, }; unsigned char pubkeyb[33]; int pubkeyblen = 33; for (int recid = 0; recid < 4; recid++) { /* (4,4) encoded in DER. */ unsigned char sigbder[8] = {0x30, 0x06, 0x02, 0x01, 0x04, 0x02, 0x01, 0x04}; /* (order + r,4) encoded in DER. */ unsigned char sigbderlong[40] = { 0x30, 0x26, 0x02, 0x21, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0xBA, 0xAE, 0xDC, 0xE6, 0xAF, 0x48, 0xA0, 0x3B, 0xBF, 0xD2, 0x5E, 0x8C, 0xD0, 0x36, 0x41, 0x45, 0x02, 0x01, 0x04 }; CHECK(secp256k1_ecdsa_recover_compact(msg32, 32, sigb64, pubkeyb, &pubkeyblen, 1, recid)); CHECK(secp256k1_ecdsa_verify(msg32, 32, sigbder, sizeof(sigbder), pubkeyb, pubkeyblen) == 1); for (int recid2 = 0; recid2 < 4; recid2++) { unsigned char pubkey2b[33]; int pubkey2blen = 33; CHECK(secp256k1_ecdsa_recover_compact(msg32, 32, sigb64, pubkey2b, &pubkey2blen, 1, recid2)); /* Verifying with (order + r,4) should always fail. */ CHECK(secp256k1_ecdsa_verify(msg32, 32, sigbderlong, sizeof(sigbderlong), pubkey2b, pubkey2blen) != 1); } /* Damage signature. */ sigbder[7]++; CHECK(secp256k1_ecdsa_verify(msg32, 32, sigbder, sizeof(sigbder), pubkeyb, pubkeyblen) == 0); } /* Test the case where ECDSA recomputes a point that is infinity. */ { secp256k1_ecdsa_sig_t sig; secp256k1_scalar_set_int(&sig.s, 1); secp256k1_scalar_negate(&sig.s, &sig.s); secp256k1_scalar_inverse(&sig.s, &sig.s); secp256k1_scalar_set_int(&sig.r, 1); secp256k1_gej_t keyj; secp256k1_ecmult_gen(&keyj, &sig.r); secp256k1_ge_t key; secp256k1_ge_set_gej(&key, &keyj); secp256k1_scalar_t msg = sig.s; CHECK(secp256k1_ecdsa_sig_verify(&sig, &key, &msg) == 0); } /* Test r/s equal to zero */ { /* (1,1) encoded in DER. */ unsigned char sigcder[8] = {0x30, 0x06, 0x02, 0x01, 0x01, 0x02, 0x01, 0x01}; unsigned char sigc64[64] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, }; unsigned char pubkeyc[65]; int pubkeyclen = 65; CHECK(secp256k1_ecdsa_recover_compact(msg32, 32, sigc64, pubkeyc, &pubkeyclen, 0, 0) == 1); CHECK(secp256k1_ecdsa_verify(msg32, 32, sigcder, sizeof(sigcder), pubkeyc, pubkeyclen) == 1); sigcder[4] = 0; sigc64[31] = 0; CHECK(secp256k1_ecdsa_recover_compact(msg32, 32, sigc64, pubkeyb, &pubkeyblen, 1, 0) == 0); CHECK(secp256k1_ecdsa_verify(msg32, 32, sigcder, sizeof(sigcder), pubkeyc, pubkeyclen) == 0); sigcder[4] = 1; sigcder[7] = 0; sigc64[31] = 1; sigc64[63] = 0; CHECK(secp256k1_ecdsa_recover_compact(msg32, 32, sigc64, pubkeyb, &pubkeyblen, 1, 0) == 0); CHECK(secp256k1_ecdsa_verify(msg32, 32, sigcder, sizeof(sigcder), pubkeyc, pubkeyclen) == 0); } }