When dealing with sensitive customer data, such as Stripe API keys, OpenAI API keys, etc, we need to be careful and only store encrypted data in the database. This tutorial will outline how we encrypt and decrypt messages within the CouchCMS workflow.
Brief Overview
Encryption is a process that converts readable data (plaintext) into an unreadable format (ciphertext), using a specific key. When it comes to web applications or services, encryption ensures that data transferred between systems or stored in databases remains safe and secure.
Simply include the ecryption.html file before you call the functions in your code.
IMP: Follow best practices here. Avoid committing the file where the key is held to version control, and consider placing that file above the webroot in case your server is mal-configured (you can never be too cautious). Thanks for the tip @KK.
Requires PHP 7.2+
Read more about PHP's Sodium extension here: https://php.watch/articles/modern-php-e ... ion-sodium
Now, let's see some basic usage of these functions.
Key Generation:
Encryption
Decryption
Now that we've got a sneak peek of how to use these functions, let's dive into the technical details.
- - - - -
Digging Deeper
Our simple toolkit consists of three primary functions built using Couch's native <cms:func> tag - encrypt-keygen, encrypt, and decrypt. Note: you can read more about the <cms:func> tag as introduced here: viewtopic.php?f=8&t=11368&start=10#p30174 and documented here: https://simonwpt.github.io/CouchDocs/ta ... /func.html
1. encrypt-keygen
The encrypt-keygen function generates a new encryption key, a vital element in the encryption and decryption process that you should store somewhere safe, like couch/config.php.
This function generates a new key using the PHP Sodium library's 'sodium_crypto_secretbox_keygen' function and then transforms this binary key into a hex string with 'sodium_bin2hex'. It's important to manually take this generated key and place it in the couch/config.php file under the K_ENCRYPTION_KEY constant.
2. encrypt
The encrypt function takes in a string and an encryption key, performing the actual encryption.
This function retrieves the key, generates a nonce (Number Used Once), and uses these alongside the 'sodium_crypto_secretbox' function to encrypt the message.
3. decrypt
Finally, the 'decrypt' function takes an encrypted string and the key, returning the original plaintext data.
Wrapping Up
1. Use 'encrypt-keygen' function to create a valid key and manually store in our database
2. Use 'encrypt' function to encrypt and safely store encrypted strings in our database
3. Use 'decrypt' to decrypt encrypted strings from the database and check them against provided strings.
By integrating these cryptography functions into our CouchCMS workflows, we can protect sensitive data. Very handy and responsible!
If you have any thoughts or suggestions, I'd love to hear them!
Happy Couch-ing
Brief Overview
Encryption is a process that converts readable data (plaintext) into an unreadable format (ciphertext), using a specific key. When it comes to web applications or services, encryption ensures that data transferred between systems or stored in databases remains safe and secure.
Simply include the ecryption.html file before you call the functions in your code.
IMP: Follow best practices here. Avoid committing the file where the key is held to version control, and consider placing that file above the webroot in case your server is mal-configured (you can never be too cautious). Thanks for the tip @KK.
Requires PHP 7.2+
Read more about PHP's Sodium extension here: https://php.watch/articles/modern-php-e ... ion-sodium
Now, let's see some basic usage of these functions.
Key Generation:
- Code: Select all
<!-- create a key and manually store it in couch/config as K_ENCRYPTION_KEY -->
<cms:call 'encrypt-keygen' />
<cms:show keygen-response />
Encryption
- Code: Select all
<!-- we can safely store this to the database -->
<cms:call 'encrypt' string='Sensitive Data' />
<cms:show encrypt-response />
Decryption
- Code: Select all
<!-- we can check given strings against the decrypted response -->
<cms:call 'decrypt' string='encrypted-string-from-earlier' />
<cms:show decrypt-response />
Now that we've got a sneak peek of how to use these functions, let's dive into the technical details.
- - - - -
Digging Deeper
Our simple toolkit consists of three primary functions built using Couch's native <cms:func> tag - encrypt-keygen, encrypt, and decrypt. Note: you can read more about the <cms:func> tag as introduced here: viewtopic.php?f=8&t=11368&start=10#p30174 and documented here: https://simonwpt.github.io/CouchDocs/ta ... /func.html
1. encrypt-keygen
The encrypt-keygen function generates a new encryption key, a vital element in the encryption and decryption process that you should store somewhere safe, like couch/config.php.
- Code: Select all
<cms:func 'encrypt-keygen' into='keygen-response' scope='global'>
<cms:php>
global $CTX;
$key = sodium_crypto_secretbox_keygen();
$hex_key = sodium_bin2hex($key);
$CTX->set("<cms:show into />", $hex_key, "<cms:show scope />");
</cms:php>
</cms:func>
This function generates a new key using the PHP Sodium library's 'sodium_crypto_secretbox_keygen' function and then transforms this binary key into a hex string with 'sodium_bin2hex'. It's important to manually take this generated key and place it in the couch/config.php file under the K_ENCRYPTION_KEY constant.
2. encrypt
The encrypt function takes in a string and an encryption key, performing the actual encryption.
- Code: Select all
<cms:func 'encrypt' string='' into='encrypt-response' scope='global'>
<cms:php>
global $CTX;
$message = "<cms:show string />";
$key = sodium_hex2bin(K_ENCRYPTION_KEY);
$nonce = random_bytes(SODIUM_CRYPTO_SECRETBOX_NONCEBYTES);
$ciphertext = sodium_crypto_secretbox($message, $nonce, $key);
$encrypted = base64_encode($nonce . $ciphertext);
$CTX->set("<cms:show into />", $encrypted, "<cms:show scope />");
</cms:php>
</cms:func>
This function retrieves the key, generates a nonce (Number Used Once), and uses these alongside the 'sodium_crypto_secretbox' function to encrypt the message.
3. decrypt
Finally, the 'decrypt' function takes an encrypted string and the key, returning the original plaintext data.
- Code: Select all
<cms:func 'decrypt' string='' into='decrypt-response' scope='global'>
<cms:php>
global $CTX;
$key = sodium_hex2bin(K_ENCRYPTION_KEY);
$nonceFromEncrypted = mb_substr(base64_decode("<cms:show string />"), 0, SODIUM_CRYPTO_SECRETBOX_NONCEBYTES, '8bit');
$ciphertextFromEncrypted = mb_substr(base64_decode("<cms:show string />"), SODIUM_CRYPTO_SECRETBOX_NONCEBYTES, null, '8bit');
$decrypted = sodium_crypto_secretbox_open($ciphertextFromEncrypted, $nonceFromEncrypted, $key);
if ($decrypted === false) {
throw new Exception('The message was tampered with in transit');
}
$CTX->set("<cms:show into />", $decrypted, "<cms:show scope />");
</cms:php>
</cms:func>
Wrapping Up
1. Use 'encrypt-keygen' function to create a valid key and manually store in our database
2. Use 'encrypt' function to encrypt and safely store encrypted strings in our database
3. Use 'decrypt' to decrypt encrypted strings from the database and check them against provided strings.
By integrating these cryptography functions into our CouchCMS workflows, we can protect sensitive data. Very handy and responsible!
If you have any thoughts or suggestions, I'd love to hear them!
Happy Couch-ing