关于OpenSSL的介绍和安装在此不多赘述,可以在网上找到很多相关资料,各位感兴趣可以去了解下(自觉对OpenSSL开源库只是初级使用阶段,也就不在此“秀下限”了),直接进入主题,本篇源码基于OpenSSL中RSA实现,除此之外还可以基于EVP实现。

示例代码:【RSA-1024bit-PKCS1Padding|x509公钥加密|pkcs12私钥解密】

****************************************************************************************

"crtdef.h":

#ifndef __CRTDEF_H

#define __CRTDEF_H

/* x509公钥文件 */

#define PUBKEY  "/home/nemo/etc/rsa/public.cer"

/* pkcs12私钥文件及密码 */

#define PRIKEY  "/home/nemo/etc/rsa/private_111111.pfx"

#define PRIPWD  "111111"

/* 校验错误函数宏 */

#define CHECK( func ) {             \

if( EXIT_FAILURE == (func) ){   \

exit( EXIT_FAILURE );       \

}                               \

}

#endif

****************************************************************************************

"rsa.c":

/* 算法:RSA-1024bit-PKCS1Padding

* 公钥加密:x509结构(.cer)

* 私钥解密:pkcs12结构(.pfx)+密码 */

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include "crtdef.h"

/* 公钥证书加密

* RSA(1024位)/PKCS1Padding算法

* 明文最大长度:128-11=117字节

* 密文长度:128字节

* 返回:成功则返回密文长度,失败则返回"EXIT_FAILURE" */

static int encryptRsa( char *plainData, char *cipherData, int plainDataSize )

{

int nResult = 0;

EVP_PKEY *pkey = NULL;

X509 *cert = NULL;

BIO *bn = NULL;

RSA *pubkey = NULL;

/* 01:加载所有的运算法则 */

OpenSSL_add_all_algorithms();

/* 02:解析cer公钥证书 */

/* 2.1.打开证书文件 */

bn = BIO_new_file( PUBKEY, "r" );

if( NULL == bn ){

nResult = EXIT_FAILURE;

fprintf( stderr, "BIO_new_file() Failed!\n" );

goto _err;

}

/* 2.2.读取X509结构 */

cert = PEM_read_bio_X509( bn, NULL, NULL, NULL );

if( NULL == cert ){

nResult = EXIT_FAILURE;

fprintf( stderr, "PEM_read_bio_X509() Failed!\n" );

goto _err;

}

/* 2.3.分解X509结构得到EVP_PKEY */

#if 0

cert = d2i_X509_bio( bn, NULL );                    /* DER格式 */

#endif

cert = PEM_read_bio_X509( bn, NULL, NULL, NULL );   /* PEM格式 */

if( NULL == pkey ){

nResult = EXIT_FAILURE;

fprintf( stderr, "X509_get_pubkey() Failed!\n" );

ERR_print_errors_fp( stderr );

goto _err;

}

/* 03:EVP_PKEY转换成RSA的KEY */

pubkey = EVP_PKEY_get1_RSA( pkey );

if( NULL == pubkey ){

nResult = EXIT_FAILURE;

fprintf( stderr, "EVP_PKEY_get1_RSA() Failed!\n" );

ERR_print_errors_fp( stderr );

goto _err;

}

/* 04:公钥加密:RSA_PKCS1_PADDING */

nResult = RSA_public_encrypt( plainDataSize, (unsigned char *)plainData,

(unsigned char *)cipherData, pubkey, RSA_PKCS1_PADDING );

if( nResult < 0 ){

nResult = EXIT_FAILURE;

fprintf( stderr, "RSA_public_encrypt() Failed!\n" );

ERR_print_errors_fp( stderr );

goto _err;

}

_err:

/* 释放BIO */

if( bn != NULL ){

BIO_free( bn );

bn = NULL;

}

/* 释放X509 */

if( cert != NULL ){

X509_free( cert );

cert = NULL;

}

/* 释放EVP_PKEY */

if( pkey != NULL ){

EVP_PKEY_free( pkey );

pkey = NULL;

}

/* 释放RSA */

if( pubkey != NULL ){

RSA_free( pubkey );

pubkey = NULL;

}

/* 清空加载的内容 */

EVP_cleanup();      /* for EVP */

return nResult;

}

/* 私钥证书解密

* RSA(1024位)/PKCS1Padding算法

* 明文最大长度:128-11=117字节

* 密文长度(固定):128字节

* 返回:成功则返回明文长度,失败则返回"EXIT_FAILURE" */

static int decryptRsa( char *cipherData, char *plainData, int cipherDataSize )

{

int nResult = 0;

EVP_PKEY *pkey = NULL;

X509 *cert = NULL;

PKCS12 *p12 = NULL;

RSA *prikey = NULL;

FILE *fp = NULL;

/* 01:加载所有的运算法则 */

OpenSSL_add_all_algorithms();

/* 02:解析pfx私钥证书 */

/* 2.1.打开pfx文件 */

if( NULL == ( fp = fopen( PRIKEY, "rb" ) ) ){

nResult = EXIT_FAILURE;

fprintf( stderr, "fopen() Failed!\n" );

goto _err;

}

/* 2.2.读取PKCS12结构 */

p12 = d2i_PKCS12_fp( fp, NULL );

if( NULL == p12 ){

nResult = EXIT_FAILURE;

fprintf( stderr, "d2i_PKCS12_fp() Failed!\n" );

goto _err;

}

/* 2.3.分解PKCS12结构得到EVP_PKEY */

if( !PKCS12_parse( p12, PRIPWD, &pkey, &cert, NULL ) ){

nResult = EXIT_FAILURE;

fprintf( stderr, "PKCS12_parse() Failed!\n" );

ERR_print_errors_fp( stderr );

goto _err;

}

/* 03:EVP_PKEY转换成RSA的KEY */

prikey = EVP_PKEY_get1_RSA( pkey );

if( NULL == prikey ){

nResult = EXIT_FAILURE;

fprintf( stderr, "EVP_PKEY_get1_RSA() Failed!\n" );

ERR_print_errors_fp( stderr );

goto _err;

}

/* 04:私钥解密:RSA_PKCS1_PADDING */

nResult = RSA_private_decrypt( cipherDataSize, (unsigned char *)cipherData,

(unsigned char *)plainData, prikey, RSA_PKCS1_PADDING );

if( nResult < 0 ){

nResult = EXIT_FAILURE;

fprintf( stderr, "RSA_private_decrypt() Failed!\n" );

ERR_print_errors_fp( stderr );

goto _err;

}

_err:

/* 关闭证书文件 */

if( fp != NULL ){

fclose( fp );

fp = NULL;

}

/* 释放PKCS12 */

if( p12 != NULL ){

PKCS12_free( p12 );

p12 = NULL;

}

/* 释放X509 */

if( cert != NULL ){

X509_free( cert );

cert = NULL;

}

/* 释放EVP_PKEY */

if( pkey != NULL ){

EVP_PKEY_free( pkey );

pkey = NULL;

}

/* 释放RSA */

if( prikey != NULL ){

RSA_free( prikey );

prikey = NULL;

}

/* 清空加载的内容 */

EVP_cleanup();      /* for EVP */

return nResult;

}

/* 测试程序

* 01:公钥加密

* 02:针对加密好的密文使用私钥解密

* 目标:解密出的明文和最初的明文一致证明功能实现

* 命令行参数:最初的明文 */

int main( int argc, char *argv[] )

{

int i = 0;

int plainDataSize = 0;

int cipherDataSize = 0;

char plainData[128 + 1] = {0};

char cipherData[128 + 1] = {0};

/* 依赖命令行参数输入 */

if( 1 == argc ){

fprintf( stderr, "Usage:[%s ]\n", argv[0] );

exit( EXIT_FAILURE );

}

printf( "【初始明文】[%s]\n", argv[1] );

/* 01:公钥加密 */

CHECK( cipherDataSize = encryptRsa( argv[1], cipherData, strlen( argv[1] ) ) );

/* LOOP:鉴于密文极有可能存在不可打印字符故而转十六进制输出 */

printf( "【加密密文】[" );

for( i = 0; i < cipherDataSize; i ++ )

{

printf( "%02X", cipherData[i] );

}

printf( "]\n" );

/* 02:私钥解密 */

CHECK( plainDataSize = decryptRsa( cipherData, plainData, cipherDataSize ) );

printf( "【解密明文】[%s]\n", plainData );

exit( EXIT_SUCCESS );

}

****************************************************************************************

"Makefile":

#执行文件

bin=irsa

#目标文件

objects=rsa.o

#连接规则

$(bin):$(objects)

gcc -o ~/bin/$(bin) $(objects) -lssl -lcrypto -ldl

#清理对象

.PHONY:clean

clean:

-rm ~/bin/$(bin) $(objects)

****************************************************************************************

验证效果:

【P.S.】说明:

鉴于RSA非对称加解密算法明文长度有限,故而通常应用场景:通过对称加密算法(例如DES)加密明文,而通过RSA加密对称加密算法密钥,两者组合即数字信封;(以上示例代码是存粹的RSA裸加密解密)

"Makefile"中"gcc"和"-rm"行首是'Tab'键入的水平制表符'\t',非此会导致"make"失败;(因为编辑器的缘故无法准确表示)

关于公钥,若无公钥文件而是公钥明文串,则可以直接从中截取出模数和指数构建RSA结构,示例代码如下:

****************************************************************************************

模数

跳过公钥明文开头的7字节(十六进制即14字节),截取256字节十六进制(以1024bit为例)

指数

公钥明文末尾3字节(十六进制即6字节)

****************************************************************************************

char *moduleHex = "xxxxxxxxx";  /* 模数16进制[256Bytes] */

char *expandHex = "xxxxxxxxx";  /* 指数16进制 */

BIGNUM *bnn = NULL; /* 模数-大数 */

BIGNUM *bne = NULL; /* 指数-大数 */

RSA *pubkey = NULL;

/* 生成大数 */

bnn = BN_new();

bne = BN_new();

BN_hex2bn( &bnn, moduleHex );

BN_hex2bn( &bne, expandHex );

if( NULL == bnn || NULL == bne ){

fprintf( stderr, "BN_new() Failed!" );

ERR_print_errors_fp( stderr );

exit( EXIT_FAILURE );

}

/* 生成公钥 */

pubkey = RSA_new();

if( NULL == pubkey ){

fprintf( stderr, "RSA_new() Failed!" );

ERR_print_errors_fp( stderr );

exit( EXIT_FAILURE );

}

pubkey->n = bnn;

pubkey->e = bne;

/* 释放大数 */

if( bnn != NULL ){

BN_free( bnn );

bnn = NULL;

}

if( bne != NULL ){

BN_free( bne );

bne = NULL;

}

/* 释放公钥 */

if( pubkey != NULL ){

RSA_free( pubkey );

pubkey = NULL;

}

****************************************************************************************

rsa大数加密c语言,C语言:基于OpenSSL-RSA实现RSA非对称加解密相关推荐

  1. MacOS下使用C语言基于openssl库进行RSA加密解密

    MacOS下使用C语言基于openssl库进行RSA加密解密 1 安装openssl并生成密钥 首先当然要安装openssl(这里记得看一下安装路径,应该是/usr/local/Cellar/open ...

  2. 基于CH375的嵌入式USB文件加解密系统的设计

    基于CH375的嵌入式USB文件加解密系统的设计 [日期:2008-7-21] 来源:电子技术应用  作者:华中科技大学 电子与信息工程系, 湖北 武汉 430074 [字体:大 中 小] <s ...

  3. 基于Java的SQL Server数据库加解密系统设计与实现

    目 录 摘 要 1 ABSTRACT 2 第1章 绪论 3 1.1 数据库加解密系统开发背景 3 1.2 国内外现状 3 1.3 本文的主要工作 4 1.4 论文的组织结构 4 第2章 数据库加密的基 ...

  4. 基于安卓系统的SM4-SM2/3加解密软件开发报告

    目 录 第一章需求分析 1.1软件功能需求 1.2平台需求 1.3人员分工 第二章概要设计 2.1 软件开发平台 2.2 软件基本流程 2.3 UML图 第三章 程序详细设计 3.1 程序接口设计 3 ...

  5. 【crypto】基于crypto.js的web前端加解密系统实现

    文章目录 一.概念介绍 1.1 crypto.js介绍 1.2 加密 / 哈希 / 编码 1.2.1 加密/解密 1.2.2 散列/哈希 1.2.3 BASE64编解码 二.加解密思想(以md5为例) ...

  6. python RSA非对称加解密模块[M2Crypto]

    python 实现rsa对称加解密目前有三个库:rsa.pycryptodome.M2Crypto 前两个库只能实现公钥加密私钥解密,M2Crypto可以实现公私钥互相加解密 M2Crypto的安装: ...

  7. TLS 改变密码标准协议(Change Cipher Spec Protocol) 就是加密传输中每隔一段时间必须改变其加解密参数的协议...

    SSL修改密文协议的设计目的是为了保障SSL传输过程的安全性,因为SSL协议要求客户端或服务器端每隔一段时间必须改变其加解密参数.当某一方要改变其加解密参数时,就发送一个简单的消息通知对方下一个要传送 ...

  8. 非对称加解密,私钥和公钥到底是谁来加密,谁来解密?

    第一种用法:公钥加密,私钥解密.-- 用于加解密 第二种用法:私钥签名,公钥验签.-- 用于签名 有点混乱,不要去硬记,总结一下: 你只要想: 既然是加密,那肯定是不希望别人知道我的消息,所以只有我才 ...

  9. 基于AES算法的英文文字加解密

    目录 一.理论基础 二.核心程序 三.仿真结论 一.理论基础 AES算法是一种对称加密算法,被广泛应用于数据加密和保护领域中.将介绍如何使用AES算法对英文文字进行加解密. 一.AES算法概述 AES ...

最新文章

  1. java.util.concurrent简介
  2. 空中楼阁成语故事,空中楼阁用来比喻什么?
  3. java中aop和aoc的区别_AOC与AOP的区别
  4. net.sf.json.JSONException: #39;object#39; is an array. Use JSONArray instead
  5. 机器学习笔记(二十二):逻辑回归中使用模型正则化
  6. 利用OneNET实现SIM868使用HTTP协议给服务器发送数据并显示
  7. java pdf 添加图片
  8. HearthBuddy卡组
  9. MyEclispe发布web项目-遁地龙卷风
  10. 银联在线支付对接流程以及签名算法
  11. Idea取消光标所在行颜色
  12. 浏览器缓存机制(强缓存和协商缓存)
  13. 「Python语法结构」数据类型与运算符示例(7)
  14. IDEA相关配置(特别完整)看完此篇就将所有的IDEA的相关配置都配置好了、设置鼠标滚轮修改字体大小、设置鼠标悬浮提示、设置主题、设置窗体及菜单的字体及字体大小、设置编辑区主题、通过插件更换主题
  15. HDU 3723 Delta Wave(卡特兰数+大数)
  16. 产品设计中的脉冲群(EFT)防护
  17. 学计算机 有什么好的二本大学排名,二本大学排名
  18. 崔庆才双十二要直播了!!!快来围观啊!!!
  19. latex梯度_一文学会基本的LaTeX公式输入
  20. jeesite 附件上传

热门文章

  1. android camera 降噪,照片噪点怎么去除?超详细!一步步教你进行相机降噪处理!...
  2. .NET Core微服务之路:文章系列和内容索引汇总 (v0.53)
  3. Android ---- Ijkplayer阅读native层源码之IjkMediaPlayer_prepareAsync(五)
  4. 个人号运营:我和微商学习,如何运营个人号?
  5. 服务器accept队列溢出及其解决
  6. 弘辽科技:不要小看微淘!微淘是商家专属的私域流量的大本营
  7. 个人网站备案起名_网站更换服务器空间后,需要重新备案吗?
  8. Go语言-Go interface 接口的最佳实践
  9. KANO模型分析法简介与应用
  10. 6.python解答蓝桥杯17年A组真题 迷宫