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

时间:2021-08-18 13:11:52

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比特。具体实现原理如图1所示。

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

图 1

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  2048int padding = RSA_PKCS1_PADDING;int encrypt_len = 0;#define PUB_EXP     3//#define PRINT_KEYS//#define WRITE_TO_FILEint GenerateRSAKey(string strKey[]){size_t pri_len;          // Length of private keysize_t pub_len;          // Length of public keychar *pri_key = NULL;           // Private keychar *pub_key = NULL;           // Public keyRSA* 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);elsersa = 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 : 2048string 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 keysize_t pub_len;            // Length of public keychar   *pri_key;           // Private keychar   *pub_key;           // Public keychar   msg[KEY_LENGTH/8];  // Message to encryptchar   *encrypt = NULL;    // Encrypted messagechar   *decrypt = NULL;    // Decrypted messagechar   *err;               // Buffer for any error messagesstring 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_KEYSprintf("\n%s\n%s\n", pri_key, pub_key);#endif//printf("done.\n");// Get the message to encryptprintf("Message to encrypt: ");fgets(msg, KEY_LENGTH-1, stdin);msg[strlen(msg)-1] = '\0';//string msg = cleartext;//cout<<"length:"<<strlen(msg)<<endl;// Encrypt the messageencrypt = (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 fileFILE *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 backprintf("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 itdecrypt = (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/

GitHubhttps://github.com/fengbingchun/OpenSSL_Test