zl程序教程

您现在的位置是:首页 >  其它

当前栏目

OpenSSL中RSA常用函数使用举例

函数 常用 rsa OpenSSL 举例 使用
2023-09-14 09:07:10 时间

下面是测试用例代码:

  1. cryptotest.h:
#ifndef _CRYPTOTEST_H_
#define _CRYPTOTEST_H_
 
#include <string>
 
using namespace std;
 
typedef enum {
	GENERAL = 0,
	ECB,
	CBC,
	CFB,
	OFB,
	TRIPLE_ECB,
	TRIPLE_CBC
}CRYPTO_MODE;
 
string DES_Encrypt(const string cleartext, const string key, CRYPTO_MODE mode);
string DES_Decrypt(const string ciphertext, const string key, CRYPTO_MODE mode);
 
string RC4_Encrypt(const string cleartext, const string key);
string RC4_Decrypt(const string ciphertext, const string key);
 
string MD5_Digest(const string cleartext);
 
int GenerateRSAKey(string strKey[]);
//string RSA_Encrypt(string cleartext, string key);
//string RSA_Decrypt(string ciphertext, string key);
void RSA_test1(const string cleartext);
void RSA_test2(const string cleartext);
 
#endif //_CRYPTOTEST_H_
  1. rsatest.cpp:
#include "stdafx.h"
#include "cryptotest.h"
#include "openssl/err.h"
#include <iostream>
 
using namespace std;
 
#define KEY_LENGTH  2048
int padding = RSA_PKCS1_PADDING;
int encrypt_len = 0;
#define PUB_EXP     3
//#define PRINT_KEYS
//#define WRITE_TO_FILE
 
int GenerateRSAKey(string strKey[])
{
	size_t pri_len;          // Length of private key
	size_t pub_len;          // Length of public key
	char *pri_key = NULL;           // Private key
	char *pub_key = NULL;           // Public key
 
	RSA* keypair = RSA_generate_key(KEY_LENGTH, RSA_3, NULL, NULL);
 
	BIO *pri = BIO_new(BIO_s_mem());
	BIO *pub = BIO_new(BIO_s_mem());
 
	PEM_write_bio_RSAPrivateKey(pri, keypair, NULL, NULL, 0, NULL, NULL);
	PEM_write_bio_RSAPublicKey(pub, keypair);
 
	pri_len = BIO_pending(pri);
	pub_len = BIO_pending(pub);
 
	pri_key = new char[pri_len + 1];
	pub_key = new char[pub_len + 1];
 
	BIO_read(pri, pri_key, pri_len);
	BIO_read(pub, pub_key, pub_len);
 
	pri_key[pri_len] = '\0';
	pub_key[pub_len] = '\0';
 
	strKey[0] = pub_key;
	strKey[1] = pri_key;
 
	//printf("\n%s\n%s\n", pri_key, pub_key);
 
	RSA_free(keypair);
	BIO_free_all(pub);
	BIO_free_all(pri);
	delete [] pri_key;
	delete [] pub_key;
 
	return 0;
}
 
RSA* createRSA(unsigned char* key, int flag)
{
	RSA *rsa= NULL;
	BIO *keybio ;
	keybio = BIO_new_mem_buf(key, -1);
 
	if (keybio==NULL) {
		printf( "Failed to create key BIO");
		return 0;
	}
 
	if(flag)
		rsa = PEM_read_bio_RSA_PUBKEY(keybio, &rsa, NULL, NULL);
	else
		rsa = PEM_read_bio_RSAPrivateKey(keybio, &rsa, NULL, NULL);
 
	if(rsa == NULL)
		printf( "Failed to create RSA");
 
	return rsa;
}
 
int public_encrypt(unsigned char* data, int data_len, unsigned char* key, unsigned char* encrypted)
{
	RSA * rsa = createRSA(key, 1);
	int result = RSA_public_encrypt(data_len, data, encrypted, rsa, padding);
	return result;
}
 
int private_decrypt(unsigned char* enc_data, int data_len, unsigned char* key, unsigned char* decrypted)
{
	RSA * rsa = createRSA(key, 0);
	int  result = RSA_private_decrypt(data_len,enc_data,decrypted,rsa,padding);
	return result;
}
 
int private_encrypt(unsigned char* data, int data_len, unsigned char* key, unsigned char* encrypted)
{
	RSA * rsa = createRSA(key, 0);
	int result = RSA_private_encrypt(data_len, data, encrypted, rsa, padding);
	return result;
}
 
int public_decrypt(unsigned char* enc_data, int data_len, unsigned char* key, unsigned char* decrypted)
{
	RSA * rsa = createRSA(key, 1);
	int  result = RSA_public_decrypt(data_len, enc_data, decrypted, rsa, padding);
	return result;
}
 
void printLastError(char *msg)
{
	char * err = (char*)malloc(130);;
	ERR_load_crypto_strings();
	ERR_error_string(ERR_get_error(), err);
	printf("%s ERROR: %s\n", msg, err);
	free(err);
}
 
void RSA_test1(const string cleartext)
{
	//char plainText[2048/8] = "Hello this is Ravi"; //key length : 2048
	string plainText = cleartext;
 
	//下面的公钥和私钥是通过命令行方式获取的
	//char publicKey[]="-----BEGIN PUBLIC KEY-----\n"
	string publicKey = "-----BEGIN PUBLIC KEY-----\n" \
		"MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAy8Dbv8prpJ/0kKhlGeJY\n" \
		"ozo2t60EG8L0561g13R29LvMR5hyvGZlGJpmn65+A4xHXInJYiPuKzrKUnApeLZ+\n" \
		"vw1HocOAZtWK0z3r26uA8kQYOKX9Qt/DbCdvsF9wF8gRK0ptx9M6R13NvBxvVQAp\n" \
		"fc9jB9nTzphOgM4JiEYvlV8FLhg9yZovMYd6Wwf3aoXK891VQxTr/kQYoq1Yp+68\n" \
		"i6T4nNq7NWC+UNVjQHxNQMQMzU6lWCX8zyg3yH88OAQkUXIXKfQ+NkvYQ1cxaMoV\n" \
		"PpY72+eVthKzpMeyHkBn7ciumk5qgLTEJAfWZpe4f4eFZj/Rc8Y8Jj2IS5kVPjUy\n" \
		"wQIDAQAB\n" \
		"-----END PUBLIC KEY-----\n";
 
	//char privateKey[]="-----BEGIN RSA PRIVATE KEY-----\n"
	string privateKey = "-----BEGIN RSA PRIVATE KEY-----\n"\
		"MIIEowIBAAKCAQEAy8Dbv8prpJ/0kKhlGeJYozo2t60EG8L0561g13R29LvMR5hy\n"\
		"vGZlGJpmn65+A4xHXInJYiPuKzrKUnApeLZ+vw1HocOAZtWK0z3r26uA8kQYOKX9\n"\
		"Qt/DbCdvsF9wF8gRK0ptx9M6R13NvBxvVQApfc9jB9nTzphOgM4JiEYvlV8FLhg9\n"\
		"yZovMYd6Wwf3aoXK891VQxTr/kQYoq1Yp+68i6T4nNq7NWC+UNVjQHxNQMQMzU6l\n"\
		"WCX8zyg3yH88OAQkUXIXKfQ+NkvYQ1cxaMoVPpY72+eVthKzpMeyHkBn7ciumk5q\n"\
		"gLTEJAfWZpe4f4eFZj/Rc8Y8Jj2IS5kVPjUywQIDAQABAoIBADhg1u1Mv1hAAlX8\n"\
		"omz1Gn2f4AAW2aos2cM5UDCNw1SYmj+9SRIkaxjRsE/C4o9sw1oxrg1/z6kajV0e\n"\
		"N/t008FdlVKHXAIYWF93JMoVvIpMmT8jft6AN/y3NMpivgt2inmmEJZYNioFJKZG\n"\
		"X+/vKYvsVISZm2fw8NfnKvAQK55yu+GRWBZGOeS9K+LbYvOwcrjKhHz66m4bedKd\n"\
		"gVAix6NE5iwmjNXktSQlJMCjbtdNXg/xo1/G4kG2p/MO1HLcKfe1N5FgBiXj3Qjl\n"\
		"vgvjJZkh1as2KTgaPOBqZaP03738VnYg23ISyvfT/teArVGtxrmFP7939EvJFKpF\n"\
		"1wTxuDkCgYEA7t0DR37zt+dEJy+5vm7zSmN97VenwQJFWMiulkHGa0yU3lLasxxu\n"\
		"m0oUtndIjenIvSx6t3Y+agK2F3EPbb0AZ5wZ1p1IXs4vktgeQwSSBdqcM8LZFDvZ\n"\
		"uPboQnJoRdIkd62XnP5ekIEIBAfOp8v2wFpSfE7nNH2u4CpAXNSF9HsCgYEA2l8D\n"\
		"JrDE5m9Kkn+J4l+AdGfeBL1igPF3DnuPoV67BpgiaAgI4h25UJzXiDKKoa706S0D\n"\
		"4XB74zOLX11MaGPMIdhlG+SgeQfNoC5lE4ZWXNyESJH1SVgRGT9nBC2vtL6bxCVV\n"\
		"WBkTeC5D6c/QXcai6yw6OYyNNdp0uznKURe1xvMCgYBVYYcEjWqMuAvyferFGV+5\n"\
		"nWqr5gM+yJMFM2bEqupD/HHSLoeiMm2O8KIKvwSeRYzNohKTdZ7FwgZYxr8fGMoG\n"\
		"PxQ1VK9DxCvZL4tRpVaU5Rmknud9hg9DQG6xIbgIDR+f79sb8QjYWmcFGc1SyWOA\n"\
		"SkjlykZ2yt4xnqi3BfiD9QKBgGqLgRYXmXp1QoVIBRaWUi55nzHg1XbkWZqPXvz1\n"\
		"I3uMLv1jLjJlHk3euKqTPmC05HoApKwSHeA0/gOBmg404xyAYJTDcCidTg6hlF96\n"\
		"ZBja3xApZuxqM62F6dV4FQqzFX0WWhWp5n301N33r0qR6FumMKJzmVJ1TA8tmzEF\n"\
		"yINRAoGBAJqioYs8rK6eXzA8ywYLjqTLu/yQSLBn/4ta36K8DyCoLNlNxSuox+A5\n"\
		"w6z2vEfRVQDq4Hm4vBzjdi3QfYLNkTiTqLcvgWZ+eX44ogXtdTDO7c+GeMKWz4XX\n"\
		"uJSUVL5+CVjKLjZEJ6Qc2WZLl94xSwL71E41H4YciVnSCQxVc4Jw\n"\
		"-----END RSA PRIVATE KEY-----\n";
 
	unsigned char  encrypted[4098] = {};
	unsigned char decrypted[4098] = {};
 
	//int encrypted_length= public_encrypt((unsigned char*)plainText,strlen(plainText),(unsigned char*)publicKey,encrypted);
	int encrypted_length= public_encrypt((unsigned char*)plainText.c_str(), plainText.length(), (unsigned char*)publicKey.c_str(), encrypted);
	if (encrypted_length == -1) {
		printLastError("Public Encrypt failed ");
		exit(0);
	}
	printf("Encrypted length =%d\n", encrypted_length);
 
	int decrypted_length = private_decrypt(encrypted, encrypted_length, (unsigned char*)privateKey.c_str(), decrypted);
	if (decrypted_length == -1) {
		printLastError("Private Decrypt failed ");
		exit(0);
	}
	printf("Decrypted Text =%s\n", decrypted);
	printf("Decrypted Length =%d\n", decrypted_length);
 
	encrypted_length= private_encrypt((unsigned char*)plainText.c_str(), plainText.length(),(unsigned char*)privateKey.c_str(), encrypted);
	if(encrypted_length == -1) {
		printLastError("Private Encrypt failed");
		exit(0);
	}
	printf("Encrypted length =%d\n", encrypted_length);
 
	decrypted_length = public_decrypt(encrypted, encrypted_length, (unsigned char*)publicKey.c_str(), decrypted);
	if(decrypted_length == -1) {
		printLastError("Public Decrypt failed");
		exit(0);
	}
	printf("Decrypted Text =%s\n", decrypted);
	printf("Decrypted Length =%d\n", decrypted_length);
}
 
void RSA_test2(const string cleartext)
{
	size_t pri_len;            // Length of private key
	size_t pub_len;            // Length of public key
	char   *pri_key;           // Private key
	char   *pub_key;           // Public key
	char   msg[KEY_LENGTH/8];  // Message to encrypt
	char   *encrypt = NULL;    // Encrypted message
	char   *decrypt = NULL;    // Decrypted message
	char   *err;               // Buffer for any error messages
	string str;
 
	// Generate key pair
	//printf("Generating RSA (%d bits) keypair...", KEY_LENGTH);
	fflush(stdout);
	RSA *keypair = RSA_generate_key(KEY_LENGTH, PUB_EXP, NULL, NULL);
 
	// To get the C-string PEM form:
	BIO *pri = BIO_new(BIO_s_mem());
	BIO *pub = BIO_new(BIO_s_mem());
 
	PEM_write_bio_RSAPrivateKey(pri, keypair, NULL, NULL, 0, NULL, NULL);
	PEM_write_bio_RSAPublicKey(pub, keypair);
 
	pri_len = BIO_pending(pri);
	pub_len = BIO_pending(pub);
 
	pri_key = (char*)malloc(pri_len + 1);
	pub_key = (char*)malloc(pub_len + 1);
 
	BIO_read(pri, pri_key, pri_len);
	BIO_read(pub, pub_key, pub_len);
 
	pri_key[pri_len] = '\0';
	pub_key[pub_len] = '\0';
 
#ifdef PRINT_KEYS
	printf("\n%s\n%s\n", pri_key, pub_key);
#endif
	//printf("done.\n");
 
	// Get the message to encrypt
	printf("Message to encrypt: ");
	fgets(msg, KEY_LENGTH-1, stdin);
	msg[strlen(msg)-1] = '\0';
	//string msg = cleartext;
	//cout<<"length:"<<strlen(msg)<<endl;
 
	// Encrypt the message
	encrypt = (char*)malloc(RSA_size(keypair));
	int encrypt_len;
	err = (char*)malloc(130);
	if((encrypt_len = RSA_public_encrypt(strlen(msg)+1, (unsigned char*)msg, (unsigned char*)encrypt, keypair, RSA_PKCS1_OAEP_PADDING)) == -1) {
	//if((encrypt_len = RSA_public_encrypt(msg.length(), (unsigned char*)msg.c_str(), (unsigned char*)encrypt, keypair, RSA_PKCS1_OAEP_PADDING)) == -1) {
		ERR_load_crypto_strings();
		ERR_error_string(ERR_get_error(), err);
		fprintf(stderr, "Error encrypting message: %s\n", err);
		goto free_stuff;
	}
 
#ifdef WRITE_TO_FILE
	// Write the encrypted message to a file
	FILE *out = fopen("out.bin", "w");
	fwrite(encrypt, sizeof(*encrypt),  RSA_size(keypair), out);
	fclose(out);
	printf("Encrypted message written to file.\n");
	free(encrypt);
	encrypt = NULL;
 
	// Read it back
	printf("Reading back encrypted message and attempting decryption...\n");
	encrypt = (char*)malloc(RSA_size(keypair));
	out = fopen("out.bin", "r");
	fread(encrypt, sizeof(*encrypt), RSA_size(keypair), out);
	fclose(out);
#endif
 
	// Decrypt it
	decrypt = (char*)malloc(encrypt_len);
	//decrypt = new char[encrypt_len + 1];
	//memset(decrypt, encrypt_len+1, 0);
 
	if(RSA_private_decrypt(encrypt_len, (unsigned char*)encrypt, (unsigned char*)decrypt, keypair, RSA_PKCS1_OAEP_PADDING) == -1) {
			ERR_load_crypto_strings();
			ERR_error_string(ERR_get_error(), err);
			fprintf(stderr, "Error decrypting message: %s\n", err);
			goto free_stuff;
	}
	printf("Decrypted message: %s\n", decrypt);
 
free_stuff:
	RSA_free(keypair);
	BIO_free_all(pub);
	BIO_free_all(pri);
	free(pri_key);
	free(pub_key);
	free(encrypt);
	free(decrypt);
	free(err);
}
  1. main.cpp:
#include "stdafx.h"
#include "cryptotest.h"
#include <iostream>
#include <string>
 
using namespace std;
 
int main(int argc, char* argv[])
{
	//string strKey[2] = {};//[0]:public key; [1]:private key 
	//GenerateRSAKey(strKey);
	//cout<<"public key:"<<endl<<strKey[0]<<endl;
	//cout<<"private key:"<<endl<<strKey[1]<<endl;
 
	string cleartext = "中国北京12345$abcde%ABCDE@!!!!";
 
	if (cleartext.length() > 256) {
		cout<<"cleartext too length!!!"<<endl;
		return -1;
	}
 
	RSA_test1(cleartext);
	//RSA_test2(cleartext);
 
	cout<<"ok!!!"<<endl;
 
	return 0;
}

RSA算法理论摘自:

  1. 《基于DES_RSA加密算法的改进与实现》

  2. 《DES和RSA混合加密算法的研究》

测试代码中:

  1. RSA_test1中的代码主要来自于: http://hayageek.com/rsa-encryption-decryption-openssl-c/

  2. RSA_test2中的代码主要来自于: https://shanetully.com/2012/04/simple-public-key-encryption-with-rsa-and-openssl/