加密算法

发布时间 2023-04-15 21:16:06作者: 夜雾
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <string.h>

#include <openssl/rsa.h>
#include <openssl/err.h>
#include <openssl/objects.h>

#pragma comment(lib,"libssl.lib")
#pragma comment(lib,"libcrypto.lib")

namespace dakuang {}

void printHex(const unsigned char* pBuf, int nLen)
{
    for (int i = 0; i < nLen; ++i)
    {
        printf("%02x", pBuf[i]);
    }
    printf("\n");
}


#include <iostream>
#include <memory>

struct Sample
{
    Sample() {
        std::cout << "Sample\n";
    }
    ~Sample() {
        std::cout << "~Sample\n";
    }
    int a{ 1 };
};

void deleter(Sample* x)
{
    std::cout << "Custom Deleter\n";
    delete[] x;
}


#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <string.h>

#include <openssl/rsa.h>
#include <openssl/err.h>
#include <openssl/x509.h>
#include <string.h>
#include <openssl/rsa.h>
#include <openssl/aes.h>


#include <cassert>  
#include <string>    
#include <vector>    
#include "openssl/md5.h"    
#include "openssl/sha.h"    
#include "openssl/des.h"    
#include "openssl/rsa.h"    
#include "openssl/pem.h"    
// ---- 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()
{
//    // 1. 产生RSA密钥对
//    // 产生512字节公钥指数为RSA_F4的密钥对,公钥指数有RSA_F4和RSA_3两种
//    // 我不清楚它们的区别,就随便选定RSA_F4
//    // 可以使用RSA_print_fp()看看RSA里面的东西
//    RSA* ClientRsa = RSA_generate_key(2048, RSA_F4, NULL, NULL);
//
//    // ---------
//    // 2. 从RSA结构中提取公钥到BUFF,以便将它传输给对方
//    // 512位的RSA其公钥提出出来长度是74字节,而私钥提取出来有超过300字节
//    // 为保险起见,建议给它们预留一个512字节的空间
//    unsigned char PublicKey[5120];
//    unsigned char* PKey = PublicKey; // 注意这个指针不是多余,是特意要这样做的,
//    int PublicKeyLen = i2d_RSAPublicKey(ClientRsa, &PKey);
//
//    // 不能采用下面的方法,因为i2d_RSAPublicKey()会修改PublicKey的值
//    // 所以要引入PKey,让它作为替死鬼
//    // unsigned char *PublicKey = (unsigned char *)malloc(512);
//    // int PublicKeyLen = i2d_RSAPublicKey(ClientRsa, &PublicKey);
//
//    // 逐个字节打印PublicKey信息
//    printf("PublicKeyBuff, Len=%d\n", PublicKeyLen);
//    for (int i = 0; i < PublicKeyLen; i++)
//    {
//        printf("0x%02x, ", *(PublicKey + i));
//    }
//    printf("\n");
//
//
//    // ---------
//    // 3. 跟据上面提出的公钥信息PublicKey构造一个新RSA密钥(这个密钥结构只有公钥信息)
//    PKey = PublicKey;
//    RSA* EncryptRsa = d2i_RSAPublicKey(NULL, (const unsigned char**)&PKey, PublicKeyLen);
//
//    // ---------
//    // 4. 使用EncryptRsa加密数据,再使用ClientRsa解密数据
//    // 注意, RSA加密/解密的数据长度是有限制,例如512位的RSA就只能最多能加密解密64字节的数据
//    // 如果采用RSA_NO_PADDING加密方式,512位的RSA就只能加密长度等于64的数据
//    // 这个长度可以使用RSA_size()来获得
//    unsigned char InBuff[640], OutBuff[640];
//
//    strcpy((char*)InBuff, "1234567890abcdefghiklmnopqrstuvwxyz.\
//1234567890abcdefghiklmnopqrstuvwxyz.\
//1234567890abcdefghiklmnopqrstuvwxyz.\
//1234567890abcdefghiklmnopqrstuvwxyz.\
//1234567890abcdefghiklmnopqrstuvwxyz.\
//1234567890abcdefghiklmnopqrstuvwxyz.\
//1234567890abcdefghiklmnopqrstuvwxyz.\
//1234567890abcdefghiklmnopqrstuvwxyz.\
//1234567890abcdefghiklmnopqrstuvwxyz.\
//1234567890abcdefghiklmnopqrstuvwxyz.\
//1234567890abcdefghiklmnopqrstuvwxyz.\
//1234567890abcdefghiklmnopqrstuvwxyz.");
//    RSA_public_encrypt(640, (const unsigned char*)InBuff, OutBuff, EncryptRsa, RSA_NO_PADDING); // 加密
//
//    memset(InBuff, 0, sizeof(InBuff));
//    RSA_private_decrypt(640, (const unsigned char*)OutBuff, InBuff, ClientRsa, RSA_NO_PADDING); // 解密
//    printf("RSADecrypt OK: %s \n", InBuff);
//
//
//    //// ----------
//    //// 5. 利用随机32字节Seed来产生256位的AES密钥对
//    //unsigned char Seed[32]; // 可以采用Rand()等方法来构造随机信息
//    //AES_KEY AESEncryptKey, AESDecryptKey;
//    //AES_set_encrypt_key(Seed, 256, &AESEncryptKey);
//    //AES_set_decrypt_key(Seed, 256, &AESDecryptKey);
//
//    //// ----------
//    //// 6. 使用AES密钥对来加密/解密数据
//    //// 注意,256位的AES密钥只能加密/解密16字节长的数据
//    //strcpy((char*)InBuff, "a1b2c3d4e5f6g7h8?");
//    //AES_encrypt(InBuff, OutBuff, &AESEncryptKey);
//
//    //memset(InBuff, 0, sizeof(InBuff));
//    //AES_decrypt(OutBuff, InBuff, &AESDecryptKey);
//    //printf("AESDecrypt OK: %s \n", InBuff);
//
//
//    // ----------
//    // 7. 谨记要释放RSA结构
//    RSA_free(ClientRsa);
//    RSA_free(EncryptRsa);

    std::string encryptText;
    std::string encryptHexText;
    std::string decryptText;
    // 原始明文    
    std::string srcText = "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
      // rsa    
    std::cout << "=== rsa加解密 ===" << std::endl;
    std::string key[2];
    generateRSAKey(key);
    std::cout << "公钥: " << std::endl;
    std::cout << key[0] << std::endl;
    std::cout << key[0].length() << 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;

    return(0);
}