c++使用openssl静态库 实现rsa 私钥加密 公钥解密

本文是在windows环境下,使用的是vs2019编译器。

下面是使用openssl静态库中的函数 实现的一个RSA加密字符串以及加密文件。

下面展示一些 本人实现代码

#pragma warning(disable:4996)
#include
#include 
#include 
#include 
#include 
#include 
#include 
// 私钥加密
#pragma comment(lib,"Iphlpapi.lib")
#pragma comment(lib,"libcrypto.lib")
#pragma comment(lib,"libssl.lib")

// ---- rsa非对称加解密 ---- //    
#define KEY_LENGTH  1024               // 密钥长度  
#define PUB_KEY_FILE "pubkey.pem"    // 公钥路径  
#define PRI_KEY_FILE "prikey.pem"    // 私钥路径  

// 函数方法生成密钥对   
void generateRSAKey(std::string strKey[])
{
    // 公私密钥对    
    size_t pri_len;
    size_t pub_len;
    char* pri_key = NULL;
    char* pub_key = NULL;

    // 生成密钥对    
    RSA* keypair = RSA_generate_key(KEY_LENGTH, RSA_F4, 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);
}

// 私钥加密
std::string rsa_pri_encrypt(const std::string& clearText, std::string& priKey)
{
    std::string strRet;
    BIO* keybio = BIO_new_mem_buf((const char*)priKey.c_str(), strlen(priKey.c_str()));
    // 此处有三种方法  
    // 1, 读取内存里生成的密钥对,再从内存生成rsa  
    // 2, 读取磁盘里生成的密钥对文本文件,在从内存生成rsa  
    // 3,直接从读取文件指针生成rsa  
    //RSA* pRSAPublicKey = RSA_new();  
    RSA* rsa = RSA_new();
    rsa = PEM_read_bio_RSAPrivateKey(keybio, &rsa, NULL, NULL);      // rsa = PEM_read_bio_RSAPublicKey(keybio, &rsa, NULL, NULL);如果要用公钥加密,函数要变化。
    if (!rsa)
    {
        BIO_free_all(keybio);
        return std::string("PEM_read_bio_RSAPrivateKey 错误");
    }

    int len = RSA_size(rsa);
    //int len = 1028;
    char* encryptedText = (char*)malloc(len + 1);
    memset(encryptedText, 0, len + 1);

    // 加密  
    int ret = RSA_private_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_pub_decrypt(const std::string& clearText, std::string& pubKey)
{
    std::string strRet;
    BIO* keybio = BIO_new_mem_buf((unsigned char*)pubKey.c_str(), -1);
    //keybio = BIO_new_mem_buf((unsigned char *)strPublicKey.c_str(), -1);  
    // 此处有三种方法  
    // 1, 读取内存里生成的密钥对,再从内存生成rsa  
    // 2, 读取磁盘里生成的密钥对文本文件,在从内存生成rsa  
    // 3,直接从读取文件指针生成rsa  
    //RSA* pRSAPublicKey = RSA_new();  
    RSA* rsa = RSA_new();
    rsa = PEM_read_bio_RSAPublicKey(keybio, &rsa, NULL, NULL); // rsa = PEM_read_bio_RSAPrivateKey(keybio, &rsa, NULL, NULL);如果要私钥解密,函数要变化。
    if (!rsa)
    {
        BIO_free_all(keybio);
        return std::string("");
    }

    int len = RSA_size(rsa);
    //int len = 1028;
    char* encryptedText = (char*)malloc(len + 1);
    memset(encryptedText, 0, len + 1);

    //解密
    int ret = RSA_public_decrypt(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_split117_encrypt(const std::string& clearText, std::string& priKey)
{
    std::string result;
    std::string input;
    result.clear();
    for (int i = 0; i < clearText.length() / 117; i++)
    {
        input.clear();
        input.assign(clearText.begin() + i * 117, clearText.begin() + i * 117 + 117);
        result = result + rsa_pri_encrypt(input, priKey);
    }
    if (clearText.length() % 117 != 0)
    {
        int tem1 = clearText.length() / 117 * 117;
        int tem2 = clearText.length() - tem1;
        input.clear();
        input.assign(clearText.begin() + tem1, clearText.end());
        result = result + rsa_pri_encrypt(input, priKey);
    }
    return result;
}


//公钥解密 + 分片
std::string rsa_pub_split128_decrypt(const std::string& clearText, std::string& pubKey)
{
    //Base64 *base = new Base64();
    std::string result;
    std::string input;
    result.clear();
    for (int i = 0; i < clearText.length() / 128; i++)
    {
        input.clear();
        input.assign(clearText.begin() + i * 128, clearText.begin() + i * 128 + 128);

        result = result + rsa_pub_decrypt(input, pubKey);
    }
    if (clearText.length() % 128 != 0)
    {
        int tem1 = clearText.length() / 128 * 128;
        int tem2 = clearText.length() - tem1;
        input.clear();
        input.assign(clearText.begin() + tem1, clearText.end());
        result = result + rsa_pri_encrypt(input, pubKey);
    }
    return result;
}


CHAR* OpenFile()
{
    CHAR* pBuffer;
    DWORD RSize;
    int fileSize = 0;
    HANDLE hOpenFile = (HANDLE)CreateFile(L"D:\\a.txt", GENERIC_WRITE | GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, NULL, NULL);
    if (hOpenFile == INVALID_HANDLE_VALUE)
    {
        hOpenFile = NULL;
        MessageBoxA(NULL, "Can not open the file", "Playwav", MB_OK);
        exit(1);
    }
    fileSize = GetFileSize(hOpenFile, NULL);
    pBuffer = (CHAR*)malloc(fileSize);
    ReadFile(hOpenFile, pBuffer, fileSize, &RSize, NULL);
    //可将pBuffer显示在某区域或写入另一个文件来检查读出是否正确

    FlushFileBuffers(hOpenFile);
    CloseHandle(hOpenFile);
    return pBuffer;
}

int main()
{
    std::string strKey[] = {"1", "2"};
    generateRSAKey(strKey);

    std::string clearText = "aasdsadsadasd";

    char* puffer = OpenFile();
    std::string strRet = rsa_pri_split117_encrypt(puffer, strKey[1]);
    std::cout << "加密后:" << strRet << std::endl;

    std::string rRet = rsa_pub_split128_decrypt(strRet, strKey[0]);
    std::cout << "解密后:" << rRet << std::endl;

    system("pause");
    return 0;
}

如果编译时发现出现链接错误,需要在属性中的附加库目录加上 ws2_32.lib、crypt32.lib这两个库。

本文部分代码来自以下链接,如果需要详细了解 可以点连接。https://www.cnblogs.com/azbane/p/10180464.html

感谢大家观看 同时如果发现问题 希望指出 大家一起进步

你可能感兴趣的:(c++,windows,openssl,c++,windows)