Sodium compatibility

Created on 6 November 2023, 8 months ago

Problem/Motivation

Trying together both sodium 's encrypted method plugin for encrypt , and this extension for webform module, results in the following php fatal error.

Drupal\Core\Database\DatabaseExceptionWrapper: SQLSTATE[HY000]: General error: 1366 Incorrect string value: '\x98\xFFf_\xC8U...' for column 'value' at row 1: INSERT INTO "webform_submission_data" ("webform_id", "sid", "name", "property", "delta", "value") VALUES (:db_insert_placeholder_0, :db_insert_placeholder_1, :db_insert_placeholder_2, :db_insert_placeholder_3, :db_insert_placeholder_4, :db_insert_placeholder_5); Array
(
    [:db_insert_placeholder_0] => sample_raw_key
    [:db_insert_placeholder_1] => 1
    [:db_insert_placeholder_2] => title
    [:db_insert_placeholder_3] => 
    [:db_insert_placeholder_4] => 0
    [:db_insert_placeholder_5] => a:2:{s:4:"data";s:148:"1B␅��f_�UR␓�j��
;e�4�?Զ�'␇����c�L�4��c³���#��9Z��)8�␕72�1>�␝����␌����T␁)W␏�µ�␕␌�␌���␟␟�ELZcQ�J ��gv�␡�}���ƪ�ܫ�p�␕�1~�␞$Ư+	␛'���ũ:��Ъ:z";s:15:"encrypt_profile";s:18:"webform_sodium_raw";}
)
 in Drupal\webform\WebformSubmissionStorage->saveData() (line 1369 of /app/web/modules/contrib/webform/src/WebformSubmissionStorage.php).

The error clearly suggest that the data received to be saved is not compatible, at least with, what mysql can receive.
In other words the are some invalid characters in the output, which is expected on the output of an encrypted value.

It is worth to mention that using real_aes 's encrypted method does not produce this problem.
On that case, instead, the module works as expected.

Trying to look into the details behind real_aes module implementation at Drupal\real_aes\Plugin\EncryptionMethod\RealAESEncryptionMethod::encrypt(), I see it is using Defuse\Crypto\Encoding::binToHex() at the end of the encryption process; after being called from Defuse\Crypto\Crypto::encryptInternal(), and that from Defuse\Crypto\Crypto::encrypt().
In other words, there is a binary to hexadecimal conversion there, that may be the real reason of why it works with one but not the other.
Instead the output that sodium produces seems to not be on the binary format.

Steps to reproduce

  1. Install key, encrypt, sodium, webform, and webform_encrypt modules.
  2. Create a key, e.g. a 256-bits key. Tangential note: problem happens with or without the base64 encode of the key itself, so that may be unrelated.
  3. Create an encryption profile for encryption, using sodium plugin, and the created 256-bits key.
  4. Create a webform with one text field, and mark it to be encrypted.
  5. Try to test the created webform, and the mentioned php error will appear.

For reference here the versions of the modules used for testing.

$ composer info | grep -E -e 'drupal\/(encrypt|key|real_aes|sodium|webform|webform_encrypt)'
drupal/encrypt                                 3.1.0        Provides an API for two-way encryption.
drupal/key                                     1.17.0       Provides the ability to manage site-wide keys
drupal/real_aes                                2.5.0        Provides an Authenticated AES encryption method for Encrypt through the Defuse PHP Encryption library.
drupal/sodium                                  2.4.0        Allows data to be encrypted and decrypted using Libsodium.
drupal/webform                                 6.2.0        Enables the creation of webforms and questionnaires.
drupal/webform_encrypt                         2.0.0-alpha1 Provides encryption for webform components.

Proposed resolution

A simple way to work-around the problem, and become compatible with sodium is to put the received encrypted data into an envelope that is converted, e.g. using base64 encoding.
This approach is part of the created merge request #4, using the 3399414-base64-as-data-envelope branch.

That solution makes the problem disappear for the sodium case, and it works as expected.

For the real_aes case, it still works on the encoding side, i.e. when the webform is created, but there is a problem when accessing the values, both form the submission page of that webform, and the list of submissions page if a webform using real_aes exist.

Remaining tasks

  1. Determine if the problem may be at the webform_encrypt module, at the sodium encryption plugin module, or if there is any missing to configure it correctly.
  2. Determine if the base64 envelope approach is reasonable, and find out why it may be non-decrypting correctly for the real_aes case but it is for the sodium case.

User interface changes

N.A.

API changes

Likely internal representation of the encrypted data in the webform does not count as API change, but noting it in case it is relevant.

Data model changes

N.A.

🐛 Bug report
Status

Needs review

Version

2.0

Component

Code

Created by

🇵🇪Peru marvil07

Live updates comments and jobs are added and updated live.
Sign in to follow issues

Comments & Activities

Production build 0.69.0 2024