Skip to main content

Explain encryption as a service

··772 words·4 mins
Vault - This article is part of a series.
Part 12: This Article

We’ve already seen the transit secrets engine in one of the previous posts in this series, but we will revisit the topic in this post.

The transit secrets engine handles encryption on data in-transit. No data handled by this secrets engine is persisted to storage in Vault. Apart from encrypting and decrypting data the transit engine can also sign and verify data, generate random bytes, and more.

There are several key types (or encryption algorithms) supported by the transit secrets engine: aes128-gcm96, aes256-gcm96, chacha20-poly1305, ed25519, ecdsa-p256, ecdsa-p384, ecdsa-p521, rsa-2048, rsa-3072, rsa-4096, and hmac.

Explaining encryption as a service make up the tenth and last objective in the Vault certification journey. This objective covers the following sub-objectives:

Configure transit secret engine
#

To start off we should enable the transit secrets engine on our Vault server. We’ve seen how to enable secrets engines before:

$ vault secrets enable transit

Success! Enabled the transit secrets engine at: transit/

The main use-case for the transit secrets engine is to encrypt and decrypt data, thus we will create a key to do just that. To create a key we run the following command:

$ vault write -f transit/keys/demo-key \
    type=rsa-4096 \
    auto_rotate_period=1h

Key                       Value
---                       -----
allow_plaintext_backup    false
auto_rotate_period        1h
deletion_allowed          false
derived                   false
exportable                false
imported_key              false
keys                      map[1:map[creation_time:2023-09-15T17:47:46.020802+02:00 name:rsa-4096 public_key:-----BEGIN PUBLIC KEY-----
MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAqF4TxwdIpmVcXTri+Y1a
MGL7fM2xUeGDpDMfxnR1gJwjhda2zFud07TZ9RwmeFgxnbj9VwYRu9ThL1tAZ+32
72nZjizb2rJWp0UUYSWk5BcgUCa1NPM7gTcrgp9INXidHeTnC5TxUC4N2alUoPsG
r5opxHEVrBWQZxRx6AuOnP6YzmQSJMS4pv+0cH+dP0HUj1X2Kso3OuFNFSplsSPm
I9bZxOazmPNz9x4MYRfp3a5EOp6FmE/EKd2kOZ6EYaD0R+oNsI1lg79lpsDckIHY
ISFZd9sM5xVZTrXhBng2MMfpWwjSqoaJVeycQ91RYr3KzkmUW5UrXN3ksq/ncLBM
SXOcfhFgkLAXUbsEaMQE08ug4J+hEJj5Jh9By9DlNS2UMASySAwuUTJ1c78SE3fs
1YGaxZkt88mEuLOY0wUD0/0gEMshn/Lh3pjJvlYxMtwsdtVMx/zUsdaa6ialAFFl
6aKMCnvaQHtwS3O3oPma6c/qX714AKGmceZswxp8IhErafG0Wca7/JHTrUQNasWZ
HzDFqS2S5F1bu7oKICl+JELnpHu570MjtYXAomw3EHqNvPvw72ihdZ5tBX/QH1l1
iwIv+a76bfM3F5myoPP5uzNk6fPt73u0zLCKYfVK4fvr/V8CtCML6foUFtXGn9OQ
0vS2bGk64K2fTNfcSbC+P6kCAwEAAQ==
-----END PUBLIC KEY-----
]]
latest_version            1
min_available_version     0
min_decryption_version    1
min_encryption_version    0
name                      demo-key
supports_decryption       true
supports_derivation       false
supports_encryption       true
supports_signing          true
type                      rsa-4096

In the previous command I specified that the key type should be rsa-4096 and I want the key to automatically rotate every hour. To see all the available configuration options when creating a key see the API documentation.

Encrypt and decrypt secrets
#

In this section I continue where I ended the last section. The status is that we have a key named demo-key. We could read information about our key using vault read transit/keys/demo-key.

Now I want to encrypt some data using my new key. Remember from earlier posts that the data I want to encrypt must be base64-encoded:

$ vault write transit/encrypt/demo-key plaintext=$(echo "s3cr3tm3ss4g3" | base64)

Key            Value
---            -----
ciphertext     vault:v1:N+bgVOhRl5xrwcZ7Aovlg2CF9I+sB9eHt8Yspxw0CrGnR/llTp+9KPZjrA8ou2pznNZ20RdVI291TB2e3jKNLVR36pPQ8iEwfm4HNv+TVS+KJl0CvCweBGa84RrDeIUauwSgHx4vWV2SSz6qJSV8qBrwXKRSq6GPWS4bAu6U9+H2Yq6Zpvr3/mpSX1oZz4HL1PP/zds0taYNWaRJBUr9TDbgRQVto57Swy408+x1Fn9tq670go/ghYbXBV5idL+8O5IndKVB5xukwXNVvrXI4fO/lMBBkSfnGsqWUiACqCzYRPABEN2MHI6Zgfjdfi3CEr2XNCMf/dqEyK01WC9S0ERJM064dT+5oCUQzsll8e0dOGSkbFrKfTGWZExMBHrSHDrGREUEf1h/fT4gNf0udg9V5SUt+dniVkKWXQt6JqUhwIMzEglkJmsmrPDOQxXt9nziiO3mUvI1f2d99nYDicdFgCBULP9jQ7EpLM8V0NC1F/J+Rqk663ZHHZrHotfK9hDk54wfWzTfqKj+XYtqmr5SneRePOyCCtB1bOSkulgrPJQpkvrWowMCGz5eiaTrbGZjPORnkYdX8nEqv3kGIrDR6ZiP+HANzU9/BQBalr05A+UWY8XMa/4P9nPCH7cnah/vZxDicvkEF8ROxoslVfZcPPhQwxSCeRwRdX7kDK4=
key_version    1

To get my data back again I can do so using the following command:

$ vault write transit/decrypt/demo-key \
    ciphertext=vault:v1:N+bgVOhRl5xrwcZ7Aovlg2CF9I+sB9eHt8Yspxw0CrGnR/llTp+9KPZjrA8ou2pznNZ20RdVI291TB2e3jKNLVR36pPQ8iEwfm4HNv+TVS+KJl0CvCweBGa84RrDeIUauwSgHx4vWV2SSz6qJSV8qBrwXKRSq6GPWS4bAu6U9+H2Yq6Zpvr3/mpSX1oZz4HL1PP/zds0taYNWaRJBUr9TDbgRQVto57Swy408+x1Fn9tq670go/ghYbXBV5idL+8O5IndKVB5xukwXNVvrXI4fO/lMBBkSfnGsqWUiACqCzYRPABEN2MHI6Zgfjdfi3CEr2XNCMf/dqEyK01WC9S0ERJM064dT+5oCUQzsll8e0dOGSkbFrKfTGWZExMBHrSHDrGREUEf1h/fT4gNf0udg9V5SUt+dniVkKWXQt6JqUhwIMzEglkJmsmrPDOQxXt9nziiO3mUvI1f2d99nYDicdFgCBULP9jQ7EpLM8V0NC1F/J+Rqk663ZHHZrHotfK9hDk54wfWzTfqKj+XYtqmr5SneRePOyCCtB1bOSkulgrPJQpkvrWowMCGz5eiaTrbGZjPORnkYdX8nEqv3kGIrDR6ZiP+HANzU9/BQBalr05A+UWY8XMa/4P9nPCH7cnah/vZxDicvkEF8ROxoslVfZcPPhQwxSCeRwRdX7kDK4=

Key          Value
---          -----
plaintext    czNjcjN0bTNzczRnMwo=

I get the base64-encoded value back, which I can decode to my secret:

$ echo "czNjcjN0bTNzczRnMwo=" | base64 -D

s3cr3tm3ss4g3

Rotate the encryption key
#

When we encrypted data in the previous section the resulting ciphertext was prepended with vault:v1. This tells us that the data has been encrypted by the transit secrets engine in Vault and the key version uses was v1. What happens if we rotate our key and get a new version of it?

Let’s do just that. I can rotate my key using the following command:

$ vault write -f transit/keys/demo-key/rotate

Key                       Value
---                       -----
allow_plaintext_backup    false
auto_rotate_period        1h
deletion_allowed          false
derived                   false
exportable                false
imported_key              false
keys                      map[1:map[creation_time:2023-09-15T17:47:46.020802+02:00 name:rsa-4096 public_key:-----BEGIN PUBLIC KEY-----
MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAqF4TxwdIpmVcXTri+Y1a
MGL7fM2xUeGDpDMfxnR1gJwjhda2zFud07TZ9RwmeFgxnbj9VwYRu9ThL1tAZ+32
72nZjizb2rJWp0UUYSWk5BcgUCa1NPM7gTcrgp9INXidHeTnC5TxUC4N2alUoPsG
r5opxHEVrBWQZxRx6AuOnP6YzmQSJMS4pv+0cH+dP0HUj1X2Kso3OuFNFSplsSPm
I9bZxOazmPNz9x4MYRfp3a5EOp6FmE/EKd2kOZ6EYaD0R+oNsI1lg79lpsDckIHY
ISFZd9sM5xVZTrXhBng2MMfpWwjSqoaJVeycQ91RYr3KzkmUW5UrXN3ksq/ncLBM
SXOcfhFgkLAXUbsEaMQE08ug4J+hEJj5Jh9By9DlNS2UMASySAwuUTJ1c78SE3fs
1YGaxZkt88mEuLOY0wUD0/0gEMshn/Lh3pjJvlYxMtwsdtVMx/zUsdaa6ialAFFl
6aKMCnvaQHtwS3O3oPma6c/qX714AKGmceZswxp8IhErafG0Wca7/JHTrUQNasWZ
HzDFqS2S5F1bu7oKICl+JELnpHu570MjtYXAomw3EHqNvPvw72ihdZ5tBX/QH1l1
iwIv+a76bfM3F5myoPP5uzNk6fPt73u0zLCKYfVK4fvr/V8CtCML6foUFtXGn9OQ
0vS2bGk64K2fTNfcSbC+P6kCAwEAAQ==
-----END PUBLIC KEY-----
] 2:map[creation_time:2023-09-15T18:00:01.621354+02:00 name:rsa-4096 public_key:-----BEGIN PUBLIC KEY-----
MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAymFiLHw/G5jZN+xtEBlb
ILhBMmn8F0CchTbKjr/cm8n5vus1OonamkuWY9Zk23al9Rf9mOYg2ZP453fJ8W0z
ZrrUJQxGsEV0T2xmjab5Xk7nUh2cDwhHGZu1t27z0up3F5XKezknokyB+EPAH33H
UrUB/AHMDGRcR0Gb0qNum0k6N2w9Y4iUO9Hq9UjnkpqoqAqY6CFScdl+QKu+kYj3
AlucROc0wR4XhhxAvl6CX25g/0kmonUjLZFylilS6qzqVQMcg7jgHqC8JwJ0S9Ds
RZr65IV4YLw5xBzZhooLEUT8E/8pIZxwJ3UmrR5EZkjkewU+D8YVJ5qYM7S785Cu
kKWB1QwGZ4Bmoue4n3Nw7y5YPGpv4KUrTB8/Kusl420LcgCRA3zENIV9zg+QAoPb
b7JJ4TV3P18uxfbNYn6v/N/GKjaCWYtCMGEKAjhzNZkvtmbGK3zZoE+HhvKb3Z7y
2D5ARe1Hu2e+z9r0PL+LH8ELQT+9kExwVBoMrxcNJq1fPtWSj2szGcq2YJMip91g
G7HQ2p28MVMkkFHSPUsDLPnBcpVs0lOb8mjwU+zeHGTTigH79R3XXsxZ0gwbSPxH
VeFcv3tFAPcQ+suyM2kpwrfFzvGopJSZuL/oUoqMHKdzrSbQy/c2t4W5pVUoHXga
2iEE0ALm/6V1W/3eqP2AIAMCAwEAAQ==
-----END PUBLIC KEY-----
]]
latest_version            2
min_available_version     0
min_decryption_version    1
min_encryption_version    0
name                      demo-key
supports_decryption       true
supports_derivation       false
supports_encryption       true
supports_signing          true
type                      rsa-4096

The metadata in the output says that latest_version is now 2. However, min_decryption_version is 1 which means that even if some ciphertext is encrypted using version one of our key it will still be possible for us to decrypt the value. You can configure what the min_decryption_version should be. Perhaps you don’t want to allow any other key than version two to be able to decrypt values, then you can configure this.

Something else you might want to do is to re-encrypt your data with the latest version of the key. You can do this without exposing the secret data at any stage. To do this run the following command together with the ciphertext from before:

$ vault write transit/rewrap/demo-key \
    ciphertext=vault:v1:N+bgVOhRl5xrwcZ7Aovlg2CF9I+sB9eHt8Yspxw0CrGnR/llTp+9KPZjrA8ou2pznNZ20RdVI291TB2e3jKNLVR36pPQ8iEwfm4HNv+TVS+KJl0CvCweBGa84RrDeIUauwSgHx4vWV2SSz6qJSV8qBrwXKRSq6GPWS4bAu6U9+H2Yq6Zpvr3/mpSX1oZz4HL1PP/zds0taYNWaRJBUr9TDbgRQVto57Swy408+x1Fn9tq670go/ghYbXBV5idL+8O5IndKVB5xukwXNVvrXI4fO/lMBBkSfnGsqWUiACqCzYRPABEN2MHI6Zgfjdfi3CEr2XNCMf/dqEyK01WC9S0ERJM064dT+5oCUQzsll8e0dOGSkbFrKfTGWZExMBHrSHDrGREUEf1h/fT4gNf0udg9V5SUt+dniVkKWXQt6JqUhwIMzEglkJmsmrPDOQxXt9nziiO3mUvI1f2d99nYDicdFgCBULP9jQ7EpLM8V0NC1F/J+Rqk663ZHHZrHotfK9hDk54wfWzTfqKj+XYtqmr5SneRePOyCCtB1bOSkulgrPJQpkvrWowMCGz5eiaTrbGZjPORnkYdX8nEqv3kGIrDR6ZiP+HANzU9/BQBalr05A+UWY8XMa/4P9nPCH7cnah/vZxDicvkEF8ROxoslVfZcPPhQwxSCeRwRdX7kDK4=

Key            Value
---            -----
ciphertext     vault:v2:aEu3sdXwj3Wp1gcu3YEwqnQ4iINzH8ZBqzpUZFuLFJjxIGHEs0W9nbeRFdn3ertys6M0yR6D+gOrl+te2tqXuwVmvmbskT9shQYFPzjVfI4L6DpjNWpOvGqXb2A+GS86UJIxwNK/5Y/S+WizSFnQ7BXpMunKvan6lIP0SPSfqfCYzWuqcWfKkftTnzLiddWYxKk8AJHd2B3z+ahSM9pkAtjmxm7I6+SCwJ+VcJRR1UMpz/4/Z9QDgzU2xEMV1Nk3VMdUppJseavXzdl98zkB6X4ulOj9zMDMLwJHpLCVTjnrENhrui4sLWqZAhzTFI5joydpqzSC3mGwHaxrMyGqJ/CQS5WivU05euiQC+QyyziPPoff1ltmgt+OkQoKzjZfgG9Vy/B2wz71NqmFY/zpF+XNrkUVs9G7TlUFCZXwwL0mqzCitUPmP8UllnWVx+s9XoZ3dtdvwHtMPoSlUmjMeftZmxUJXglA6YZXvsI1vhDY7jpornJmlwz2a2L0HsK0zVFGwJE7DKAFBeR85U7XQZmXl+CYS0WE/Mm3VycwQWdxfUpAz7niYz3bfKbSIGJ5b/fsMvHvDQc4nPszdVMqEe5NV6RPFlR0APfl/ys64Izl+GLagitrMzc89PJzj8Y/Z6umz/29hkBb8uom6YTf3cgHLIQEC4HTCV7KZ7wTGzA=
key_version    2

The new ciphertext is prepended with vault:v2 which indicates that it is now encrypted with the latest version of the key. Let’s verify that we can still decrypt the data:

$ vault write transit/decrypt/demo-key \
    ciphertext=vault:v2:aEu3sdXwj3Wp1gcu3YEwqnQ4iINzH8ZBqzpUZFuLFJjxIGHEs0W9nbeRFdn3ertys6M0yR6D+gOrl+te2tqXuwVmvmbskT9shQYFPzjVfI4L6DpjNWpOvGqXb2A+GS86UJIxwNK/5Y/S+WizSFnQ7BXpMunKvan6lIP0SPSfqfCYzWuqcWfKkftTnzLiddWYxKk8AJHd2B3z+ahSM9pkAtjmxm7I6+SCwJ+VcJRR1UMpz/4/Z9QDgzU2xEMV1Nk3VMdUppJseavXzdl98zkB6X4ulOj9zMDMLwJHpLCVTjnrENhrui4sLWqZAhzTFI5joydpqzSC3mGwHaxrMyGqJ/CQS5WivU05euiQC+QyyziPPoff1ltmgt+OkQoKzjZfgG9Vy/B2wz71NqmFY/zpF+XNrkUVs9G7TlUFCZXwwL0mqzCitUPmP8UllnWVx+s9XoZ3dtdvwHtMPoSlUmjMeftZmxUJXglA6YZXvsI1vhDY7jpornJmlwz2a2L0HsK0zVFGwJE7DKAFBeR85U7XQZmXl+CYS0WE/Mm3VycwQWdxfUpAz7niYz3bfKbSIGJ5b/fsMvHvDQc4nPszdVMqEe5NV6RPFlR0APfl/ys64Izl+GLagitrMzc89PJzj8Y/Z6umz/29hkBb8uom6YTf3cgHLIQEC4HTCV7KZ7wTGzA=

Key          Value
---          -----
plaintext    czNjcjN0bTNzczRnMwo=

And we must remember to decode the base64-encoded value:

$ echo "czNjcjN0bTNzczRnMwo=" | base64 -D

s3cr3tm3ss4g3
Mattias Fjellström
Author
Mattias Fjellström
Cloud architect · Author · HashiCorp Ambassador
Vault - This article is part of a series.
Part 12: This Article