9.79 ENCRYPT
Þ Note: Built-In Function Rules.
Encrypt a text string.
A companion Built-in Function, 9.35 DECRYPT, is used to decode the encrypted text string.
Warning: From this version (LANSA V11 SP4) onward, a blank key won't be used to encrypt, a generated key will be used instead if the key argument is passed with all blanks. In versions prior to V11 SP4, encrypt will have a key of all spaces.
|
Arguments
|
Return Values
|
Technical Notes
- Cipher block encryption algorithms always encrypt and decrypt blocks of 8 characters. Therefore the actual value you encrypt must have a length that is a multiple of 8.
- The encrypted data returned by the encryption algorithm is binary data and can contain any value. As such, using it or passing it through environments where it may be subject to code page conversion (eg: database managers, communications links, etc) or where special characters like CR, LF or binary zero may cause issues (eg: HTML or XML documents, string processing, stream file processing, etc) may prove to be problematic. As such it is recommended that encrypted data is physically stored in hexadecimal format.
- Unicode fields are converted to UTF-8 before encryption. This allows a Unicode field to be encrypted on one platform and decrypted on another. It also means that the encryption length (argument 2) can be up to 3 times the length of the text to be encrypted (argument 1). And then if the result is stored in hex it's further doubled in size. So if you have a 500 character NVarchar then the encrypted length should be 1500 and the size of the returned encrypted text should be 3000. If you do not have the lengths in this ratio then data may be lost.
Examples
Following are two RDML subroutines that demonstrate a generic encryption technique for any information up to 16 characters in length.
For example EXECUTE ENCRYPT (#KEY #PROD_NUM #PROD_ENC) might encrypt #PROD_NUM (char 10) to produce encrypted #PROD_ENC (char 32).
Note that even though the subroutine parameter #PROD_NUM is a char 10 field, the resulting encryption field #PROD_ENC is char 32.
This is because the initial binary encryption requires an input that is a multiple of 8 (ie: char 10 #PROD_NUM is padded with blanks to be 16 bytes long by the subroutine execution) and it produces a hexadecimal representation of the encrypted binary data, which is therefore 32 bytes long.
All 32 bytes of #PROD_ENC need to be stored for successful decryption to occur later.
To decrypt these values you would code EXECUTE DECRYPT (#KEY #PROD_ENC #PROD_NUM).
Here the 32 byte hexadecimal value is first converted to binary, decrypted and then returned as a char 16.
The subroutine finally returns the decrypted value right truncated into #PROD_NUM as a char 10.
ENCRYPT a value with a supplied key and return a 32 byte encrypted value in hex
********** =======================================================
********** Sample routine to Encrypt a passed in value (up to 16
********** bytes in length) with a supplied key and return a
********** 32 byte encrypted value in hex (suitable for storing in
********** database, etc)
********** =======================================================
SUBROUTINE NAME(ENCRYPT) PARMS((#KEY16 *RECEIVED) (#VAL16 *RECEIVED) (#HEX32 *RETURNED))
DEFINE FIELD(#KEY16) TYPE(*CHAR) LENGTH(16) DESC('Encryption key supplied')
DEFINE FIELD(#VAL16) TYPE(*CHAR) LENGTH(16) DESC('Value to be encrypted')
DEFINE FIELD(#HEX32) TYPE(*CHAR) LENGTH(32) DESC('Encrypted value in Hex')
DEFINE FIELD(#LEN) TYPE(*DEC) LENGTH(5) DECIMALS(0)
CHANGE #LEN 16
********** Use ENCRYPT BIF to encrypt #VAL16 of length #LEN using
********** #KEY16 to return encrypted value in #HEX32
********** The encrypted value is converted into HEX resulting in
********** a 32 byte value.
USE BUILTIN(ENCRYPT) WITH_ARGS(#VAL16 #LEN #KEY16 YES) TO_GET(#HEX32)
ENDROUTINE
********** =======================================================
DECRYPT a Hex value using the supplied key and return the unencrypted value
********** =======================================================
********** Sample routine to Decrypt a passed in Hex value
********** using the supplied key and return the unencrypted
********** value.
********** =======================================================
SUBROUTINE DECRYPT ((#DKEY16 *Received)(#DHEX32 *Received) (#DVAL16 *Returned))
********** Key to be used for the decryption. This must be the
********** same key that was used for the encryption.
DEFINE #DKEY16 *char 16
DEFINE FIELD(#DHEX32) TYPE(*CHAR) LENGTH(32) DESC('Encrypted value in hex')
DEFINE FIELD(#DVAL16) TYPE(*CHAR) LENGTH(16) DESC('Decrypted value returned')
DEFINE FIELD(#DLEN) TYPE(*DEC) LENGTH(5) DECIMALS(0)
CHANGE FIELD(#DLEN) TO(16)
**********
**********
********** Use DECRYPT BIF to decrypt character #HEX32 of length
********** #DLEN using #DKEY16 to return decrypted value,#DVAL16
**********
USE BUILTIN(DECRYPT) WITH_ARGS(#HEX32 #DLEN #DKEY16 YES) TO_GET(#DVAL16)
ENDROUTINE
ENCRYPT a password and then DECRYPT
DEFINE FIELD(#PASSWORD) TYPE(*CHAR) LENGTH(10)
DEFINE FIELD(#TEXT) TYPE(*CHAR) LENGTH(16)
DEFINE FIELD(#LENGTH) TYPE(*DEC) LENGTH(11) DECIMALS(0)
DEFINE FIELD(#KEY) TYPE(*CHAR) LENGTH(16)
DEFINE FIELD(#RETCODE) TYPE(*CHAR) LENGTH(2)
DEFINE FIELD(#ENCRYPTED) TYPE(*CHAR) LENGTH(16)
DEFINE FIELD(#DECRYPTED) TYPE(*CHAR) LENGTH(16)
**********
********** Encrypt password with key
CHANGE #TEXT #PASSWORD
CHANGE #LENGTH 16
CHANGE #KEY 'AXG12345lj0gtUMX'
USE BUILTIN(ENCRYPT) WITH_ARGS(#TEXT #LENGTH #KEY) TO_GET(#ENCRYPTED #RETCODE)
**********
********** Decrypt password with same key as provided for encryption
CHANGE #LENGTH 16
USE BUILTIN(DECRYPT) WITH_ARGS(#ENCRYPTED #LENGTH #KEY) TO_GET(#DECRYPTED #RETCODE)
**********