生成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