diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
new file mode 100644
index 0000000000000000000000000000000000000000..f787f8b897e8ec6b3718158257f9f360e3bbb5b3
--- /dev/null
+++ b/.gitlab-ci.yml
@@ -0,0 +1,29 @@
+################
+# GitLabCI template for Drupal projects.
+#
+# This template is designed to give any Contrib maintainer everything they need to test, without requiring modification.
+# It is also designed to keep up to date with Core Development automatically through the use of include files that can be centrally maintained.
+# As long as you include the project, ref and three files below, any future updates added by the Drupal Association will be used in your
+# pipelines automatically. However, you can modify this template if you have additional needs for your project.
+# The full documentation is on https://project.pages.drupalcode.org/gitlab_templates/
+################
+
+# For information on alternative values for 'ref' see https://project.pages.drupalcode.org/gitlab_templates/info/templates-version/
+# To test a Drupal 7 project, change the first include filename from .main.yml to .main-d7.yml
+include:
+  - project: $_GITLAB_TEMPLATES_REPO
+    ref: $_GITLAB_TEMPLATES_REF
+    file:
+      - '/includes/include.drupalci.main.yml'
+      - '/includes/include.drupalci.variables.yml'
+      - '/includes/include.drupalci.workflows.yml'
+#
+################
+# Pipeline configuration variables are defined with default values and descriptions in the file
+# https://git.drupalcode.org/project/gitlab_templates/-/blob/main/includes/include.drupalci.variables.yml
+# Uncomment the lines below if you want to override any of the variables. The following is just an example.
+################
+variables:
+  _TARGET_PHP: "8.1"
+  _TARGET_CORE: "10.1.3"
+  SYMFONY_DEPRECATIONS_HELPER: disabled
diff --git a/src/WebformEncryptSubmissionStorage.php b/src/WebformEncryptSubmissionStorage.php
index 6e5622bef99dc8e9dd54fb9f9afa22b9127f90fe..28304e7cd6001252dd9e40173006215f3d7ac9ee 100644
--- a/src/WebformEncryptSubmissionStorage.php
+++ b/src/WebformEncryptSubmissionStorage.php
@@ -143,6 +143,12 @@ class WebformEncryptSubmissionStorage extends WebformSubmissionStorage {
    * @throws \Drupal\encrypt\Exception\EncryptException
    */
   protected function encrypt($string, EncryptionProfileInterface $encryption_profile) {
+    // Prevent multiple encryptions.
+    $unserialized = @unserialize($string, ['allowed_classes' => FALSE]);
+    if ($unserialized !== FALSE && !empty($unserialized['data']) && !empty($unserialized['encrypt_profile'])) {
+      return $string;
+    }
+
     // Serialize the data to include the encryption profile.
     // This is used later to check for changes in the profile.
     $encrypted_data = [
@@ -169,8 +175,8 @@ class WebformEncryptSubmissionStorage extends WebformSubmissionStorage {
     if ($check_permissions && !$this->currentUser->hasPermission('view encrypted values')) {
       return '[Value Encrypted]';
     }
-    $unserialized = unserialize($data);
-    if (isset($unserialized['data']) && isset($unserialized['encrypt_profile'])) {
+    $unserialized = @unserialize($data, ['allowed_classes' => FALSE]);
+    if ($unserialized !== FALSE && isset($unserialized['data']) && isset($unserialized['encrypt_profile'])) {
       $encryption_profile = EncryptionProfile::load($unserialized['encrypt_profile']);
       return $this->encryptionService->decrypt($unserialized['data'], $encryption_profile);
     }
@@ -236,6 +242,25 @@ class WebformEncryptSubmissionStorage extends WebformSubmissionStorage {
     }
   }
 
+  /**
+   * {@inheritdoc}
+   */
+  public function resave(EntityInterface $entity) {
+    /** @var \Drupal\webform\WebformSubmissionInterface $entity */
+
+    $data_original = $entity->getData();
+    $webform = $entity->getWebform();
+
+    $encrypted_data = $this->encryptElements($data_original, $webform);
+    $entity->setData($encrypted_data);
+
+    $id = parent::resave($entity);
+
+    $entity->setData($data_original);
+
+    return $id;
+  }
+
   /**
    * {@inheritdoc}
    */
diff --git a/tests/src/Kernel/WebformEncryptSubmissionStorageTest.php b/tests/src/Kernel/WebformEncryptSubmissionStorageTest.php
index 298bbcbae1431c39beba53e62a36e75170cfb474..d0052a992204dc40784c731325e265da4877ae19 100644
--- a/tests/src/Kernel/WebformEncryptSubmissionStorageTest.php
+++ b/tests/src/Kernel/WebformEncryptSubmissionStorageTest.php
@@ -216,4 +216,83 @@ class WebformEncryptSubmissionStorageTest extends KernelTestBase {
     $this->assertEquals('Test text field value', $data['test_text_field']);
   }
 
+  /**
+   * Tests save and resave methods encrypt data correctly.
+   */
+  public function testSaveResaveWebform() {
+    $this->assertEquals(NULL, $this->container->get('state')->get('test_webform_handler_counter'));
+
+    $webform = Webform::load('test_encryption');
+    $original_values = [
+      'id' => 'webform_submission_test',
+      'webform_id' => $webform->id(),
+      'data' => [
+        'test_text_field' => 'Test text field value',
+        'test_multiple_text_field' => [
+          0 => 'Test multiple text field value 1',
+        ],
+        'test_text_area' => 'Test text area value',
+        'test_not_encrypted' => 'Test not encrypted value',
+        'test_address_field' => [
+          'address' => 'Test address field address',
+          'address_2' => 'Test address field address 2',
+          'city' => 'Test address field city',
+          'state_province' => 'California',
+          'postal_code' => 'AA11AA',
+          'country' => 'United Kingdom',
+        ],
+        'test_multiple_address_field' => [
+          0 => [
+            'address' => 'Test multiple address field address',
+            'address_2' => 'Test multiple address field address 2',
+            'city' => 'Test multiple address field city',
+            'state_province' => 'California',
+            'postal_code' => 'AA11AA',
+            'country' => 'United Kingdom',
+          ],
+        ],
+      ],
+    ];
+    /** @var \Drupal\webform\WebformSubmissionInterface $webform_submission */
+    $webform_submission = WebformSubmission::create($original_values);
+    // Calling the save method should encrypt the data in the DB.
+    $webform_submission->save();
+    $submissions_after_save = \Drupal::database()->select('webform_submission_data', 'wsd')
+      ->fields('wsd', [])
+      ->execute()
+      ->fetchAllAssoc('name');
+    foreach ($submissions_after_save as $name => $submission) {
+      if ($name == 'test_not_encrypted') {
+        $this->assertEquals($original_values['data'][$name], $submission->value);
+        continue;
+      }
+      $this->assertNotEquals($original_values['data'][$name], $submission->value);
+    }
+    // All data should be decrypted as normally after being saved.
+    $data = $webform_submission->getData();
+    foreach ($data as $name => $value) {
+      $this->assertEquals($original_values['data'][$name], $value);
+    }
+
+    // Calling the resave method should keep the data encrypted in the DB.
+    $webform_submission->resave();
+    $submissions_after_resave = \Drupal::database()->select('webform_submission_data', 'wsd')
+      ->fields('wsd', [])
+      ->execute()
+      ->fetchAllAssoc('name');
+    foreach ($submissions_after_resave as $name => $submission) {
+      if ($name == 'test_not_encrypted') {
+        $this->assertEquals($original_values['data'][$name], $submission->value);
+        continue;
+      }
+      $this->assertNotEquals($original_values['data'][$name], $submission->value);
+    }
+
+    // All data should be decrypted as normally after calling resave.
+    $data = $webform_submission->getData();
+    foreach ($data as $name => $value) {
+      $this->assertEquals($original_values['data'][$name], $value);
+    }
+  }
+
 }