设置private后设置public key有什么用?
What is the purpose of setting public key after setting private?
我想知道为什么我必须在调用 EC_POINT_point2hex 之前调用 EC_KEY_set_public_key
已经调用了 EC_KEY_set_private_key
?是不是已经通过设置私钥确定了?
#include <stdio.h>
#include <stdlib.h>
#include <openssl/ec.h>
#include <openssl/obj_mac.h>
#include <openssl/bn.h>
#include <openssl/ossl_typ.h>
int main()
{
EC_KEY *eckey = NULL;
EC_POINT *pub_key = NULL;
const EC_GROUP *group = NULL;
BIGNUM *priv;
BN_CTX *ctx;
priv = BN_new();
ctx = BN_CTX_new();
BN_hex2bn(&priv, "EDCC6224FEE390A57C76C13A9BECC9502A6F3B1BF6F72B6ED11B83A0F0E3E9FC");
eckey = EC_KEY_new_by_curve_name(NID_secp256k1);
group = EC_KEY_get0_group(eckey);
pub_key = EC_POINT_new(group);
EC_KEY_set_private_key(eckey, priv);
if (!EC_POINT_mul(group, pub_key, priv, NULL, NULL, ctx))
printf("Error at EC_POINT_mul.\n");
EC_KEY_set_public_key(eckey, pub_key);
char *cc = EC_POINT_point2hex(group, pub_key, POINT_CONVERSION_UNCOMPRESSED, ctx);
char *c=cc;
int i;
for (i=0; i<130; i++)
{
printf("%c", *c++);
}
printf("\n");
BN_CTX_free(ctx);
free(cc);
BN_free(priv);
return 0;
}
根据1.1.1f
版本的libssl1.1
,我偶然发现了如下定义:
int EC_KEY_set_private_key(EC_KEY *key, const BIGNUM *priv_key)
{
if (key->group == NULL || key->group->meth == NULL)
return 0;
if (key->group->meth->set_private != NULL
&& key->group->meth->set_private(key, priv_key) == 0)
return 0;
if (key->meth->set_private != NULL
&& key->meth->set_private(key, priv_key) == 0)
return 0;
BN_clear_free(key->priv_key);
key->priv_key = BN_dup(priv_key);
return (key->priv_key == NULL) ? 0 : 1;
}
int EC_KEY_set_public_key(EC_KEY *key, const EC_POINT *pub_key)
{
if (key->meth->set_public != NULL
&& key->meth->set_public(key, pub_key) == 0)
return 0;
EC_POINT_free(key->pub_key);
key->pub_key = EC_POINT_dup(pub_key, key->group);
return (key->pub_key == NULL) ? 0 : 1;
}
我试图深入研究 apt source
提供的 libssl1.1
来源,但我没有得到 key->meth->set_private
/ 'key->meth->set_public' 因为那:
void EC_KEY_METHOD_set_init(EC_KEY_METHOD *meth,
int (*init)(EC_KEY *key),
void (*finish)(EC_KEY *key),
int (*copy)(EC_KEY *dest, const EC_KEY *src),
int (*set_group)(EC_KEY *key, const EC_GROUP *grp),
int (*set_private)(EC_KEY *key,
const BIGNUM *priv_key),
int (*set_public)(EC_KEY *key,
const EC_POINT *pub_key))
{
meth->init = init;
meth->finish = finish;
meth->copy = copy;
meth->set_group = set_group;
meth->set_private = set_private;
meth->set_public = set_public;
}
和
user@host openssl-1.1.1f$ grep -R "EC_KEY_METHOD_set_init"
util/libcrypto.num:EC_KEY_METHOD_set_init 3777 1_1_0 EXIST::FUNCTION:EC
include/openssl/ec.h:void EC_KEY_METHOD_set_init(EC_KEY_METHOD *meth,
crypto/ec/ec_kmeth.c:void EC_KEY_METHOD_set_init(EC_KEY_METHOD *meth,
user@host openssl-1.1.1f$
那么...为什么在调用 pub_key
作为参数的 EC_POINT_point2hex
之前必须将 pub_key
设置为 eckey
?
EC_KEY_METHOD_set_init 用于修改默认方法,但未使用。默认情况下函数指针 set_private 和 set_pucblic 等于 0.
static const EC_KEY_METHOD openssl_ec_key_method = {
"OpenSSL EC_KEY method",
0,
0,0,0,0,0,0,
ossl_ec_key_gen,
ossl_ecdh_compute_key,
ossl_ecdsa_sign,
ossl_ecdsa_sign_setup,
ossl_ecdsa_sign_sig,
ossl_ecdsa_verify,
ossl_ecdsa_verify_sig
};
static const EC_KEY_METHOD *default_ec_key_meth = &openssl_ec_key_method;
EC_KEY_METHOD的定义是:
struct ec_key_method_st {
const char *name;
int32_t flags;
int (*init)(EC_KEY *key);
void (*finish)(EC_KEY *key);
int (*copy)(EC_KEY *dest, const EC_KEY *src);
int (*set_group)(EC_KEY *key, const EC_GROUP *grp);
int (*set_private)(EC_KEY *key, const BIGNUM *priv_key);
int (*set_public)(EC_KEY *key, const EC_POINT *pub_key);
int (*keygen)(EC_KEY *key);
int (*compute_key)(unsigned char **pout, size_t *poutlen,
const EC_POINT *pub_key, const EC_KEY *ecdh);
int (*sign)(int type, const unsigned char *dgst, int dlen, unsigned char
*sig, unsigned int *siglen, const BIGNUM *kinv,
const BIGNUM *r, EC_KEY *eckey);
int (*sign_setup)(EC_KEY *eckey, BN_CTX *ctx_in, BIGNUM **kinvp,
BIGNUM **rp);
ECDSA_SIG *(*sign_sig)(const unsigned char *dgst, int dgst_len,
const BIGNUM *in_kinv, const BIGNUM *in_r,
EC_KEY *eckey);
int (*verify)(int type, const unsigned char *dgst, int dgst_len,
const unsigned char *sigbuf, int sig_len, EC_KEY *eckey);
int (*verify_sig)(const unsigned char *dgst, int dgst_len,
const ECDSA_SIG *sig, EC_KEY *eckey);
};
因此 EC_KEY_set_private_key
将仅设置 priv_key 而不是 pub_key,后者必须由 EC_KEY_set_public_key
设置。一般来说,拥有私钥并不意味着拥有public密钥,而是意味着我们可以计算它。所以最好保存起来,免得重做几次重算。
最后,EC_POINT_point2hex 允许以十六进制格式打印一个点。 y你打印 pub_key 但它可能是曲线上的任何一点。
我想知道为什么我必须在调用 EC_POINT_point2hex 之前调用 EC_KEY_set_public_key
已经调用了 EC_KEY_set_private_key
?是不是已经通过设置私钥确定了?
#include <stdio.h>
#include <stdlib.h>
#include <openssl/ec.h>
#include <openssl/obj_mac.h>
#include <openssl/bn.h>
#include <openssl/ossl_typ.h>
int main()
{
EC_KEY *eckey = NULL;
EC_POINT *pub_key = NULL;
const EC_GROUP *group = NULL;
BIGNUM *priv;
BN_CTX *ctx;
priv = BN_new();
ctx = BN_CTX_new();
BN_hex2bn(&priv, "EDCC6224FEE390A57C76C13A9BECC9502A6F3B1BF6F72B6ED11B83A0F0E3E9FC");
eckey = EC_KEY_new_by_curve_name(NID_secp256k1);
group = EC_KEY_get0_group(eckey);
pub_key = EC_POINT_new(group);
EC_KEY_set_private_key(eckey, priv);
if (!EC_POINT_mul(group, pub_key, priv, NULL, NULL, ctx))
printf("Error at EC_POINT_mul.\n");
EC_KEY_set_public_key(eckey, pub_key);
char *cc = EC_POINT_point2hex(group, pub_key, POINT_CONVERSION_UNCOMPRESSED, ctx);
char *c=cc;
int i;
for (i=0; i<130; i++)
{
printf("%c", *c++);
}
printf("\n");
BN_CTX_free(ctx);
free(cc);
BN_free(priv);
return 0;
}
根据1.1.1f
版本的libssl1.1
,我偶然发现了如下定义:
int EC_KEY_set_private_key(EC_KEY *key, const BIGNUM *priv_key)
{
if (key->group == NULL || key->group->meth == NULL)
return 0;
if (key->group->meth->set_private != NULL
&& key->group->meth->set_private(key, priv_key) == 0)
return 0;
if (key->meth->set_private != NULL
&& key->meth->set_private(key, priv_key) == 0)
return 0;
BN_clear_free(key->priv_key);
key->priv_key = BN_dup(priv_key);
return (key->priv_key == NULL) ? 0 : 1;
}
int EC_KEY_set_public_key(EC_KEY *key, const EC_POINT *pub_key)
{
if (key->meth->set_public != NULL
&& key->meth->set_public(key, pub_key) == 0)
return 0;
EC_POINT_free(key->pub_key);
key->pub_key = EC_POINT_dup(pub_key, key->group);
return (key->pub_key == NULL) ? 0 : 1;
}
我试图深入研究 apt source
提供的 libssl1.1
来源,但我没有得到 key->meth->set_private
/ 'key->meth->set_public' 因为那:
void EC_KEY_METHOD_set_init(EC_KEY_METHOD *meth,
int (*init)(EC_KEY *key),
void (*finish)(EC_KEY *key),
int (*copy)(EC_KEY *dest, const EC_KEY *src),
int (*set_group)(EC_KEY *key, const EC_GROUP *grp),
int (*set_private)(EC_KEY *key,
const BIGNUM *priv_key),
int (*set_public)(EC_KEY *key,
const EC_POINT *pub_key))
{
meth->init = init;
meth->finish = finish;
meth->copy = copy;
meth->set_group = set_group;
meth->set_private = set_private;
meth->set_public = set_public;
}
和
user@host openssl-1.1.1f$ grep -R "EC_KEY_METHOD_set_init"
util/libcrypto.num:EC_KEY_METHOD_set_init 3777 1_1_0 EXIST::FUNCTION:EC
include/openssl/ec.h:void EC_KEY_METHOD_set_init(EC_KEY_METHOD *meth,
crypto/ec/ec_kmeth.c:void EC_KEY_METHOD_set_init(EC_KEY_METHOD *meth,
user@host openssl-1.1.1f$
那么...为什么在调用 pub_key
作为参数的 EC_POINT_point2hex
之前必须将 pub_key
设置为 eckey
?
EC_KEY_METHOD_set_init 用于修改默认方法,但未使用。默认情况下函数指针 set_private 和 set_pucblic 等于 0.
static const EC_KEY_METHOD openssl_ec_key_method = {
"OpenSSL EC_KEY method",
0,
0,0,0,0,0,0,
ossl_ec_key_gen,
ossl_ecdh_compute_key,
ossl_ecdsa_sign,
ossl_ecdsa_sign_setup,
ossl_ecdsa_sign_sig,
ossl_ecdsa_verify,
ossl_ecdsa_verify_sig
};
static const EC_KEY_METHOD *default_ec_key_meth = &openssl_ec_key_method;
EC_KEY_METHOD的定义是:
struct ec_key_method_st {
const char *name;
int32_t flags;
int (*init)(EC_KEY *key);
void (*finish)(EC_KEY *key);
int (*copy)(EC_KEY *dest, const EC_KEY *src);
int (*set_group)(EC_KEY *key, const EC_GROUP *grp);
int (*set_private)(EC_KEY *key, const BIGNUM *priv_key);
int (*set_public)(EC_KEY *key, const EC_POINT *pub_key);
int (*keygen)(EC_KEY *key);
int (*compute_key)(unsigned char **pout, size_t *poutlen,
const EC_POINT *pub_key, const EC_KEY *ecdh);
int (*sign)(int type, const unsigned char *dgst, int dlen, unsigned char
*sig, unsigned int *siglen, const BIGNUM *kinv,
const BIGNUM *r, EC_KEY *eckey);
int (*sign_setup)(EC_KEY *eckey, BN_CTX *ctx_in, BIGNUM **kinvp,
BIGNUM **rp);
ECDSA_SIG *(*sign_sig)(const unsigned char *dgst, int dgst_len,
const BIGNUM *in_kinv, const BIGNUM *in_r,
EC_KEY *eckey);
int (*verify)(int type, const unsigned char *dgst, int dgst_len,
const unsigned char *sigbuf, int sig_len, EC_KEY *eckey);
int (*verify_sig)(const unsigned char *dgst, int dgst_len,
const ECDSA_SIG *sig, EC_KEY *eckey);
};
因此 EC_KEY_set_private_key
将仅设置 priv_key 而不是 pub_key,后者必须由 EC_KEY_set_public_key
设置。一般来说,拥有私钥并不意味着拥有public密钥,而是意味着我们可以计算它。所以最好保存起来,免得重做几次重算。
最后,EC_POINT_point2hex 允许以十六进制格式打印一个点。 y你打印 pub_key 但它可能是曲线上的任何一点。