我一直在努力让ecdh通过传入字节键缓冲区来处理openssl 用于私钥和对等密钥。在线查看,我可以看到如果键,如何做ecdh 在ecdh函数中生成。我没想到的是与评论有关 在示例代码中,“假设pkey,peerkey已经设置好了”。 (我不 我认为我正在正确地设置它们.--我是openssl的新手,可能也是 我缺少的一些基本内容。)我已经生成了两对公共/私人 密钥使用包含的generateAsymmetricKeyPair()函数。然后我硬编码这些值 所以我可以为每个测试都有相同的值。 (请注意,有一个前置的0x04值 在公钥上进行压缩)。我发现的是我没有任何错误 但每次调用函数时,我得到的ecdh值都不同。 (我会 预计会得到相同的结果,即使它是错误的。)我的代码包含在内,如果有的话 可以提醒我我做错了什么,非常感谢。
int32_t generateAsymmetricKeyPair(
int32_t keySizeBits,
unsigned char* publicKeyData,
unsigned char* privateKeyData,
unsigned char* keyIdData)
{
EC_KEY *ecKey = EC_KEY_new();
EC_POINT *ecPoint = NULL;
const EC_POINT *ecPoint2 = NULL;
EC_GROUP *ecGroup = NULL;
point_conversion_form_t form = POINT_CONVERSION_UNCOMPRESSED;
int32_t asn1_flag = OPENSSL_EC_NAMED_CURVE;
int32_t sizePrvKeyBytes = 0;
int32_t sizePubKeyBytes = 0;
switch(keySizeBits)
{
case 256:
ecGroup = EC_GROUP_new_by_curve_name(OBJ_sn2nid("prime256v1"));
break;
case 384:
ecGroup = EC_GROUP_new_by_curve_name(OBJ_sn2nid("secp384r1"));
break;
case 521:
ecGroup = EC_GROUP_new_by_curve_name(OBJ_sn2nid("secp521r1"));
break;
default:
return 0;
}
sizePrvKeyBytes = keySizeBits / 8 + (((keySizeBits % 8) > 0 ) ? 1 : 0);
sizePubKeyBytes = sizePrvKeyBytes * 2 + 1;
EC_GROUP_set_asn1_flag(ecGroup, asn1_flag);
EC_GROUP_set_point_conversion_form(ecGroup, form);
EC_KEY_set_group(ecKey, ecGroup);
ecPoint = EC_POINT_new(ecGroup);
if(EC_KEY_generate_key(ecKey))
{
const BIGNUM *bn;
/* Get Private Key */
bn = EC_KEY_get0_private_key(ecKey);
BN_bn2bin(bn, privateKeyData);
/* Get Public Key */
ecPoint2 = EC_KEY_get0_public_key(ecKey);
EC_POINT_point2oct(EC_KEY_get0_group(ecKey),
ecPoint2,
POINT_CONVERSION_UNCOMPRESSED,
publicKeyData,
sizePubKeyBytes,
NULL);
/* Calculate keyId, Ignore format byte[0] */
SHA1(publicKeyData + 1, sizePubKeyBytes - 1, keyIdData);
}
else
{
return 0;
}
return 1;
}
void deriveSharedSecret(
unsigned char* pKey,
unsigned char* peerKey,
unsigned char* &secretKey,
size_t* secretLen,
int32_t privKeySize)
{
bool grpForEc = true;
EVP_PKEY_CTX *sharedCtx;
EC_KEY *ecPrivKey = NULL;
EC_KEY *ecPeerKey = NULL;
EVP_PKEY *evpPrivKey = EVP_PKEY_new();
EVP_PKEY *evpPeerKey = EVP_PKEY_new();
BIGNUM *privBN = BN_new();
EC_POINT *ecPubKey = NULL;
EC_POINT *point = NULL;
BN_CTX *ctx = BN_CTX_new();
int32_t curve = -1;
int32_t peerKeySize = -1;
// One way of setting up EC key
EC_GROUP *ecGroup = NULL;
point_conversion_form_t form = POINT_CONVERSION_UNCOMPRESSED;
int32_t asn1_flag = OPENSSL_EC_NAMED_CURVE;
// Initialize output so that a return will result to NULL key and zero
// length if error condition.
*secretLen = 0;
secretKey = NULL;
// Create EC priv Key
switch(privKeySize)
{
case 32:
curve = NID_X9_62_prime256v1;
break;
case 48:
curve = NID_secp384r1;
break;
case 66:
curve = NID_secp521r1;
break;
default:
return;
}
peerKeySize = (2 * privKeySize + 1); // Add one for compression byte
try {
if(NULL == (ecGroup = EC_GROUP_new_by_curve_name(curve))) {throw ossl_error();}
EC_GROUP_set_asn1_flag(ecGroup, asn1_flag);
EC_GROUP_set_point_conversion_form(ecGroup, form);
if(NULL == (ecPrivKey = EC_KEY_new())) {throw ossl_error();}
if(NULL == (ecPeerKey = EC_KEY_new())) {throw ossl_error();}
if(1 != (EC_KEY_set_group(ecPrivKey, ecGroup))) {throw ossl_error();}
if(1 != (EC_KEY_set_group(ecPeerKey, ecGroup))) {throw ossl_error();}
/* PRIVATE KEY SETUP */
// Convert to BIGNUM for private key conversion
if(NULL == (BN_bin2bn(pKey, (privKeySize * 8), privBN))) {throw ossl_error();}
// Convert private key to EC_KEY
if(1 != (EC_KEY_set_private_key(ecPrivKey, privBN))) {throw ossl_error();}
// Set the public key from the private key
if(NULL == (ecPubKey = EC_POINT_new(EC_KEY_get0_group(ecPrivKey)))) {throw ossl_error();}
if(1 != (EC_POINT_mul(EC_KEY_get0_group(ecPrivKey), ecPubKey,
EC_KEY_get0_private_key(ecPrivKey), NULL, NULL, NULL))) {throw ossl_error();}
if(1 != (EC_KEY_set_public_key(ecPrivKey, ecPubKey))) {throw ossl_error();}
// Set the key in EVP_PKEY to ecPrivKey
evpPrivKey = EVP_PKEY_new();
if(1 != (EVP_PKEY_set1_EC_KEY(evpPrivKey, ecPrivKey))) {throw ossl_error();}
/* PUBLIC PEER KEY SETUP */
if(NULL == (point = EC_POINT_new(EC_KEY_get0_group(ecPeerKey)))) {throw ossl_error();}
if(1 != (EC_POINT_oct2point(EC_KEY_get0_group(ecPeerKey), point, peerKey,
peerKeySize, ctx))) {throw ossl_error();}
if(1 != (EC_KEY_set_public_key(ecPeerKey, point))) {throw ossl_error();}
// Set the key in EVP_PKEY to ecPeerKey
if(1 != (EVP_PKEY_set1_EC_KEY(evpPeerKey, ecPeerKey))) {throw ossl_error();}
/* SHARED SECRET SETUP */
if(NULL == (sharedCtx = EVP_PKEY_CTX_new(evpPrivKey, NULL))) {throw ossl_error();}
// Initialize
if(1 != (EVP_PKEY_derive_init(sharedCtx))) {throw ossl_error();}
// Provide the peer (public) key
if(1 != (EVP_PKEY_derive_set_peer(sharedCtx, evpPeerKey))){throw ossl_error();}
// Determine the buffer length for shared secret
if((1 != EVP_PKEY_derive(sharedCtx, NULL, secretLen))) {throw ossl_error();}
// Generate the shared secret buffer
if(NULL == (secretKey = reinterpret_cast<unsigned char *>(OPENSSL_malloc(*secretLen))))
{throw ossl_error();}
// Derive the shared secret
if(1 != (EVP_PKEY_derive(sharedCtx, secretKey, secretLen))) {throw ossl_error();}
} catch(ossl_error& ex) {
*secretLen = 0;
secretKey = NULL;
if(NULL != ecPrivKey) { EC_KEY_free(ecPrivKey); }
if(NULL != ecPeerKey) { EC_KEY_free(ecPeerKey); }
if(NULL != ecPubKey) { EC_POINT_free(ecPubKey); }
if(NULL != point) { EC_POINT_free(point); }
if(NULL != sharedCtx) { EVP_PKEY_CTX_free(sharedCtx); }
if(NULL != evpPrivKey) { EVP_PKEY_free(evpPrivKey); }
if(NULL != evpPeerKey) { EVP_PKEY_free(evpPeerKey); }
if(NULL != ctx) { BN_CTX_free(ctx); }
if(NULL != privBN) { BN_free(privBN); }
return;
}
EC_KEY_free(ecPrivKey);
EC_KEY_free(ecPeerKey);
EC_POINT_free(ecPubKey);
EC_POINT_free(point);
EVP_PKEY_CTX_free(sharedCtx);
EVP_PKEY_free(evpPrivKey);
EVP_PKEY_free(evpPeerKey);
BN_CTX_free(ctx);
BN_free(privBN);
}
int main ()
{
int32_t keySizeBits = 384;
int32_t keySize = keySizeBits / 8;
unsigned char privateKeyData[keySize];
unsigned char publicKeyData[keySize * 2 + 1];
unsigned char keyIdData[keySize];
unsigned char privateKeyData2[keySize];
unsigned char publicKeyData2[keySize * 2 + 1];
unsigned char keyIdData2[keySize];
unsigned char* sharedSecret = new unsigned char[keySize];
unsigned char* sharedSecret2 = new unsigned char[keySize];
size_t secretLen = 0;
size_t secretLen2 = 0;
unsigned char _privateKeyData[] = {
0x5d, 0xf0, 0x0d, 0x0f, 0x47, 0x1b, 0x3c, 0x11, 0xb7, 0x5d,
0x12, 0x90, 0xff, 0x91, 0x93, 0xe6, 0xba, 0xd0, 0x75, 0xf9,
0xe3, 0x48, 0xa2, 0x09, 0x85, 0x05, 0xe1, 0x0a, 0xf2, 0xfd,
0xad, 0x9a, 0xf7, 0x98, 0xa3, 0xb3, 0x5f, 0x23, 0x80, 0xf2,
0x05, 0x73, 0xeb, 0x73, 0x85, 0x0c, 0x1b, 0x3e
};
unsigned char _publicKeyData[] = {
0x04, 0x9b, 0x6e, 0x53, 0x33, 0x4f, 0x87, 0x18, 0x45, 0xee,
0x17, 0x9a, 0xbe, 0xa6, 0x41, 0xe1, 0xf0, 0xb2, 0x52, 0x9f,
0xe5, 0x22, 0x67, 0x80, 0x64, 0x3b, 0x1b, 0x34, 0x8e, 0xa5,
0x01, 0x2a, 0x06, 0xe4, 0xaa, 0xd2, 0xea, 0x29, 0x0a, 0xf5,
0xa0, 0x80, 0x49, 0x1f, 0xa9, 0x4a, 0x30, 0x91, 0xd7, 0x59,
0x27, 0x9c, 0xa8, 0x9b, 0x18, 0x76, 0xe4, 0xd6, 0x27, 0x93,
0x0a, 0x6f, 0x01, 0x4d, 0x7d, 0x72, 0xb5, 0x78, 0x91, 0x8f,
0x30, 0x9b, 0xe2, 0x55, 0x3f, 0xfa, 0x13, 0x3c, 0x52, 0x1b,
0x5f, 0x56, 0xf7, 0x24, 0x3b, 0x54, 0x19, 0x0b, 0x61, 0x28,
0x54, 0x72, 0x04, 0xd5, 0xb8, 0x0a, 0x76
};
unsigned char _privateKeyData2[] = {
0x50, 0x96, 0xce, 0x89, 0xb3, 0x17, 0xbf, 0x63, 0x3d, 0x05,
0x95, 0x82, 0x99, 0xc5, 0xd1, 0x75, 0x0d, 0x21, 0x23, 0x38,
0xd6, 0x5e, 0x2a, 0xc6, 0x11, 0x09, 0xb4, 0xb0, 0x07, 0x18,
0x0d, 0xa4, 0xb5, 0x2c, 0xf3, 0x96, 0x0d, 0x9c, 0x6e, 0xad,
0x7c, 0x14, 0x7f, 0x5b, 0xcd, 0xfd, 0x33, 0xce
};
unsigned char _publicKeyData2[] = {
0x04, 0x29, 0x00, 0x8a, 0xe7, 0xe2, 0x81, 0xab, 0xf2, 0xf4,
0x2e, 0x1b, 0xb3, 0x73, 0xb4, 0xfd, 0xc6, 0x7e, 0x5e, 0x02,
0x61, 0x25, 0x65, 0x6d, 0x5e, 0x44, 0xc9, 0x66, 0x21, 0x83,
0x10, 0xea, 0xdc, 0x36, 0xa9, 0x7d, 0x1a, 0x55, 0xf0, 0x27,
0xa5, 0x6f, 0x71, 0x36, 0x70, 0x57, 0xf7, 0x9f, 0x3b, 0x58,
0x78, 0x3a, 0x14, 0x42, 0x58, 0x13, 0xf6, 0xef, 0xcb, 0x55,
0xe2, 0xaa, 0x50, 0x95, 0x20, 0xa7, 0x29, 0x9c, 0x78, 0x94,
0x9e, 0xe8, 0x81, 0x5a, 0x8e, 0x6e, 0x45, 0xd8, 0xd1, 0xae,
0x1b, 0x51, 0x80, 0xcf, 0xce, 0x0c, 0x06, 0xab, 0x7d, 0xca,
0xa3, 0xff, 0x4e, 0x65, 0x97, 0xb8, 0xd6
};
memset(privateKeyData, 0, keySize);
memset(publicKeyData, 0, keySize * 2 + 1);
memset(privateKeyData2, 0, keySize);
memset(publicKeyData2, 0, keySize * 2 + 1);
memset(sharedSecret, 0, keySize);
memset(sharedSecret2, 0, keySize);
memcpy(privateKeyData, _privateKeyData, keySize);
memcpy(publicKeyData, _publicKeyData, keySize * 2 + 1);
memcpy(privateKeyData2, _privateKeyData2, keySize);
memcpy(publicKeyData2, _publicKeyData2, keySize * 2 + 1);
deriveSharedSecret(privateKeyData, publicKeyData2,
reinterpret_cast<unsigned char * &>(sharedSecret), &secretLen, keySizeBits / 8);
deriveSharedSecret(privateKeyData2, publicKeyData,
reinterpret_cast<unsigned char * &>(sharedSecret2), &secretLen2, keySizeBits / 8);
OPENSSL_free(sharedSecret);
OPENSSL_free(sharedSecret2);
cout << "Out of Main" << endl;
return 0;
}
答案 0 :(得分:0)
问题在于我向BN_bin2bn提供了不正确的尺寸。我无意中将字节转换为位(乘以8),并将参数更改为私钥大小,导致共享密钥正确。此外,我发现没有必要从私钥设置公钥,因为 set_private_key 函数已经这样做了,尽管这样做并没有引起我的问题。此外,如果有人想使用此代码作为参考,最好不要让公钥在传入时包含编码字符;编码应该可以动态完成。