OpenSSL C++简单应用
1.加密后得内容中带有结束符,cout输出不能正常输出
2.将加密后的内容存到文件,解密的时候再读出来,可能会碰到结束符而提前终止读取文件,导致解密失败
3.将加密后的内容转为十六进制,解密再转回来是完全可以的,但是我将加密后的内容转为二进制会有问题,我看解密的时候具体数据都是一样的,却解密失败。这个我也未解决。
// OpenSSLDemo.cpp : 定义控制台应用程序的入口点。
//#include "stdafx.h"
#include<iostream>
#include <windows.h>
#include <string>
#include <iterator>
#include <algorithm>
#include <vector>
#include <sstream>
#include <io.h>
#include <direct.h>
#include "openssl/md5.h"
#include "openssl/sha.h"
#include "openssl/des.h"
#include "openssl/rsa.h"
#include "openssl/pem.h"
#include "base64.h"
#include "memery.h"
using namespace std;
#define KEY_LENGTH 2048
#define PUB_KEY_FILE "pubkey.pem"
#define PRI_KEY_FILE "prikey.pem"#pragma warning(disable:4996)void str_to_two(const UCHAR *str,int strLen,UCHAR *twoStr);
void two_to_str(const UCHAR *inData,int inDataLen,UCHAR *outStr);
string string_to_hex(std::string const &str);
string hex_to_string(std::string const &str);string getMsg(int ret)
{string message;switch (ret){case 0:message="失败"; break;case 1:message="成功"; break;default: message="未知错误";break;}return message;
}
//2进制转16进制
unsigned char char2HexChar(const unsigned char &x)
{return x>9?(x-10+'A'):x+'0';
}
//sha1加密
string sha1(const string &str)
{SHA_CTX c;SHA1_Init(&c);SHA1_Update(&c,str.c_str(),str.size());unsigned char szSha1[SHA_DIGEST_LENGTH]={0};SHA1_Final(szSha1,&c);string strSha1="";// unsigned char strTmpHex;char buf[41] = {0}; char tmp[3] = {0}; for (int i=0;i<SHA_DIGEST_LENGTH;i++){/*strTmpHex=char2HexChar(szSha1[i]/16);strSha1.append(1,strTmpHex);strTmpHex=char2HexChar(szSha1[i]%16);strSha1.append(1,strTmpHex);*/sprintf_s(tmp,"%02x",szSha1[i]);strcat_s(buf,tmp);}//transform(strSha1.begin(), strSha1.end(), strSha1.begin(), ::tolower); return buf;}
string md5(const string &str)
{unsigned char md[16]={0};MD5_CTX md5;MD5_Init(&md5);MD5_Update(&md5,str.c_str(),str.size());MD5_Final(md,&md5);char buf[33]={0};char tmp[3]={0};for(int i=0;i<16;i++){sprintf_s(tmp,"%02x",md[i]);strcat_s(buf,tmp);}return buf;
}
//sha256加密
string sha256(const string &srcStr)//, std::string &encodedStr, std::string &encodedHexStr)
{ // 调用sha256哈希 unsigned char mdStr[SHA256_DIGEST_LENGTH] = {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}; string encodedStr;string encodedHexStr;for (int i = 0; i < 32; i++) { sprintf(tmp, "%02x", mdStr[i]); strcat(buf, tmp); } //buf[32] = '\0'; // 后面都是0,从32字节截断 return buf;
}//des对称加密
/********************************************************
DES加密原理:DES 使用一个 56 位的密钥以及附加的 8 位奇偶校验位
(每组的第8位作为奇偶校验位),产生最大 64 位的分组大小。
这是一个迭代的分组密码,使用称为 Feistel 的技术,其中将
加密的文本块分成两半。使用子密钥对其中一半应用循环功能,
然后将输出与另一半进行“异或”运算;接着交换这两半,
这一过程会继续下去,但最后一个循环不交换。DES 使用 16
轮循环,使用异或,置换,代换,移位操作四种基本运算。
**********************************************************/
// ecb模式
string des_encrypt(string &text,const string &key)
{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;vector<unsigned char> vecCiphertext;unsigned char tmp[8]={0};for (size_t i=0;i<text.length()/8;i++){memcpy(inputText,text.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(text.length()%8!=0){int tmp1=text.length()/8*8;int tmp2=text.length()-tmp1;memset(inputText,0,8);memcpy(inputText,text.c_str()+tmp1,tmp2);//加密函数DES_ecb_encrypt(&inputText,&outputText,&keySchedule,DES_ENCRYPT);memcpy(tmp,outputText,8);for (int i=0;i<8;i++){vecCiphertext.push_back(tmp[i]);}}cipherText.clear();cipherText.assign(vecCiphertext.begin(),vecCiphertext.end());return cipherText;
}//解密ecb
string des_decrypt(const string &cipherText,const string &key)
{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 keyScheule;DES_set_key_unchecked(&keyEncrypt,&keyScheule); //设置密码表,不校验const_DES_cblock inputText;DES_cblock outputText;vector<unsigned char> vecClearText;unsigned char tmp[8];for (size_t i=0;i<cipherText.length()/8;i++){memcpy(inputText,cipherText.c_str()+i*8,8);DES_ecb_encrypt(&inputText,&outputText,&keyScheule,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,&keyScheule,DES_DECRYPT);memcpy(tmp,outputText,8);for (int i=0;i<8;i++){vecClearText.push_back(tmp[i]);}}clearText.clear();clearText.assign(vecClearText.begin(),vecClearText.end());return clearText;
}
int writeFile(const char *fileName,const string data)
{string path="..//file//";if(access(path.c_str(),0)==-1) //-1为未创建{int i=mkdir(path.c_str());if (i){cout<<"创建目录失败"<<endl;return 0;}}FILE *f=NULL;path+=fileName; //文件的完整路径f=fopen(path.c_str(),"w");if(f==NULL){cout<<"打开文件失败!"<<endl;return 0;}if(fwrite(data.c_str(),data.size(),1,f)==EOF){cout<<"写入文件错误!"<<endl;return 0;}fclose(f);return 1;
}string readFile(const string fileName)
{string data;string path="..//file//";path+=fileName; //完整路径FILE *f=NULL;f=fopen(path.c_str(),"rb");if(f==NULL){cout<<"读取文件失败!"<<endl;return 0;}//char *buf=new char[2048];unsigned char buf={0};int i=0;while (fread(&buf,sizeof(unsigned char),1,f)) //一直读 {//fgets(buf,2048,f);//cout<<buf;//data.append(( char*)buf);data+=buf;//memset(buf,0,strlen((char*)buf));}fclose(f);//delete [] buf;//buf=NULL;//cout<<data<<endl;//memcpy((char*)data.c_str(),tmp,i);return data;}
/***********************
* rsa非对称加密 **
************************
*///生成密钥对
int generateRSAkey()
{string pubKey;string priKey;//公私密钥对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=new char[pri_len+1];pub_key=new char[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';//存储秘钥对pubKey=pub_key;priKey=pri_key;//存储到磁盘(这种方式)writeFile(PUB_KEY_FILE,pub_key);writeFile(PRI_KEY_FILE,pri_key);//内存释放RSA_free(keypair);BIO_free_all(pub);BIO_free_all(pri);delete []pri_key;delete []pub_key;return 1;}
//公钥加密
int rsa_pub_encrypt(const string &clearText,const string &pubKey)
{string strRet;RSA *rsa=NULL;BIO *keybio=BIO_new_mem_buf((unsigned char*)pubKey.c_str(),-1);//三种方式//1.读取内存里生成的密钥对,再从内存生成rsa//2.读取磁盘里生成的密钥对文本文件,再从内存生成rsa//3.直接从读取文件指针生成rsaRSA *pRSAPublicKey=RSA_new();rsa=PEM_read_bio_RSAPublicKey(keybio,&rsa,NULL,NULL);int len=RSA_size(rsa);char *encryptedText=new char[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=string(encryptedText,ret);writeFile("rsa_en.txt",strRet);string strHex=string_to_hex(strRet); //将加密后的内容转为16进制writeFile("rsa_en_16.txt",strHex);unsigned char twoArray[5000]={0};str_to_two((unsigned char*)strRet.c_str(),strRet.size(),twoArray); //将加密后的内容转为2进制//memcpy((char*)strTwo.c_str(),twoArray,strlen((char*)twoArray));writeFile("rsa_en_2.txt",string((char*)twoArray));}//释放内存delete []encryptedText;BIO_free_all(keybio);RSA_free(rsa);return 1;}
//私钥解密
int rsa_pri_decrypt(const string cipherText,const string priKey)
{//将16进制字符转为原加密后的字符string en_data=hex_to_string(cipherText); //转换成原 加密后的内容writeFile("cipherText.txt",en_data);//以下生成的16进制字符 是为了 和 rsa加密后字符转为16进制字符串 进行比对的文件 string cipherText16=string_to_hex(en_data); writeFile("A_rsa_de_16.txt",cipherText16);//一下生成的2进制字符是 为了和之前加密后内容转换成的2进制字符进行比较unsigned char twoArray[5000]={0};str_to_two((unsigned char*)en_data.c_str(),en_data.size(),twoArray);writeFile("A_rsa_de_2.txt",string((char*)twoArray));string strRet;RSA *rsa=RSA_new();//string path="..//file//prikey.pem";/*FILE *f=fopen(path.c_str(),"rb+");rsa = PEM_read_RSAPrivateKey(f, NULL, NULL, NULL);if(rsa==NULL){printf("unable to read private key!\n");return NULL; } */BIO *keybio;keybio=BIO_new_mem_buf((unsigned char*)priKey.c_str(),-1);//三种方式//1.读取内存里生成的密钥对,再从内存生成rsa//2.读取磁盘里生成的密钥对文本文件,再从内存生成rsa//3.直接从读取文件指针生成rsarsa=PEM_read_bio_RSAPrivateKey(keybio,&rsa,NULL,NULL);// 从文件中读取私钥int len=RSA_size(rsa);char *decryptedText=new char[len+1];memset(decryptedText,0,len+1);int ret=RSA_private_decrypt(en_data.size(),(unsigned char*)en_data.c_str(),(unsigned char*)decryptedText,rsa,RSA_PKCS1_PADDING);if(ret>=0){strRet=string(decryptedText,ret);writeFile("rsa_de.txt",decryptedText);}elsereturn 0;//释放内存delete []decryptedText;BIO_free_all(keybio);RSA_free(rsa);return 1;}
/******************************************
** 功能:字符转二进制
** 参数:
** str:输入的字符
** strLen:输入字符串的长度
** twoStr:字符串转换成的二进制
*******************************************
*/
void str_to_two(const UCHAR *str,int strLen,UCHAR *twoStr)
{UCHAR k=0x80; //解密按位与运算 128 10000000for (int i = 0; i < strLen; i++,str++){k = 0x80;for (int j=1; j<=8; j++, k >>= 1){if (*str & k){*twoStr='1';twoStr++;}else{*twoStr='0';*twoStr++;}}}twoStr++;*twoStr='\0'; //结束字符串}/******************************************
** 功能:二进制转字符
** 参数:
** inData:输入的二进制数组
** inDataLen:输入二进制数组的长度
** outStr:二进制转换后的字符
*******************************************
*/
void two_to_str(const UCHAR *inData,int inDataLen,UCHAR *outStr)
{char TwoStr[9]=""; //存放每个字符 8bitint kk=0; //记录字符串的数量for(int i=0;i<inDataLen;i=i+8){int l=0;strncpy(TwoStr,(const char*)inData+i,8);//把每一个字符的8bit 复制给outDatafor(int j=0;j<8;j++) { l+=(TwoStr[j]-'0')<<(7-j); //转换成十进制outStr[kk]=l;}++kk;}outStr[kk]='\0';}string string_to_hex(string const &str)
{string ret;for (unsigned i = 0; i != str.size(); ++i){char hex[6]={0};sprintf(hex, "%#.2x ", (unsigned char)str[i]);ret += hex;}return ret;
}string hex_to_string(string const &str)
{string ret;istringstream iss(str);for (string buf; getline(iss, buf, ' ');){unsigned int value;sscanf(buf.c_str(), "%x", &value);ret += ((char)value);}return ret;
}int _tmain(int argc, _TCHAR* argv[])
{const char* str="shenxuebing hello wordl!沈雪冰**--(1995.5.19)*)(&*%@‘;。《》";int ret=-1;cout<<"------------------------------MD5-----------------------------"<<endl;writeFile("MD5.txt",md5(str));cout<<md5(str)<<endl;cout<<"------------------------------SHA1-----------------------------"<<endl;writeFile("SHA1.txt",sha1(str));cout<<sha1(str)<<endl;cout<<"------------------------------SH256----------------------------"<<endl;writeFile("SHA256.txt",sha256(str));cout<<sha256(str)<<endl;cout<<"------------------------------DES_ECB加密----------------------------"<<endl;string desKey="123456";string enstr=des_encrypt(string(str),desKey);writeFile("DES_ECB_en.txt",enstr);//readFile("DES_ECB.txt");cout<<"------------------------------DES_ECB解密----------------------------"<<endl;string destr=des_decrypt(enstr,"123456");writeFile("DES_ECB_de.txt",destr);cout<<"------------------------------生成密钥对----------------------------";ret=generateRSAkey();cout<<getMsg(ret)<<endl;cout<<"------------------------------公钥加密----------------------------";string pubKey;pubKey=readFile("pubkey.pem");cout<<getMsg(rsa_pub_encrypt(str,pubKey))<<endl;cout<<"------------------------------私钥解密----------------------------";string priKey=readFile("prikey.pem");string rsa_en_16=readFile("rsa_en_16.txt");ret=rsa_pri_decrypt(rsa_en_16,priKey);cout<<getMsg(ret)<<endl;system("pause");return 0;
}
OpenSSL C++简单应用相关推荐
- Linux OPENSSL的简单用法
使用OPENSSL可以加密用户数据 openssl paswd 可以加密用户的密码 -1代表使用MD5的加密方式 -salt指定随机数 虽然这个随机数是静态指定的. 生成随机数 输出内容中两个等号是b ...
- 基于openEuler的OpenSSL编译安装和编程基础
文章目录 基于openEuler的OpenSSL编译安装和编程基础 OpenSSL编译安装 OpenSSL命令的使用 OpenSSL编程 简单测试 BASE64算法 作业 参考资料 基于openEul ...
- HTTPS通信的C++实现
HTTPS是以安全为目标的HTTP通道,简单讲是HTTP的安全版.即HTTP下加入SSL层,HTTPS的安全基础是SSL,因此加密的详细内容就需要SSL.Nebula是一个为开发者提供一个快速开发高并 ...
- php composer 安装,composer安装的方法步骤(图文)
composer的安装 注:我是的PHPstudy下安装的,其他情况也相似 一.配置环境变量 1.打开系统高级设置,具体操作如下图: 路径就是php根目录 2.打开openssl 注:phpstudy ...
- error: invalid application of 'sizeof' to an incomplete type 'JNINativeMethod []'
android studio比较奇葩得把new char[100]{"fff"}这样的直接写成字面值常量 而window 的jni则必须使用这种 -- 尴尬 然后发现2个jni文件 ...
- OPENSSL-CA
一.OpenSSL简单介绍 OpenSSL 是一个强大的安全套接字层密码库,囊括主要的密码算法.常用的密钥和证书封装管理功能及SSL协议,并提供丰富的应用程序供测试或其它目的使用. SSL是Secur ...
- ACE 安装指南及示例
The ADAPTIVE Communication Environment (ACE) 是一套免费的.开源的面向对象框架,它为大规模并发通信软件实现了许多核心的设计模式.ACE提供了一套丰富的.可重 ...
- vc8+ACE5.5 安装心得
网上的一些文章对于ACE的安装很详细,但也很千篇一律.实践中你会遇到很多问题,但网上解决办法比较少.为此写了这篇文章,分享之. 由于VC6.0对c++标准支持的不好,所以编译ACE,虽然不会报错,但编 ...
- RTMP推流及协议学习
前期准备 了解RTMP定义 准备RTMPDump中的librtmp 使用openssl中的libssllibcrypto 推流工作 整体框架图 使用libtrmp提供的API 将streaming封装 ...
最新文章
- 计算机网络协议教案,计算机网络实验教案(6)网络协议分析-IP协议3.pdf
- 如何用视觉的方法量身高?
- 49.检测对象是否为原始对象
- Android学习--持久化(三) SQLite LitePal
- Python之区块链入门,揭秘比特币
- linux设备和驱动注册,Linux驱动第五篇-----驱动注册和生成设备节点
- Linux Kernel Oops异常分析
- Linux CPU 信息查看
- 公司为什么宁愿花11K月薪招新人,也不愿意花9K的月薪留住老员工?
- snownlp文本分词、情感分析、文本相似度与摘要生成
- php算法求出一个数可以被分解成多少个_程序员的算法趣题
- 10G家庭光纤网络如何部署?
- 查看思科交换机出厂时间
- es拼音分词 大帅哥_elasticsearch实现中文分词和拼音分词混合查询+CompletionSuggestion...
- 视频如何做成gif动图?
- Nmap常用扫描命令
- 数据库的升序降序排列
- 漫步数理统计三十——依概率收敛
- vue 多页面应用搭建
- js判断身份证号码是否正确