Method: Generate Data Key


This endpoint generates a new random key and the value of the new key is wrapped (encrypted) with the named key in the specified vault. Optionally return the plaintext of the key as well. Whether plaintext is returned depends on the type used (wrapped vs plaintext) and the users permission in the vault.


This endpoint requires at least Read permission in the affected vault.


Returning the plaintext requires Write permission in the affected vault.

See the overview of how transparent encryption in StoredSafe can help solve key distribution problems.

URL Syntax


HTTP Method


Successful HTTP Response



Parameter name Description Parameter type Type Default Mandatory Comment
X-Http-Token StoredSafe token HTTP Header String   1) Preferred method
token StoredSafe token JSON-encoded String   1) Legacy method
vaultid Vault-ID URL-encoded String   Yes  
type Wrapped or plaintext URL-encoded String plaintext Yes wrapped, plaintext (plaintext requires Write permission in the vault)
name Key name URL-encoded String   Yes  
key_version Key version JSON-encoded String     Will use Latest version if unspecified
bits Key size JSON-encoded Integer 256   128, 256 or 512


1) One of the methods is required.

Response Attributes

Attribute Description Type
CALLINFO.errorcodes Number of errors Integer
CALLINFO.errors Number of errors Integer
CALLINFO.general Information Array
CALLINFO.handler Handler used String
CALLINFO.token Rotated StoredSafe token 1) String
CALLINFO.key_version Latest key version String
CALLINFO.ciphertext Ciphertext (Base64 encoded) String
CALLINFO.plaintext Plaintext (Base64 encoded) String
CALLINFO.objectid Object-ID String
DATA Supplied data in prior API-call String
HEADERS.(headers) HTTP Headers String
PARAMS Route parameters (empty) Array
ERRORCODES Error code and text 2) Object
ERRORS Error code and text 2) Array


1) Token to be used in subsequent calls
2) Only present if errors


Obtain a randomized datakey using high entropy in both plaintext and chipertext, wrapped using the latest version (v2) of the key my-new-key in the vault (vaultid) 179.


POST /api/1.0/transparent/179/datakey/plaintext/my-new-key
x-http-token: your_storedsafe_token


HTTP/2 200
Content-type: application/json; charset=UTF-8
    "CALLINFO": {
        "errorcodes": 0,
        "errors": 0,
        "general": [],
        "handler": "EncryptionHandler",
        "status": "SUCCESS",
        "token": "rotated_storedsafe_token",
        "name": "my-new-key",
        "ciphertext": "storedsafe:v2:rsUKcXUaeUqIlAihBB7c5NoX9xAUxcJt8L1xS1bDuIulobKIp1OAOQ==",
        "plaintext": "Z0VNRHZRcUIwVmhhNE5UZjdZSlU5Y091QTFlZTZRbVNEVTRJNnFVWQo="
    "DATA": {
        "name": "my-new-key",
        "vaultid": "179",
        "token": "your_storedsafe_token"
    "HEADERS": {
        "Accept": "*/*",
        "Content-Length": "169",
        "Content-Type": "application/json",
        "Host": "",
        "User-Agent": "curl/7.64.1",
        "X-Http-Token": "your_storedsafe_token"
    "PARAMS": []

Annotated example

In this example, we will show how to encrypt a local file (/data/large_file.blob) using AES256-GCM and using StoredSafe to maintain and secure the key for the symmetric encryption.

  1. Start by generating a datakey using the /datakey endpoint, requesting both a wrapped key and a copy in cleartext (/plaintext/).

The ciphertext returned is wrapped (encrypted) with the named key my-new-key, as specified in the REST call.

$ curl --header "x-http-token: ..." --request GET
Content-type: application/json; charset=UTF-8
    "CALLINFO": {
        "ciphertext": "storedsafe:v2:rsUKcXUaeUqIlAihBB7c5NoX9xAUxcJt8L1xS1bDuIulobKIp1OAOQ==",
        "plaintext": "Z0VNRHZRcUIwVmhhNE5UZjdZSlU5Y091QTFlZTZRbVNEVTRJNnFVWQo="
  1. Next step is to base64 decode the plaintext key and save it to a file.
$ base64 -d <<<Z0VNRHZRcUIwVmhhNE5UZjdZSlU5Y091QTFlZTZRbVNEVTRJNnFVWQo= >/data/key.bin
  1. And then use the plaintext key to encrypt a local file, after creating (and saving) a random 12-byte IV to a file.
$ dd if=/dev/random bs=12 count=1 >/data/iv.file
$ aesgcm enc -iv /data/iv.file -tag /data/tag.file -in /data/large_file.blob -out /data/large_file.blob.enc -key /data/key.bin
  1. Finally, save the wrapped encryption key.

Since it wrapped (e.g. encrypted by another key), it can safely be stored together with the encrypted file.

$ echo "storedsafe:v2:rsUKcXUaeUqIlAihBB7c5NoX9xAUxcJt8L1xS1bDuIulobKIp1OAOQ==" > /data/key.wrapped
  1. Securely delete the plaintext key.
$ sterialize --passes 20 /data/key.bin


Now several days, weeks, months or years can pass. Members in vault 179 might have shifted over time, but as long as the current user has at least read permission in the vault at the time of decryption, decryption will work.

  1. When the file needs to be decrypted, use the decrypt endpoint to unwrap the wrapped key.
$ curl --header "x-http-token: ..." --request POST --data '{ "ciphertext": "storedsafe:v2:rsUKcXUaeUqIlAihBB7c5NoX9xAUxcJt8L1xS1bDuIulobKIp1OAOQ==" }'
Content-type: application/json; charset=UTF-8
    "CALLINFO": {
        "plaintext": "Z0VNRHZRcUIwVmhhNE5UZjdZSlU5Y091QTFlZTZRbVNEVTRJNnFVWQo="
$ base64 -d <<<Z0VNRHZRcUIwVmhhNE5UZjdZSlU5Y091QTFlZTZRbVNEVTRJNnFVWQo= >key.bin
  1. And finally, use the unwrapped key to decrypt the locally stored data.
$ aesgcm dec -iv /data/iv.file -tag /data/tag.file -in /data/large_file.blob.enc -out /data/large_file.blob -key /data/key.bin