gpt4 book ai didi

java - BouncyCaSTLe Java API 和 OpenSSL 生成的 ECDH key 不同

转载 作者:行者123 更新时间:2023-11-30 04:00:16 25 4
gpt4 key购买 nike

我正在尝试利用椭圆曲线加密。我需要同一件事的两种实现,一种在 Java 中,一种在 C 中。我正在使用使用曲线 secp256k1 生成的两个 key 对来测试它们。当我在 Java 中生成派生 secret 时,我总是得到与从 OpenSSL 得到的不同的数字。

Java代码:

/* privateKey and peerPublicKey are generated with the following parameters */
ECParameterSpec paramSpec = ECNamedCurveTable.getParameterSpec("secp256k1");
/* ... */
Provider BC = new BouncyCastleProvider();
KeyAgreement agr = KeyAgreement.getInstance("ECDH", BC);
agr.init(privateKey);
agr.doPhase(peerPublicKey, true);
byte[] secret = agr.generateSecret();

C代码

/* pkey and peerkey are generated using EC_KEY_new_by_curve_name(NID_secp256k1) */
/* and than wrapped in an EVP_PKEY */
EVP_PKEY_CTX *ctx = EVP_PKEY_CTX_new(pkey, NULL);
uint8_t *secret = NULL;
size_t secret_len;
EVP_PKEY_derive_init(ctx);
EVP_PKEY_derive_set_peer(ctx, peerkey);
EVP_PKEY_derive(ctx, NULL, &secret_len);
secret = malloc(secret_len);
EVP_PKEY_derive(ctx, secret, &secret_len);

我确信 key 是有效的,并且它们在 C 和 Java 代码中都是相同的,但我不明白为什么派生的 secret 不同。我错过了什么吗?

谢谢

最佳答案

EVP_PKEY_CTX *ctx = EVP_PKEY_CTX_new(pkey, NULL);
uint8_t *secret = NULL;
size_t secret_len;
EVP_PKEY_derive_init(ctx);
EVP_PKEY_derive_set_peer(ctx, peerkey);
EVP_PKEY_derive(ctx, NULL, &secret_len);
secret = malloc(secret_len);
EVP_PKEY_derive(ctx, secret, &secret_len);

这段代码看起来缺少几个步骤。例如,EVP_PKEY_paramgen_init 不存在。

OpenSSL wiki 在 Elliptic Curve Diffie-Hellman 有一个示例。我将复制/粘贴到下面以避免仅链接的答案,但我相信这是马特·卡斯韦尔的作品。

EVP_PKEY_CTX *pctx, *kctx;
EVP_PKEY_CTX *ctx;
unsigned char *secret;
EVP_PKEY *pkey = NULL, *peerkey, *params = NULL;

/* Create the context for parameter generation */
if(NULL == (pctx = EVP_PKEY_CTX_new_id(EVP_PKEY_EC, NULL))) handleErrors();

/* Initialise the parameter generation */
if(1 != EVP_PKEY_paramgen_init(pctx)) handleErrors();

/* We're going to use the ANSI X9.62 Prime 256v1 curve */
if(1 != EVP_PKEY_CTX_set_ec_paramgen_curve_nid(pctx, NID_X9_62_prime256v1)) handleErrors();

/* Create the parameter object params */
if (!EVP_PKEY_paramgen(pctx, &params)) handleErrors();

/* Create the context for the key generation */
if(NULL == (kctx = EVP_PKEY_CTX_new(params, NULL))) handleErrors();

/* Generate the key */
if(1 != EVP_PKEY_keygen_init(kctx)) handleErrors();
if (1 != EVP_PKEY_keygen(kctx, &pkey)) handleErrors();

/* Get the peer's public key, and provide the peer with our public key -
* how this is done will be specific to your circumstances */
peerkey = get_peerkey(pkey);

/* Create the context for the shared secret derivation */
if(NULL == (ctx = EVP_PKEY_CTX_new(pkey, NULL))) handleErrors();

/* Initialise */
if(1 != EVP_PKEY_derive_init(ctx)) handleErrors();

/* Provide the peer public key */
if(1 != EVP_PKEY_derive_set_peer(ctx, peerkey)) handleErrors();

/* Determine buffer length for shared secret */
if(1 != EVP_PKEY_derive(ctx, NULL, secret_len)) handleErrors();

/* Create the buffer */
if(NULL == (secret = OPENSSL_malloc(*secret_len))) handleErrors();

/* Derive the shared secret */
if(1 != (EVP_PKEY_derive(ctx, secret, secret_len))) handleErrors();

EVP_PKEY_CTX_free(ctx);
EVP_PKEY_free(peerkey);
EVP_PKEY_free(pkey);
EVP_PKEY_CTX_free(kctx);
EVP_PKEY_free(params);
EVP_PKEY_CTX_free(pctx);

/* Never use a derived secret directly. Typically it is passed
* through some hash function to produce a key */
return secret;
<小时/>

When I generate the derived secret in Java I always get a different number from what I get from OpenSSL.

协议(protocol)的每次运行都会产生不同的结果。这是因为每一方都会为协议(protocol)的每次运行选择一个随机值。也就是说,g^a 中的 a 是随机的,并且每次运行都不同,因此公钥 A = g^a 是不同的每次运行。

如果一切正常,您将永远不会看到各方使用相同的值,或者一方重复使用过去的值。独立执行永远不会产生相同的结果。 OpenSSL ↔ OpenSSL、OpenSSL ↔ Java 或 Java ↔ Java 并不重要。他们总是会产生不同的结果。

关于java - BouncyCaSTLe Java API 和 OpenSSL 生成的 ECDH key 不同,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22149271/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com