Hi all!
I've been programming with SAS in my job for 6 years. One thing I miss in Base SAS is the functionality of encrypting a single value or a collection of them, like a variable in a dataset. I'm not talking about hashing a variable, nor encrypting the entire dataset...I want to genuinely encrypt and decrypt values, using some encryption scheme, as defined in the Password-Based Cryptography Specificaton, aka PKCS #5
I have initiated a project to develop code (100% SAS code) to implement this functionality. For now, the basic AES algorithm for encrypting and decrypting basic 128 bits-lengh blocks is done. You can encrypt them with a single macro call:
/* Message to be encrypted */
%let message=00112233445566778899aabbccddeeff;
%put NOTE: Original message: &message;
/* Encryption with a 128-bit key */
%let key128=000102030405060708090a0b0c0d0e0f;
%let cryptogram128=%cipherAES(&message, &key128);
%put NOTE: Message encrypted with 128-bit key: &cryptogram128;
and then decrypt with another call:
/* Decryption with a 128-bit key */
%let messageDecrypted128=%invCipherAES(&cryptogram128, &key128);
%put NOTE: Message decrypted with 128-bit key: &messageDecrypted128;
The encryption key can have 3 lengths: 128, 192 and 256 bit, according to the AES:
/* Encryption with a 192-bit key */
%let key192=000102030405060708090a0b0c0d0e0f1011121314151617;
%let cryptogram192=%cipherAES(&message, &key192);
%put NOTE: Message encrypted with 192-bit key: &cryptogram192;
/* Encryption with a 256-bit key */
%let key256=000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f;
%let cryptogram256=%cipherAES(&message, &key256);
%put NOTE: Message encrypted with 256-bit key: &cryptogram256;
These macros are, in fact, macrofunctions, but they can encrypt the N values of a dataset variable too:
/* Compute cryptograms and store them in macrovar */
proc sql noprint;
select '%cipherAES('||m||','||k||')' into :cryptograms separated by ' ' from testMessages;
quit;
The project is a work in progress. To be fully functional, at least one of the encryption Schemes defined in the PKCS #5 specification must be fully implemented. For this purpose, it will be needed at least:
a password-based key derivation function, tipically PBKDF2
a block cypher mode of operation, for example Cipher Block Chaining
a padding scheme, defined in Cryptographic Message Syntax
With that elements implemented, the implementation of the AES-CBC-Pad would be complete.
For now, the AES protocol implementation is all I have done. The project can be found here:
https://github.com/AlexBennasar/Crypto-SAS
Maybe this project will be interesting/useful for somebody.
EDIT 14/07/2022
The Password-Based Key Derivation Function (PBKDF2) is now implemented, for now with only one pseudorandom function (PRF), the HMAC-SHA256.
As an example of use, we derive here a key given a password, a salt, an iteration count (number of rounds to perform), and the desired derived key length:
/* Password */
%let password=%str(//superSecretPW***);
/* Salt */
%let salt=12a5bc669820edc56710bbf55210aaed;
/* Number of rounds */
%let iCount=1024;
/* Pseudorandom function */
%let PRF=%str(hmac-sha256);
/* Length in bytes of the derived key */
%let derivedKeyLength=32;
/* Key derivation */
%let derivedKey=%PBKDF2(&password, &salt, &iCount, &PRF, &derivedKeyLength);
%put NOTE: Derived key: &derivedKey;
You can check the code and the example here: Crypto-SAS/PBKDF2
... View more