非对称加密算法之RSA介绍及OpenSSL中RSA常用函数使用举例

2023-05-16

RSA算法,在1977年由Ron Rivest、Adi Shamirh和LenAdleman,在美国的麻省理工学院开发完成。这个算法的名字,来源于三位开发者的名字。RSA已经成为公钥数据加密标准。

RSA属于公开密钥密码体制。公开密钥体制就是产生两把密钥,一把用于加密,一把用于解密,而且不能根据算法和其中的一把密钥,而去推出另外的一把密钥。在使用的时候,将公钥公开,对方用公开的公钥加密数据后,将密文发回,然后用另一把私钥进行解密,从而还原出明文。

RSA算法的数学基础是数论中的素数相关性质。RSA的算法如下:

(1)、找出两个数p和q,其中p与q都是比较大的素数,其中p不等于q,为了保证安全性,RSA中使用的素数都比较大,且对这两个数要进行严格的保密;

(2)、计算乘积n = p *q;

(3)、计算乘积f(p,q) =(p - 1) * (q - 1);

(4)、找到一个素数e,使1 < e< f(p,q),并且e与f(p,q)互素;

(5)、将(e, n)做公钥,对明文按公式C=p^e mod n进行加密;

(6)、计算私钥d=e^-1mod f(p,q);对密文按P = C^d mod n进行解密。

其中,e,n作为公钥公开,任何人都可以知道。而f(p,q)作为密钥,要进行保密。一旦f(p,q)被别人获取,那么该RSA算法就不再安全。并且RSA算法的安全性和p,q的长度直接相关,长度越长安全性越高。因此,实际应用中p,q的长度至少为512比特。具体实现原理下图所示。

RSA在加解密的运用中,公钥是公开的,即有很多人都能得到,第三方也很容易窃取到e和n的数值。所以破解的关键就在,从e和n这两个数值开始,想办法求出数值d,如果能够得到d的值,也就是能够找到私钥,那么就可以破解相应的信息,达到情报窃取的目的。RSA算法的安全性完全依赖于大数的分解。

优缺点:由于RSA算法的理论基础是大数的分集,它是公认的世界难题,这就为RSA的安全性作了保障,所以它在一定程度上能抵抗外界的各种攻击。RSA是公钥加密系统中使用最广的加密算法,也是第一个既可以用于数据加密,同时还可以用于数字签名的算法。它的缺点:由于没有直接产生大素数的技术,RSA算法密钥产生比较麻烦;其次,为保证安全性,n一般要达到1024bit,使加密解密运算代价很高,严重影响了其加密速度,因此RSA算法不适合用于加密数据量大的信息;随着保密级别的提高,密钥的长度也在随着增加。

RSA is vulnerable to timing attacks. In a setup where attackers can measure the timeof RSA decryption or signature operations, blinding must be used to protect theRSA operation from that attack. RSA_blinding_on(),RSA_blinding_off():protectthe RSA operation from timing attacks.

1. RSA_blinding_on():turnsblinding on for key B<rsa> and generates a random blinding factor.B<ctx> is B<NULL> or a pre-allocated and initializedB<BN_CTX>. The random number generator must be seeded prior to callingRSA_blinding_on().returns 1 on success, and 0 if an error occurred.

2. RSA_blinding_off():turnsblinding off and frees the memory used for the blinding factor.

3. RSA_check_key():validateprivate RSA keys. This function validates RSA keys. It checks that B<p>and B<q> are in fact prime, and that B<n = p*q>. It also checksthat B<d*e = 1 mod (p-1*q-1)>, and that B<dmp1>, B<dmq1> andB<iqmp> are set correctly or are B<NULL>. As such, this functioncan not be used with any arbitrary RSA key object, even if it is otherwise fitfor regular RSA operation. returns 1 if B<rsa> is a valid RSA key, and 0otherwise. -1 is returned if an error occurs while checking the key. Thisfunction does not work on RSA public keys that have only the modulus and publicexponent elements populated. It performs integrity checks on all the RSA keymaterial, so the RSA key structure must contain all the private key data too.

4. RSA_generate_key():generates akey pair and returns it in a newly allocated B<RSA> structure. Thepseudo-random number generator must be seeded prior to callingRSA_generate_key().The modulus size will be B<num> bits, and the publicexponent will be B<e>. Key sizes with B<num> E<lt> 1024should be considered insecure. The exponent is an odd number, typically 3, 17or 65537. A callback function may be used to provide feedback about the progressof the key generation. If key generation fails, RSA_generate_key() returnsB<NULL>. RSA_generate_key() goes into an infinite loop for illegal inputvalues.

5. RSA_set_ex_data():is used toset application specific data, the data is supplied in the B<arg>parameter and its precise meaning is up to the application. returns 1 onsuccess or 0 on failure.

6. RSA_get_ex_data():is used toretrieve application specific data. The data is returned to the application,this will be the same value as supplied to a previousB<RSA_set_ex_data()> call. returns the application data or 0 on failure.0 may also be valid application data but currently it can only fail if given aninvalid B<idx> parameter.

7. RSA_get_ex_new_index():returnsa new index or -1 on failure (note 0 is a valid index value).

8. RSA_new():allocate RSA objects.allocates and initializes an B<RSA> structure. It is equivalent to callingRSA_new_method(NULL).

9. RSA_free():free RSA objects. freesthe B<RSA> structure and its components. The key is erased before thememory is returned to the system.

10. RSA_padding_xxx_xxx(): these functionsare called from the RSA encrypt, decrypt, sign and verify functions. Normallythey should not be called from application programs. However, they can also becalled directly to implement padding for other asymmetric ciphers.

11. RSA_private_encrypt():owlevel signature operations. signs the B<flen> bytes atB<from> (usually a message digest with an algorithm identifier) using theprivate key B<rsa> and stores the signature in B<to>. B<to>must point to B<RSA_size(rsa)> bytes of memory. returns the size of thesignature (i.e.,RSA_size(rsa)).

12. RSA_public_decrypt():ow levelsignature operations. recovers the message digest from the B<flen> byteslong signature at B<from> using the signer's public key B<rsa>.B<to> must point to a memory section large enough to hold the messagedigest (which is smaller than B<RSA_size(rsa) - 11>). B<padding> isthe padding mode that was used to sign the data. returns the size of the recoveredmessage digest.

13. RSA_public_encrypt():encryptsthe B<flen> bytes at B<from> (usually a session key) using thepublic key B<rsa> and stores the ciphertext in B<to>. B<to>must point to RSA_size(B<rsa>) bytes of memory. returns the size of theencrypted data (i.e., RSA_size(B<rsa>)).

14. RSA_private_decrypt():decryptsthe B<flen> bytes at B<from> using the private key B<rsa> andstores the plaintext in B<to>. B<to> must point to a memory sectionlarge enough to hold the decrypted data (which is smaller thanRSA_size(B<rsa>)). B<padding> is the padding mode that was used toencrypt the data. returns the size of the recovered plaintext.

15. RSA_set_default_method():makesB<meth> the default method for all RSA structures created later.B<NB>: This is true only whilst no ENGINE has been set as a default forRSA, so this function is no longer recommended.

16. RSA_get_default_method():returnsa pointer to the current default RSA_METHOD. However, the meaningfulness ofthis result is dependent on whether the ENGINE API is being used, so thisfunction is no longer recommended.

17. RSA_set_method():selectsB<meth> to perform all operations using the key B<rsa>. This willreplace the RSA_METHOD used by the RSA key and if the previous method wassupplied by an ENGINE, the handle to that ENGINE will be released during thechange. It is possible to have RSA keys that only work with certain RSA_METHODimplementations (eg. from an ENGINE module that supports embeddedhardware-protected keys), and in such cases attempting to change the RSA_METHODfor the key can have unexpected results.

18. RSA_get_method():returns apointer to the RSA_METHOD being used by B<rsa>. This method may or maynot be supplied by an ENGINE implementation, but if it is, the return value canonly be guaranteed to be valid as long as the RSA key itself is valid and doesnot have its implementation changed by RSA_set_method().

19. RSA_flags():returns theB<flags> that are set for B<rsa>'s current RSA_METHOD.

20. RSA_new_method():allocates andinitializes an RSA structure so that B<engine> will be used for the RSAoperations. If B<engine> is NULL, the default ENGINE for RSA operationsis used, and if no default ENGINE is set, the RSA_METHOD controlled byRSA_set_default_method() is used.

21. RSA_sign():signs the messagedigest B<m> of size B<m_len> using the private key B<rsa> asspecified in PKCS #1 v2.0. It stores the signature in B<sigret> and thesignature size in B<siglen>. B<sigret> must point to RSA_size(B<rsa>)bytes of memory.

22. RSA_verify():verifies that thesignature B<sigbuf> of size B<siglen> matches a given messagedigest B<m> of size B<m_len>. B<type> denotes the messagedigest algorithm that was used to generate the signature. B<rsa> is thesigner's public key.

23. RSA_sign_ASN1_OCTET_STRING():signsthe octet string B<m> of size B<m_len> using the private keyB<rsa> represented in DER using PKCS #1 padding. It stores the signaturein B<sigret> and the signature size in B<siglen>. B<sigret>must point to B<RSA_size(rsa)> bytes of memory.

24. RSA_verify_ASN1_OCTET_STRING():verifiesthat the signature B<sigbuf> of size B<siglen> is the DERrepresentation of a given octet string B<m> of size B<m_len>.B<dummy> is ignored. B<rsa> is the signer's public key.

25. RSA_size():getRSA modulus size. This function returns the RSA modulus size in bytes. It canbe used to determine how much memory must be allocated for an RSA encrypted value.

下面是测试用例代码:

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_

2. 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);
}

3. 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/

GitHub:https://github.com/fengbingchun/OpenSSL_Test

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

非对称加密算法之RSA介绍及OpenSSL中RSA常用函数使用举例 的相关文章

  • Cadence 17.2学习笔记--显示元件丝印及元件标号的设置

    快捷键Ctrl 43 F5 调出Color Dialog 左侧菜单第三项Geometry选项 钩选图中Silkscreen Top或Silkscreen Bottom可打开或关闭元件外形丝印的显示 同样Color Dialog对话框 左侧菜
  • 【Android UI】色板

    Hex CodeColor FFFFFF FFFFCC FFFF99 FFFF66 FFFF33 FFFF00 FFCCFF FFCCCC FFCC99 FFCC66 FFCC33 FFCC00 FF99FF FF99CC FF9999 F
  • 对称加密算法AES简介及在OpenSSL中使用举例

    高级加密标准 AES Advanced Encryption Standard 由美国国家标准和技术协会 NIST 于2000年公布 xff0c 它是一种对称加密算法 xff0c 用来替代DES AES也称为Rijndael算法 xff0c
  • 基于Hash的消息认证码HMAC简介及在OpenSSL中使用举例

    HMAC Hash based Message Authentication Code xff1a 基于Hash的消息认证码 xff0c 是一种通过特别计算方式之后产生的消息认证码 MAC xff0c 使用密码散列函数 xff0c 同时结合
  • 在Windows和Linux上编译gRPC源码操作步骤(C++)

    gRPC最新发布版本为v1 23 0 xff0c 下面以此版本为例说明在Windows和Linux下编译过程 Windows7 10 vs2103编译gRPC源码操作步骤 xff1a 1 需要本机已安装Git CMake Perl Go y
  • gRPC简介及简单使用(C++)

    gRPC是一个现代的 开源的 高性能远程过程调用 RPC 框架 xff0c 可以在任何平台运行 gRPC使客户端和服务器端应用程序能够透明地进行通信 xff0c 并简化了连接系统的构建 gRPC支持的语言包括C 43 43 Ruby Pyt
  • C语言中select函数简介及使用

    select函数用来检查套接字描述符 sockets descriptors 是否已准备好读 写 xff0c 提供了一种同时检查多个套接字的方法 Linux中select函数的声明在 usr include x86 64 linux gnu
  • VS Code离线安装C/C++插件cpptools-linux-aarch64.vsix

    一 问题 最近VS Code连接jetson nano xff0c 经常提示加载C C 43 43 插件失败 二 解决方法 根据提示 xff0c 在githup上 https github com microsoft vscode cppt
  • 开源库BearSSL介绍及使用

    BearSSL是用C语言实现的SSL TLS协议 xff0c 它的源码可直接通过git clone https www bearssl org git BearSSL 下载 xff0c 它的license是MIT xff0c 最新版本为0
  • 对称加密算法AES之GCM模式简介及在OpenSSL中使用举例

    AES Advanced Encryption Standard 即高级加密标准 xff0c 由美国国家标准和技术协会 NIST 于2000年公布 xff0c 它是一种对称加密算法 关于AES的更多介绍可以参考 xff1a https bl
  • ASN.1简介及OpenSSL中ASN.1接口使用举例

    ASN 1 Abstract Syntax Notation One 是一套标准 xff0c 是描述数据的表示 编码传输 解码的灵活的记法 它提供了一套正式 无歧义和精确的规则以描述独立于特定计算机硬件的对象结构 OpenSSL的编码方法就
  • 从openssl rsa pem文件中提取公私钥数据实现

    RSA为非对称加密算法 xff0c 关于其介绍可以参考 xff1a https blog csdn net fengbingchun article details 43638013 OpenSSL最新版为 1 1 1g xff0c 在Wi
  • 通过OpenSSL的接口实现Base64编解码

    对openssl genrsa产生的rsa私钥pem文件 xff0c 使用普通的base64解码会有问题 xff0c 如使用https blog csdn net fengbingchun article details 85218653
  • JWT(JSON Web Token)简介及实现

    JWT JSON Web Token xff1a 是一个开放标准 RFC 7519 xff0c 它定义了一种紧凑且自包含的方式 xff0c 用于在各方之间作为Json对象安全地传输信息 由于此信息是经过数字签名的 xff0c 因此可以被验证
  • SSL/TLS单向认证和双向认证介绍

    为了便于理解SSL TLS的单向认证和双向认证执行流程 xff0c 这里先介绍一些术语 1 散列函数 Hash function xff1a 又称散列算法 哈希函数 xff0c 是一种从任何一种数据中创建小的数字 指纹 的方法 散列函数把消
  • 使用OpenSSL生成自签名证书相关命令

    在用于小范围测试等目的的时候 xff0c 用户也可以自己生成数字证书 xff0c 但没有任何可信赖的机构签名 xff0c 此类数字证书称为自签名证书 证书一般采用X 509标准格式 下面通过OpenSSL相关命令介绍如何生成自签证书 1 生
  • Windows/Linux TCP Socket网络编程简介及测试代码

    典型的网络应用是由一对程序 即客户程序和服务器程序 组成的 xff0c 它们位于两个不同的端系统中 当运行这两个程序时 xff0c 创建了一个客户进程和一个服务器进程 xff0c 同时它们通过从套接字 socket 读出和写入数据在彼此之间
  • 基于BearSSL实现自签名证书双向认证测试代码

    客户端 服务器端双向认证大致过程 xff1a 可以参考 xff1a https blog csdn net fengbingchun article details 106856332 1 客户端发起连接请求 xff1b 2 服务器端返回消
  • C:\KEIL\C51\intrins.h包含不正确的路径。Keil 头文件路径错误

    步骤1 xff1a 先检查工程中的 include intrins h include stdio h xff0c 各文件之间 是否正确调用 步骤2 xff1a 将 include lt intrins h gt lt reg52 h gt
  • 分享一个Centos8的国内yum源

    使用的是阿里巴巴开源镜像站 xff0c 文件地址 xff1a https span class token punctuation span span class token operator span span class token o

随机推荐

  • 网络数据包分析软件Wireshark简介

    Wireshark是被广泛使用的免费开源的网络协议分析软件 network protocol analyzer 或网络数据包分析软件 xff0c 它可以让你在微观层面上查看网络上发生的事情 xff0c 它的功能是截取网络数据包 xff0c
  • HTTP请求方法介绍

    之前在https blog csdn net fengbingchun article details 85039308 中介绍过HTTP协议 xff0c 在https blog csdn net fengbingchun article
  • TCP Flags标志位介绍

    传输控制协议 Transmission Control Protocol xff0c TCP 是一种传输层协议 TCP使数据包从源到目的地的传输更加顺畅 它是一种面向连接的端到端协议 每个数据包由TCP包裹在一个报头中 xff0c 该报头由
  • 代理服务器简介及libcurl测试

    代理服务器英文全称是Proxy Server xff0c 其功能就是将局域网用户连接到Internet xff0c 代理网络用户去获得网络信息 形象地说 xff0c 它是网络信息的中转站 xff0c 是连接内部局域网和Internet的一种
  • CMake中find_package的使用

    CMake中的命令find package用于查找指定的package find package支持两种主要的搜索方法 xff1a 注意 xff1a lt PackageName gt 是区分大小写的 1 Config mode 配置模式
  • CMake中link_directories/target_link_directories的使用

    CMake中的link directories命令用于添加目录使链接器能在其查找库 add directories in which the linker will look for libraries xff0c 其格式如下 xff1a
  • UDP协议在Windows上使用示例

    UDP User Datagram Protocol xff0c 用户数据报协议 是无连接的 xff0c 因此在两个进程通信前没有握手过程 UDP协议提供一种不可靠数据传送服务 xff0c 也就是说 xff0c 当进程将一个报文发送进UDP
  • 代码覆盖率工具OpenCppCoverage在Windows上的使用

    OpenCppCoverage是用在Windows C 43 43 上的开源的代码覆盖率工具 xff0c 源码地址为https github com OpenCppCoverage OpenCppCoverage xff0c 最新发布版本为
  • nerfstudio介绍及在windows上的配置、使用

    nerfstudio提供了一个简单的API xff0c 可以简化创建 训练和可视化NeRF的端到端过程 该库通过模块化每个组件来支持可解释的NeRF实现 nerfstudio源码地址 https github com nerfstudio
  • Qt中QDebug的使用

    QDebug类为调试信息 debugging information 提供输出流 它的声明在 lt QDebug gt 中 xff0c 实现在Core模块中 将调试或跟踪信息 debugging or tracing information
  • OkHttpUtil

    package com example someutil util import com google gson Gson import java util Iterator import java util Map import java
  • Sourcetree介绍及使用

    Sourcetree是一个操作简单但功能强大的免费Git客户端管理工具 xff0c 可应用在Windows和Mac平台 Sourcetree的安装 xff1a 1 从Sourcetree Free Git GUI for Mac and W
  • C++14中lambda表达式新增加的features的使用

    lambda表达式是在C 43 43 11中引入的 xff0c 它们可以嵌套在其它函数甚至函数调用语句中 xff0c C 43 43 11中lambda表达式的使用参考 xff1a https blog csdn net fengbingc
  • OpenSSL简介及在Windows、Linux、Mac系统上的编译步骤

    OpenSSL介绍 xff1a OpenSSL是一个强大的安全套接字层密码库 xff0c 囊括主要的密码算法 常用的密钥和证书封装管理功能及SSL协议 xff0c 并提供丰富的应用程序供测试或其它目的使用 SSL是SecureSockets
  • 信息安全领域相关术语介绍

    一 SSL 安全套接字层 SSL Secure Sockets Layer 是一种协议 xff0c 支持服务通过网络进行通信而不损害安全性 它在客户端和服务器之间创建一个安全连接 然后通过该连接安全地发送任意数据量 SSL最初是用来保障数据
  • 对称加密算法之DES介绍

    DES Data Encryption Standard 是分组对称密码算法 DES采用了64位的分组长度和56位的密钥长度 xff0c 它将64位的输入经过一系列变换得到64位的输出 解密则使用了相同的步骤和相同的密钥 DES的密钥长度为
  • OpenSSL中对称加密算法DES常用函数使用举例

    主要包括3个文件 xff1a 1 cryptotest h ifndef CRYPTOTEST H define CRYPTOTEST H include lt string gt using namespace std typedef e
  • 对称加密算法之RC4介绍及OpenSSL中RC4常用函数使用举例

    RC4是一种对称密码算法 xff0c 它属于对称密码算法中的序列密码 streamcipher 也称为流密码 xff0c 它是可变密钥长度 xff0c 面向字节操作的流密码 RC4是流密码streamcipher中的一种 xff0c 为序列
  • 摘要算法之MD5介绍及OpenSSL中MD5常用函数使用举例

    MD5 Message DigestAlgorithm 5 是计算机中广泛使用的杂凑算法之一 主要可以实现将数据运算后转换为一串固定值 xff0c 其前身主要有MD2 MD3和MD4算法 MD2算法在1989年由Rivest设计开发 xff
  • 非对称加密算法之RSA介绍及OpenSSL中RSA常用函数使用举例

    RSA算法 xff0c 在1977年由Ron Rivest Adi Shamirh和LenAdleman xff0c 在美国的麻省理工学院开发完成 这个算法的名字 xff0c 来源于三位开发者的名字 RSA已经成为公钥数据加密标准 RSA属