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.直接从读取文件指针生成rsa
    RSA *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.直接从读取文件指针生成rsa
    rsa=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);
    }
    else
        return 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 10000000
    for (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]=""; //存放每个字符 8bit
    int kk=0; //记录字符串的数量
    for(int i=0;i<inDataLen;i=i+8)
    {
        int l=0;
        strncpy(TwoStr,(const char*)inData+i,8);//把每一个字符的8bit 复制给outData
        for(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;
}

  • 0
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
在C++中,可以使用OpenSSL库进行加密、解密、哈希和SSL/TLS等操作。以下是一个简单的示例代码,展示了如何使用OpenSSL库进行SHA-256哈希计算: ```cpp #include <iostream> #include <openssl/sha.h> #include <iomanip> std::string sha256(const std::string& input) { unsigned char hash[SHA256_DIGEST_LENGTH]; SHA256_CTX sha256; SHA256_Init(&sha256); SHA256_Update(&sha256, input.c_str(), input.length()); SHA256_Final(hash, &sha256); std::stringstream ss; for (int i = 0; i < SHA256_DIGEST_LENGTH; i++) { ss << std::hex << std::setw(2) << std::setfill('0') << (int)hash[i]; } return ss.str(); } int main() { std::string input = "Hello, World!"; std::string hash = sha256(input); std::cout << "Input: " << input << std::endl; std::cout << "SHA-256 Hash: " << hash << std::endl; return 0; } ``` 在上述示例中,我们使用了OpenSSL的SHA-256哈希函数来计算输入字符串的哈希值。首先,我们定义了一个名为sha256的函数,它接受一个输入字符串,使用SHA256_Init函数初始化SHA-256上下文,然后使用SHA256_Update函数更新上下文,并使用SHA256_Final函数获取最终的哈希值。最后,我们将哈希值转换为十六进制字符串,并返回结果。 请确保你已经安装了OpenSSL库,并在编译时链接到相应的库文件。编译命令可能类似于: ``` g++ yourfile.cpp -lcrypto ``` 请注意,只是一个基本的示例,实际应用中可能需要更多的错误处理和输入验证。同时,OpenSSL库还提供了许多其他的加密和安全功能,例如对称加密、非对称加密、数字签名等。你可以根据自己的需求选择适合的功能和函数来使用OpenSSL库。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

离水的鱼儿

一分也是爱

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值