Problem/Motivation
The Webform Encrypt module could be enabled at any point after installing the Webform module. It means at some point, we would have both original and encrypted submissions, and one of them wouldn't be able to retrieve. Similar scenario applicable when the encryption profile and/or key used in the profile changes.
We need the ability to encrypt pre-existing data, for this we would need the ability to encrypt a large amount of submissions in one shot.
Scenarios
Scenario 1: No encrypt
1. Enable Webform module
2. Create a webform node (i.e. nid=1).
3. Submit an entry (i.e. sid=1).
4. Export ALL submissions of nid=1
Expected: Data of sid 1 is exported correctly.
Actual: PASS: works by default.
Scenario 2: With a new encrypt profile
6. Enable Webform Encrypt module
7. Add a key
8. Add an encryption profile and assign the key created in #7
9. Edit the webform node
10. Assign the profile created in step #7 to a field(i.e. "email address" field) in the form
11. Submit an entry (i.e. sid=2) on webform node created in step #2
12. Export ALL submissions of nid=1
Expected: Data of sid 1 & 2 are exported correctly.
Actual: SUCCESS: successfully downloaded sid=1 & 2. As the sid=1 data saved as original and sid=2's encrypted data saved as serialized value with profile details (e.g. a:2:{s:4:"data";s:210:"def5020037cc29bb09c7efc78614c5370d0c16a384231a9c31cbb7a825f87f48b7794d74d02112e2fa1cf24ffe2f79f2df4f7a01fbea92822932339061e48ff7d1381dcee235dd364f4aef6864e9faa5e428e59edf94b430ebfe9d46e9ebac60464b99e17847e722fa";s:15:"encrypt_profile";s:15:"webform_profile";}), we don't really loose any data in this scenario.
Scenario 3: With an updated key
13. Update the key created in #7
14. Submit an entry (i.e. sid=3) on webform node created in step #2
15. Export ALL submissions of nid=1
Expected: Data of sid 1 , 2 & 3 are exported correctly.
Actual: FAIL: successfully downloaded sid=1 and 3, but sid=2 data currepted/empty.
Scenario 4: With an updated encrypt profile
13. Edit the encryption profile created in #8 and update e.g. "Encryption method".
14. Submit an entry (i.e. sid=4) on webform node created in step #2
15. Export ALL submissions of nid=1
Expected: Data of sid 1, 2, 3 & 4 are exported correctly.
Actual: FAIL: successfully downloaded sid=1 & 4, but sid=2 & 3 data currepted/empty.
Scenario 5: without an encrypt profile
16. Delete the encrypt profile created in step #8
17. Submit an entry (i.e. sid=4) on webform node created in step #2
18. Export ALL submissions of nid=1
Expected: Data of sid 1, 2, 3, 4 & 5 are exported correctly.
Actual: FAIL: successfully downloaded sid=1 & 5, but data of sid=2, 3 & 4 are currepted.
Test setup
Above scenarios are tested with:
Encryption method: Real AES
Encryption key: Config based key.
Proposed resolution
Scenario 1: No encrypt - Already working!
Scenario 2: With a new encrypt profile - functionally working (Thanks to #2931711: Tracking an elements encryption status) but the old submission with original data in DB wouldn't be encrypted when assigning the new profile.
Proposed solution(s): As part of profile save, trigger the bulk encrypt to convert existing entries.
Scenario 3: With an updated key - Not working
IMO, this is the hardest of all scenarios as there are few cases the key can be changed/removed:
1. Update key from an encryption profile (via. admin/config/system/encryption/profiles/manage/[profile_name]
2. Update the key value in the existing key (via. admin/config/system/keys/manage/[key_name]
3. Change at source (e.g. update the content of key file directly)
Even though use cases #1 and #2 warn the user editing them would cause data loss, doesn't prevent the user to do so. As @Rob Holmes mentioned in #12 there could be a valid reasons (e.g. key breached) to update the key.
Proposed solution(s):
1. For use case #1, Disable option to change/delete encryption method/key at the profile - Suggest an alternative way to change them by creating a new profile with new key and method and switch profile. - This would align with the approach in the latest patch.
2. For use case #2, Provide an alternative approach for a key change - Create a new profile with a new key and switch profile - This would align with the approach in the latest patch. I also think some of these approaches should be pushed to upstream (encrypt and key modules) rather than try to solve here.
3. use case #3 is the tricky one and a) we could make it an exception and not provide any solution. b) Wonder if we could do a hash approach (like the core's config _core.hash) where we can keep the important data that could break the encryption/decryption as hash and try to check if any part of the profile has changed. The solution could be similar to #2931711: Tracking an elements encryption status where save the MD5 of profile data in a table. This could cause performance issues though.
Scenario 4: With an updated encrypt profile
Proposed solution(s): Solution in scenario 3 use case #1 applicable here.
Scenario 5: without an encrypt profile
Proposed solution(s): This would require bulk decryption similar to scenario 2, but it's mandatory to run it as part of field config update.
Proposed resolution
Create a BulkEncryption service class to facilitate these kinds of bulk operations, the current uninstall hook decryption could then be replaced by a call to this class.
I think it makes sense for these to be batch operations that can be called progressively or non-progressively depending on the situation.