C/C++使用openssl进行摘要和加密解密(md5, sha256, des, rsa)
2017-12-01 17:39
861 查看
penssl里面有很多用于摘要哈希、加密解密的算法,方便集成于工程项目,被广泛应用于网络报文中的安全传输和认证。下面以md5,sha256,des,rsa几个典型的api简单使用作为例子。
算法介绍
md5:https://en.wikipedia.org/wiki/MD5
sha256:https://en.wikipedia.org/wiki/SHA-2
des: https://en.wikipedia.org/wiki/Data_Encryption_Standard
rsa: https://en.wikipedia.org/wiki/RSA_(cryptosystem)
工程配置
以windows下为例
编译openssl库,得到头文件include和链接库lib和dll
配置包含头文件目录和库目录
工程中设置链接指定的lib:fenbieshlibssl.lib,libcrypto.lib
将对应的dll拷贝到exe执行目录:libcrypto-1_1.dll, libssl-1_1.dll
linux下同理
代码
#include <iostream>
#include <cassert>
#include <string>
#include <vector>
#include "openssl/md5.h"
#include "openssl/sha.h"
#include "openssl/des.h"
#include "openssl/
f8ed
rsa.h"
#include "openssl/pem.h"
=== 原始明文 ===
this is an example
=== md5哈希 ===
摘要字符: 乵驥!範
摘要串: 9202816dabaaf34bb106a10421b9a0d0
=== sha256哈希 ===
摘要字符: 訪X5衽鄁媫j/醢?17?P?4膡zD
摘要串: d44c035835f1c5e0668b7d186a2ff5b0
=== des加解密 ===
加密字符:
?/灲取鮋t8:夽U錺?说
解密字符:
this is an example
=== rsa加解密 ===
公钥:
-----BEGIN RSA PUBLIC KEY-----
MIIBCAKCAQEA59WESdYbPsD6cYATooC4ebClTpvbTsu3X29Ha0g31kW3AmLR2zLj
hMvdWjUhhVuM7xBoh3Ufoyj4jTGHVhunFfbzxNrt1Nb64N95bZH8e9u6LjJYqh4e
sNoFknG+McjoSLNqGW9Yd8ejKH1Ju6C9SBUcC43XbB3XdC2matgV1zTsKhqjuywm
gVN9DZdo2TlZkqsvOHC23rbQ+lP09rpQJ/RI4NQSnCUBqQxErCN85trcWRj1zyJA
WaBZSvKh7J5RJcrC2ByMDmL7jrDDZl7YEolyW93SSc4xTE9Dr20OXznXNDsfQc9r
RQHBri8Aqsu4WW3tHSBRmjW5kxFMxS4qxwIBAw==
-----END RSA PUBLIC KEY-----
私钥:
-----BEGIN RSA PRIVATE KEY-----
MIIEowIBAAKCAQEA59WESdYbPsD6cYATooC4ebClTpvbTsu3X29Ha0g31kW3AmLR
2zLjhMvdWjUhhVuM7xBoh3Ufoyj4jTGHVhunFfbzxNrt1Nb64N95bZH8e9u6LjJY
qh4esNoFknG+McjoSLNqGW9Yd8ejKH1Ju6C9SBUcC43XbB3XdC2matgV1zTsKhqj
uywmgVN9DZdo2TlZkqsvOHC23rbQ+lP09rpQJ/RI4NQSnCUBqQxErCN85trcWRj1
zyJAWaBZSvKh7J5RJcrC2ByMDmL7jrDDZl7YEolyW93SSc4xTE9Dr20OXznXNDsf
Qc9rRQHBri8Aqsu4WW3tHSBRmjW5kxFMxS4qxwIBAwKCAQEAmo5YMTlnfytRoQAN
FwB6+8sY3xKSNIfPlPTaR4V6jtkkrEHhPMyXrd0+PCNrrj0In2BFr6NqbMX7CMuv
jr0aDqSigzyejeSnQJT7nmFS/T0myXblxr6/IJFZDEvUITCa2yJGu5+QT9psxajb
0mso2ri9XQk6SBPk+B5u8eVj5Myt4tqpWL0DEEDzwfhihs+uEGM7g6bPvQBI4JXu
8uxfSRUkpyZ5s1koEhqj+RCguksPzSWO/Ut2Sd60iOUMRhya2aEbAyRTtfhsXja3
4NMWjXorJ0SRkryM1iLJvVWkhkcr2vShH9rm9qz16BkrkI9/9Yx++GNNr6VU/p/+
Waa8CwKBgQD4m0ryXi6rCqazdCICGoZJGzaljApOZ1rWOiotM9TekaYE7tZ2NDAT
eytiCzxvs4/+1Jt5XzdGJ035VJKSai/n2ZzAq1YYtVHy5CG2olmeFtwaIWU18m2s
RjHQf/FiscVB4XdKrHjh3gLgSB8MWMDg/krisxT86HNyp1UE2jZv+QKBgQDuuoez
V+H23ktb9oDS9HuLXt+wZuww29uNb0jhVoLiqK6M90Pl2u8yErjsq04cG9pF0MUl
8/nIw4RRKQh9GUOBBbxZqA/1yBxmHTz48siYJ3YXf5HB+0WxxOlEk3s05AnTilTi
5Y4u9Ptwieoy+TOXatBL9XZgKkpHbcxKZH2gvwKBgQClvNyhlB8cscR3osFWvFmG
EiRuXVw0ROc5fBweIo3ptm6t9I75eCAM/MeWsihKd7VUjbz7lM+EGjP7jbcMRsqa
kRMrHOQQeOFMmBZ5wZEUDz1mwO4j9vPILsvgVUuXIS4r66TccvtBPqyVhWoIOytA
qYdBzLiomvehxONYkXmf+wKBgQCfJwUiOpaklDI9TwCMov0HlJUgRJ115+ezn4Xr
jwHscHRd+i1D50ohYdCdx4loEpGD4INuoqaF162LcLBTZi0Arn2RGrVOhWhEE337
TIW6xPlk/7aBUi52g0Ytt6d4mAaNBuNB7l7J+KegW/F3UM0PnIrdTk7qxtwvnogx
mFPAfwKBgAEuRGqF2Q9bNu/r0OufeFxsYm0zFvWBIxbq3DxPYRtzfhiQMeTOzl1g
5rowAtb/w1SusGAZ4/lEUZoBgzV+8fr+rpx3eavVCmcXBVjDi9B5nNLIXWkcoEQG
G/4ZwXUr5kyTBktL6mIBVNJ8dJUQo8xyxK0GjfWhlsk5t/Zu8tmK
-----END RSA PRIVATE KEY-----
加密字符:
佷篒?z_&欗霐嗪K赸;J╄[i9?S絑?て晄p?[hD∞51鱠,k|1裡郿 犓鈪鑒?饞w2?`vlu
L<萿囂?圖L潥?O0佲y▃飕E堿^桮??,e鉀煯ACsJ挈R聡-鳊帔!eQC乥+1\(齀
я盈Xj饮[o6覾羂≯傁澓
解密字符:
this is an example
注:
(1)在读取公钥文件时,PEM_read_RSA_PUBKEY()函数和PEM_read_RSAPublicKEY()的疑惑。有时候为什么读取私钥文件用的PEM_read_RSAPrivateKey(),针对上述openssl命令生成的公钥文件,在读取其内容时用对称的PEM_read_RSAPublicKEY()接口却会报错,必须要用PEM_read_RSA_PUBKEY()才可以。
RSA PUBLIC KEY和PUBLIC KEY的两种公钥文件其存储方式是不一样的,PEM_read_RSAPublicKEY()只能读取RSA PUBLIC KEY开头形式的公钥文件(用函数生成的);而PEM_read_RSA_PUBKEY()只能读取PUBLIC KEY开头格式的公钥文件(用命令行生成),所以公钥私钥读取函数一定要跟生成的密钥对的格式对应起来。
(2)公钥加密和私钥解密, 私钥加密公钥解密 这两种都可以使用
(3)一般加密之后的字符串因为编码跟中文对应不上所以是乱码,在很多场合选择用十六进制串输出
(4)实际的工程应用中读取密钥对需要加安全验证
(5)用纯代码不依赖openssl库也是可以自己实现这些加解密算法的,搞清楚原理就行
以上代码为函数格式的公钥和私钥
不同之处在于:
生成密钥对的调用函数不同
PEM_write_bio_RSAPublicKey(pub, keypair);//函数专用
PEM_write_bio_RSA_PUBKEY(pub, keypair); //命令行专用
公钥加密的调用函数不同
rsa = PEM_read_bio_RSAPublicKey(keybio, &rsa, NULL, NULL); //函数专用
rsa = PEM_read_bio_RSA_PUBKEY(keybio, &rsa, NULL, NULL); //命令行专用
以下代码为命令行格式的公钥和私钥
//// rsa_test_04.cpp : 定义控制台应用程序的入口点。
////
//
#include "stdafx.h"
//
//
//int _tmain(int argc, _TCHAR* argv[])
//{
// return 0;
//}
#include "stdafx.h"
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <openssl/rsa.h>
#include <openssl/evp.h>
#include <openssl/objects.h>
#include <openssl/x509.h>
#include <openssl/err.h>
#include <openssl/pem.h>
#include <openssl/ssl.h>
#include <openssl/engine.h>
#include <openssl/rand.h>
#include <openssl/bio.h>
//#include <unistd.h>
#include <iostream>
#include <io.h>
//#pragma comment(lib,"ws2_32.lib")
const char *g_pPubFile = "public.pem";
const char *g_pPriFile = "private.pem";
//maxCodeByte = g_nBits/8-11
const int g_nBits = 1024;
using namespace std;
以上文章借鉴与两位前辈的经验加工而成
传送门:https://www.cnblogs.com/findumars/p/7252839.html
http://blog.csdn.net/cyuyan112233/article/details/45693519
算法介绍
md5:https://en.wikipedia.org/wiki/MD5
sha256:https://en.wikipedia.org/wiki/SHA-2
des: https://en.wikipedia.org/wiki/Data_Encryption_Standard
rsa: https://en.wikipedia.org/wiki/RSA_(cryptosystem)
工程配置
以windows下为例
编译openssl库,得到头文件include和链接库lib和dll
配置包含头文件目录和库目录
工程中设置链接指定的lib:fenbieshlibssl.lib,libcrypto.lib
将对应的dll拷贝到exe执行目录:libcrypto-1_1.dll, libssl-1_1.dll
linux下同理
代码
#include <iostream>
#include <cassert>
#include <string>
#include <vector>
#include "openssl/md5.h"
#include "openssl/sha.h"
#include "openssl/des.h"
#include "openssl/
f8ed
rsa.h"
#include "openssl/pem.h"
#pragma comment(lib,"libeay32.lib") #pragma comment(lib,"ssleay32.lib") // ---- md5摘要哈希 ---- // void md5(const std::string &srcStr, std::string &encodedStr, std::string &encodedHexStr) { // 调用md5哈希 unsigned char mdStr[33] = {0}; MD5((const unsigned char *)srcStr.c_str(), srcStr.length(), mdStr); // 哈希后的字符串 encodedStr = std::string((const char *)mdStr); // 哈希后的十六进制串 32字节 char buf[65] = {0}; char tmp[3] = {0}; for (int i = 0; i < 32; i++) { sprintf(tmp, "%02x", mdStr[i]); strcat(buf, tmp); } buf[32] = '\0'; // 后面都是0,从32字节截断 encodedHexStr = std::string(buf); } // ---- sha256摘要哈希 ---- // void sha256(const std::string &srcStr, std::string &encodedStr, std::string &encodedHexStr) { // 调用sha256哈希 unsigned char mdStr[33] = {0}; SHA256((const unsigned char *)srcStr.c_str(), srcStr.length(), mdStr); // 哈希后的字符串 encodedStr = std::string((const char *)mdStr); // 哈希后的十六进制串 32字节 char buf[65] = {0}; char tmp[3] = {0}; for (int i = 0; i < 32; i++) { sprintf(tmp, "%02x", mdStr[i]); strcat(buf, tmp); } buf[32] = '\0'; // 后面都是0,从32字节截断 encodedHexStr = std::string(buf); } // ---- des对称加解密 ---- // // 加密 ecb模式 std::string des_encrypt(const std::string &clearText, const std::string &key) { std::string cipherText; // 密文 DES_cblock keyEncrypt; memset(keyEncrypt, 0, 8); // 构造补齐后的密钥 if (key.length() <= 8) memcpy(keyEncrypt, key.c_str(), key.length()); else memcpy(keyEncrypt, key.c_str(), 8); // 密钥置换 DES_key_schedule keySchedule; DES_set_key_unchecked(&keyEncrypt, &keySchedule); // 循环加密,每8字节一次 const_DES_cblock inputText; DES_cblock outputText; std::vector<unsigned char> vecCiphertext; unsigned char tmp[8]; for (int i = 0; i < clearText.length() / 8; i++) { memcpy(inputText, clearText.c_str() + i * 8, 8); DES_ecb_encrypt(&inputText, &outputText, &keySchedule, DES_ENCRYPT); memcpy(tmp, outputText, 8); for (int j = 0; j < 8; j++) vecCiphertext.push_back(tmp[j]); } if (clearText.length() % 8 != 0) { int tmp1 = clearText.length() / 8 * 8; int tmp2 = clearText.length() - tmp1; memset(inputText, 0, 8); memcpy(inputText, clearText.c_str() + tmp1, tmp2); // 加密函数 DES_ecb_encrypt(&inputText, &outputText, &keySchedule, DES_ENCRYPT); memcpy(tmp, outputText, 8); for (int j = 0; j < 8; j++) vecCiphertext.push_back(tmp[j]); } cipherText.clear(); cipherText.assign(vecCiphertext.begin(), vecCiphertext.end()); return cipherText; } // 解密 ecb模式 std::string des_decrypt(const std::string &cipherText, const std::string &key) { std::string clearText; // 明文 DES_cblock keyEncrypt; memset(keyEncrypt, 0, 8); if (key.length() <= 8) memcpy(keyEncrypt, key.c_str(), key.length()); else memcpy(keyEncrypt, key.c_str(), 8); DES_key_schedule keySchedule; DES_set_key_unchecked(&keyEncrypt, &keySchedule); const_DES_cblock inputText; DES_cblock outputText; std::vector<unsigned char> vecCleartext; unsigned char tmp[8]; for (int i = 0; i < cipherText.length() / 8; i++) { memcpy(inputText, cipherText.c_str() + i * 8, 8); DES_ecb_encrypt(&inputText, &outputText, &keySchedule, DES_DECRYPT); memcpy(tmp, outputText, 8); for (int j = 0; j < 8; j++) vecCleartext.push_back(tmp[j]); } if (cipherText.length() % 8 != 0) { int tmp1 = cipherText.length() / 8 * 8; int tmp2 = cipherText.length() - tmp1; memset(inputText, 0, 8); memcpy(inputText, cipherText.c_str() + tmp1, tmp2); // 解密函数 DES_ecb_encrypt(&inputText, &outputText, &keySchedule, DES_DECRYPT); memcpy(tmp, outputText, 8); for (int j = 0; j < 8; j++) vecCleartext.push_back(tmp[j]); } clearText.clear(); clearText.assign(vecCleartext.begin(), vecCleartext.end()); return clearText; } // ---- rsa非对称加解密 ---- // #define KEY_LENGTH 2048 // 密钥长度 #define PUB_KEY_FILE "pubkey.pem" // 公钥路径 #define PRI_KEY_FILE "prikey.pem" // 私钥路径 // 函数方法生成密钥对 void generateRSAKey(std::string strKey[2]) { // 公私密钥对 size_t pri_len; size_t pub_len; char *pri_key = NULL; char *pub_key = NULL; // 生成密钥对 RSA *keypair = RSA_generate_key(KEY_LENGTH, RSA_3, NULL, NULL); BIO *pri = BIO_new(BIO_s_mem()); BIO *pub = BIO_new(BIO_s_mem()); PEM_write_bio_RSAPrivateKey(pri, keypair, NULL, NULL, 0, NULL, NULL); PEM_write_bio_RSAPublicKey(pub, keypair); // 获取长度 pri_len = BIO_pending(pri); pub_len = BIO_pending(pub); // 密钥对读取到字符串 pri_key = (char *)malloc(pri_len + 1); pub_key = (char *)malloc(pub_len + 1); BIO_read(pri, pri_key, pri_len); BIO_read(pub, pub_key, pub_len); pri_key[pri_len] = '\0'; pub_key[pub_len] = '\0'; // 存储密钥对 strKey[0] = pub_key; strKey[1] = pri_key; // 存储到磁盘(这种方式存储的是begin rsa public key/ begin rsa private key开头的) FILE *pubFile = fopen(PUB_KEY_FILE, "w"); if (pubFile == NULL) { assert(false); return; } fputs(pub_key, pubFile); fclose(pubFile); FILE *priFile = fopen(PRI_KEY_FILE, "w"); if (priFile == NULL) { assert(false); return; } fputs(pri_key, priFile); fclose(priFile); // 内存释放 RSA_free(keypair); BIO_free_all(pub); BIO_free_all(pri); free(pri_key); free(pub_key); } // 命令行方法生成公私钥对(begin public key/ begin private key) // 找到openssl命令行工具,运行以下 // openssl genrsa -out prikey.pem 1024 // openssl rsa - in privkey.pem - pubout - out pubkey.pem // 公钥加密 std::string rsa_pub_encrypt(const std::string &clearText, const std::string &pubKey) { std::string strRet; RSA *rsa = NULL; BIO *keybio = BIO_new_mem_buf((unsigned char *)pubKey.c_str(), -1); // 此处有三种方法 // 1, 读取内存里生成的密钥对,再从内存生成rsa // 2, 读取磁盘里生成的密钥对文本文件,在从内存生成rsa // 3,直接从读取文件指针生成rsa RSA* pRSAPublicKey = RSA_new(); rsa = PEM_read_bio_RSAPublicKey(keybio, &rsa, NULL, NULL); int len = RSA_size(rsa); char *encryptedText = (char *)malloc(len + 1); memset(encryptedText, 0, len + 1); // 加密函数 int ret = RSA_public_encrypt(clearText.length(), (const unsigned char*)clearText.c_str(), (unsigned char*)encryptedText, rsa, RSA_PKCS1_PADDING); if (ret >= 0) strRet = std::string(encryptedText, ret); // 释放内存 free(encryptedText); BIO_free_all(keybio); RSA_free(rsa); return strRet; } // 私钥解密 std::string rsa_pri_decrypt(const std::string &cipherText, const std::string &priKey) { std::string strRet; RSA *rsa = RSA_new(); BIO *keybio; keybio = BIO_new_mem_buf((unsigned char *)priKey.c_str(), -1); // 此处有三种方法 // 1, 读取内存里生成的密钥对,再从内存生成rsa // 2, 读取磁盘里生成的密钥对文本文件,在从内存生成rsa // 3,直接从读取文件指针生成rsa rsa = PEM_read_bio_RSAPrivateKey(keybio, &rsa, NULL, NULL); int len = RSA_size(rsa); char *decryptedText = (char *)malloc(len + 1); memset(decryptedText, 0, len + 1); // 解密函数 int ret = RSA_private_decrypt(cipherText.length(), (const unsigned char*)cipherText.c_str(), (unsigned char*)decryptedText, rsa, RSA_PKCS1_PADDING); if (ret >= 0) strRet = std::string(decryptedText, ret); // 释放内存 free(decryptedText); BIO_free_all(keybio); RSA_free(rsa); return strRet; } int main(int argc, char **argv) { // 原始明文 std::string srcText = "this is an example"; std::string encryptText; std::string encryptHexText; std::string decryptText; std::cout << "=== 原始明文 ===" << std::endl; std::cout << srcText << std::endl; // md5 std::cout << "=== md5哈希 ===" << std::endl; md5(srcText, encryptText, encryptHexText); std::cout << "摘要字符: " << encryptText << std::endl; std::cout << "摘要串: " << encryptHexText << std::endl; // sha256 std::cout << "=== sha256哈希 ===" << std::endl; sha256(srcText, encryptText, encryptHexText); std::cout << "摘要字符: " << encryptText << std::endl; std::cout << "摘要串: " << encryptHexText << std::endl; // des std::cout << "=== des加解密 ===" << std::endl; std::string desKey = "12345"; encryptText = des_encrypt(srcText, desKey); std::cout << "加密字符: " << std::endl; std::cout << encryptText << std::endl; decryptText = des_decrypt(encryptText, desKey); std::cout << "解密字符: " << std::endl; std::cout << decryptText << std::endl; // rsa std::cout << "=== rsa加解密 ===" << std::endl; std::string key[2]; generateRSAKey(key); std::cout << "公钥: " << std::endl; std::cout << key[0] << std::endl; std::cout << "私钥: " << std::endl; std::cout << key[1] << std::endl; encryptText = rsa_pub_encrypt(srcText, key[0]); std::cout << "加密字符: " << std::endl; std::cout << encryptText << std::endl; decryptText = rsa_pri_decrypt(encryptText, key[1]); std::cout << "解密字符: " << std::endl; std::cout << decryptText << std::endl; system("pause"); return 0; }运行结果
=== 原始明文 ===
this is an example
=== md5哈希 ===
摘要字符: 乵驥!範
摘要串: 9202816dabaaf34bb106a10421b9a0d0
=== sha256哈希 ===
摘要字符: 訪X5衽鄁媫j/醢?17?P?4膡zD
摘要串: d44c035835f1c5e0668b7d186a2ff5b0
=== des加解密 ===
加密字符:
?/灲取鮋t8:夽U錺?说
解密字符:
this is an example
=== rsa加解密 ===
公钥:
-----BEGIN RSA PUBLIC KEY-----
MIIBCAKCAQEA59WESdYbPsD6cYATooC4ebClTpvbTsu3X29Ha0g31kW3AmLR2zLj
hMvdWjUhhVuM7xBoh3Ufoyj4jTGHVhunFfbzxNrt1Nb64N95bZH8e9u6LjJYqh4e
sNoFknG+McjoSLNqGW9Yd8ejKH1Ju6C9SBUcC43XbB3XdC2matgV1zTsKhqjuywm
gVN9DZdo2TlZkqsvOHC23rbQ+lP09rpQJ/RI4NQSnCUBqQxErCN85trcWRj1zyJA
WaBZSvKh7J5RJcrC2ByMDmL7jrDDZl7YEolyW93SSc4xTE9Dr20OXznXNDsfQc9r
RQHBri8Aqsu4WW3tHSBRmjW5kxFMxS4qxwIBAw==
-----END RSA PUBLIC KEY-----
私钥:
-----BEGIN RSA PRIVATE KEY-----
MIIEowIBAAKCAQEA59WESdYbPsD6cYATooC4ebClTpvbTsu3X29Ha0g31kW3AmLR
2zLjhMvdWjUhhVuM7xBoh3Ufoyj4jTGHVhunFfbzxNrt1Nb64N95bZH8e9u6LjJY
qh4esNoFknG+McjoSLNqGW9Yd8ejKH1Ju6C9SBUcC43XbB3XdC2matgV1zTsKhqj
uywmgVN9DZdo2TlZkqsvOHC23rbQ+lP09rpQJ/RI4NQSnCUBqQxErCN85trcWRj1
zyJAWaBZSvKh7J5RJcrC2ByMDmL7jrDDZl7YEolyW93SSc4xTE9Dr20OXznXNDsf
Qc9rRQHBri8Aqsu4WW3tHSBRmjW5kxFMxS4qxwIBAwKCAQEAmo5YMTlnfytRoQAN
FwB6+8sY3xKSNIfPlPTaR4V6jtkkrEHhPMyXrd0+PCNrrj0In2BFr6NqbMX7CMuv
jr0aDqSigzyejeSnQJT7nmFS/T0myXblxr6/IJFZDEvUITCa2yJGu5+QT9psxajb
0mso2ri9XQk6SBPk+B5u8eVj5Myt4tqpWL0DEEDzwfhihs+uEGM7g6bPvQBI4JXu
8uxfSRUkpyZ5s1koEhqj+RCguksPzSWO/Ut2Sd60iOUMRhya2aEbAyRTtfhsXja3
4NMWjXorJ0SRkryM1iLJvVWkhkcr2vShH9rm9qz16BkrkI9/9Yx++GNNr6VU/p/+
Waa8CwKBgQD4m0ryXi6rCqazdCICGoZJGzaljApOZ1rWOiotM9TekaYE7tZ2NDAT
eytiCzxvs4/+1Jt5XzdGJ035VJKSai/n2ZzAq1YYtVHy5CG2olmeFtwaIWU18m2s
RjHQf/FiscVB4XdKrHjh3gLgSB8MWMDg/krisxT86HNyp1UE2jZv+QKBgQDuuoez
V+H23ktb9oDS9HuLXt+wZuww29uNb0jhVoLiqK6M90Pl2u8yErjsq04cG9pF0MUl
8/nIw4RRKQh9GUOBBbxZqA/1yBxmHTz48siYJ3YXf5HB+0WxxOlEk3s05AnTilTi
5Y4u9Ptwieoy+TOXatBL9XZgKkpHbcxKZH2gvwKBgQClvNyhlB8cscR3osFWvFmG
EiRuXVw0ROc5fBweIo3ptm6t9I75eCAM/MeWsihKd7VUjbz7lM+EGjP7jbcMRsqa
kRMrHOQQeOFMmBZ5wZEUDz1mwO4j9vPILsvgVUuXIS4r66TccvtBPqyVhWoIOytA
qYdBzLiomvehxONYkXmf+wKBgQCfJwUiOpaklDI9TwCMov0HlJUgRJ115+ezn4Xr
jwHscHRd+i1D50ohYdCdx4loEpGD4INuoqaF162LcLBTZi0Arn2RGrVOhWhEE337
TIW6xPlk/7aBUi52g0Ytt6d4mAaNBuNB7l7J+KegW/F3UM0PnIrdTk7qxtwvnogx
mFPAfwKBgAEuRGqF2Q9bNu/r0OufeFxsYm0zFvWBIxbq3DxPYRtzfhiQMeTOzl1g
5rowAtb/w1SusGAZ4/lEUZoBgzV+8fr+rpx3eavVCmcXBVjDi9B5nNLIXWkcoEQG
G/4ZwXUr5kyTBktL6mIBVNJ8dJUQo8xyxK0GjfWhlsk5t/Zu8tmK
-----END RSA PRIVATE KEY-----
加密字符:
佷篒?z_&欗霐嗪K赸;J╄[i9?S絑?て晄p?[hD∞51鱠,k|1裡郿 犓鈪鑒?饞w2?`vlu
L<萿囂?圖L潥?O0佲y▃飕E堿^桮??,e鉀煯ACsJ挈R聡-鳊帔!eQC乥+1\(齀
я盈Xj饮[o6覾羂≯傁澓
解密字符:
this is an example
注:
(1)在读取公钥文件时,PEM_read_RSA_PUBKEY()函数和PEM_read_RSAPublicKEY()的疑惑。有时候为什么读取私钥文件用的PEM_read_RSAPrivateKey(),针对上述openssl命令生成的公钥文件,在读取其内容时用对称的PEM_read_RSAPublicKEY()接口却会报错,必须要用PEM_read_RSA_PUBKEY()才可以。
RSA PUBLIC KEY和PUBLIC KEY的两种公钥文件其存储方式是不一样的,PEM_read_RSAPublicKEY()只能读取RSA PUBLIC KEY开头形式的公钥文件(用函数生成的);而PEM_read_RSA_PUBKEY()只能读取PUBLIC KEY开头格式的公钥文件(用命令行生成),所以公钥私钥读取函数一定要跟生成的密钥对的格式对应起来。
(2)公钥加密和私钥解密, 私钥加密公钥解密 这两种都可以使用
(3)一般加密之后的字符串因为编码跟中文对应不上所以是乱码,在很多场合选择用十六进制串输出
(4)实际的工程应用中读取密钥对需要加安全验证
(5)用纯代码不依赖openssl库也是可以自己实现这些加解密算法的,搞清楚原理就行
以上代码为函数格式的公钥和私钥
不同之处在于:
生成密钥对的调用函数不同
PEM_write_bio_RSAPublicKey(pub, keypair);//函数专用
PEM_write_bio_RSA_PUBKEY(pub, keypair); //命令行专用
公钥加密的调用函数不同
rsa = PEM_read_bio_RSAPublicKey(keybio, &rsa, NULL, NULL); //函数专用
rsa = PEM_read_bio_RSA_PUBKEY(keybio, &rsa, NULL, NULL); //命令行专用
以下代码为命令行格式的公钥和私钥
//// rsa_test_04.cpp : 定义控制台应用程序的入口点。
////
//
#include "stdafx.h"
//
//
//int _tmain(int argc, _TCHAR* argv[])
//{
// return 0;
//}
#include "stdafx.h"
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <openssl/rsa.h>
#include <openssl/evp.h>
#include <openssl/objects.h>
#include <openssl/x509.h>
#include <openssl/err.h>
#include <openssl/pem.h>
#include <openssl/ssl.h>
#include <openssl/engine.h>
#include <openssl/rand.h>
#include <openssl/bio.h>
//#include <unistd.h>
#include <iostream>
#include <io.h>
//#pragma comment(lib,"ws2_32.lib")
const char *g_pPubFile = "public.pem";
const char *g_pPriFile = "private.pem";
//maxCodeByte = g_nBits/8-11
const int g_nBits = 1024;
using namespace std;
#pragma comment(lib,"libeay32.lib") #pragma comment(lib,"ssleay32.lib") int MakeKey() { /*if (access(g_pPubFile,0) != 0 || access(g_pPriFile,0) != 0) { return 0; }*/ //生成key,这里设置了1024,意味着最多可以编解码1024/8-11=117个字节, //RSA_F4为公钥指数,一般情况下使用RSA_F4即可, //其它两个参数可以设置为NULL RSA *pRsa = RSA_generate_key(g_nBits,RSA_F4,NULL,NULL); if (pRsa == NULL) { cout << "rsa_generate_key error" << endl; return -1; } BIO *pBio = BIO_new_file(g_pPubFile,"wb"); if (pBio == NULL) { cout << "BIO_new_file " << g_pPubFile << " error" << endl; return -2; } if(PEM_write_bio_RSAPublicKey(pBio,pRsa) == 0) { cout << "write public key error" << endl; return -3; } BIO_free_all(pBio); pBio = BIO_new_file(g_pPriFile,"w"); if (pBio == NULL) { cout << "BIO_new_file " << g_pPriFile << " error" << endl; return -4; } if(PEM_write_bio_RSAPrivateKey(pBio,pRsa,NULL,NULL,0,NULL,NULL) == 0) { cout << "write private key error" << endl; return -5; } BIO_free_all(pBio); RSA_free(pRsa); return 0; } int MakeKey_test_01() { /*if (access(g_pPubFile,0) != 0 || access(g_pPriFile,0) != 0) { return 0; }*/ //生成key,这里设置了1024,意味着最多可以编解码1024/8-11=117个字节, //RSA_F4为公钥指数,一般情况下使用RSA_F4即可, //其它两个参数可以设置为NULL RSA *pRsa = RSA_generate_key(g_nBits,RSA_F4,NULL,NULL); if (pRsa == NULL) { cout << "rsa_generate_key error" << endl; return -1; } BIO *pBio = BIO_new_file(g_pPubFile,"wb"); if (pBio == NULL) { cout << "BIO_new_file " << g_pPubFile << " error" << endl; return -2; } ////PEM_write_bio_RSA_PUBKEY //if(PEM_write_bio_RSAPublicKey(pBio,pRsa) == 0) if(PEM_write_bio_RSA_PUBKEY(pBio,pRsa) == 0) { cout << "write public key error" << endl; return -3; } BIO_free_all(pBio); pBio = BIO_new_file(g_pPriFile,"w"); if (pBio == NULL) { cout << "BIO_new_file " << g_pPriFile << " error" << endl; return -4; } //PEM_write_bio_PKCS8PrivateKey if(PEM_write_bio_RSAPrivateKey(pBio,pRsa,NULL,NULL,0,NULL,NULL) == 0) //if(PEM_write_bio_PKCS8PrivateKey(pBio,pRsa,NULL,NULL,0,NULL,NULL) == 0) { cout << "write private key error" << endl; return -5; } BIO_free_all(pBio); RSA_free(pRsa); return 0; } //测试使用PEM_write_bio_RSA_PUBKEY 生成的公钥加密,测试私钥解密 int Enc_test_01(char *in, int inLen, char *out, int &outLen) { BIO *pBio = BIO_new_file(g_pPubFile,"r"); //RSA *pRsa = PEM_read_bio_RSAPublicKey(pBio,NULL,NULL,NULL); RSA *pRsa = PEM_read_bio_RSA_PUBKEY(pBio,NULL,NULL,NULL); BIO_free_all(pBio); outLen = RSA_public_encrypt( (RSA_size(pRsa)-11)>inLen?inLen:RSA_size(pRsa)-11, reinterpret_cast<unsigned char*>(in), reinterpret_cast<unsigned char*>(out), pRsa, RSA_PKCS1_PADDING); std::cout << out << std::endl; //RSA_free(pRsa); if(outLen >= 0) return 0; return -1; } int Enc(char *in, int inLen, char *out, int &outLen) { BIO *pBio = BIO_new_file(g_pPubFile,"r"); RSA *pRsa = PEM_read_bio_RSAPublicKey(pBio,NULL,NULL,NULL); BIO_free_all(pBio); outLen = RSA_public_encrypt( (RSA_size(pRsa)-11)>inLen?inLen:RSA_size(pRsa)-11, reinterpret_cast<unsigned char*>(in), reinterpret_cast<unsigned char*>(out), pRsa, RSA_PKCS1_PADDING); std::cout << out << std::endl; //RSA_free(pRsa); if(outLen >= 0) return 0; return -1; } int Dec(char *in, int inLen, char *out, int &outLen) { BIO *pBio = BIO_new_file(g_pPriFile,"r"); RSA *pRsa = PEM_read_bio_RSAPrivateKey(pBio,NULL,NULL,NULL); BIO_free_all(pBio); outLen = RSA_private_decrypt( inLen, reinterpret_cast<unsigned char*>(in), reinterpret_cast<unsigned char*>(out), pRsa, RSA_PKCS1_PADDING); //RSA_free(pRsa); if(outLen >= 0) return 0; return -1; } //RSA_PUBKEY //test base64 int main() { //MakeKey(); //char pOld[100]="for test"; //char szEnc[1024] = {0}; //int nEncLen = 0; //char szDec[1024] = {0}; //int nDecLen = 0; //Enc(pOld,strlen(pOld),szEnc,nEncLen); //Dec(szEnc,nEncLen,szDec,nDecLen); //cout << "decode: " << szDec << endl; //MakeKey_test_01(); //--Enc_test_01-- //char pOld[100]="for test"; //char szEnc[1024] = {0}; //int nEncLen = 0; //char szDec[1024] = {0}; //int nDecLen = 0; //Enc_test_01(pOld,strlen(pOld),szEnc,nEncLen); //Dec(szEnc,nEncLen,szDec,nDecLen); //cout << "decode: " << szDec << endl; cin.get(); }
以上文章借鉴与两位前辈的经验加工而成
传送门:https://www.cnblogs.com/findumars/p/7252839.html
http://blog.csdn.net/cyuyan112233/article/details/45693519
相关文章推荐
- C/C++使用openssl进行摘要和加密解密(md5, sha256, des, rsa)
- C/C++使用openssl进行摘要和加密解密(md5, sha256, des, rsa)
- C/C++使用openssl进行摘要和加密解密(md5, sha256, des, rsa)
- 常用加密解密算法【RSA、AES、DES、MD5】介绍和使用
- php使用openssl进行Rsa长数据加密(117)解密(128) 和 DES 加密解密
- C#加密解密(DES,AES,Base64,md5,SHA256,RSA,RC4)
- 常用加密解密算法【RSA、AES、DES、MD5】介绍和使用
- 用openssl进行rsa的加密与解密(linux,C++版)
- 使用openssl进行RSA加密解密
- 用openssl进行rsa的加密与解密(linux,C++版)
- 加密解密算法【RSA、AES、DES、MD5】介绍和使用
- 用openssl进行rsa的加密与解密(linux,C++版)
- 常用加密解密算法【RSA、AES、DES、MD5】介绍和使用
- PHP使用DES进行加密和解密
- 使用des进行加密和解密
- PHP使用DES进行加密与解密的方法详解
- Java中不依赖于第三方库使用OpenSSL生成的RSA公私钥进行数据加解密
- openssl签名验证、信封加密解密、产生随机数、md5摘要
- Java中使用OpenSSL生成的RSA公私钥进行数据加解密
- 【转】PHP使用DES进行加密和解密