• 基于 OpenSSL 的 RSA 消息加密及签名实现


    众所周知,知名项目 OpenSSL 是教科书式的屎山,代码耦合程度高达 99%,项目结构和文档都混乱不堪,自从接口封装成 EVP 之后就彻底放弃治疗了,只有命令行还算好用一点。

    当然其实也有更好的选择,比如简单强大的 mbedTLS(PolarSSL) 就深得我心,可惜学校课程要求使用 OpenSSL 完成作业,笔者也就只能硬糊了。

    下面是基于 OpenSSLRSA 消息加密及签名实现代码:

    • load_RSA_keys 用于加载 PEM 公钥及私钥

    • RSA_Encryption 用于 RSA 消息加密

    • RSA_Decryption 用于 RSA 消息解密

    • RSA_signature_signing 用于产生 RSA 消息签名

    • RSA_signature_verify 用于验证 RSA 消息签名

    #include <bits/stdc++.h>
    #include <openssl/bn.h>
    #include <openssl/pem.h>
    #include <openssl/rsa.h>
    #include <openssl/evp.h>
    
    #define PUBLICKEY "../keys/public.pem"
    #define PRIVATEKEY "../keys/private.pem"
    
    using namespace std;
    
    RSA* rsa_private_key = NULL;
    RSA* rsa_public_key = NULL;
    
    bool load_RSA_keys() {
        FILE *fp = NULL;
    
        if ((fp = fopen(PUBLICKEY,"r"))==NULL){
            printf("ERROR
    ");
            return 0;
        }
        PEM_read_RSA_PUBKEY(fp,&rsa_public_key,nullptr,nullptr);
        fclose(fp);
    
        if ((fp = fopen(PRIVATEKEY,"r"))==NULL){
            printf("ERROR
    ");
            return 0;
        }
        PEM_read_RSAPrivateKey(fp,&rsa_private_key,nullptr,nullptr);
        fclose(fp);
        return 1;
    }
    
    string RSA_Encryption(string plaintext)
    {
        load_RSA_keys();
    
        EVP_PKEY_CTX *ctx;
        unsigned char out[256];
        
        RSA_public_encrypt(plaintext.length(),(const unsigned char *)plaintext.c_str(),out,rsa_public_key,RSA_PKCS1_PADDING);
    
        unsigned char output[512];
        memset(output,0,sizeof(output));
        EVP_EncodeBlock((unsigned char *)output, (const unsigned char *)out, 256);
    
        return string((char *)output);
    }
    
    string RSA_Decryption(string ciphertext)
    {
        load_RSA_keys();
    
        unsigned char out[256];
        EVP_DecodeBlock(out, (const unsigned char *)ciphertext.c_str(), ciphertext.length());
    
        unsigned char output[256];
        memset(output,0,sizeof(output));
        RSA_private_decrypt(256,out,output,rsa_private_key,RSA_PKCS1_PADDING);
        return string((char *)output);
    }
    
    string RSA_signature_signing(string input)
    {
        load_RSA_keys();
        
        EVP_PKEY* priKey  = EVP_PKEY_new();
        EVP_PKEY_assign_RSA(priKey, rsa_private_key);
    
        EVP_MD_CTX *mdctx = NULL;
        size_t slen = 0;
        size_t blen = 0;
    
        unsigned char sig[256];
        mdctx = EVP_MD_CTX_create();
    
        EVP_DigestSignInit(mdctx, NULL, EVP_sha1(), NULL, priKey);
        EVP_DigestSignUpdate(mdctx, input.c_str(), input.length());
        EVP_DigestSignFinal(mdctx, NULL, &slen);
    
        OPENSSL_malloc(sizeof(unsigned char) * (slen));
        EVP_DigestSignFinal(mdctx, sig, &slen);
        EVP_MD_CTX_destroy(mdctx);
    
        unsigned char output[512];
        memset(output,0,sizeof(output));
        EVP_EncodeBlock((unsigned char *)output, (const unsigned char *)sig, 256);
    
        return string((char *)output);
        
    }
    
    bool RSA_signature_verify(string message, string signature)
    {
        load_RSA_keys();
        
        unsigned char out[256];
        EVP_DecodeBlock(out, (const unsigned char *)signature.c_str(), signature.length());
    
        EVP_PKEY* pubKey  = EVP_PKEY_new();
        EVP_PKEY_assign_RSA(pubKey, rsa_public_key);
        EVP_MD_CTX *mdctx = NULL;
    
        mdctx = EVP_MD_CTX_create();
        EVP_DigestVerifyInit(mdctx, NULL, EVP_sha1(), NULL, pubKey);
        EVP_DigestVerifyUpdate(mdctx, message.c_str(), message.length());
    
        bool ret = 0;
        if(1 == EVP_DigestVerifyFinal(mdctx, out, 256))
            ret = 1;
        EVP_MD_CTX_destroy(mdctx);
        return ret;
    }
    
    int main(){
        string c = RSA_Encryption(string("1234567890"));
        printf("c:%s
    ",c.c_str());
        string m = RSA_Decryption(c);
        printf("m:%s
    ",m.c_str());
        string s = RSA_signature_signing(string("1234567890"));
        printf("s:%s
    ",s.c_str());
        printf("v:%d
    ",RSA_signature_verify(string("1234567890"),s));
        printf("v:%d
    ",RSA_signature_verify(string("1234567899"),s));
    }
    `
  • 相关阅读:
    Screen print or copy
    <转>关于SQL Server数据库的若干注意事项
    sql server 链接到oracle库,读取对应信息
    LinkedServer链接服务器的使用
    序号生成一例
    新解:报表服务器数据库的版本格式无效,或无法读取。已找到的版本为“Unknown”,而所需的版本为“C.0.8.40”。
    GridView to Excel
    sql server临时表是否存在
    <转>SQL Server大表转为分区表实例
    <转> 人生十二个经典领悟
  • 原文地址:https://www.cnblogs.com/algonote/p/15410898.html
Copyright © 2020-2023  润新知