<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Md. Rakibul Hasan</title>
    <description>The latest articles on DEV Community by Md. Rakibul Hasan (@rakib455).</description>
    <link>https://dev.to/rakib455</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3931660%2Faf8d9079-8f65-45fa-a209-044eaeba0d6b.png</url>
      <title>DEV Community: Md. Rakibul Hasan</title>
      <link>https://dev.to/rakib455</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/rakib455"/>
    <language>en</language>
    <item>
      <title>Encrypting Sensitive Data in Spring Boot: AES-256-GCM Explained with a Real-World Example</title>
      <dc:creator>Md. Rakibul Hasan</dc:creator>
      <pubDate>Mon, 26 Oct 2026 07:02:24 +0000</pubDate>
      <link>https://dev.to/rakib455/encrypting-sensitive-data-in-spring-boot-aes-256-gcm-explained-with-a-real-world-example-3a3o</link>
      <guid>https://dev.to/rakib455/encrypting-sensitive-data-in-spring-boot-aes-256-gcm-explained-with-a-real-world-example-3a3o</guid>
      <description>&lt;p&gt;When building an insurance application, we often store sensitive information such as a driver's date of birth (DOB), driver's license number, phone number, and other personally identifiable information (PII).&lt;/p&gt;

&lt;p&gt;But what happens if someone gets access to our database?&lt;/p&gt;

&lt;p&gt;Database authentication and access control are important, but they do not necessarily protect data from someone who obtains a database dump or gains unauthorized direct database access.&lt;/p&gt;

&lt;p&gt;One way to add another layer of protection is &lt;strong&gt;application-level encryption&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;In this article, we'll explore how AES-256-GCM works, how encryption keys are managed, and how to implement field-level encryption in a Spring Boot application.&lt;/p&gt;

&lt;h2&gt;
  
  
  1. The Problem: Storing Sensitive Data in Plaintext
&lt;/h2&gt;

&lt;p&gt;Imagine our insurance application stores driver information in PostgreSQL.&lt;/p&gt;

&lt;p&gt;A database record might look like this:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;id&lt;/th&gt;
&lt;th&gt;date_of_birth&lt;/th&gt;
&lt;th&gt;driver_license&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;101&lt;/td&gt;
&lt;td&gt;2000-05-15&lt;/td&gt;
&lt;td&gt;D1234567&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The application can read this information directly from the database. Unfortunately, anyone who obtains an unauthorized copy of the database can read it too.&lt;/p&gt;

&lt;p&gt;We could hash these values, but hashing is a one-way operation. We need to recover a driver's original date of birth when calculating age or performing underwriting checks.&lt;/p&gt;

&lt;p&gt;Therefore, we need &lt;strong&gt;encryption&lt;/strong&gt;, not ordinary hashing.&lt;/p&gt;

&lt;h2&gt;
  
  
  2. Encryption vs. Hashing
&lt;/h2&gt;

&lt;p&gt;These two concepts serve different purposes.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Encryption&lt;/strong&gt; transforms readable data into ciphertext using a key. The original data can be recovered using the appropriate decryption key.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Hashing&lt;/strong&gt; transforms data into a fixed-length digest. A cryptographic hash is designed to be one-way, so the original input cannot practically be recovered from the hash.&lt;/p&gt;

&lt;p&gt;For our insurance application:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;DOB: Use encryption because the application may need the original value.&lt;/li&gt;
&lt;li&gt;Driver's license number: Use encryption if the original value must be recovered.&lt;/li&gt;
&lt;li&gt;Passwords: Use a dedicated password-hashing algorithm such as Argon2id, not reversible encryption.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Now let's look at how encryption works.&lt;/p&gt;

&lt;h2&gt;
  
  
  3. How AES-256-GCM Works
&lt;/h2&gt;

&lt;p&gt;AES stands for Advanced Encryption Standard. It is a symmetric encryption algorithm, meaning the same secret key is used for encryption and decryption.&lt;/p&gt;

&lt;p&gt;AES-256 uses a 256-bit key, which is 32 bytes long.&lt;/p&gt;

&lt;p&gt;GCM stands for Galois/Counter Mode. It is an authenticated encryption mode that provides two important security properties:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Confidentiality:&lt;/strong&gt; Unauthorized readers cannot recover the plaintext without the key.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Integrity and authenticity:&lt;/strong&gt; Modifications to the ciphertext are detected during decryption.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Let's walk through the process.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 1: Start with plaintext
&lt;/h3&gt;

&lt;p&gt;Suppose the user enters the following information:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;DOB: 2000-05-15
Driver's License: D1234567
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is plaintext: the original, readable information.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 2: Generate a random IV
&lt;/h3&gt;

&lt;p&gt;Before encrypting the data, the application generates a random 12-byte initialization vector (IV).&lt;/p&gt;

&lt;p&gt;An IV is a value used by the encryption algorithm to ensure that encrypting the same plaintext with the same key does not normally produce the same ciphertext.&lt;/p&gt;

&lt;p&gt;For example, encrypting the same license number twice should produce different encrypted outputs.&lt;/p&gt;

&lt;p&gt;The IV is not a secret. It can be stored alongside the ciphertext.&lt;/p&gt;

&lt;p&gt;However, with AES-GCM, an IV must never be reused with the same encryption key.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 3: Encrypt the plaintext
&lt;/h3&gt;

&lt;p&gt;The application passes three things to the encryption algorithm:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The plaintext.&lt;/li&gt;
&lt;li&gt;The secret AES-256 key.&lt;/li&gt;
&lt;li&gt;The randomly generated IV.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;AES-GCM produces ciphertext and an authentication tag.&lt;/p&gt;

&lt;p&gt;Conceptually:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Plaintext + Secret Key + Random IV
                  |
                  v
             AES-256-GCM
                  |
                  v
       Ciphertext + Authentication Tag
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The authentication tag allows the application to detect tampering when decrypting the data.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 4: Store the encrypted result
&lt;/h3&gt;

&lt;p&gt;The application stores the IV, ciphertext, and authentication tag together, usually encoded as Base64 for convenient database storage.&lt;/p&gt;

&lt;p&gt;The database might now contain:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;id&lt;/th&gt;
&lt;th&gt;dob_encrypted&lt;/th&gt;
&lt;th&gt;license_encrypted&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;101&lt;/td&gt;
&lt;td&gt;Base64-encoded ciphertext&lt;/td&gt;
&lt;td&gt;Base64-encoded ciphertext&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The values shown here are illustrative; actual encrypted values are longer and look like opaque encoded strings.&lt;/p&gt;

&lt;p&gt;Base64 is not encryption. It is only an encoding format for storing binary data in a text column.&lt;/p&gt;

&lt;p&gt;The security comes from AES-GCM and proper key management, not from Base64.&lt;/p&gt;

&lt;h2&gt;
  
  
  4. Where Should the Encryption Key Be Stored?
&lt;/h2&gt;

&lt;p&gt;This is one of the most important parts of the design.&lt;/p&gt;

&lt;p&gt;Suppose we encrypt every driver's DOB and license number but store the encryption key in the same database.&lt;/p&gt;

&lt;p&gt;An attacker who obtains both the database records and the key can decrypt the data.&lt;/p&gt;

&lt;p&gt;That defeats much of the intended protection.&lt;/p&gt;

&lt;p&gt;Instead, keep the key separate from the database.&lt;/p&gt;

&lt;p&gt;For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;                 Spring Boot
                      |
          +-----------+-----------+
          |                       |
          v                       v
    PostgreSQL              Key Management
    Encrypted data           Secret key
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For a small deployment, a protected environment variable can be a starting point. In a production environment, a managed Key Management Service (KMS) or secrets-management system provides stronger separation and additional operational controls.&lt;/p&gt;

&lt;p&gt;The encryption key should never be committed to Git, embedded in the Docker image, or printed in application logs.&lt;/p&gt;

&lt;p&gt;You must also maintain secure backups of the key. If the key is permanently lost, the corresponding encrypted data may become unrecoverable.&lt;/p&gt;

&lt;h2&gt;
  
  
  5. Implementing Encryption in Spring Boot
&lt;/h2&gt;

&lt;p&gt;Java provides cryptographic APIs through the Java Cryptography Architecture (JCA), so we do not need an external library just to use AES-GCM.&lt;/p&gt;

&lt;p&gt;First, generate a random 256-bit key in a trusted environment:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;openssl rand &lt;span class="nt"&gt;-base64&lt;/span&gt; 32
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Store the generated value securely and expose it to Spring Boot through your deployment's secret configuration.&lt;/p&gt;

&lt;p&gt;In &lt;code&gt;application.yml&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;app&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;encryption&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;key&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${QUOTE_ENCRYPTION_KEY}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Next, create a service responsible for encryption and decryption.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="nd"&gt;@Service&lt;/span&gt;
&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;FieldEncryptionService&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;

    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="no"&gt;TRANSFORMATION&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
            &lt;span class="s"&gt;"AES/GCM/NoPadding"&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="no"&gt;IV_LENGTH&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;12&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="no"&gt;TAG_LENGTH&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;128&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="nc"&gt;SecretKey&lt;/span&gt; &lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="nc"&gt;SecureRandom&lt;/span&gt; &lt;span class="n"&gt;secureRandom&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
            &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;SecureRandom&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;

    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nf"&gt;FieldEncryptionService&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;
            &lt;span class="nd"&gt;@Value&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"${app.encryption.key}"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;base64Key&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;

        &lt;span class="kt"&gt;byte&lt;/span&gt;&lt;span class="o"&gt;[]&lt;/span&gt; &lt;span class="n"&gt;keyBytes&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
                &lt;span class="nc"&gt;Base64&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getDecoder&lt;/span&gt;&lt;span class="o"&gt;().&lt;/span&gt;&lt;span class="na"&gt;decode&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;base64Key&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;

        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;keyBytes&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;length&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="mi"&gt;32&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;IllegalArgumentException&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;
                    &lt;span class="s"&gt;"AES-256 requires a 32-byte key"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
        &lt;span class="o"&gt;}&lt;/span&gt;

        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;key&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;SecretKeySpec&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;keyBytes&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"AES"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="nf"&gt;encrypt&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;plaintext&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;plaintext&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
        &lt;span class="o"&gt;}&lt;/span&gt;

        &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
            &lt;span class="kt"&gt;byte&lt;/span&gt;&lt;span class="o"&gt;[]&lt;/span&gt; &lt;span class="n"&gt;iv&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="kt"&gt;byte&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="no"&gt;IV_LENGTH&lt;/span&gt;&lt;span class="o"&gt;];&lt;/span&gt;
            &lt;span class="n"&gt;secureRandom&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;nextBytes&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;iv&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;

            &lt;span class="nc"&gt;Cipher&lt;/span&gt; &lt;span class="n"&gt;cipher&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
                    &lt;span class="nc"&gt;Cipher&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getInstance&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="no"&gt;TRANSFORMATION&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;

            &lt;span class="n"&gt;cipher&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;init&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;
                    &lt;span class="nc"&gt;Cipher&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;ENCRYPT_MODE&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
                    &lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
                    &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;GCMParameterSpec&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="no"&gt;TAG_LENGTH&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;iv&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
            &lt;span class="o"&gt;);&lt;/span&gt;

            &lt;span class="kt"&gt;byte&lt;/span&gt;&lt;span class="o"&gt;[]&lt;/span&gt; &lt;span class="n"&gt;ciphertext&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;cipher&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;doFinal&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;
                    &lt;span class="n"&gt;plaintext&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getBytes&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;StandardCharsets&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;UTF_8&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
            &lt;span class="o"&gt;);&lt;/span&gt;

            &lt;span class="nc"&gt;ByteBuffer&lt;/span&gt; &lt;span class="n"&gt;buffer&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;ByteBuffer&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;allocate&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;
                    &lt;span class="n"&gt;iv&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;length&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;ciphertext&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;length&lt;/span&gt;
            &lt;span class="o"&gt;);&lt;/span&gt;

            &lt;span class="n"&gt;buffer&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;put&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;iv&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
            &lt;span class="n"&gt;buffer&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;put&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ciphertext&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;

            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nc"&gt;Base64&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getEncoder&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt;
                    &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;encodeToString&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;buffer&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;array&lt;/span&gt;&lt;span class="o"&gt;());&lt;/span&gt;

        &lt;span class="o"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;GeneralSecurityException&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;IllegalStateException&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;
                    &lt;span class="s"&gt;"Encryption failed"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
        &lt;span class="o"&gt;}&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="nf"&gt;decrypt&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;encryptedValue&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;encryptedValue&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
        &lt;span class="o"&gt;}&lt;/span&gt;

        &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
            &lt;span class="kt"&gt;byte&lt;/span&gt;&lt;span class="o"&gt;[]&lt;/span&gt; &lt;span class="n"&gt;combined&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Base64&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getDecoder&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt;
                    &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;decode&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;encryptedValue&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;

            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;combined&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;length&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;=&lt;/span&gt; &lt;span class="no"&gt;IV_LENGTH&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="no"&gt;TAG_LENGTH&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
                &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;IllegalArgumentException&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;
                        &lt;span class="s"&gt;"Invalid encrypted payload"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
            &lt;span class="o"&gt;}&lt;/span&gt;

            &lt;span class="nc"&gt;ByteBuffer&lt;/span&gt; &lt;span class="n"&gt;buffer&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;ByteBuffer&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;wrap&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;combined&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;

            &lt;span class="kt"&gt;byte&lt;/span&gt;&lt;span class="o"&gt;[]&lt;/span&gt; &lt;span class="n"&gt;iv&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="kt"&gt;byte&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="no"&gt;IV_LENGTH&lt;/span&gt;&lt;span class="o"&gt;];&lt;/span&gt;
            &lt;span class="n"&gt;buffer&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;get&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;iv&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;

            &lt;span class="kt"&gt;byte&lt;/span&gt;&lt;span class="o"&gt;[]&lt;/span&gt; &lt;span class="n"&gt;ciphertext&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="kt"&gt;byte&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="n"&gt;buffer&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;remaining&lt;/span&gt;&lt;span class="o"&gt;()];&lt;/span&gt;
            &lt;span class="n"&gt;buffer&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;get&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ciphertext&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;

            &lt;span class="nc"&gt;Cipher&lt;/span&gt; &lt;span class="n"&gt;cipher&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
                    &lt;span class="nc"&gt;Cipher&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getInstance&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="no"&gt;TRANSFORMATION&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;

            &lt;span class="n"&gt;cipher&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;init&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;
                    &lt;span class="nc"&gt;Cipher&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;DECRYPT_MODE&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
                    &lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
                    &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;GCMParameterSpec&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="no"&gt;TAG_LENGTH&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;iv&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
            &lt;span class="o"&gt;);&lt;/span&gt;

            &lt;span class="kt"&gt;byte&lt;/span&gt;&lt;span class="o"&gt;[]&lt;/span&gt; &lt;span class="n"&gt;plaintext&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;cipher&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;doFinal&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ciphertext&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;

            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;String&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;
                    &lt;span class="n"&gt;plaintext&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
                    &lt;span class="nc"&gt;StandardCharsets&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;UTF_8&lt;/span&gt;
            &lt;span class="o"&gt;);&lt;/span&gt;

        &lt;span class="o"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;GeneralSecurityException&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;IllegalStateException&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;
                    &lt;span class="s"&gt;"Decryption failed"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
        &lt;span class="o"&gt;}&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The imports are omitted for readability. They include the relevant &lt;code&gt;javax.crypto&lt;/code&gt;, &lt;code&gt;java.security&lt;/code&gt;, &lt;code&gt;java.nio&lt;/code&gt;, &lt;code&gt;java.nio.charset&lt;/code&gt;, and &lt;code&gt;java.util&lt;/code&gt; classes.&lt;/p&gt;

&lt;p&gt;Notice that the IV is stored together with the ciphertext. During decryption, the application extracts the IV, reconstructs the GCM parameters, and verifies the authentication tag as part of &lt;code&gt;doFinal()&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;If the ciphertext or authentication tag has been modified, decryption fails instead of returning unauthenticated plaintext.&lt;/p&gt;

&lt;p&gt;In a production implementation, malformed Base64, authentication failures, and other decryption errors should be handled safely without exposing sensitive information in logs or API responses.&lt;/p&gt;

&lt;h2&gt;
  
  
  6. Encrypt the Data Before Saving It
&lt;/h2&gt;

&lt;p&gt;Now let's connect encryption to our insurance quote workflow.&lt;/p&gt;

&lt;p&gt;Suppose our database entity stores encrypted values as strings:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="nd"&gt;@Entity&lt;/span&gt;
&lt;span class="nd"&gt;@Table&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"quote_driver"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;QuoteDriver&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;

    &lt;span class="nd"&gt;@Id&lt;/span&gt;
    &lt;span class="nd"&gt;@GeneratedValue&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;strategy&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;GenerationType&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;IDENTITY&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="nc"&gt;Long&lt;/span&gt; &lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

    &lt;span class="nd"&gt;@Column&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"dob_encrypted"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;dobEncrypted&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

    &lt;span class="nd"&gt;@Column&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"license_encrypted"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;licenseEncrypted&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

    &lt;span class="c1"&gt;// Other fields, constructors, and accessors&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When a quote is submitted, the service encrypts the values before persistence.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nc"&gt;QuoteDriver&lt;/span&gt; &lt;span class="nf"&gt;saveDriver&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;
        &lt;span class="nc"&gt;LocalDate&lt;/span&gt; &lt;span class="n"&gt;dob&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
        &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;licenseNumber&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;

    &lt;span class="nc"&gt;QuoteDriver&lt;/span&gt; &lt;span class="n"&gt;driver&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;QuoteDriver&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;

    &lt;span class="n"&gt;driver&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;setDobEncrypted&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;
            &lt;span class="n"&gt;encryptionService&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;encrypt&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;dob&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;toString&lt;/span&gt;&lt;span class="o"&gt;())&lt;/span&gt;
    &lt;span class="o"&gt;);&lt;/span&gt;

    &lt;span class="n"&gt;driver&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;setLicenseEncrypted&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;
            &lt;span class="n"&gt;encryptionService&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;encrypt&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;licenseNumber&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
    &lt;span class="o"&gt;);&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;quoteDriverRepository&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;save&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;driver&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The flow becomes:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Angular Form
     |
     v
Spring Boot API
     |
     v
Validate Input
     |
     v
Encrypt Sensitive Fields
     |
     v
Save to PostgreSQL
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The browser does not need to encrypt these fields with the server's encryption key. The server performs encryption inside its trusted application boundary after receiving the request over HTTPS.&lt;/p&gt;

&lt;p&gt;When an authorized operation needs the original DOB, the service decrypts it and converts it back to a &lt;code&gt;LocalDate&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="nc"&gt;LocalDate&lt;/span&gt; &lt;span class="n"&gt;dob&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;LocalDate&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;parse&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;encryptionService&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;decrypt&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;
                &lt;span class="n"&gt;driver&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getDobEncrypted&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt;
        &lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="o"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The same approach applies to the driver's license number.&lt;/p&gt;

&lt;p&gt;Keep decrypted values inside the business-service boundary where possible. Do not automatically expose them in API responses simply because they have been decrypted.&lt;/p&gt;

&lt;h2&gt;
  
  
  7. What Happens When We Need to Validate a Driver's Age?
&lt;/h2&gt;

&lt;p&gt;This is an important consideration for insurance systems.&lt;/p&gt;

&lt;p&gt;Suppose the business rule requires drivers to be at least 18 years old.&lt;/p&gt;

&lt;p&gt;Because DOB is encrypted in the database, we cannot directly perform ordinary date comparisons against that ciphertext.&lt;/p&gt;

&lt;p&gt;Instead, the application retrieves the encrypted value, decrypts it in the authorized service, and performs the validation:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="nc"&gt;LocalDate&lt;/span&gt; &lt;span class="n"&gt;dob&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;LocalDate&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;parse&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;encryptionService&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;decrypt&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;
                &lt;span class="n"&gt;driver&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getDobEncrypted&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt;
        &lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="o"&gt;);&lt;/span&gt;

&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;age&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Period&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;between&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;dob&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
        &lt;span class="nc"&gt;LocalDate&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;now&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt;
&lt;span class="o"&gt;).&lt;/span&gt;&lt;span class="na"&gt;getYears&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;

&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;age&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;18&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;IllegalArgumentException&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;
            &lt;span class="s"&gt;"Driver must be at least 18 years old"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The example demonstrates the flow; production validation should use the application's agreed business rules, clock and timezone.&lt;/p&gt;

&lt;p&gt;Encryption does not remove the need for normal validation. It changes how sensitive information is stored and accessed.&lt;/p&gt;

&lt;p&gt;If the application needs frequent age checks, carefully evaluate whether the original DOB must be retrieved each time or whether an appropriate derived value can meet the requirement. Any derived field should be designed to avoid introducing unnecessary privacy risks.&lt;/p&gt;

&lt;h2&gt;
  
  
  8. Can We Search Encrypted Data?
&lt;/h2&gt;

&lt;p&gt;Randomized AES-GCM encryption creates a challenge for database queries.&lt;/p&gt;

&lt;p&gt;Consider the same license number encrypted twice:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;D1234567 -&amp;gt; Ciphertext A
D1234567 -&amp;gt; Ciphertext B
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The ciphertexts differ because the IVs differ.&lt;/p&gt;

&lt;p&gt;Consequently, a normal SQL query cannot find a license number by comparing the plaintext against the encrypted column.&lt;/p&gt;

&lt;p&gt;If exact matching is necessary, a separate keyed HMAC-SHA-256 lookup value can be stored alongside the encrypted license number. The HMAC key must be independent of the encryption key.&lt;/p&gt;

&lt;p&gt;The application can calculate the HMAC for a search request and compare it with the stored lookup value without decrypting every record.&lt;/p&gt;

&lt;p&gt;This design requires careful handling of key rotation, normalization and access control. HMAC lookup values also reveal equality: records with the same normalized input produce the same lookup value under the same key.&lt;/p&gt;

&lt;p&gt;Do not add searchable derived fields unless the business actually requires them.&lt;/p&gt;

&lt;h2&gt;
  
  
  9. Common Mistakes to Avoid
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;1. Hardcoding the encryption key&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Never commit a real key to Git or embed it in source code.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. Reusing the IV&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Generate a fresh, cryptographically random IV for every encryption under the same AES-GCM key.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. Assuming Base64 is encryption&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Base64 can be decoded by anyone. It does not provide confidentiality.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;4. Logging plaintext&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Application logs, exception messages, debugging statements and monitoring systems can inadvertently expose sensitive information.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;5. Forgetting key rotation&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Encryption keys have a lifecycle. Store a key version with encrypted data or use a versioned ciphertext format so the application can identify which key is required for decryption.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;6. Ignoring existing database records&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Adding encryption to a new entity does not automatically encrypt previously stored plaintext. Existing records need a controlled migration, verification and removal of the original plaintext values.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;7. Decrypting everything unnecessarily&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Decrypt sensitive data only when an authorized operation needs it. Apply role-based access controls and audit access to sensitive fields.&lt;/p&gt;

&lt;h2&gt;
  
  
  10. Is Application-Level Encryption Enough?
&lt;/h2&gt;

&lt;p&gt;Application-level encryption is one layer of a broader security strategy.&lt;/p&gt;

&lt;p&gt;For a production insurance application, consider combining:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;HTTPS/TLS for data in transit.&lt;/li&gt;
&lt;li&gt;AES-256-GCM for sensitive fields at the application layer.&lt;/li&gt;
&lt;li&gt;A managed KMS or vault for encryption-key management.&lt;/li&gt;
&lt;li&gt;Database access controls and encryption at rest.&lt;/li&gt;
&lt;li&gt;Secure backups and recovery procedures.&lt;/li&gt;
&lt;li&gt;Least-privilege access, audit logging and data-retention policies.&lt;/li&gt;
&lt;li&gt;Protection against sensitive information appearing in logs, traces and API responses.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Also remember that if an attacker compromises the running application and can access both the encryption key and the decryption functionality, they may still obtain plaintext. Encryption does not replace application security.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Protecting sensitive insurance data requires more than securing database credentials.&lt;/p&gt;

&lt;p&gt;With AES-256-GCM, Spring Boot can encrypt DOB and driver's license numbers before saving them to PostgreSQL and decrypt them when authorized business operations need the original values.&lt;/p&gt;

&lt;p&gt;The essential principles are straightforward:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Encrypt sensitive fields before persistence.&lt;/li&gt;
&lt;li&gt;Use authenticated encryption with a fresh IV for every operation.&lt;/li&gt;
&lt;li&gt;Keep encryption keys separate from the encrypted database.&lt;/li&gt;
&lt;li&gt;Control decryption through the application’s authorization layer.&lt;/li&gt;
&lt;li&gt;Plan for key rotation, migration, backups and data retention.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The result is a stronger security boundary: someone who obtains only the database contents cannot directly read the original sensitive values.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Further reading: OWASP Cryptographic Storage Cheat Sheet and Java Cryptography Architecture (JCA) documentation.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>backend</category>
      <category>java</category>
      <category>security</category>
      <category>springboot</category>
    </item>
  </channel>
</rss>
