### Bookstore

 Computer Math and Games in Pascal (preview) Lazarus Handbook

### Author Topic: Need Examples of Use of RSA With OpenSSL Library  (Read 310 times)

#### garlar27

• Hero Member
• Posts: 652
##### Need Examples of Use of RSA With OpenSSL Library
« on: January 19, 2021, 04:41:28 pm »
Hi everybody,

I don't know if this is the best place for this question.

I need to decrypt a string from a JSON/XML attribute/text field using RSA private key and exponent. Also I need to generate the Public Key, Private Key and exponent using through the OpenSSl library.

I know that OpenSSL is been used in the https and sftp connection. But I don't know where to look to find out how all of this is done and therefore comes my question:

Where can I find examples of how to decrypt an encrypted string using RSA private key and exponent?

#### garlar27

• Hero Member
• Posts: 652
##### Re: Need Examples of Use of RSA With OpenSSL Library
« Reply #1 on: January 29, 2021, 01:59:38 am »
MAYBE THIS POST SHOULD BE MOVED TO THE GENERAL CATEGORY...

First things first. I suck at C code!! Thus I need help to use this function from openssl.pas:
Code: Pascal  [Select][+][-]
1. function RSA_private_decrypt(flen: cint; from_buf, to_buf: PByte; arsa: PRSA; padding: cint): cint;
2.

I'm using this example in C as a guide:
Code: C  [Select][+][-]
1. #include <openssl/rsa.h>
2. #include <openssl/pem.h>
3. #include <openssl/err.h>
4. #include <stdio.h>
5. #include <string.h>
6.
7. #define KEY_LENGTH  2048
8. #define PUB_EXP     3
9. #define PRINT_KEYS
10. #define WRITE_TO_FILE
11.
12. int main(void) {
13.     size_t pri_len;            // Length of private key
14.     size_t pub_len;            // Length of public key
15.     char   *pri_key;           // Private key
16.     char   *pub_key;           // Public key
17.     char   msg[KEY_LENGTH/8];  // Message to encrypt
18.     char   *encrypt = NULL;    // Encrypted message
19.     char   *decrypt = NULL;    // Decrypted message
20.     char   *err;               // Buffer for any error messages
21.
22.     // Generate key pair
23.     printf("Generating RSA (%d bits) keypair...", KEY_LENGTH);
24.     fflush(stdout);
25.     RSA *keypair = RSA_generate_key(KEY_LENGTH, PUB_EXP, NULL, NULL);
26.
27.     // To get the C-string PEM form:
28.     BIO *pri = BIO_new(BIO_s_mem());
29.     BIO *pub = BIO_new(BIO_s_mem());
30.
31.     PEM_write_bio_RSAPrivateKey(pri, keypair, NULL, NULL, 0, NULL, NULL);
32.     PEM_write_bio_RSAPublicKey(pub, keypair);
33.
34.     pri_len = BIO_pending(pri);
35.     pub_len = BIO_pending(pub);
36.
37.     pri_key = malloc(pri_len + 1);
38.     pub_key = malloc(pub_len + 1);
39.
42.
43.     pri_key[pri_len] = '\0';
44.     pub_key[pub_len] = '\0';
45.
46.     #ifdef PRINT_KEYS
47.         printf("\n%s\n%s\n", pri_key, pub_key);
48.     #endif
49.     printf("done.\n");
50.
51.     // Get the message to encrypt
52.     printf("Message to encrypt: ");
53.     fgets(msg, KEY_LENGTH-1, stdin);
54.     msg[strlen(msg)-1] = '\0';
55.
56.     // Encrypt the message
57.     encrypt = malloc(RSA_size(keypair));
58.     int encrypt_len;
59.     err = malloc(130);
60.     if((encrypt_len = RSA_public_encrypt(strlen(msg)+1, (unsigned char*)msg, (unsigned char*)encrypt,
61.                                          keypair, RSA_PKCS1_OAEP_PADDING)) == -1) {
63.         ERR_error_string(ERR_get_error(), err);
64.         fprintf(stderr, "Error encrypting message: %s\n", err);
65.         goto free_stuff;
66.     }
67.
68.     #ifdef WRITE_TO_FILE
69.     // Write the encrypted message to a file
70.         FILE *out = fopen("out.bin", "w");
71.         fwrite(encrypt, sizeof(*encrypt),  RSA_size(keypair), out);
72.         fclose(out);
73.         printf("Encrypted message written to file.\n");
74.         free(encrypt);
75.         encrypt = NULL;
76.
78.         printf("Reading back encrypted message and attempting decryption...\n");
79.         encrypt = malloc(RSA_size(keypair));
80.         out = fopen("out.bin", "r");
82.         fclose(out);
83.     #endif
84.
85.     // Decrypt it
86.     decrypt = malloc(encrypt_len);
87.     if(RSA_private_decrypt(encrypt_len, (unsigned char*)encrypt, (unsigned char*)decrypt,
88.                            keypair, RSA_PKCS1_OAEP_PADDING) == -1) {
90.         ERR_error_string(ERR_get_error(), err);
91.         fprintf(stderr, "Error decrypting message: %s\n", err);
92.         goto free_stuff;
93.     }
94.     printf("Decrypted message: %s\n", decrypt);
95.
96.     free_stuff:
97.     RSA_free(keypair);
98.     BIO_free_all(pub);
99.     BIO_free_all(pri);
100.     free(pri_key);
101.     free(pub_key);
102.     free(encrypt);
103.     free(decrypt);
104.     free(err);
105.
106.     return 0;
107. }
I'll appreciate any help on this subject.

Now the whining and wailing (you can skip this part):

Well, I have my eyes sore reading code from lNet, Synapse and code in JAVA as well, and I couldn't find much.

In lNet it seams like there is no RSA decryption or it is really hard for me to find the place where decryption is done.

In Synapse I can't see how it is done either.

The LockBox component has an implementation for RSA but it can't decrypt beyond 1024 bit, so for what we need is useless and didn't even try to use it.

Then after a long time of looking to the Lazarus forum and the wiki. Digging in JAVA Android Studio code. And also googling around I found the C code example (above mentioned) doing the decryption (I stumbled many times on it thanks to this old post RSA Encryption ).
At first I didn't pay attention to it because I'm not comfortable with C code and there's a lot of things that I don't know well how to wrap it around with Pascal code.

But after reaching the end of the road I found that FPC has something done with OpenSSL and there is an example (located in {Lazarusfolder}\fpc\3.2.0\source\packages\openssl\examples\genkeypair.lpr) to generate both keys (public and private) which is good but not good enough. So I looked through the whole FPC and Lazarus code and couldn't find a place where the (deprecated from OpenSSL library) function RSA_private_decrypt(flen: cint; from_buf, to_buf: PByte; arsa: PRSA; padding: cint): cint; from openssl.pas is used

Thank you very much if you went this far reading.