Shift encrypted data in DB

Post Written by
Ivan Dabić
Last modified on July 6th, 2020 at 11:50 am

I wanted to share interesting approach to storing sensitive data in DB where the same has to be encrypted and decrypted gracefully. I’d like to point out that there is a difference between sensitive data that needs to be stored for usage in plain form and sensitive data that needs no lain form presentation (passwords). Common use of passwords: Passwords are never decrypted as that presents a security weakness by allowing 3rd party to intersect the plain form password and use it to take over the existing or create new “valid” session as someone else (someone with legitimate privilege to do so). To prevent this from happening passwords are kep in form of a hash value and validation is performed as comparison of repeated hash calculation of validated string against existing hash string in DB. With data set where sensitive data like API keys for different sub-services and every time API key needs to be used to establish new connections to API servers these keys refer to, we want to have a safe way of decrypting these keys - use them - close the connections. To address just one term used here: “safe way of decrypting”, whatever you do it’s only way of decrypting data - safe, unless you are transporting decrypted data or keys through unprotected channel. In a localized environment we want to grab the encryption key, decrypt data and use it. The idea behind this post is to define a new level of encrypted data store in environment where encrypted data is transferred through potentially unsafe channel and there could be justified threat of a man in the middle attack. Good approach is to have a matrix that is capable of generating pseudo random arrays subsequently and mix it with secondary source of PRNG as required per individual basis. This will be used to generate master encryption key. Eventually the data flow and encrypt - decrypt flow should be as follows:

  1. Initial encryption of data with master key
  2. Decrypt data with master key
  3. Use matrix and PRNG to generate NEW master key
  4. Use NEW master key to encrypt decrypted data and store it back to DB

To prevent efficient brute force attack regeneration of NEW master key was set to happen on 2 minute basis. Generating new master encryption key happens by the steps described on the scheme below:

  1. PRNG generates 22 characters long string from the array of alphanumeric characters which is then being base64 encoded creating initial_secret.
  2. Timestamp (UNIX timestamp) is generated and concatenated with initial_secret and pulled through sha512 algorithm to create block_1.
  3. Then block_1 and initial_salt (pre-generated private secret) are being concatenated to make block_2 together.
  4. initial_salt and initial_secret are concatenated to make block_3 together.
  5. block_3 is hashed via sha512 to make pre_encryption_salt_block.
  6. block_2 is hashed via sha512 to make pre_encryption_block.
  7. block_2 and block_3 are concatenated and hashed via sha512 to make final encryption_key which is used in AES (MCRYPT_RIJNDAEL_256 - MCRYPT_MODE_CBC) implementation further.

PRNG and initial_secret:

$chars = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'; $charsLen = strlen($chars); $initial_secret = ''; for ($i = 0; $i < 22; $i++) { $initial_secret .= $characters[rand(0, $charsLen - 1)]; }

RIJNDAEL implementation

I’ve chosen to go with RIJNDAEL-256 and following implementation described on scheme below.

Encryption

  1. Function gets the encryption key it suppose to perform the encryption with
  2. Get last 64 characters from it (used for internal standardisation with the rest of the system)
  3. Convert given string to HEXADECIMAL format
  4. I am using RIJNDAEL in CBC mode so, in order for CBC to be performed properly I’ll need IV generated (PRNG)
  5. Encryption is performed
  6. Finally, appending previously generated IV to the beginning of the newly generated ciphertext
  7. Before storing it base64 encoding is applied to ciphertext

Decryption

  1. Similar to encryption process when decrypting we need same key (same 64 characters from input master encryption key)
  2. Then, again, convert it to HEXADECIMAL format
  3. Get the IV from ciphertext that will be used for decryption cycles in CBC mode
  4. Get the actual ciphertext without IV
  5. Perform decryption

This is the process I’ve cron’ed to 2-minute cycles. These were my two cents on having fun with encryption and inventing new ways to complicate things :)

Contact Us

Fill out the enquiry form and we'll get back to you as soon as possible.