RSA Encrypting in PL/SQL

The RSA encryption engine takes as input a public RSA key (X.509, certificate) and using PKCS1 padding scheme produces encrypted output. The ORA_RSA PL/SQL package expects the public keys to be supplied as values of type RAW.

Note: A special caution that we have to take into account when performing RSA encryption is that the input data is limited to 245 bytes with a 2048 bit RSA key.

In the examples below, you can see how to encrypt by using keys loaded from the server file system, hard coded inside the PL/SQL code, or by simply providing the public exponent and modulus of the key.

Table of contents
1. RSA encrypting with key loaded from a file
2. RSA encrypting with key in a LOB field
3. RSA encrypting with modulus and public exponent

1. RSA encrypting with key loaded from a file

PL/SQL code can load external files in variables of type BFILE. Keys loaded this way can be stored for subsequent use in special database tables. In order to access keys from the server file system we must create directory object pointing to their location, like:

CREATE DIRECTORY KEYS_DIR AS '/demo/schema/my_keys_folder';

In the code block below we are going to load the contents of a key file inside a BLOB field and pass it to the ORA_RSA.ENCRYPT method:

DECLARE
  public_key_file_handle  BFILE;
  public_key  BLOB;
 
  encrypted_data raw(32000);
BEGIN
    -- initialize the public key BLOB storage
    DBMS_LOB.createtemporary(public_key, TRUE);
 
    -- load a key from the flesystem
    -- the direcory name must be created upfront with CREATE DIRECTORY
    -- for example: CREATE DIRECTORY KEYS_DIR AS '/demo/schema/my_keys_folder';
    --public_key_file_handle := BFILENAME('KEYS_DIR', 'DidiSoftEood.crt'); -- Note: directory name must be Upper case 
    public_key_file_handle := BFILENAME('KEYS_DIR', 'didisoft_public.der'); -- Note: directory name must be Upper case
 
    -- load the key into a BLOB
    DBMS_LOB.OPEN(public_key_file_handle, DBMS_LOB.LOB_READONLY);
    DBMS_LOB.LoadFromFile( DEST_LOB => public_key,
                         SRC_LOB  => public_key_file_handle,
                         AMOUNT   => DBMS_LOB.GETLENGTH(public_key_file_handle) );
    DBMS_LOB.CLOSE(public_key_file_handle);
 
    -- RSA Encrypt
    encrypted_data := ORA_RSA.ENCRYPT(message => UTL_I18N.STRING_TO_RAW('Hello World', 'AL32UTF8'),
                                      public_key => DBMS_LOB.substr(public_key));
 
END;

2. RSA encrypting with key in a LOB field

Another option is to have the keys hard coded inside PL/SQL procedures. This is suitable if we are going to use only one key.

In this case we need the key in PEM format (text based format) and as you can see from the example below we use a CLOB field for a placeholder:

DECLARE
  public_key CLOB := '-----BEGIN PUBLIC KEY-----
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDCTlRzFkKRlk4kexec91kCCLyW
FA7m2QD1Mc49jYK4qJoZ6MI4IiuNENlDzcYAat8JTITKQKdNfjq+kdppDnLTmeeU
I4Jtlc06L1uDLji1hgeN315t6g3tOf0iHVdyt4dilcHDannCU0duU0TXhh6OK/HH
HtwZ7lcxCo5NgzUDlwIDAQAB
-----END PUBLIC KEY-----';
  encrypted_data raw(32000);
BEGIN
  -- RSA Encrypt
  encrypted_data := ORA_RSA.ENCRYPT(message => UTL_I18N.STRING_TO_RAW('Hello World', 'AL32UTF8'),
                             public_key => UTL_RAW.CAST_TO_RAW(public_key));  
END;

3. RSA encrypting with modulus and exponent

RSA keys are nothing more than two big integer values called modulus and exponent. Although not common we may like to encrypt by just supplying those numbers. For that purpose the package provides a special function called ORA_RSA.ENCRYPT_WITH_MODULUS:

DECLARE
  public_key_modulus CLOB := 'c24e5473164291964e247b179cf7590208bc96140ee6d900f531ce3d8d82b8a89a19e8c238222b8d10d943cdc6006adf094c84ca40a74d7e3abe91da690e72d399e79423826d95cd3a2f5b832e38b586078ddf5e6dea0ded39fd221d5772b7876295c1c36a79c253476e5344d7861e8e2bf1c71edc19ee57310a8e4d83350397';
  public_key_exponent CLOB := '10001';
 
  encrypted_data raw(32000);
BEGIN
  -- RSA Encrypt
  encrypted_data := ORA_RSA.ENCRYPT_WITH_MODULUS(message => UTL_I18N.STRING_TO_RAW('Hello World', 'AL32UTF8'),
                             public_key_modulus => DBMS_LOB.substr(public_key_modulus), 
                             public_key_exponent => DBMS_LOB.substr(public_key_exponent));  
END;

Summary

This article demonstrated RSA encryption with the DidiSoft ORA_RSA PL/SQL package.