Skip to main content

Cryptographic Procedures

Stronghold ensures that sensitive data cannot easily escape from memory. This requires a mechanism to work with secrets stored inside Stronghold's vault. While parts of Stronghold are primarily concerned with writing secrets, the question arises: "What can you do with a secret that is never exposed? Why even store it?”.

Cryptographic Procedures Pipeline

Stronghold features a framework to build pipelines of cryptographic operations. The pipeline pattern is an abstraction over chained function calls. Each stage of a pipeline can either:

  • Produce a value. For example, generate a secret (BIP39 and Mnemonic, Ed25519)
  • Process an existing value. For example, deriving a secret key from an existing key (SLIP10)
  • Export a value from an existing secret. For example, export the public key of a key pair.

The framework is abstracted in a way that allows you to combine simple and complex cryptographic procedures. However, custom procedures are not possible within Stronghold. This is because a procedure can access secrets. Providing a custom procedure that exposes a secret and returns it would violate the Stronghold core principle.

The procedures framework is built upon a pipeline pattern. Each stage is only given the location inside the vault to access or work with secret data. The following schematic showcases the generation of a public / private keypair that gets stored in location1. The following step takes the previous location1 and derives a new keypair to store it in location2. Eventually, the last stage takes location2, extracts the public key and returns it to some publicly accessible data.

Generation of a Public / Private Keypair

The pipeline pattern handles three kinds of primitives:

  1. A Generator / Source that produces secret keys or seeds and does not take any inputs. In most cases, it generates either a key pair (e.g. Ed25519) or a mnemonic (BIP39) to create a seed for a deterministic wallet
  2. A Processor that takes in locations or data, and produces some new secret, stores it in a location. It is usually used to derive a new keypair (SLIP10).
  3. A Receiver / Sink that takes a location, produces a value and returns it. It does not store any product inside the vault.

All operations involving sensitive data make heavy use of the procedures framework.

Code Example

//  .. we initialize `client` somewhere before the calls
// This constructs a `GenerateKey` procedure, that will generate a key at given
// output location in the vault
let generate_key_procedure = GenerateKey {
ty: keytype.clone(),
output: output_location.clone(),
};

// Even though this procedure does not create a useful output, the result can be
// used to check for errors
let procedure_result = client.execute_procedure(StrongholdProcedure::GenerateKey(generate_key_procedure));

// Front the previously generate key, we want to export the public key
let public_key_procedure = stronghold::procedures::PublicKey {
ty: keytype,
private_key: output_location,
};