Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/133.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 无法使用C+;中的OpenSSL派生Diffie Hellman共享机密+;_C++_Openssl_Diffie Hellman - Fatal编程技术网

C++ 无法使用C+;中的OpenSSL派生Diffie Hellman共享机密+;

C++ 无法使用C+;中的OpenSSL派生Diffie Hellman共享机密+;,c++,openssl,diffie-hellman,C++,Openssl,Diffie Hellman,我试图熟悉OpenSSL Diffie-Hellman的特性,在这样做的过程中,我试图创建一个简单的程序,它将生成两组Diffie-Hellman私钥和公钥,然后派生出共享密钥。我遵循了OpenSSL wiki上的Diffie Hellman教程,我能够生成密钥,但是我无法导出共享密钥。我的C++(Linux)代码如下: #include <iostream> #include <openssl/dh.h> #include <openssl/engine.h>

我试图熟悉OpenSSL Diffie-Hellman的特性,在这样做的过程中,我试图创建一个简单的程序,它将生成两组Diffie-Hellman私钥和公钥,然后派生出共享密钥。我遵循了OpenSSL wiki上的Diffie Hellman教程,我能够生成密钥,但是我无法导出共享密钥。我的C++(Linux)代码如下:

#include <iostream>
#include <openssl/dh.h>
#include <openssl/engine.h>
#include <openssl/err.h>
#include <openssl/evp.h>
#include <openssl/rsa.h>

int main(int argc, char** argv)
{

    EVP_PKEY* params;

    EVP_PKEY_CTX *kctx1, *kctx2, *dctx1, *dctx2;

    unsigned char *skey1, *skey2;
    size_t skeylen1, skeylen2;
    EVP_PKEY *dh_1, *dh_2;
    BIO* bio_out = NULL;
    int result = 0;
    ENGINE* eng;

    BIO* fp = BIO_new_fp(stdout, BIO_NOCLOSE);

    // Initalise Diffie Hellman PKEY for client 1
    if(NULL == (dh_1 = EVP_PKEY_new())) {
        std::cout << "error 1" << std::endl;
    }

    // Initalise Diffie Hellman PKEY for client 2
    if(NULL == (dh_2 = EVP_PKEY_new())) {
        std::cout << "error 2" << std::endl;
    }

    // Initalise Diffie Hellman parameter PKEY
    if(NULL == (params = EVP_PKEY_new())) {
        std::cout << "error 3" << std::endl;
    }

    // Set Diffie Hellman paramerers
    if(1 != EVP_PKEY_set1_DH(params, DH_get_2048_256())) {
        std::cout << "error 4" << std::endl;
    }

    // Initalise client 1 PKEY Context
    if(!(kctx1 = EVP_PKEY_CTX_new(params, NULL))) {
        std::cout << "error 5" << std::endl;
    }

    // Initalise client 2 PKEY Context
    if(!(kctx2 = EVP_PKEY_CTX_new(params, NULL))) {
        std::cout << "error 6" << std::endl;
    }

    if(!kctx1) {
        std::cout << "error 7" << std::endl;
    }

    if(!kctx2) {
        std::cout << "error 8" << std::endl;
    }

    // Initalise both contexts key generators
    if(1 != EVP_PKEY_keygen_init(kctx1)) {
        std::cout << "error 9" << std::endl;
    }

    if(1 != EVP_PKEY_keygen_init(kctx2)) {
        std::cout << "error 10" << std::endl;
    }

    // Generate DH public and private keys for client 1
    if(1 != EVP_PKEY_keygen(kctx1, &dh_1)) {
        std::cout << "error 11" << std::endl;
    }

    // Generate DH public and private keys for client 2
    if(1 != EVP_PKEY_keygen(kctx2, &dh_2)) {
        std::cout << "error 12" << std::endl;
    }

    // EVP_PKEY_print_public(fp, dh_1, 3, NULL);

    // EVP_PKEY_print_public(fp, dh_2, 3, NULL);

    // Create key derivation context
    if(NULL == (dctx1 = EVP_PKEY_CTX_new(dh_1, NULL))) {
        std::cout << "error 13" << std::endl;
    }

    if(!dctx1) {
        std::cout << "error 14" << std::endl;
    }

    // Initalise first key derivation context
    if(1 != EVP_PKEY_derive_init(dctx1)) {
        std::cout << "error 15" << std::endl;
    }

    if(1 != EVP_PKEY_check(dctx1)) {
        std::cout << "error 16" << std::endl;
    }

    if(1 != EVP_PKEY_param_check(dctx1)) {
        std::cout << "error 17" << std::endl;
    }

    // Set first key derivation context peer key to the second DH PKEY
    if(1 != EVP_PKEY_derive_set_peer(dctx1, dh_2)) {
        std::cout << "error 18" << std::endl;
    }

    if(1 != EVP_PKEY_public_check(dctx1)) {
        std::cout << "error 19" << std::endl;
    }

    /* Determine buffer length */
    if(EVP_PKEY_derive(dctx1, NULL, &skeylen1) <= 0) {
    }

    // Assign memory for shared key variable
    skey1 = (unsigned char*)OPENSSL_malloc(skeylen1);

    if(result = EVP_PKEY_derive(dctx1, skey1, &skeylen1) <= 0) {
        std::cout << "Key: " << skey1 << std::endl;

        for(int i = 0; i < skeylen1; i++) {
            std::cout << std::hex << (unsigned int)skey1[i];
        }
    }

    ERR_print_errors_fp(stdout);

    std::cout << result << std::endl;
}
    if(1 != EVP_PKEY_assign(params, EVP_PKEY_DHX, DH_get_2048_256())) {
        std::cout << "error 4" << std::endl;
    }
当我使用

    if(NULL == (dctx1 = EVP_PKEY_CTX_new(dh_1, NULL))) {
        std::cout << "error 13" << std::endl;
    }
当我将“EVP_PKEY_CTX_new(dh_1,NULL)”更改为“EVP_PKEY_CTX_new(params,NULL)”时,如下所示:

    if(NULL == (dctx1 = EVP_PKEY_CTX_new(params, NULL))) {
        std::cout << "error 13" << std::endl;
    }
if(NULL==(dctx1=EVP\u PKEY\u CTX\u new(params,NULL))){

std::cout对于您发布的代码版本,我得到了与您略有不同的错误。我从您的代码中得到以下输出(与OpenSSL 1.1.1链接):

第一个“错误16”输出只是因为OpenSSL目前不支持对Diffie-Hellman密钥的
EVP\u PKEY\u check()
调用。因此可以安全地忽略这一点

第二个“error 17”输出(与错误队列中的“check p not safe prime”错误相关)是一个更大的问题。这是因为Diffie-Hellman密钥有两种不同的类型。默认情况下,OpenSSL使用PKCS#3 Diffie-Hellman密钥。但是它也支持X9.42 Diffie-Hellman密钥。函数
DH_get_2048_256()
为X9.42密钥提供一组内置参数。但是函数
EVP_PKEY_set1_DH()
要求提供的DH对象是PKCS#3密钥

在我看来,这实际上像是OpenSSL中的一个bug(
EVP_PKEY_set1_DH()
应该真正检测到它是什么类型的密钥并做正确的事情),因此我为此提出了以下OpenSSL问题:

您可以将
EVP\u PKEY\u set1\u DH()
调用替换为一个to
EVP\u PKEY\u assign()
,并将类型指定为
EVP\u PKEY\u DHX
,如下所示:

#include <iostream>
#include <openssl/dh.h>
#include <openssl/engine.h>
#include <openssl/err.h>
#include <openssl/evp.h>
#include <openssl/rsa.h>

int main(int argc, char** argv)
{

    EVP_PKEY* params;

    EVP_PKEY_CTX *kctx1, *kctx2, *dctx1, *dctx2;

    unsigned char *skey1, *skey2;
    size_t skeylen1, skeylen2;
    EVP_PKEY *dh_1, *dh_2;
    BIO* bio_out = NULL;
    int result = 0;
    ENGINE* eng;

    BIO* fp = BIO_new_fp(stdout, BIO_NOCLOSE);

    // Initalise Diffie Hellman PKEY for client 1
    if(NULL == (dh_1 = EVP_PKEY_new())) {
        std::cout << "error 1" << std::endl;
    }

    // Initalise Diffie Hellman PKEY for client 2
    if(NULL == (dh_2 = EVP_PKEY_new())) {
        std::cout << "error 2" << std::endl;
    }

    // Initalise Diffie Hellman parameter PKEY
    if(NULL == (params = EVP_PKEY_new())) {
        std::cout << "error 3" << std::endl;
    }

    // Set Diffie Hellman paramerers
    if(1 != EVP_PKEY_set1_DH(params, DH_get_2048_256())) {
        std::cout << "error 4" << std::endl;
    }

    // Initalise client 1 PKEY Context
    if(!(kctx1 = EVP_PKEY_CTX_new(params, NULL))) {
        std::cout << "error 5" << std::endl;
    }

    // Initalise client 2 PKEY Context
    if(!(kctx2 = EVP_PKEY_CTX_new(params, NULL))) {
        std::cout << "error 6" << std::endl;
    }

    if(!kctx1) {
        std::cout << "error 7" << std::endl;
    }

    if(!kctx2) {
        std::cout << "error 8" << std::endl;
    }

    // Initalise both contexts key generators
    if(1 != EVP_PKEY_keygen_init(kctx1)) {
        std::cout << "error 9" << std::endl;
    }

    if(1 != EVP_PKEY_keygen_init(kctx2)) {
        std::cout << "error 10" << std::endl;
    }

    // Generate DH public and private keys for client 1
    if(1 != EVP_PKEY_keygen(kctx1, &dh_1)) {
        std::cout << "error 11" << std::endl;
    }

    // Generate DH public and private keys for client 2
    if(1 != EVP_PKEY_keygen(kctx2, &dh_2)) {
        std::cout << "error 12" << std::endl;
    }

    // EVP_PKEY_print_public(fp, dh_1, 3, NULL);

    // EVP_PKEY_print_public(fp, dh_2, 3, NULL);

    // Create key derivation context
    if(NULL == (dctx1 = EVP_PKEY_CTX_new(dh_1, NULL))) {
        std::cout << "error 13" << std::endl;
    }

    if(!dctx1) {
        std::cout << "error 14" << std::endl;
    }

    // Initalise first key derivation context
    if(1 != EVP_PKEY_derive_init(dctx1)) {
        std::cout << "error 15" << std::endl;
    }

    if(1 != EVP_PKEY_check(dctx1)) {
        std::cout << "error 16" << std::endl;
    }

    if(1 != EVP_PKEY_param_check(dctx1)) {
        std::cout << "error 17" << std::endl;
    }

    // Set first key derivation context peer key to the second DH PKEY
    if(1 != EVP_PKEY_derive_set_peer(dctx1, dh_2)) {
        std::cout << "error 18" << std::endl;
    }

    if(1 != EVP_PKEY_public_check(dctx1)) {
        std::cout << "error 19" << std::endl;
    }

    /* Determine buffer length */
    if(EVP_PKEY_derive(dctx1, NULL, &skeylen1) <= 0) {
    }

    // Assign memory for shared key variable
    skey1 = (unsigned char*)OPENSSL_malloc(skeylen1);

    if(result = EVP_PKEY_derive(dctx1, skey1, &skeylen1) <= 0) {
        std::cout << "Key: " << skey1 << std::endl;

        for(int i = 0; i < skeylen1; i++) {
            std::cout << std::hex << (unsigned int)skey1[i];
        }
    }

    ERR_print_errors_fp(stdout);

    std::cout << result << std::endl;
}
    if(1 != EVP_PKEY_assign(params, EVP_PKEY_DHX, DH_get_2048_256())) {
        std::cout << "error 4" << std::endl;
    }

上面是伊犁曲线Diffie和Hellman。OpenSSL 3的一个工作示例(无伊犁曲线)


你说你无法导出共享秘密。当你尝试时会发生什么?当你调用
ERR\u print\u errors\u fp
时,你会收到某种错误消息吗?如果是这样,那是什么?在你遇到麻烦之前,这个过程能走多远?嗨@MattCaswell,我更新了我的帖子来回答你的问题。谢谢!令人惊讶的是,这解决了我的问题,谢谢您的帮助!顺便问一下,您是如何发现的:“但是函数EVP_PKEY_set1_DH()希望提供的DH对象是PKCS#3密钥。”我是OpenSSL开发人员;-)
    if(1 != EVP_PKEY_assign(params, EVP_PKEY_DHX, DH_get_2048_256())) {
        std::cout << "error 4" << std::endl;
    }
--- derive.cpp  2019-12-09 11:11:15.493349734 +0000
+++ derive-new.cpp  2019-12-09 11:14:59.348715074 +0000
@@ -37,7 +37,7 @@
     }

     // Set Diffie Hellman paramerers
-    if(1 != EVP_PKEY_set1_DH(params, DH_get_2048_256())) {
+    if(1 != EVP_PKEY_assign(params, EVP_PKEY_DHX, DH_get_2048_256())) {
         std::cout << "error 4" << std::endl;
     }

@@ -96,9 +96,11 @@
         std::cout << "error 15" << std::endl;
     }

+#if 0
     if(1 != EVP_PKEY_check(dctx1)) {
         std::cout << "error 16" << std::endl;
     }
+#endif

     if(1 != EVP_PKEY_param_check(dctx1)) {
         std::cout << "error 17" << std::endl;
@@ -120,7 +122,7 @@
     // Assign memory for shared key variable
     skey1 = (unsigned char*)OPENSSL_malloc(skeylen1);

-    if(result = EVP_PKEY_derive(dctx1, skey1, &skeylen1) <= 0) {
+    if((result = EVP_PKEY_derive(dctx1, skey1, &skeylen1)) > 0) {
         std::cout << "Key: " << skey1 << std::endl;

         for(int i = 0; i < skeylen1; i++) {