openssl3.2 - exp - export ecc pubkey from ecc priv key

文章目录

    • openssl3.2 - exp - export ecc pubkey from ecc priv key
    • 概述
    • 笔记
    • END

openssl3.2 - exp - export ecc pubkey from ecc priv key

概述

前面实验已经生成了ECC私钥, 现在做从ECC私钥(内容为公私钥对, 里面既有私钥信息, 也有公钥信息)导出ECC公钥.
实验对应的命令行为

openssl ec -in ecc_priv_key.pem -pubout -out ecc_pub_key_s.pem

单步调试, 发现命令行实现用的OSSL_STORE_open_ex(), 这个很难受, 没办法移植. 里面没有openssl API可用.
还好运气不错, 前面实验有从buffer load key的实现, 改了一下, 可以正常从buffer载入到私钥的EVP_PKEY*
然后就可以按照openssl命令行的实验进行移植了, 机智:P

如果没有前面做的那些实验, 直接从命令行实现迁移实现, 那就难了(关键调用. e.g. 官方从文件载入私钥(用的API内部完全看不出载入buffer时的openssl API调用), 我是从buffer载入私钥, 没有交集啊). 只能说运气还不错.

最后程序导出的公钥和命令行导出的公钥, 只有回车的区别, 用起来是一样的.
在这里插入图片描述

笔记

/*!
* \file exp021_export_pubkey_from_ecc_priv_key.cpp
* \note openssl3.2 - exp - export ecc pubkey from ecc priv key 
* 对应的命令 openssl ec -in ecc_priv_key.pem -pubout -out ecc_pub_key_s.pem
* 现在的实现和命令行实现并不一致, 无法从命令行实现中完全移植, 主要是从buffer中载入私钥这块
* 命令行实现是 OSSL_STORE_open_ex(), 里面没用可以参考的openssl API调用
* 换成了前面实验得到的load_priv_key(), 用OSSL_DECODER_from_bio()得到EVP_PKEY*, 后续就一致了
*/#include "my_openSSL_lib.h"
#include <openssl/crypto.h>
#include <openssl/bio.h>#include <stdlib.h>
#include <stdio.h>
#include <assert.h>#include "CMemHookRec.h"#include "ecc_priv_key_s.h"
#include <openssl/decoder.h>
#include <openssl/encoder.h>
#include <openssl/evp.h>
#include <openssl/core_names.h>void my_openssl_app();
bool export_ecc_pub_key_from_ecc_priv_key(const UCHAR* pBuf, int lenBuf, unsigned char*& pdata, size_t& pdata_len);
EVP_PKEY* load_priv_key(bool isPrivkeyBuffer, const char* key_type, OSSL_LIB_CTX* libctx, const char* pBufPrivKey, int lenPrivKey, const char* passphrase);int main(int argc, char** argv)
{setvbuf(stdout, NULL, _IONBF, 0); // 清掉stdout缓存, 防止调用printf时阻塞mem_hook();my_openssl_app();mem_unhook();return 0;
}void my_openssl_app()
{unsigned char* pdata = NULL;size_t pdata_len = 0;FILE* fp = NULL;size_t sz_wr = 0;do {if (!export_ecc_pub_key_from_ecc_priv_key((const UCHAR*)ucAry_ecc_priv_key_s, sizeof(ucAry_ecc_priv_key_s), pdata, pdata_len)){break;}// 实际应用中, 就可以那取到的公钥数据干活了(e.g. 转成公钥的EVP_PKEY*)// 现在将公钥数据保存成文件, 然后和用命令行从同一个私钥导出的公钥比对一下, 看看是否一样fp = fopen("ecc_pub_key_export_by_app.pem", "wb");if (NULL != fp){sz_wr = fwrite(pdata, sizeof(char), pdata_len, fp);assert(sz_wr == pdata_len);fclose(fp);fp = NULL;// fc /B ecc_pub_key_s.pem ecc_pub_key_export_by_app.pem// 除了回车, 内容一摸一样// openssl.exe 导出的公钥.pem 回车是\r\n// 用 openssl API导出的公钥.pem 回车是 \n}} while (false);if (NULL != pdata){OPENSSL_free(pdata);pdata = NULL;}
}bool export_ecc_pub_key_from_ecc_priv_key(const UCHAR* pBuf, int lenBuf, unsigned char*& pdata, size_t& pdata_len)
{bool b_rc = false;int i_rc = 0;EVP_PKEY* priv_key = NULL;int selection = 0;const char* output_structure = NULL;OSSL_ENCODER_CTX* _ossl_encoder_ctx = NULL;do {// 从buffer载入私钥用了 exp018_from_PrivKeyDat_export_PubKeyDat_ecc 的实现// openssl命令行实现是从文件中拿的, 还不是直接拿, 是用了OSSL_STORE_open_ex(), 实在没办法用, 里面都是内部函数// 看官方实现, 载入私钥和载入公钥是2个实现priv_key = load_priv_key(true, "EC", NULL, (const char*)pBuf, lenBuf, NULL);if (NULL == priv_key){break;}i_rc = EVP_PKEY_set_int_param(priv_key, OSSL_PKEY_PARAM_EC_INCLUDE_PUBLIC, 1);if (1 != i_rc){break;}selection = OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS | OSSL_KEYMGMT_SELECT_PUBLIC_KEY;output_structure = "SubjectPublicKeyInfo";_ossl_encoder_ctx = OSSL_ENCODER_CTX_new_for_pkey(priv_key, selection,"PEM", output_structure,NULL);if (NULL == _ossl_encoder_ctx){break;}// 从私钥载入公钥成功, _ossl_encoder_ctx中包含公钥if (1 != OSSL_ENCODER_to_data(_ossl_encoder_ctx, &pdata, &pdata_len)){break;}b_rc = true;} while (false);if (NULL != priv_key){EVP_PKEY_free(priv_key);priv_key = NULL;}if (NULL != _ossl_encoder_ctx){OSSL_ENCODER_CTX_free(_ossl_encoder_ctx);_ossl_encoder_ctx = NULL;}return b_rc;
}EVP_PKEY* load_priv_key(bool isPrivkeyBuffer, const char* key_type, OSSL_LIB_CTX* libctx, const char* pBufPrivKey, int lenPrivKey, const char* passphrase)
{int ret = 0;EVP_PKEY* pkey = NULL;OSSL_DECODER_CTX* dctx = NULL;int selection = 0;int i_tmp = 0;BIO* bio_privKey = NULL;if (NULL == key_type){goto cleanup;}bio_privKey = BIO_new(BIO_s_mem());if (NULL == bio_privKey){goto cleanup;}i_tmp = BIO_write(bio_privKey, pBufPrivKey, lenPrivKey);if (i_tmp != lenPrivKey){goto cleanup;}/** Create PEM decoder context expecting an RSA key.** For raw (non-PEM-encoded) keys, change "PEM" to "DER".** The selection argument here specifies whether we are willing to accept a* public key, private key, or either. If it is set to zero, either will be* accepted. If set to EVP_PKEY_KEYPAIR, a private key will be required, and* if set to EVP_PKEY_PUBLIC_KEY, a public key will be required.*/// 在执行 OSSL_DECODER_CTX_new_for_pkey() 之前, 要选择啥要定好, 否则后面从pkey中取不到东西(公私钥对)// selection = (isPrivkeyBuffer ? EVP_PKEY_KEYPAIR : EVP_PKEY_PUBLIC_KEY);// EVP_PKEY_KEY_PARAMETERS// selection = EVP_PKEY_PUBLIC_KEY; // 如果载入的是纯公钥数据, 好使// selection = EVP_PKEY_PRIVATE_KEY; // 如果载入的是openssl.exe生成的私钥, 去私钥不好使, OSSL_DECODER_from_bio()就失败selection = EVP_PKEY_KEYPAIR; //如果载入私钥, 就是一个公私钥对dctx = OSSL_DECODER_CTX_new_for_pkey(&pkey, "PEM", NULL, key_type,selection,libctx, NULL);if (dctx == NULL) {// fprintf(stderr, "OSSL_DECODER_CTX_new_for_pkey() failed\n");goto cleanup;}/** Set passphrase if provided; needed to decrypt encrypted PEM files.* If the input is not encrypted, any passphrase provided is ignored.** Alternative methods for specifying passphrases exist, such as a callback* (see OSSL_DECODER_CTX_set_passphrase_cb(3)), which may be more useful for* interactive applications which do not know if a passphrase should be* prompted for in advance, or for GUI applications.*/if (passphrase != NULL) {if (OSSL_DECODER_CTX_set_passphrase(dctx,(const unsigned char*)passphrase,strlen(passphrase)) == 0) {// fprintf(stderr, "OSSL_DECODER_CTX_set_passphrase() failed\n");goto cleanup;}}/* Do the decode, reading from file. */if (OSSL_DECODER_from_bio(dctx, bio_privKey) == 0) { // 如果f是stdin, 就需要自己输入私钥内容, 所以函数入参的f必须是一个实际文件的FILE*// fprintf(stderr, "OSSL_DECODER_from_fp() failed\n");goto cleanup;}ret = 1;
cleanup:if (NULL != dctx){OSSL_DECODER_CTX_free(dctx);dctx = NULL;}/** pkey is created by OSSL_DECODER_CTX_new_for_pkey, but we* might fail subsequently, so ensure it's properly freed* in this case.*/if (ret == 0) {EVP_PKEY_free(pkey);pkey = NULL;}if (NULL != bio_privKey){BIO_free(bio_privKey);bio_privKey = NULL;}return pkey;
}

END

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/537151.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

<支持向量机算法(SVM:Support Vector Machine)>——《机器学习算法初识》

目录 一、⽀持向量机(SVM)算法 1 SVM算法导⼊ 2 SVM算法定义 2.1 定义 2.2 超平⾯最⼤间隔介绍 2.3 硬间隔和软间隔 2.3.1 硬间隔分类 2.3.2 软间隔分类 3 ⼩结 二、 SVM算法api初步使⽤ 三、 SVM算法原理 1 定义输⼊数据 2 线性可分⽀持向量机 3 SVM的计算过程与算…

爬虫与DataFrame对象小小结合

import pandas as pd import requests from lxml import etree #数据请求 url"https://www.maigoo.com/brand/list_1715.html" headers{User-Agent:} #数据响应 resrequests.get(url,headersheaders) tree etree.HTML(res.text) #数据解析 titletree.xpath(.//div[c…

【Vue】Request模块 - axios 封装Vuex的持久化存储

&#x1f4dd;个人主页&#xff1a;五敷有你 &#x1f525;系列专栏&#xff1a;Vue ⛺️稳中求进&#xff0c;晒太阳 Request模块 - axios 封装 使用axios来请求后端接口&#xff0c;一般会对axios进行一些配置&#xff08;比如配置基础地址&#xff0c;请求响应拦截器…

六 超级数据查看器 讲解稿 详情1 概述

六 超级数据查看器 讲解稿 详情1 概述 点此此处 以新界面 打开B站 当前视频教程 APP下载地址 百度 下载地址 ​ 讲解稿全文&#xff1a; 大家好&#xff0c;今天我们讲解一下超级数据查看器详情界面。由于内容较多&#xff0c;讲解要分为7集&#xff0c;这是第一集 首…

Pulsar消息路由深入剖析

一、概述 大数据背景下&#xff0c;分区应该是所有组件必备的基本条件&#xff0c;否则面对海量数据时无论是计算还是存储都容易遇到瓶颈。跟其他消息系统一样&#xff0c;Pulsar通过Topic将消息数据进行业务层面划分管理&#xff0c;同时也支持Topic分区&#xff0c;通过将多…

何为一致性哈希?一致性哈希和哈希有什么区别?一文深入理解一致性哈希

目录 一、前言二、哈希2.1、哈希碰撞2.2、针对哈希碰撞的两种方案2.3、为什么用哈希2.4、普通哈希的缺点 三、一致性哈希3.1、实现方式 - 哈希环3.2、场景复现3.3、优化版本的哈希环 四、总结 一、前言 在学到分布式负载均衡时&#xff0c;负载均衡的方式有很多种&#xff0c;…

*地宫取宝c++

题目 输入样例1&#xff1a; 2 2 2 1 2 2 1输出样例1&#xff1a; 2输入样例2&#xff1a; 2 3 2 1 2 3 2 1 5输出样例2&#xff1a; 14 思路 题目说从入口开始&#xff0c;只能向右或向下行走到达右下角&#xff0c;类似“摘花生”这道题的模型。题目又说只有当格子里的宝…

数据结构知识点总结00-知识点目录

专栏主页&#xff1a; 数据结构算法程序设计基础C语言知识点总结https://blog.csdn.net/seeker1994/category_12585732.html C语言知识点总结00-C语言知识点目录 最优算法100例00-最优算法100例目录 ...... 数据结构知识点目录 要求&#xff1a; &#xff08;1&#xff…

Devin,第一位AI软件工程师

每周跟踪AI热点新闻动向和震撼发展 想要探索生成式人工智能的前沿进展吗&#xff1f;订阅我们的简报&#xff0c;深入解析最新的技术突破、实际应用案例和未来的趋势。与全球数同行一同&#xff0c;从行业内部的深度分析和实用指南中受益。不要错过这个机会&#xff0c;成为AI领…

微信小程序上传图片到服务端,springboot项目。避免踩坑保姆教程

多方查找终于搞懂了如何去上传文件到本地服务器 前端代码 <view class"operation_row common_mb0"><view class"upload_btn" bindtap"clickUpload"><image src"../../common/images/icon/icon02.png"></image&g…

跨境电商怎么使用动态住宅代理IP?

在数字化时代&#xff0c;隐私保护和信息安全成为全球网民的共同关切。特别是对于海外用户&#xff0c;由于地理位置和网络监管政策的不同&#xff0c;访问全球信息资源变得更加复杂。使用动态住宅IP搭建代理&#xff0c;作为解决这一问题的有效手段&#xff0c;动态IP代理通过…

qiankun:vite/webpack项目配置

相关博文&#xff1a; https://juejin.cn/post/7216536069285429285?searchId202403091501088BACFF113F980BA3B5F3 https://www.bilibili.com/video/BV12T411q7dq/?spm_id_from333.337.search-card.all.click qiankun结构&#xff1a; 主应用base&#xff1a;vue3historyv…