生成RSA密钥对


#include <openssl/rsa.h>
#include <openssl/pem.h>

/////////////////////////////////////////////////////////////// 加密解密
// 公钥加密
int RSA_public_encrypt(int flan,const unsigned char* from,unsigned char* to,RSA* rsa,int padding)
// 私钥加密
int RSA_private_decrypt(int flan,const unsigned char* from,unsigned char* to,RSA* rsa,int padding)
///////////////////////// 签名使用 //////////////////////
// 私钥加密
int RSA_private_encrypt(int flan,const unsigned char* from,unsigned char* to,RSA* rsa,int padding)
// 公钥解密
int RSA_public_decrypt(int flan,const unsigned char* from,unsigned char* to,RSA* rsa,int padding)

参数:
  - flen: 要加密/解密的数据长度 
      长度  0 < flen <= 密钥长度-11
  - from: 传入,要加密/解密的数据
  - to: 传出,存储数据,加密->存储密文, 解密->存储明文
  - rsa: 密钥:公钥/私钥
  - padding: 指定填充方案,数据填充,不需要使用做
    - RSA_PKCS1_PADDING -> 使用该方案会填充11字节
/////////////////////////////////////////////////////////////// 生成密钥对
// 创建bio对象
// 密钥对写磁盘文件的时候, 需要编码 -> base64
// 封装了fopen
BIO *BIO_new_file(const char *filename, const char *mode);
	参数:
		- filename: 文件名
		- mode: 文件打开方式和fopen打开方式的指定相同
		
int PEM_write_bio_RSAPublicKey(BIO* bp, const RSA* r);
int PEM_write_bio_RSAPrivateKey(BIO* bp, const RSA* r, const EVP_CIPHER* enc, 
	unsigned char* kstr, int klen, pem_password_cb *cb, void* u);
RSA* PEM_read_bio_RSAPublicKey(BIO* bp, RSA** r, pem_password_cb *cb, void* u);
RSA* PEM_read_bio_RSAPrivateKey(BIO* bp, RSA** r, pem_password_cb *cb, void* u);
	参数: 
		- bp: 通过BIO_new_file();函数得到该对象
		- r: 传递一个RSA* rsa指针的地址, 传出参数-> 公钥/私钥
		- cb: 回调函数, 用不到, 指定为NULL
		- u: 给回调传参, 用不到, 指定为NULL

// 释放资源
    BIO_free(bio);
///////////////////////////////////////////////////////////////
FILE* fd = fopen("xxxx.pem","w");
int PEM_write_RSAPublicKey(FILE* fp,const RSA* r);
int PEM_write_RSAPrivateKey(FILE* fp,const RSA* r,const EVP_CIPHER* enc,
  unsigned char* kstr,int klen,pem_password_cb* cb,void* u);
参数:
  - fp: 需要打开一个磁盘文件,并且指定写权限
  - r: 存储了密钥对
//////// - 私钥独有的参数
  - enc: 指定的加密算法 -> 堆成加密 -> NULL
  - kstr: 对称加密的密钥 -> NULL
  - klen: 密钥长度 -> 0
  - cb:回调函数,用不到,NULL
  - u: 给回调传参,用不到,NULL

/////////////////////////////////////////////////////////////// 从内存中读取
// 从内存中将参数rsa中的公钥提取出来
RSA* RSAPublicKey_dup(RSA* rsa);
// 从内存中将参数rsa中的私钥提取出来
RSA* RSAPrivateKey_dup(RSA* rsa);

签名

int RSA_sign(int type, const unsigned char *m, unsigned int m_length,
             unsigned char *sigret, unsigned int *siglen, RSA *rsa);
	参数:
		- type: 使用的哈希算法
			- NID_MD5
			- NID_SHA1
			- NID_SHA224
			- .....
        - m: 要进行签名的数据
        - m_length: 要签名的数据长度
        	- 0 < m_length <= 秘钥长度-11
        - sigret: 传出, 存储了签名之后的数据 -> 密文
        - siglen: sigret密文长度
        - rsa: 私钥
     返回值: 判断函数状态

int RSA_verify(int type, const unsigned char *m, unsigned int m_length,
               const unsigned char *sigbuf, unsigned int siglen, RSA *rsa);
	参数:
		- type: 使用的哈希算法, 和签名使用的哈希算法一致
			- NID_MD5
			- NID_SHA1
			- NID_SHA224
			- .....
        - m: 进行签名的原始数据 -> 接收到的
        - m_length: m参数字符串的长度
        - sigbuf: 接收到的签名数据
        - siglen: sigbuf接收到的签名数据的长度
        - rsa: 公钥
	返回值:
		如果!=1: 失败
		如果==1: 成功
		

代码演示

#include <iostream>
#include <openssl/rsa.h>
#include <openssl/pem.h>
#include <cstdio>

void generateRsaKey()
{
//  创建RSA变量
    RSA* rsa = RSA_new();
//  创建bignum对象并初始化
    BIGNUM* e = BN_new();
    BN_set_word(e,12345);
//  生成密钥对  -> 保存在内存中                                                                               
    RSA_generate_key_ex( rsa,1024,e,NULL );
//---------生成密钥对 1024代表密钥长度
//  RSA_F4为公钥指数,一般情况下使用RSA_F4即可,
//  RSA_generate_key( 1024,RSA_F4,NULL,NULL );
//  将密钥对写入到磁盘
#if 0
    FILE* fp = fopen("public.pem","w"); // 写公钥
    PEM_write_RSAPublicKey(fp,rsa);
    fclose(fp);
    fp = fopen("private.pem","w"); // 写私钥
    PEM_write_RSAPrivateKey(fp,rsa,NULL,NULL,0,NULL,NULL);
    fclose(fp);
#else
    BIO* bio = BIO_new_file("public-1.pem","w");
    PEM_write_bio_RSAPublicKey(bio,rsa);
    // 释放资源
    BIO_free(bio);
    bio = BIO_new_file("private-1.pem","w");
    PEM_write_bio_RSAPrivateKey(bio,rsa,NULL,NULL,0,NULL,NULL);
    // 释放资源
    BIO_free(bio);
#endif 
//  密钥对写入文件的时候,需要编码 -> base64
    
}
int main()
{
    generateRsaKey();
    return 0;
}

加解密函数

// 公钥加密
string  encryptPublicKey(){
    // 准备要加密的数据
    string test = "让编程改编世界";
    // 准备密钥 - > 公钥
    // 磁盘文件
    BIO* bio = BIO_new_file("public-1.pem","r");
    RSA* pubKey = RSA_new();
    if(  PEM_read_bio_RSAPublicKey(bio,&pubKey,NULL,NULL) == NULL )
    {
        cout<<"读密钥失败了..."<<endl;
        return 0;
    }
    BIO_free(bio);
    // 加密 -> 密文
    // 通过函数计算密钥长度
    int keyLen = RSA_size(pubKey);
    char* buf = new char[keyLen];
    // 返回值就是密文长度
    int len = RSA_public_encrypt(test.size(),(unsigned char*)test.data(),(unsigned char*)buf,pubKey,RSA_PKCS1_PADDING);
    // 将密文返回
    return string(buf,len);
    // 分发密钥
}
// 私钥解密
string decryptPrivateKey(string str){
    BIO* bio = BIO_new_file("private-1.pem","r");
    RSA* priKey = RSA_new();
    if( PEM_read_bio_RSAPrivateKey(bio,&priKey,NULL,NULL) == NULL )
    {
        cout<<"读取私钥失败..."<<endl;
        return string();
    }
    BIO_free(bio);
    int keyLen = RSA_size(priKey);
    char* buf = new char[keyLen];
    // 原始数据的长度
    int len = RSA_private_decrypt(str.size(),(const unsigned char*)str.data(),(unsigned char*)buf,priKey,RSA_PKCS1_PADDING);
    cout<<buf<<endl;
    return string(buf,len);
}
// 签名和验证签名
void rsaSigAndVerfiy()
{
    // 签名数据
    string str = "我叫小赵";
    // 密钥
    BIO* pubBio = BIO_new_file("public.pem","r");
    RSA* pubKey = RSA_new();
    if( PEM_read_bio_RSAPublicKey(pubBio,&pubKey,NULL,NULL) == NULL )
        cout<< "读取私钥失败..."<<endl;
    BIO_free(pubBio);

    BIO* priBio = BIO_new_file("private.pem","r");
    RSA* priKey = RSA_new();
    if( PEM_read_bio_RSAPrivateKey(priBio,&priKey,NULL,NULL) == NULL )
        cout<< "读取公钥失败..."<<endl;
    BIO_free(priBio);
    // 签名
    int len = RSA_size(priKey);
    unsigned char* out = new unsigned char[len];
    unsigned int outLen = 0;
    RSA_sign(NID_sha1,(const unsigned char*)str.data(),str.size(),out,&outLen,priKey);
    // 要给到用户的数据
    string sigbuf((char*)out,outLen);

    // 验证签名
    int ret = RSA_verify(NID_sha1,(const unsigned char*)str.data(),(unsigned int)str.size(),(const unsigned char*)sigbuf.data(),sigbuf.size(),pubKey);
    cout<< ret <<endl;
}


免责声明!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系本站邮箱yoyou2525@163.com删除。



 
粤ICP备18138465号  © 2018-2025 CODEPRJ.COM