Release 10.1A: OpenEdge Development:
Programming Interfaces

> ## Implementing symmetric cryptography in the 4GL

> Once you have established an appropriate cryptography policy for your application, including the necessary key values and algorithms, you can begin to apply encryption and decryption to your data. However, you must also thoroughly plan the role that cryptography plays in your application in order to use it safely and effectively. While the 4GL provides powerful tools for generating keys and encrypting data, you must manage these tools carefully in your application to avoid serous problems that could result in loss of data.

> Caution: Before encrypting any data that you intend to have decrypted, be certain that you can recover the unencrypted data if either the encryption or decryption fails.

> For more information, in general, on managing data encryption and decryption, see the Security whitepaper prepared by Progress Marketing, which can be found on the PSDN Web site.

> ##### Using the 4GL encryption and decryption functions

> The Progress 4GL provides two 4GL built-in functions, `DECRYPT` and `ENCRYPT`, to encrypt and decrypt data. Both functions rely on cryptographic parameters that you set using the `SECURITY-POLICY` system handle or using options for invoking each function.

> These functions have the following syntax:

> Syntax
>     ENCRYPT ( data-to-encrypt [ , encrypt-key [ , iv-value [ , algorithm ] ] ] )

>     DECRYPT ( data-to-decrypt [ , encrypt-key [ , iv-value [ , algorithm ] ] ] )

> You can provide the `data-to-encrypt` as a `CHARACTER`, `LONGCHAR`, `RAW`, or `MEMPTR` variable, and the `ENCRYPT` function evaluates to a `MEMPTR` value containing the encrypted binary byte stream of the data. You can provide the `data-to-decrypt` as a `MEMPTR` or `RAW` variable containing an encrypted binary byte stream, and the `DECRYPT` function evaluates to a `MEMPTR` value containing the decrypted binary byte stream of the data. You can then convert the decrypted `MEMPTR` value to a `CHARACTER` or `LONGCHAR` in order to make the decrypted data human-readable. If you need to encrypt and decrypt more than one value, you can marshall these items to and unmarshall them from a `MEMPTR` using `PUT-``datatype` statements and `GET-``datatype` functions.

> If you specify a parameter value for any of the function options, it overrides any setting of the corresponding `SECURITY-POLICY` handle attribute. In order to successful decrypt an encrypted value (resulting in a `DECRYPT` return value identical to the `data-to-encrypt` value that you input to `ENCRYPT)`, you must invoke both functions using identical cryptographic parameters as shown in Table 2–14, whether you supply them as function options or as attributes of your application cryptography policy.

> Table 2–14: ENCRYPT/DECRYPT function parameters
> Set this cryptographic parameter using... | This function option... | Or this SECURITY-POLICY handle attribute...
> --- | --- | ---
> Symmetric key |
>     encrypt-key
>     SYMMETRIC-ENCRYPTION-KEY
> Initialization vector |
>     iv-value
>     SYMMETRIC-ENCRYPTION-IV
> Algorithm, mode, and key size |
>     algorithm
>     SYMMETRIC-ENCRYPTION-ALGORITHM

> For many applications, you do not need to specify an initialization vector and can use the default algorithm, mode, and key size (`"AES_CBC_128"`). Typically, you only need to set these values to satisfy specific application requirements.

> You must handle all generation, storage, transportation, and provision of the symmetric key and all other values required to decrypt data that you have encrypted. This includes maintaining binary keys in the correct byte endian order for the platform or platforms where cryptographic operations occur.

> For information on:

> - The `SECURITY-POLICY` system handle, see the "Creating and maintaining a cryptography policy" section.

> - Key generation, see the "Generating encryption keys" section.

> - Managing and transporting keys and data, see the "Managing and transporting crypto data" section.

> The following section describes some code examples using the 4GL cryptographic functions.

> Example code using the ENCRYPT and DECRYPT functions

> This section shows basic uses of the 4GL symmetric cryptography functions and related 4GL elements.

> Example 2–1 shows the use of a random binary key to encrypt the text `"Bathtub Pancake Ladybug"`.

>     DEFINE VARIABLE binary-key AS RAW.
>     DEFINE VARIABLE clear-text AS CHARACTER INIT "Bathtub Pancake Ladybug".
>     DEFINE VARIABLE crypto-value AS RAW.
>     binary-key = GENERATE-RANDOM-KEY.
>     SECURITY-POLICY:SYMMETRIC-ENCRYPTION-KEY = binary-key.
>     SECURITY-POLICY:SYMMETRIC-ENCRYPTION-IV = ?.
>     crypto-value = Encrypt (clear-text).

> Example 2–1: Encryption using a random binary key

> For the receiver of the crypto-value to be able to successfully decrypt the value and recover the clear text requires the following information:

> 1. The name of the algorithm (the default, "AES_CBC_128", used and obtained by reading `SECURITY-POLICY:SYMMETRIC-ENCRYPTION-ALGORITHM`).

> 2. The initialization vector (none used, but available by reading `SECURITY-POLICY:SYMMETRIC-ENCRYPTION-IV`).

> 3. The binary key value.

> Note: Setting `SECURITY-POLICY:SYMMETRIC-ENCRYPTION-KEY` directly from the `GENERATE-RANDOM-KEY` function leads to an irrecoverable key because this attribute is write-only and `GENERATE-RANDOM-KEY` returns a different value if called again.

> Example 2–2 shows the use of a binary key to decrypt the text from the previous example.

>     DEFINE VARIABLE binary-key AS RAW.
>     DEFINE VARIABLE clear-text AS CHARACTER.
>     DEFINE VARIABLE crypto-value AS RAW.
>     /* binary-key is set to the same value as in the previous example */
>     SECURITY-POLICY:SYMMETRIC-ENCRYPTION-KEY = binary-key.
>     SECURITY-POLICY:SYMMETRIC-ENCRYPTION-IV = ?.
>     /* crypto-value is obtained by some means */
>     clear-text = DECRYPT (crypto-value).

> Example 2–2: Decryption using a random binary key

> Example 2–3 shows the use of a password-based key to encrypt the text, `"Matter Property Mass Solid"`. The password is `"Migratory Blueberries"`.

>     DEFINE OUTPUT PARAMETER salt-value AS RAW.
>     DEFINE VARIABLE password AS CHARACTER INIT "Migratory Blueberries".
>     DEFINE VARIABLE clear-text AS CHARACTER INIT "Matter Property Mass Solid".
>     DEFINE VARIABLE crypto-value AS RAW.
>     SECURITY-POLICY:SYMMETRIC-ENCRYPTION-ALGORITHM = "AES_CBC_256".
>     SECURITY-POLICY:PBE-KEY-ROUNDS = 2000.
>     SECURITY-POLICY:PBE-HASH-ALGORITHM = "MD5".
>     SECURITY-POLICY:ENCRYPTION-SALT = GENERATE-PBE-SALT.
>     /* The salt value is passed as an OUTPUT parameter for use by the
>      * following password decryption example */
>     salt-value = SECURITY-POLICY:ENCRYPTION-SALT.
>     SECURITY-POLICY:SYMMETRIC-ENCRYPTION-KEY = GENERATE-PBE-KEY (password).
>     SECURITY-POLICY:SYMMETRIC-ENCRYPTION-IV = ?.
>     crypto-value = ENCRYPT (clear-text).

> Example 2–3: Encryption using a password-based key

> For the receiver of the crypto-value to be able to successfully decrypt the value and recover the clear text, the following information is necessary:

> 1. The name of the algorithm (a non-default value specified and obtained by reading `SECURITY-POLICY:SYMMETRIC-ENCRYPTION-ALGORITHM`).

> 2. The initialization vector (none is used, but can be set using `SECURITY-POLICY:SYMMETRIC-ENCRYPTION-IV`).

> 3. The number of hashing algorithm iterations to generate the key (a non-default value specified and obtained by reading `SECURITY-POLICY:PBE-KEY-ROUNDS`).

> 4. The salt value (obtained by reading `SECURITY-POLICY:ENCRYPTION-SALT)`.

> Note: Calling `GENERATE-PBE-SALT` function again produces a different salt value and is not useful in generating the binary key necessary to decrypt the text.

> 5. The hash algorithm used to transform the password into the binary key (a non-default value specified and obtained by reading `SECURITY-POLICY:PBE-HASH-ALGORITHM`).

> 6. The password text.

> In place of items 3 through 6, the binary key value itself can be supplied. Because `SECURITY-POLICY:SYMMETRIC-ENCRYPTION-KEY` is write-only, an intermediate `RAW` variable can be used to hold the value returned from the `GENERATE-PBE-KEY` function, or the function may be called again with the same password value (it will return the same result provided the `SECURITY-POLICY` system handle attributes `SYMMETRIC-ENCRYPTION-ALGORITHM, PBE-KEY-ROUNDS`, `PBE-HASH-ALGORITHM`, and `ENCRYPTION-SALT` all have the same values).

> Example 2–4 shows the use of a password-based key to decrypt the text from the previous example. The password is `"Migratory Blueberries"`.

>     /* The salt value from the previous password encryption example is
>      * passed in as an INPUT parameter */
>     DEFINE INPUT PARAMETER salt-value AS RAW.
>     /* The password is most likely obtained from the user and not
>      * in the code as shown here. */
>     DEFINE VARIABLE password AS CHARACTER INIT "Migratory Blueberries".
>     DEFINE VARIABLE clear-text AS CHARACTER.
>     DEFINE VARIABLE crypto-value AS RAW.
>     SECURITY-POLICY:SYMMETRIC-ENCRYPTION-ALGORITHM = "AES_CBC_256".
>     SECURITY-POLICY:PBE-KEY-ROUNDS = 2000.
>     SECURITY-POLICY:PBE-HASH-ALGORITHM "MD5".
>     SECURITY-POLICY:ENCRYPTION-SALT = salt-value.
>     SECURITY-POLICY:SYMMETRIC-ENCRYPTION-KEY = GENERATE-PBE-KEY (password).
>     SECURITY-POLICY:SYMMETRIC-ENCRYPTION-IV = ?.
>     /* crypto-value is obtained by some means */
>     clear-text = DECRYPT (crypto-value).

> Example 2–4: Decryption using a password-based key

Copyright © 2005 Progress Software Corporation www.progress.com Voice: (781) 280-4000 Fax: (781) 280-4095