openssl3.2 - 官方demo学习 - encode - rsa_encode.c

2024-03-11 06:44

本文主要是介绍openssl3.2 - 官方demo学习 - encode - rsa_encode.c,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

文章目录

    • openssl3.2 - 官方demo学习 - encode - rsa_encode.c
    • 概述
    • 笔记
    • END

openssl3.2 - 官方demo学习 - encode - rsa_encode.c

概述

上次学习官方demo - rsa_encode.c 时, 程序要在UI上输入东西, 不知道输入啥, 就先放着.
现在需要非对称加解密的例子, rsa_encode.c就是相关的demo, 必须搞懂啊.
现在回过头来再看, 挺简单的.
估计当时几百个demo摆在哪里, 太着急了. 内心必须平静才能将事情做好:P

功能 :
从RSA私钥数据中导出RSA公钥.
如果给出输出的口令, 可以导出公私钥对.
不过, 谁也不会直接导出私钥(知道可以从私钥数据中导出私钥, 有这么回事就行).

官方demo设计是在linux下用的, 用管道来输入要操作的私钥数据.
在windows下运行, 还是用文件方便一些. 改了一下, 用命令行来输入私钥数据文件名.

试了一下, 好使, 可以从私钥数据中导出公钥数据.

笔记

/*!
\file rsa_encode.c
\note openssl3.2 - 官方demo学习 - encode - rsa_encode.c命令行参数 - THE_EXE priv_key.pem pwd_for_the_pem
功能 - 导出公钥并打印到UI(stdout)
备注 - 官方程序原来是在linux下用管道输入的私钥数据, 现在改为从文件输入.
*//*-* Copyright 2022-2023 The OpenSSL Project Authors. All Rights Reserved.** Licensed under the Apache License 2.0 (the "License").  You may not use* this file except in compliance with the License.  You can obtain a copy* in the file LICENSE in the source distribution or at* https://www.openssl.org/source/license.html*/#include <string.h>
#include <openssl/decoder.h>
#include <openssl/encoder.h>
#include <openssl/evp.h>#include "my_openSSL_lib.h"/** Example showing the encoding and decoding of RSA public and private keys. A* PEM-encoded RSA key is read in from stdin, decoded, and then re-encoded and* output for demonstration purposes. Both public and private keys are accepted.** This can be used to load RSA keys from a file or save RSA keys to a file.*//* A property query used for selecting algorithm implementations. */
static const char* propq = NULL;/** Load a PEM-encoded RSA key from a file, optionally decrypting it with a* supplied passphrase.*/
static EVP_PKEY* load_key(OSSL_LIB_CTX* libctx, FILE* f, const char* passphrase)
{int ret = 0;EVP_PKEY* pkey = NULL;OSSL_DECODER_CTX* dctx = NULL;int selection = 0;/** 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.*/dctx = OSSL_DECODER_CTX_new_for_pkey(&pkey, "PEM", NULL, "RSA",selection,libctx, propq);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_fp(dctx, f) == 0) { // 如果f是stdin, 就需要自己输入私钥内容, 所以函数入参的f必须是一个实际文件的FILE*fprintf(stderr, "OSSL_DECODER_from_fp() failed\n");goto cleanup;}ret = 1;
cleanup:OSSL_DECODER_CTX_free(dctx);/** 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;}return pkey;
}/** Store an RSA public or private key to a file using PEM encoding.** If a passphrase is supplied, the file is encrypted, otherwise* it is unencrypted.*/
static int store_key(EVP_PKEY* pkey, FILE* f, const char* passphrase)
{int ret = 0;int selection;OSSL_ENCODER_CTX* ectx = NULL;/** Create a PEM encoder context.** For raw (non-PEM-encoded) output, change "PEM" to "DER".** The selection argument controls whether the private key is exported* (EVP_PKEY_KEYPAIR), or only the public key (EVP_PKEY_PUBLIC_KEY). The* former will fail if we only have a public key.** Note that unlike the decode API, you cannot specify zero here.** Purely for the sake of demonstration, here we choose to export the whole* key if a passphrase is provided and the public key otherwise.*/// 如果给出口令, 就导出公私钥对;// 如果不给口令, 就只导出公钥// 实际应用中, 我们就只有导出公钥的需求selection = (passphrase != NULL)? EVP_PKEY_KEYPAIR: EVP_PKEY_PUBLIC_KEY;ectx = OSSL_ENCODER_CTX_new_for_pkey(pkey, selection, "PEM", NULL, propq);if (ectx == NULL) {fprintf(stderr, "OSSL_ENCODER_CTX_new_for_pkey() failed\n");goto cleanup;}/** Set passphrase if provided; the encoded output will then be encrypted* using the passphrase.** Alternative methods for specifying passphrases exist, such as a callback* (see OSSL_ENCODER_CTX_set_passphrase_cb(3), just as for OSSL_DECODER_CTX;* however you are less likely to need them as you presumably know whether* encryption is desired in advance.** Note that specifying a passphrase alone is not enough to cause the* key to be encrypted. You must set both a cipher and a passphrase.*/if (passphrase != NULL) {/* Set cipher. AES-128-CBC is a reasonable default. */if (OSSL_ENCODER_CTX_set_cipher(ectx, "AES-128-CBC", propq) == 0) {fprintf(stderr, "OSSL_ENCODER_CTX_set_cipher() failed\n");goto cleanup;}/* Set passphrase. */if (OSSL_ENCODER_CTX_set_passphrase(ectx,(const unsigned char*)passphrase,strlen(passphrase)) == 0) {fprintf(stderr, "OSSL_ENCODER_CTX_set_passphrase() failed\n");goto cleanup;}}/* Do the encode, writing to the given file. */if (OSSL_ENCODER_to_fp(ectx, f) == 0) {fprintf(stderr, "OSSL_ENCODER_to_fp() failed\n");goto cleanup;}ret = 1;
cleanup:OSSL_ENCODER_CTX_free(ectx);return ret;
}int main(int argc, char** argv)
{int ret = EXIT_FAILURE;OSSL_LIB_CTX* _ossl_lib_ctx = NULL;EVP_PKEY* _evp_pkey = NULL;const char* passphrase_in = NULL, * passphrase_out = NULL;const char* pszFilePathName = NULL;FILE* fp = NULL;/* usage: rsa_encode rsa_priv_key.PEM <passphrase-in> <passphrase-out> */if (argc > 1){pszFilePathName = argv[1];fp = fopen(pszFilePathName, "rb");if (NULL == fp){goto cleanup;}}if (argc > 2 && argv[2][0])passphrase_in = argv[2];if (argc > 3 && argv[3][0])passphrase_out = argv[3];/* Decode PEM key from stdin and then PEM encode it to stdout. */_evp_pkey = load_key(_ossl_lib_ctx, fp, passphrase_in);if (_evp_pkey == NULL) {fprintf(stderr, "Failed to decode key\n");goto cleanup;}if (store_key(_evp_pkey, stdout, passphrase_out) == 0) {fprintf(stderr, "Failed to encode key\n");goto cleanup;}ret = EXIT_SUCCESS;
cleanup:if (NULL != fp){fclose(fp);fp = NULL;}EVP_PKEY_free(_evp_pkey);OSSL_LIB_CTX_free(_ossl_lib_ctx);return ret;
}

END

这篇关于openssl3.2 - 官方demo学习 - encode - rsa_encode.c的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!


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

相关文章

Go学习记录之runtime包深入解析

《Go学习记录之runtime包深入解析》Go语言runtime包管理运行时环境,涵盖goroutine调度、内存分配、垃圾回收、类型信息等核心功能,:本文主要介绍Go学习记录之runtime包的... 目录前言:一、runtime包内容学习1、作用:① Goroutine和并发控制:② 垃圾回收:③ 栈和

Android学习总结之Java和kotlin区别超详细分析

《Android学习总结之Java和kotlin区别超详细分析》Java和Kotlin都是用于Android开发的编程语言,它们各自具有独特的特点和优势,:本文主要介绍Android学习总结之Ja... 目录一、空安全机制真题 1:Kotlin 如何解决 Java 的 NullPointerExceptio

重新对Java的类加载器的学习方式

《重新对Java的类加载器的学习方式》:本文主要介绍重新对Java的类加载器的学习方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录1、介绍1.1、简介1.2、符号引用和直接引用1、符号引用2、直接引用3、符号转直接的过程2、加载流程3、类加载的分类3.1、显示

ubuntu系统使用官方操作命令升级Dify指南

《ubuntu系统使用官方操作命令升级Dify指南》Dify支持自动化执行、日志记录和结果管理,适用于数据处理、模型训练和部署等场景,今天我们就来看看ubuntu系统中使用官方操作命令升级Dify的方... Dify 是一个基于 docker 的工作流管理工具,旨在简化机器学习和数据科学领域的多步骤工作流。

Java学习手册之Filter和Listener使用方法

《Java学习手册之Filter和Listener使用方法》:本文主要介绍Java学习手册之Filter和Listener使用方法的相关资料,Filter是一种拦截器,可以在请求到达Servl... 目录一、Filter(过滤器)1. Filter 的工作原理2. Filter 的配置与使用二、Listen

Springboot处理跨域的实现方式(附Demo)

《Springboot处理跨域的实现方式(附Demo)》:本文主要介绍Springboot处理跨域的实现方式(附Demo),具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不... 目录Springboot处理跨域的方式1. 基本知识2. @CrossOrigin3. 全局跨域设置4.

Java进阶学习之如何开启远程调式

《Java进阶学习之如何开启远程调式》Java开发中的远程调试是一项至关重要的技能,特别是在处理生产环境的问题或者协作开发时,:本文主要介绍Java进阶学习之如何开启远程调式的相关资料,需要的朋友... 目录概述Java远程调试的开启与底层原理开启Java远程调试底层原理JVM参数总结&nbsMbKKXJx

Java深度学习库DJL实现Python的NumPy方式

《Java深度学习库DJL实现Python的NumPy方式》本文介绍了DJL库的背景和基本功能,包括NDArray的创建、数学运算、数据获取和设置等,同时,还展示了如何使用NDArray进行数据预处理... 目录1 NDArray 的背景介绍1.1 架构2 JavaDJL使用2.1 安装DJL2.2 基本操

Mybatis官方生成器的使用方式

《Mybatis官方生成器的使用方式》本文详细介绍了MyBatisGenerator(MBG)的使用方法,通过实际代码示例展示了如何配置Maven插件来自动化生成MyBatis项目所需的实体类、Map... 目录1. MyBATis Generator 简介2. MyBatis Generator 的功能3

HarmonyOS学习(七)——UI(五)常用布局总结

自适应布局 1.1、线性布局(LinearLayout) 通过线性容器Row和Column实现线性布局。Column容器内的子组件按照垂直方向排列,Row组件中的子组件按照水平方向排列。 属性说明space通过space参数设置主轴上子组件的间距,达到各子组件在排列上的等间距效果alignItems设置子组件在交叉轴上的对齐方式,且在各类尺寸屏幕上表现一致,其中交叉轴为垂直时,取值为Vert