Chalk Secret Manager API

Chalk can make use of the Crash Override Secret Manager API to securely backup the secret used by chalk for a variety of signing and attestation operations.

All secrets and keying material are locally generated on the system running chalk, with the secret itself being encrypted locally prior to being sent to the API.

This document provides an overview of the Secret Manager API, how data is stored securely, and how chalk interacts with the API as a client.

Using the Chalk Secret Manager

Use of the Secret Manager API is simple and chalk provides a builtin command to help get things setup, and backed up, securely.

To generate new keys and secrets, and have them securely backed up:

chalk setup

You will then prompted to authenticate to the API, the encrypted secret being backed up will only be retrievable by the same user who saved it.

Once you have successfully authenticated chalk will upload the encrypted secret to the API under your account.

To test the retrieval of the encrypted secret simply re-run the command:

chalk setup

Chalk will detect that keys have already been generated and instead retrieve the encrypted secret and use it to perform test sign and verify operations.

The encrypted secret will be automatically retrieved by chalk as needed as should not be something you have to worry about further.

If you have previously run chalk setup but did not backup the keys a new keypair along with a new random secret can be generated:

chalk setup gen

NOTE This command will replace previously generated local keys

If you would like to run the key generation and setup process but do not want to backup the encrypted secret to the API then the --no-api-login switch can be passed to chalk:

chalk setup --no-api-login

If you chose to not use the API and self-manage your secrets please ensure make a copy of the randomly generated password that will be displayed and save it somewhere securely.

FAQ

What exactly is saved to the Chalk Secret Manager API?

Chalk saves the minimum required to backup your secret. All key materials are generated and handled locally, with only an encrypted form of the secret ever leaving your system.

Specifically the Chalk Secret Manager API stores the following data for each secret that is backed up to it:

  • secret_id - This is the unique identifier of each backed up secret. It is generated by chalk locally using the following scheme:
sha256(16_bytes_random + private_key)
  • encrypted_secret - This is the encrypted form of the secret used to secure the private key. The value is constructed using a Luby-Rackoff cipher with a random nonce. (More details here)

  • owner - The owner of the backed-up encrypted secret. This value is constructed using the following scheme that avoids any plaintext identities being saved but still allowing the authenticated identity to be used for access control to the data:

sha256(salt + authenticated_user_id)
  • creation_ts - This is the timestamp at which the encrypted secret was created

  • accessed_ts - This is the timestamp at which the encrypted secret was last accessed

How long will stored data be saved for?

Backed up encrypted secrets will be saved for 30 days from the last time they were accessed. Simply invoking chalk after you have backed up keys will cause the backed up keys to be read and ensure they continue to be fresh.

How does the Chalk Secret Manager API backup its own data?

The Chalk Secret Manager API makes use of the AWS Backup service to periodically snapshot all application state. Backups are encrypted at rest and are kept for 1 year.

Are there more specifics on the encryption scheme used?

There sure are! In addition to the details provided below you can review the code that is used for the encryption of the secret in prp.nim that is part of the nimutils project that Crash Override has released open source.

The encryption scheme makes use of a PRP using the Luby-Rackoff construction. The easiest thing for us to do is to break the input into two 'halves',one being 128 bits (the width of AES, which we will call the 'left half'), and the other the rest of the remaining width of the input (the 'right half').

The nonce is random.

We first take the key passed in and, use it to generate pre-round keys.

The pre-round keys work by running a PRF in counter mode, where the starting value of the counter is the nonce. We use this to get the actual round keys (the nonce is not necessary in the luby-rackoff proof, but helps prevent dictionary attacks if they're viable in the threat model).

Each round of luby-rackoff requires a PRF. One is AES-CTR mode. We key with the round key, and use the left half as the starting position of the counter. We use that to generate a key stream, that we XOR into the right half. The other PRF is HMAC-3. We take the round key, HMAC the right side, truncate the result to 128 bits, then XOR into the left half.

The PRFs are used in a Feistel cipher, so we alternate PRFs through our four Feistel rounds.

While three-round Luby-Rackoff is secure against some use cases, we go through the full four rounds.

PRPs are reversible, and with Feistel construction, it's by running the rounds backward.

Once constructed it is this encrypted value that is sent to the API for secure backup.

I have more questions that are not answered here, where should I go?

We'd love to hear from you, please reach out to us at hello@crashoverride.com