日本a√视频在线,久久青青亚洲国产,亚洲一区欧美二区,免费g片在线观看网站

        <style id="k3y6c"><u id="k3y6c"></u></style>
        <s id="k3y6c"></s>
        <mark id="k3y6c"></mark>
          
          

          <mark id="k3y6c"></mark>

          "); //-->

          博客專欄

          EEPW首頁 > 博客 > 基于openssl3.0,已知ECC算法x,y如何構(gòu)建公鑰的EVP_PKEY結(jié)構(gòu)

          基于openssl3.0,已知ECC算法x,y如何構(gòu)建公鑰的EVP_PKEY結(jié)構(gòu)

          發(fā)布人:電子禪石 時間:2025-02-25 來源:工程師 發(fā)布文章

          前言

          在將項目從 OpenSSL 1.1 升級到 OpenSSL 3.0 的過程中,

          開發(fā)者可能會遇到許多 API 的變化和棄用,尤其是在處理橢圓曲線(ECC)相關(guān)的函數(shù)時。

          OpenSSL 3.0 引入了一些新的 API,并對原有的 EC 相關(guān)函數(shù)進行了替換或棄用。

          盡管如此,我們?nèi)匀豢梢允褂眠@些新 API 來創(chuàng)建和處理 EVP_PKEY 結(jié)構(gòu),以滿足現(xiàn)代加密需求。在已知ECC算法公鑰下x,y以及算法NID的前提下,如何使用openssl-3.0中的接口構(gòu)建EVP_PKEY結(jié)構(gòu)呢?


          一、問題分析

          在openssl-1.1中,我們可以很輕松創(chuàng)建ECC公鑰,但在openssl-3.0中很多相關(guān)的API已經(jīng)被

          替換或棄用,導(dǎo)致代碼無法使用。


          二、在openssl-1.1中的解決方案

          注:

          1.代碼實現(xiàn)中的返回值定義,日志輸出函數(shù),內(nèi)存釋放函數(shù)需自行實現(xiàn)。


          2.1使用ECC算法的NID構(gòu)建EC_KEY結(jié)構(gòu)

          1

          EC_KEY  ecPublicKey  = NULL;

          ecPublicKey = EC_KEY_new_by_curve_name(nid);

          if (NULL == (*ecPublicKey)) {

                  LOG_E("EC_KEY_new_by_curve_name error : %ld, %s", ERR_get_error(), ERR_reason_error_string(ERR_get_error()));

                  return -1;

          }

          2.2將公鑰的x,y轉(zhuǎn)換成大數(shù)BIGNUM


          BIGNUM* bnX = NULL;

              BIGNUM* bnY = NULL;

              bnX = BN_bin2bn(x, 32, NULL);

              if (NULL == bnX) {

                  LOG_E("BN_bin2bn error : %ld, %s", ERR_get_error(), ERR_reason_error_string(ERR_get_error()));

                  EC_KEY_free(*ecPublicKey);

                  *ecPublicKey = NULL;

                  return -1;

              }


              bnY = BN_bin2bn(y, 32, NULL);

              if (NULL == bnY) {

                  LOG_E("BN_bin2bn error : %ld, %s", ERR_get_error(), ERR_reason_error_string(ERR_get_error()));

                  EC_KEY_free(*ecPublicKey);

                  *ecPublicKey = NULL;

                  WY_OPENSSL_FREE(BIGNUM, bnX);

                  return -1;

              }

          2.3將公鑰信息x,y大數(shù)存放在EC_KEY結(jié)構(gòu)中

          1

          if (1 != EC_KEY_set_public_key_affine_coordinates(*ecPublicKey, bnX, bnY)) {

                  LOG_E("BN_bin2bn : %ld, %s", ERR_get_error(), ERR_reason_error_string(ERR_get_error()));

                  EC_KEY_free(*ecPublicKey);

                  *ecPublicKey = NULL;

                  WY_OPENSSL_FREE(BIGNUM, bnX);

                  WY_OPENSSL_FREE(BIGNUM, bnY);

                  return -1;

              }

          2.4完整代碼

          1

          int get_ec_public_key_from_x_y(const unsigned char *x, const unsigned char *y, int nid, EC_KEY **ecPublicKey)

          {

              if ((NULL == x) || (NULL == y)) {

                  LOG_E("param error");

                  return ERROR_PARAM;

              }


              if (NULL != (*ecPublicKey)) {

                  WY_OPENSSL_FREE(EC_KEY, *ecPublicKey);

                  *ecPublicKey = NULL;

              }

              

              *ecPublicKey = EC_KEY_new_by_curve_name(nid);

              if (NULL == (*ecPublicKey)) {

                  LOG_E("EC_KEY_new_by_curve_name error : %ld, %s", ERR_get_error(), ERR_reason_error_string(ERR_get_error()));

                  return -1;

              }


              BIGNUM* bnX = NULL;

              BIGNUM* bnY = NULL;

              bnX = BN_bin2bn(x, 32, NULL);

              if (NULL == bnX) {

                  LOG_E("BN_bin2bn error : %ld, %s", ERR_get_error(), ERR_reason_error_string(ERR_get_error()));

                  EC_KEY_free(*ecPublicKey);

                  *ecPublicKey = NULL;

                  return -1;

              }


              bnY = BN_bin2bn(y, 32, NULL);

              if (NULL == bnY) {

                  LOG_E("BN_bin2bn error : %ld, %s", ERR_get_error(), ERR_reason_error_string(ERR_get_error()));

                  EC_KEY_free(*ecPublicKey);

                  *ecPublicKey = NULL;

                  WY_OPENSSL_FREE(BIGNUM, bnX);

                  return -1;

              }


              if (1 != EC_KEY_set_public_key_affine_coordinates(*ecPublicKey, bnX, bnY)) {

                  LOG_E("BN_bin2bn : %ld, %s", ERR_get_error(), ERR_reason_error_string(ERR_get_error()));

                  EC_KEY_free(*ecPublicKey);

                  *ecPublicKey = NULL;

                  WY_OPENSSL_FREE(BIGNUM, bnX);

                  WY_OPENSSL_FREE(BIGNUM, bnY);

                  return -1;

              }


              WY_OPENSSL_FREE(BIGNUM, bnX);

              WY_OPENSSL_FREE(BIGNUM, bnY);

              return 0;

          }


          int EC_KEY_to_EVP_PKEY(const EC_KEY *ecKey, EVP_PKEY **evpKey)

          {

              if (NULL == ecKey) {

                  LOG_E("param error");

                  return ERROR_PARAM;

              }


              if (NULL != (*evpKey)) {

                  EVP_PKEY_free(*evpKey);

                  *evpKey = NULL;

              }


              *evpKey = EVP_PKEY_new();

              if (NULL == (*evpKey)) {

                  LOG_E("EVP_PKEY_new : %ld, %s", ERR_get_error(), ERR_reason_error_string(ERR_get_error()));

                  return ERROR_EVP_PKEY_NEW;

              }


              if (1 != EVP_PKEY_set1_EC_KEY(*evpKey, (EC_KEY*)ecKey)) {

                  LOG_E("EVP_PKEY_set1_EC_KEY : %ld, %s", ERR_get_error(), ERR_reason_error_string(ERR_get_error()));

                  EVP_PKEY_free(*evpKey);

                  *evpKey = NULL;

                  return -1;

              }

              LOG_D("ec key to evp key success");

              return 0;

          }


          int get_evp_public_key_ecc(const unsigned char *, size_t keyLen, int nid, EVP_PKEY **evpKey)

          {

              if ((NULL == key) || (keyLen <= 0)) {

                  LOG_E("param error");

                  return ERROR_PARAM;

              }


              int ret = 0;

              unsigned char tmpPublicKey[1024] = {0};


              if (keyLen == 65) {

                  memcpy(tmpPublicKey, key + 1, keyLen -1);

              } else if (keyLen == 64) {

                  memcpy(tmpPublicKey, key, keyLen);

              } else {

                  return ERROR_NOT_SUPPORT;

              }

              unsigned char tmpX[64] = {0};

              unsigned char tmpY[64] = {0};

              memcpy(tmpX, tmpPublicKey, 32);

              memcpy(tmpY, tmpPublicKey + 32, 32);

              LOG_H((const unsigned char*)tmpX, 32);

              LOG_H((const unsigned char*)tmpY, 32);

              EC_KEY *ecPublicKey = NULL;

              ret = get_ec_public_key_from_x_y(tmpX, tmpY, nid, &ecPublicKey);

              if (0 != ret) {

                  LOG_E("get ec public key error");

                  return ret;

              }


              ret = EC_KEY_to_EVP_PKEY(ecPublicKey, evpKey);

              if (0 != ret) {

                  LOG_E("ec key to evp key error");

                  EC_KEY_free(ecPublicKey);

                  ecPublicKey = NULL;

                  return ret;

              }

              EC_KEY_free(ecPublicKey);

              ecPublicKey = NULL;

              return ret;

          }

          三、在openssl-3.0中的解決方案

          注:

          1.代碼實現(xiàn)中的返回值定義,日志輸出函數(shù),內(nèi)存釋放函數(shù)需自行實現(xiàn)。

          2.如果x,y的二進制數(shù)據(jù)中包含0x00構(gòu)建EVP_PKEY結(jié)構(gòu)將失敗。


          /**

           * @brief                               通過x,y,以及算法的nid構(gòu)建公鑰的EVP_PKEY結(jié)構(gòu)

           *

           * @param x[in]                    ECC算法公鑰中,x的數(shù)據(jù)

           * @param y[in]                ECC算法公鑰中,y的數(shù)據(jù)

           * @param nid[in]                當(dāng)前ECC算法的NID

           * @param evpPublicKey[out]                     公鑰的ECVP_PKEY結(jié)構(gòu)

           *

           * @return                              0 - success, !0 - error

           */

          int get_evp_pkey_from_ecc_xy(const unsigned char *x, const unsigned char *y, int nid, 

          EVP_PKEY **evpPublicKey)

          {

          // 判斷參數(shù)是否為空

             if ((NULL == x) || (NULL == y) || (NULL == evpPublicKey)) {

                 LOG_E("param error");

                 return ERROR_PARAM;

             }


             if (NULL != (*evpPublicKey)) {

                 WY_OPENSSL_FREE(EVP_PKEY, *evpPublicKey);

                 *evpPublicKey = NULL;

             }


             unsigned char publicKey[512] = {0};

             int tmpPublicKeyLen = 0;

             char* algStr = NULL;

             switch (nid)

             {

             case NID_X9_62_prime256v1:

                 algStr = "prime256v1";

                 break;

             default:

                 return ERROR_NOT_SUPPORT; 

                 break;

             }


             size_t xLen = strlen((const char*)x);

             size_t yLen = strlen((const char*)y);

             // 用于表是數(shù)據(jù)的格式,通常使用0x04表示,構(gòu)建公鑰數(shù)據(jù): 格式: 0x04 + x + y

             int hea = POINT_CONVERSION_UNCOMPRESSED;

             memcpy(publicKey + tmpPublicKeyLen, (unsigned char*)&hea, 1);

             tmpPublicKeyLen += 1;

             memcpy(publicKey + tmpPublicKeyLen, x, xLen);

             tmpPublicKeyLen += xLen;

             memcpy(publicKey + tmpPublicKeyLen, y, yLen);

             size_t publicKeyLen = tmpPublicKeyLen + yLen;


          // 

             OSSL_PARAM_BLD *paramsBuild = OSSL_PARAM_BLD_new();

             if (NULL == paramsBuild) {

                 LOG_E("OSSL_PARAM_BLD_new error : %ld, %s", ERR_get_error(), ERR_reason_error_string(ERR_get_error()));

                 return 1;

             }

          // 將ECC算法名稱構(gòu)建到結(jié)構(gòu)體中

             OSSL_PARAM_BLD_push_utf8_string(paramsBuild, OSSL_PKEY_PARAM_GROUP_NAME, algStr, 0);

             // 將公鑰數(shù)據(jù)構(gòu)建到結(jié)構(gòu)體中

             OSSL_PARAM_BLD_push_octet_string(paramsBuild, OSSL_PKEY_PARAM_PUB_KEY, publicKey, publicKeyLen);

             // 將構(gòu)建器中已經(jīng)定義的參數(shù)轉(zhuǎn)換成可以被 OpenSSL 的其他部分使用的 OSSL_PARAM 數(shù)組

             OSSL_PARAM *params = OSSL_PARAM_BLD_to_param(paramsBuild);

             if (NULL == params) {

                 LOG_E("OSSL_PARAM_BLD_to_param error : %ld, %s", ERR_get_error(), ERR_reason_error_string(ERR_get_error()));

                 WY_OPENSSL_FREE(OSSL_PARAM_BLD, paramsBuild);

                 return 1;

             }


          // 根據(jù)給定的算法名稱創(chuàng)建一個 EVP_PKEY_CTX 上下文

             EVP_PKEY_CTX* ctx = EVP_PKEY_CTX_new_from_name(NULL, "EC", NULL);

             if (NULL == ctx) {

                 LOG_E("EVP_PKEY_CTX_new_from_name error : %ld, %s", ERR_get_error(), ERR_reason_error_string(ERR_get_error()));

                 WY_OPENSSL_FREE(OSSL_PARAM_BLD, paramsBuild);

                 return 1;

             }


             EVP_PKEY *tmpEvpPublicKey = NULL;

             EVP_PKEY_fromdata_init(ctx);

             int status = EVP_PKEY_fromdata(ctx, &tmpEvpPublicKey, EVP_PKEY_PUBLIC_KEY, params);

             if (status <= 0 || tmpEvpPublicKey == NULL) {

                 LOG_E("status : %d", status);

                 LOG_E("EVP_PKEY_fromdata error : %ld, %s", ERR_get_error(), ERR_reason_error_string(ERR_get_error()));

                 WY_OPENSSL_FREE(OSSL_PARAM, params);

                 WY_OPENSSL_FREE(OSSL_PARAM_BLD, paramsBuild);

                 WY_OPENSSL_FREE(EVP_PKEY_CTX, ctx);

                 return 1;

             }


             *evpPublicKey = EVP_PKEY_dup(tmpEvpPublicKey);


             WY_OPENSSL_FREE(EVP_PKEY, tmpEvpPublicKey);

             WY_OPENSSL_FREE(OSSL_PARAM, params);

             WY_OPENSSL_FREE(OSSL_PARAM_BLD, paramsBuild);

             WY_OPENSSL_FREE(EVP_PKEY_CTX, ctx);


             return 0;

          }



          ————————————————


                                  

          原文鏈接:https://blog.csdn.net/dream_yaya/article/details/140553623


          *博客內(nèi)容為網(wǎng)友個人發(fā)布,僅代表博主個人觀點,如有侵權(quán)請聯(lián)系工作人員刪除。



          關(guān)鍵詞: openssl

          技術(shù)專區(qū)

          關(guān)閉