In Quform version 2.9.0 we added hooks to allow storage of encrypted form element values: quform_get_value_for_storage for encrypting values before they are saved in the database, and quform_set_value_from_storage for decrypting values when they are retrieved from the database.

Conveniently, around the same time WordPress 5.2 added the sodium_compat library to core, allowing for simple, secure encryption without any external dependencies.

After implementing this code, any currently stored form data will not be able to be retrieved. For this reason it’s best to implement it on a fresh Quform install with no existing entries.

Additionally, the entries search will no longer match any submitted form values, as they will be encrypted.

Below is an example of using the Quform hooks and sodium functions to store encrypted values. Add the following code to the WordPress theme functions.php file (or create a plugin for it).

This code requires either WordPress 5.2 or the sodium PHP extension.

1
2
34
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
function my_encryption_key()
{
    return sodium_hex2bin('aa3ef6b8f66889b149c9ec9fdbfa6644ab73c7d4fc7d2d187ce5ac7b12ad52f6');}
 
add_filter('quform_get_value_for_storage', function ($value) {
    $key = my_encryption_key();
    $nonce = random_bytes(SODIUM_CRYPTO_SECRETBOX_NONCEBYTES);
    $ciphertext = sodium_crypto_secretbox($value, $nonce, $key);
 
    return sodium_bin2hex($nonce . $ciphertext);
});
 
add_filter('quform_set_value_from_storage', function ($value) {
    if ( ! is_string($value) || $value === '') {
        return false;
    }
 
    $key = my_encryption_key();
    $value = sodium_hex2bin($value);
    $nonce = mb_substr($value, 0, SODIUM_CRYPTO_SECRETBOX_NONCEBYTES, '8bit');
    $ciphertext = mb_substr($value, SODIUM_CRYPTO_SECRETBOX_NONCEBYTES, null, '8bit');
 
    try {
        $plaintext = sodium_crypto_secretbox_open($ciphertext, $nonce, $key);
    } catch (Exception $e) {
        $plaintext = false;
    }
 
    return $plaintext;
});
function my_encryption_key()
{
    return sodium_hex2bin('aa3ef6b8f66889b149c9ec9fdbfa6644ab73c7d4fc7d2d187ce5ac7b12ad52f6');
}

add_filter('quform_get_value_for_storage', function ($value) {
    $key = my_encryption_key();
    $nonce = random_bytes(SODIUM_CRYPTO_SECRETBOX_NONCEBYTES);
    $ciphertext = sodium_crypto_secretbox($value, $nonce, $key);

    return sodium_bin2hex($nonce . $ciphertext);
});

add_filter('quform_set_value_from_storage', function ($value) {
    if ( ! is_string($value) || $value === '') {
        return false;
    }

    $key = my_encryption_key();
    $value = sodium_hex2bin($value);
    $nonce = mb_substr($value, 0, SODIUM_CRYPTO_SECRETBOX_NONCEBYTES, '8bit');
    $ciphertext = mb_substr($value, SODIUM_CRYPTO_SECRETBOX_NONCEBYTES, null, '8bit');

    try {
        $plaintext = sodium_crypto_secretbox_open($ciphertext, $nonce, $key);
    } catch (Exception $e) {
        $plaintext = false;
    }

    return $plaintext;
});
  • On line 3, set your own encryption key which can be generated by running sodium_bin2hex(random_bytes(SODIUM_CRYPTO_SECRETBOX_KEYBYTES)); – you may want to also store the key in a secure location outside of the web root. The key size must be 32 bytes.
Be inspired. © 2019 ThemeCatcher Ltd. 20-22 Wenlock Road, London, England, N1 7GU | Company No. 08120384 | Built with React | Privacy Policy