 
 카톡
카톡
◎위챗 : speedseoul
 
                http://hayageek.com/rsa-encryption-decryption-openssl-c/
In this article, I have explained how to do RSA Encryption and Decryption with OpenSSL Library in C.
1).Generate RSA keys with OpenSSL
2).Public Encryption and Private Decryption
3).Private Encryption and Public Decryption.
4).Encryption and Decryption Example code.
Use the below command to generate RSA keys with length of 2048.
| 1 | openssl genrsa -out private.pem 2048 | 
Extract public key from private.pem with the following command.
| 1 | openssl rsa -inprivate.pem -outform PEM -pubout -out public.pem | 
public.pem is RSA public key in PEM format.
private.pem is RSA private key in PEM format.
Below is the OpenSSL API for Public encryption and Private decryption.
| 1 2 3 4 5 | int RSA_public_encrypt(int flen, unsigned char *from,   unsigned char *to, RSA *rsa, int padding);int RSA_private_decrypt(int flen, unsigned char *from,    unsigned char *to, RSA *rsa, int padding); | 
2.1 Preparing RSA Structure
For encryption and decryption we need to prepare RSA structure. Use the below function to create RSA with key buffer.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | RSA * createRSA(unsigned char* key,intpublic){    RSA *rsa= NULL;    BIO *keybio ;    keybio = BIO_new_mem_buf(key, -1);    if(keybio==NULL)    {        printf( "Failed to create key BIO");        return0;    }    if(public)    {        rsa = PEM_read_bio_RSA_PUBKEY(keybio, &rsa,NULL, NULL);    }    else    {        rsa = PEM_read_bio_RSAPrivateKey(keybio, &rsa,NULL, NULL);    }    returnrsa;} | 
Usage for public key: createRSA(“PUBLIC_KEY_BUFFER”,1);
Usage for private key: createRSA(“PRIVATE_KEY_BUFFER”,0);
If you want to create RSA with key file name, you can use this function
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | RSA * createRSAWithFilename(char* filename,intpublic){    FILE* fp = fopen(filename,"rb");    if(fp == NULL)    {        printf("Unable to open file %s \n",filename);        returnNULL;        }    RSA *rsa= RSA_new() ;    if(public)    {        rsa = PEM_read_RSA_PUBKEY(fp, &rsa,NULL, NULL);    }    else    {        rsa = PEM_read_RSAPrivateKey(fp, &rsa,NULL, NULL);    }    returnrsa;} | 
2.1 Public Key Encryption.
For encryption we can use padding, below is the list of supported paddings.
RSA_PKCS1_PADDING
PKCS #1 v1.5 padding. This currently is the most widely used mode.
RSA_PKCS1_OAEP_PADDING
EME-OAEP as defined in PKCS #1 v2.0 with SHA-1, MGF1 and an empty encoding parameter. This mode is recommended for all new applications.
RSA_SSLV23_PADDING
PKCS #1 v1.5 padding with an SSL-specific modification that denotes that the server is SSL3 capable.
RSA_NO_PADDING
Raw RSA encryption. This mode should only be used to implement cryptographically sound padding modes in the application code. Encrypting user data directly with RSA is insecure.
You can use the below method, to encrypt the data with public key.
| 1 2 3 4 5 6 7 8 | int padding = RSA_PKCS1_PADDING;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);    returnresult;} | 
Note: public key encryption supports all the paddings.
2.2 Private Decryption.
You can use the below method to decrypt the data with private key
| 1 2 3 4 5 6 | intprivate_decrypt(unsigned char* enc_data,intdata_len,unsigned char* key, unsigned char*decrypted){    RSA * rsa = createRSA(key,0);    intresult = RSA_private_decrypt(data_len,enc_data,decrypted,rsa,padding);    returnresult;} | 
Below is the OpenSSL API for private encryption and public decryption.
| 1 2 3 4 5 | intRSA_private_encrypt(intflen, unsigned char*from,   unsigned char*to, RSA *rsa, intpadding);intRSA_public_decrypt(intflen, unsigned char*from,   unsigned char*to, RSA *rsa, intpadding); | 
Note: private key encryption supports only these paddings. RSA_PKCS1_PADDING and RSA_NO_PADDING.
3.1 Private Key Encryption.
You can use the below function for private key encryption.
| 1 2 3 4 5 6 | intprivate_encrypt(unsigned char* data,intdata_len,unsigned char* key, unsigned char*encrypted){    RSA * rsa = createRSA(key,0);    intresult = RSA_private_encrypt(data_len,data,encrypted,rsa,padding);    returnresult;} | 
3.2 Public Key Decryption.
You can use the below function for public key decryption.
| 1 2 3 4 5 6 | 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);    returnresult;} | 
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 | #include <openssl/pem.h>#include <openssl/ssl.h>#include <openssl/rsa.h>#include <openssl/evp.h>#include <openssl/bio.h>#include <openssl/err.h>#include <stdio.h>intpadding = RSA_PKCS1_PADDING;RSA * createRSA(unsigned char* key,intpublic){    RSA *rsa= NULL;    BIO *keybio ;    keybio = BIO_new_mem_buf(key, -1);    if(keybio==NULL)    {        printf( "Failed to create key BIO");        return0;    }    if(public)    {        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");    }    returnrsa;}intpublic_encrypt(unsigned char* data,intdata_len,unsigned char* key, unsigned char*encrypted){    RSA * rsa = createRSA(key,1);    intresult = RSA_public_encrypt(data_len,data,encrypted,rsa,padding);    returnresult;}intprivate_decrypt(unsigned char* enc_data,intdata_len,unsigned char* key, unsigned char*decrypted){    RSA * rsa = createRSA(key,0);    intresult = RSA_private_decrypt(data_len,enc_data,decrypted,rsa,padding);    returnresult;}intprivate_encrypt(unsigned char* data,intdata_len,unsigned char* key, unsigned char*encrypted){    RSA * rsa = createRSA(key,0);    intresult = RSA_private_encrypt(data_len,data,encrypted,rsa,padding);    returnresult;}intpublic_decrypt(unsigned char* enc_data,intdata_len,unsigned char* key, unsigned char*decrypted){    RSA * rsa = createRSA(key,1);    intresult = RSA_public_decrypt(data_len,enc_data,decrypted,rsa,padding);    returnresult;}voidprintLastError(char*msg){    char* err = malloc(130);;    ERR_load_crypto_strings();    ERR_error_string(ERR_get_error(), err);    printf("%s ERROR: %s\n",msg, err);    free(err);}intmain(){  charplainText[2048/8] = "Hello this is Ravi"; //key length : 2048 charpublicKey[]="-----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";  charprivateKey[]="-----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 charencrypted[4098]={};unsigned chardecrypted[4098]={};intencrypted_length= public_encrypt(plainText,strlen(plainText),publicKey,encrypted);if(encrypted_length == -1){    printLastError("Public Encrypt failed ");    exit(0);}printf("Encrypted length =%d\n",encrypted_length);intdecrypted_length = private_decrypt(encrypted,encrypted_length,privateKey, 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(plainText,strlen(plainText),privateKey,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,publicKey, decrypted);if(decrypted_length == -1){    printLastError("Public Decrypt failed");    exit(0);}printf("Decrypted Text =%s\n",decrypted);printf("Decrypted Length =%d\n",decrypted_length);} |