• 基于 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));
    }
    `
  • 相关阅读:
    小米笔试(09-15)
    58同城笔试(09-14)
    Java中的static总结
    【Linux】常用代码
    【项目部署】上线
    入职一年高校的体会
    小团队管理总结
    从windows到Linux的再次转身,这次是硬件开发
    了解到雪花算法
    CCAI观后
  • 原文地址:https://www.cnblogs.com/algonote/p/15410898.html
Copyright © 2020-2023  润新知