Lazarus

Programming => Networking and Web Programming => Topic started by: garlar27 on January 19, 2021, 04:41:28 pm

Title: Need Examples of Use of RSA With OpenSSL Library
Post by: garlar27 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?
Title: Re: Need Examples of Use of RSA With OpenSSL Library
Post by: garlar27 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 (https://shanetully.com/2012/04/simple-public-key-encryption-with-rsa-and-openssl/) 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.  
  40.     BIO_read(pri, pri_key, pri_len);
  41.     BIO_read(pub, pub_key, pub_len);
  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) {
  62.         ERR_load_crypto_strings();
  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.  
  77.         // Read it back
  78.         printf("Reading back encrypted message and attempting decryption...\n");
  79.         encrypt = malloc(RSA_size(keypair));
  80.         out = fopen("out.bin", "r");
  81.         fread(encrypt, sizeof(*encrypt), RSA_size(keypair), out);
  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) {
  89.         ERR_load_crypto_strings();
  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 (https://forum.lazarus.freepascal.org/index.php/topic,22583.msg133520.html#msg133520) ).
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.
TinyPortal © 2005-2018