OpenSSL - RSA非对称加密实现

非对称加密:即两端使用一对不同的密钥进行加密。 在非对称加密中,需要两对密钥,公钥和私钥。 公钥个私钥属于对立关系,一把加密后,只有另一把才可以进行解密。

  • 公钥数据加密

数字证书内包含了公钥,在进行会话连接时,双方交换各自的公钥,保留自己的私钥。进行数据传输时,利用对方的公钥进行数据加密。加密后的数据只有对方的私钥才能进行解密。

  • 私钥数字签名

私钥进行数据加密,所有人用公钥都能解密数据,但是加密后的数据却唯有私钥能生成。可以用于消息来源验证。将数据用私钥加密并明文告诉用户密文内容,用户进行公钥解密比较确认数据来源可靠。

在非对称加密算法中有RSA、Elgamal、背包算法、Rabin、D-H、ECC(椭圆曲线加密算法)等。 其中RSA加密最为广泛利用,毫不夸张地说,只要有计算机网络的地方,就有RSA算法。 其原理为数论中一个公认的定论:两个大素数相乘非常容易,但是这个数要分解成二个质数的积,非常困难。 根据已经披露的文献,目前被破解的最长RSA密钥是768个二进制位。也就是说,长度超过768位的密钥,还无法破解(至少没人公开宣布)。因此可以认为,1024位的RSA密钥基本安全,2048位的密钥极其安全。

具体RSA加密算法在计算机网络中的运用方式和原理可以查看:OpenSSL - 网络安全之数据加密和数字证书 如何利用openssl命令行来生成证书和密钥可查看:OpenSSL - 利用OpenSSL自签证书和CA颁发证书

在使用OpenSSL进行RSA加密算法时,流程与上述理论流程保持一致。

  • 生成密钥或读取密钥
  • 根据需要选择签名还是加密
  • 使用公钥进行数据加密
  • 使用私钥进行数字签名
  • 数据通过网络进行安全传输
  • 对端进行解密获取明文

下面是OpenSSL的RSA加密算法对数据进行加密解密过程实现:

#include <iostream>
#include <fstream>
#include <openssl/bn.h>
#include <openssl/rsa.h>
#include <openssl/pem.h>

#define DATA_BUFF_LENTH 1024
#define RSA_BIT 1024

using namespace std;

class File
{
public:
    File(string strFilePath):m_strFilePath(strFilePath){};
    ~File(){};
    bool open(_Ios_Openmode opreator);
    void close();
    void read(char* buff,int length);
private:
    fstream m_file;
    string m_strFilePath;
};

bool File::open(_Ios_Openmode opreator)
{
    m_file.open(m_strFilePath.c_str(),opreator);
    if (m_file.fail())   //打开失败
    {
        cout<<"open file failure!"<<endl;
        return false;    
    } 
    return true;
}

void File::close()
{
    m_file.close();
}

void File::read(char* buff,int length)
{
    m_file.read(buff,length);
}

class RSAKey
{
public:
    RSAKey(int rsabit,int bignum);
    ~RSAKey();
    void UsePrivateRSAKeyDecode(char* dsc,char* src);   //加密解密操作
    void UsePublicRSAKeyEncode(char* dsc,char* src);
    void printPublicKey();  //打印秘钥操作
    void printPrivateKey();
    void exportPrivateKey(string fileName); //导出秘钥操作
    void exportPublicKey(string fileName);
    /*
    We can also output the key into an encrypted PEM file.

    And the APIs is easy to use.

    PEM_write_bio_RSAPrivateKey

    PEM_write_bio_RSAPublicKey

    PEM_read_bio_RSAPrivateKey

    PEM_read_bio_RSAPublicKey
    */
    void importPrivateKey(string fileName); //导入秘钥操作,也可利用上述API通过证书导入秘钥,证书命令行生成和颁发签证
    void importPublicKey(string fileName);
private:
    BIGNUM* m_bigNum;
    RSA* m_rsa;
    int m_rsa_bit;
    RSA* m_pubKey;
    RSA* m_privateKey;
};

RSAKey::RSAKey(int rsabit,int bignum)
{
    m_rsa_bit = rsabit;
    m_rsa = RSA_new();
    m_pubKey = RSA_new();
    m_privateKey = RSA_new();
    m_bigNum = BN_new();
    BN_set_word(m_bigNum,bignum);   //设置大数
    RSA_generate_key_ex(m_rsa,m_rsa_bit,m_bigNum,NULL); //生成密钥
}

RSAKey::~RSAKey()
{
    RSA_free(m_rsa);
    RSA_free(m_pubKey);
    RSA_free(m_privateKey);
    BN_free(m_bigNum);    
}

void RSAKey::UsePrivateRSAKeyDecode(char* dsc,char* src)
{
    int rsa_len = RSA_size(m_privateKey);
    RSA_private_decrypt(rsa_len,(unsigned char *)src,(unsigned char*)dsc,m_privateKey,RSA_NO_PADDING);
}

void RSAKey::UsePublicRSAKeyEncode(char* dsc,char* src)
{
    int rsa_len = RSA_size(m_pubKey);
    RSA_public_encrypt(rsa_len, (unsigned char *)src,(unsigned char*)dsc,m_pubKey, RSA_NO_PADDING);
}

void RSAKey::printPublicKey()
{
    RSA_print_fp(stdout,m_pubKey,11);
}

void RSAKey::printPrivateKey()
{
    RSA_print_fp(stdout,m_privateKey,11);
}

void RSAKey::exportPrivateKey(string fileName)
{
    FILE *ifile;
    ifile = fopen(fileName.c_str(),"w");
    PEM_write_RSAPrivateKey(ifile,m_rsa, NULL, NULL, 0, NULL, NULL);
    fclose(ifile);
}

void RSAKey::exportPublicKey(string fileName)
{
    FILE *ifile;
    ifile = fopen(fileName.c_str(),"w");
    PEM_write_RSAPublicKey(ifile,m_rsa);
    fclose(ifile);
}

void RSAKey::importPrivateKey(string fileName)
{
    FILE *ifile;
    ifile = fopen(fileName.c_str(),"r");
    m_privateKey = PEM_read_RSAPrivateKey(ifile, NULL, NULL, NULL);
}

void RSAKey::importPublicKey(string fileName)
{
    FILE *ifile;
    ifile = fopen(fileName.c_str(),"r");
    m_pubKey = PEM_read_RSAPublicKey(ifile,NULL,NULL,NULL);
}

int main(int arc,char *arv[])
{
    RSAKey rsa(RSA_BIT,RSA_F4);
    rsa.exportPrivateKey("private.key");    // 导出密钥
    rsa.exportPublicKey("public.key");

    string strFilePath = arv[1];
    File ifile(strFilePath.c_str());
    ifile.open(ios::in);

    char DataBuff[DATA_BUFF_LENTH];
    ifile.read(DataBuff,DATA_BUFF_LENTH);   //读文件内容
    ifile.close();

    rsa.importPublicKey("public.key");  //导入公钥
    rsa.importPrivateKey("private.key");    //导入秘钥
    
    rsa.printPrivateKey();  //打印秘钥信息
    rsa.printPublicKey();   //打印公钥信息

    cout<<"-----------------------------------"<<endl;
    cout<<"source :"<<DataBuff<<endl;   //源数据
    cout<<"-----------------------------------"<<endl;
    
    char enData[DATA_BUFF_LENTH];
    rsa.UsePublicRSAKeyEncode(enData,DataBuff);
    cout<<"-----------------------------------"<<endl;
    cout<<"encode :"<<enData<<endl;     //加密数据
    cout<<"-----------------------------------"<<endl;
    
    char deData[DATA_BUFF_LENTH];
    rsa.UsePrivateRSAKeyDecode(deData,enData);
    cout<<"-----------------------------------"<<endl;
    cout<<"decode :"<<deData<<endl;     //解密数据
    cout<<"-----------------------------------"<<endl;

    return 0;
}

scons编译脚本如下:

Program('pubkey','rsa_genkey.cpp',LIBS = ['ssl','crypto'])

执行可执行文件,输入文件路径,即可查看到经过RSA加密后的数据内容和解密后的内容。 从证书中提取公钥加密与上述代码类似,替换相应API即可。

tips:本来把这篇OpenSSL的RSA加密算法和代码写好点的,但是由于最近时间越来越紧张。后续有机会在扩充吧。代码部分很多地方没有做异常判段和处理,只是保证了正常功能。 由于后面参与公司新的后台服务器架构开发,将会使用到RabbitMQ中间件,后续将不定期慢速更新RabbitMQ及后台架构设计相关博客,欢迎关注!

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏区块链

什么是证书链?

证书链是由两个环节组成—信任锚(CA 证书)环节和已签名证书环节。即由 CA 证书发出的证书序列,最终以根 CA 证书结束。 证书链可以有任意环节的长度,所以在...

6569
来自专栏喵了个咪的博客空间

[Golang软件推荐] RSA公私钥加解密(解决Golang私钥加密公钥解密问题)

安全是软件开始中很重要的一个环节,在金融场景以及设计资产的场景下更是如此,在加密算法中主要使用较多加密方式分别是对称加密和非对称加密,对称加密中的代表是AES,...

6934
来自专栏Android互联网技术开发

应用加密一;非对称加密算法揭秘

  RSA、Elgamal、背包算法、Rabin、D-H、ECC(椭圆曲线加密算法)

1762
来自专栏北京马哥教育

5大导致"SSL证书不被信任"的原因

前言 今天在这里主要总结一下使用SSL的过程中遇到的坑(注意事项)。SSL是什么东西?(请自行搜索) 我(叫龙君)接触SSL证书已经4年了,算上今年,最开始我认...

54110
来自专栏互联网大杂烩

对称加密和非对称加密

对称密钥是双方使用相同的密钥 。 对称加密的要求   (1)需要强大的加密算法。算法至少应该满足:即使分析人员知道了算法并能访问一些或者更多的密文,也不能译...

1323
来自专栏技术碎碎念

HTTPS握手

作用 内容加密 建立一个信息安全通道,来保证数据传输的安全; 身份认证 确认网站的真实性 数据完整性 防止内容被第三方冒充或者篡改 https的采用了对称加密和...

3477
来自专栏木可大大

Web安全概述

互联网刚开始是安全的,但是伴随着黑客(Hacker)的诞生,互联网变得越来越不安全。任何一个事情都有两面性,黑客也有好有坏,好的黑客叫白帽子,坏的黑客叫黑帽子。...

49413
来自专栏Rgc

前端js,后台python实现RSA非对称加密

先熟悉使用 在后台使用RSA实现秘钥生产,加密,解密;   # -*- encoding:utf-8 -*- import base64 from C...

7526
来自专栏安智客

五分钟掌握PKI核心原理!

公开密钥基础设施( PKI, Public Key Infrastructure )逐步在国内外得到广泛应用。我们是否真的需要 PKI , PKI 究竟有什么用...

37310
来自专栏Python小屋

Python使用RSA+MD5实现数字签名

数字签名主要有防抵赖和防篡改两种功能:一是能确定消息确实是由发送方签名并发出来的,因为别人假冒不了发送方的签名,二是能确定消息的完整性。 作为具体实现,发送报文...

5029

扫码关注云+社区

领取腾讯云代金券