mirror of
https://github.com/hashicorp/vault.git
synced 2026-05-28 04:10:44 -04:00
Vault-5626: add key wrapping guide for transit import (#16365)
* add key wrapping guide for transit import * link to key wrap guide from transit overview * add new page to nav * fix formatting * fix note format * fix link
This commit is contained in:
parent
546fd7e8e9
commit
3c8fdf0a39
3 changed files with 177 additions and 1 deletions
|
|
@ -287,6 +287,9 @@ either SHA-1, SHA-224, SHA-256, SHA-384, or SHA-512.
|
|||
|
||||
- Base64 encode the result.
|
||||
|
||||
For more details about wrapping the key for import into transit, see the
|
||||
[key wrapping guide](/docs/transit/key-wrapping-guide).
|
||||
|
||||
## Tutorial
|
||||
|
||||
Refer to the [Encryption as a Service: Transit Secrets
|
||||
164
website/content/docs/secrets/transit/key-wrapping-guide.mdx
Normal file
164
website/content/docs/secrets/transit/key-wrapping-guide.mdx
Normal file
|
|
@ -0,0 +1,164 @@
|
|||
---
|
||||
layout: docs
|
||||
page_title: Key Wrapping for Transit Key Import - Transit - Secrets Engines
|
||||
description: |-
|
||||
Details about wrapping keys for import into the transit secrets engine.
|
||||
---
|
||||
|
||||
# Key Wrapping for Transit Key Import
|
||||
|
||||
The "bring your own key" (BYOK) functionality for the transit
|
||||
secrets engine allows users to import keys that were generated
|
||||
outside of Vault into the transit secrets engine.
|
||||
|
||||
This document describes the process for wrapping an externally-generated
|
||||
key (the target key) for import into Vault. It describes the processes
|
||||
for importing a software-stored key using Golang and for importing a key
|
||||
that is stored in an HSM.
|
||||
|
||||
### Mount the secrets engine
|
||||
|
||||
```shell-session
|
||||
$ vault secrets enable transit
|
||||
Success! Enabled the transit secrets engine at: transit/
|
||||
```
|
||||
|
||||
### Retrieve the transit wrapping key
|
||||
|
||||
```shell-session
|
||||
$ vault read transit/wrapping_key
|
||||
```
|
||||
|
||||
This returns a 4096-bit RSA key.
|
||||
|
||||
The steps after this depend on whether the key is stored using
|
||||
a software solution or in an HSM.
|
||||
|
||||
### Software Example (Go)
|
||||
|
||||
This example assumes that the key is stored in software using the
|
||||
variable name `key`. It demonstrates how to wrap the target key using
|
||||
Golang crypto libraries.
|
||||
|
||||
Once you have the wrapping key, you can parse it using the `encoding/pem`
|
||||
and `crypto/x509` libraries (the example code below assumes that the wrapping
|
||||
key has been written to a variable called `wrappingKeyString`):
|
||||
|
||||
```
|
||||
keyBlock, _ := pem.Decode([]byte(wrappingKeyString))
|
||||
parsedKey, err := x509.ParsePKIXPublicKey(keyBlock.Bytes)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
```
|
||||
|
||||
Then generate an ephemeral AES key for wrapping the target key.
|
||||
This example uses Golang's `crypto/rand` library for generating the key:
|
||||
|
||||
```
|
||||
ephemeralAESKey := make([]byte, 32)
|
||||
_, err := rand.Read(ephemeralAESKey)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
```
|
||||
|
||||
~> **NOTE**: Be sure to securely delete the ephemeral AES key once it
|
||||
has been used!
|
||||
|
||||
Google's [tink library](https://pkg.go.dev/github.com/google/tink/go@v1.6.1/kwp/subtle)
|
||||
provides a function for performing the key wrap operation:
|
||||
|
||||
```
|
||||
wrapKWP, err := subtle.NewKWP(aesKey)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
wrappedTargetKey, err := wrapKWP.Wrap(key)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
```
|
||||
|
||||
Then encrypt the ephemeral AES key using the transit wrapping key:
|
||||
|
||||
```
|
||||
wrappedAESKey, err := rsa.EncryptOAEP(
|
||||
sha256.New(),
|
||||
rand.Reader,
|
||||
wrappingKey,
|
||||
ephemeralAESKey,
|
||||
[]byte{},
|
||||
)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
```
|
||||
|
||||
Note that though this example uses SHA256, Vault also supports the use of
|
||||
SHA1, SHA384, or SHA512. The hash function that was used at this step will
|
||||
need to be provided as a parameter when importing the key.
|
||||
|
||||
Finally, concatenate the wrapped keys into a single byte string.
|
||||
The leftmost 4096 bits of the string should be the wrapped AES key, and
|
||||
the remaining bits should be the wrapped target key. Then the resulting
|
||||
bytes should be base64-encoded.
|
||||
|
||||
```
|
||||
combinedCiphertext := append(wrappedAESKey, wrappedTargetKey...)
|
||||
base64Ciphertext := base64.StdEncoding.EncodeToString(combinedCiphertext)
|
||||
```
|
||||
|
||||
This is the ciphertext that should be provided to Vault when importing a
|
||||
key into the transit secrets engine.
|
||||
|
||||
```shell-session
|
||||
$ vault write transit/keys/test-key/import ciphertext=$CIPHERTEXT hash_function=SHA256 type=$KEY_TYPE
|
||||
```
|
||||
|
||||
|
||||
### AWS CloudHSM Example
|
||||
|
||||
This example demonstrates how to import a key into the transit secrets engine from
|
||||
an AWS CloudHSM cluster. The process and mechanisms used will apply to importing
|
||||
a key from an HSM in general, but the details will differ between HSMs.
|
||||
|
||||
For information on creating and communicating with an AWS CloudHSM cluster, see
|
||||
the [Getting Started guide in the AWS CloudHSM documentation](https://docs.aws.amazon.com/cloudhsm/latest/userguide/getting-started.html).
|
||||
|
||||
Communication with the HSM uses AWS's `key_mgmt_util` tool. For help setting that
|
||||
up, see the [Getting Started page for key_mgmt_util](https://docs.aws.amazon.com/cloudhsm/latest/userguide/key_mgmt_util-getting-started.html).
|
||||
|
||||
The first step is writing the transit wrapping key to the HSM. This involves
|
||||
creating a new RSA public key object with the key returned by transit's
|
||||
`wrapping_key` endpoint.
|
||||
|
||||
```shell-session
|
||||
$ importPubKey -f wrapping_key.pem -l "vault-transit-wrapping-key"
|
||||
```
|
||||
|
||||
This will create the public key in the HSM with all of the necessary permissions.
|
||||
If you're using a different tool, make sure that the usage for the wrapping key
|
||||
includes the attribute `CKA_WRAP`.
|
||||
|
||||
The next step is wrapping the target key using the wrapping key. If the
|
||||
ID of the target key is `1` and the wrapping key is `2`, the command looks like this:
|
||||
|
||||
```shell-session
|
||||
$ wrapKey -k 1 -w 2 -t 3 -m 7 -out ciphertext.key
|
||||
```
|
||||
|
||||
The `-m 7` flag specifies the mechanism to use for the key wrapping. For AWS CloudHSM,
|
||||
7 corresponds to the PKCS11 mechanism `CKM_AES_RSA_KEY_WRAP` ([see the AWS documentation for details](https://docs.aws.amazon.com/cloudhsm/latest/userguide/key_mgmt_util-wrapKey.html)).
|
||||
The `-t 3` flag specifies `SHA256` as the hash function. The result is written to a
|
||||
file called `ciphertext.key`.
|
||||
|
||||
The output from this is a binary file, which needs to be base64-encoded when it
|
||||
is provided to Vault.
|
||||
|
||||
```shell-session
|
||||
$ export CIPHERTEXT=$(base64 ciphertext.key)
|
||||
$ vault write transit/keys/test-key/import ciphertext=$CIPHERTEXT hash_function=SHA256 type=$KEY_TYPE
|
||||
```
|
||||
|
||||
Once the key has been imported, it can be used like any other transit key.
|
||||
|
|
@ -1174,7 +1174,16 @@
|
|||
},
|
||||
{
|
||||
"title": "Transit",
|
||||
"path": "secrets/transit"
|
||||
"routes": [
|
||||
{
|
||||
"title": "Overview",
|
||||
"path": "secrets/transit"
|
||||
},
|
||||
{
|
||||
"title": "Import Key Wrapping Guide",
|
||||
"path": "secrets/transit/key-wrapping-guide"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"title": "Venafi (Certificates)",
|
||||
|
|
|
|||
Loading…
Reference in a new issue