created_at2020-01-21 22:27:06.443816
updated_at2022-08-02 18:55:56.58293
descriptionSecureStore API for creating or decrypting user secrets
Mahmoud Al-Qudsi (mqudsi)



Rust SecureStore library

This crate contains a rusty implementation of the open SecureStore secrets storage protocol, that can read, write and update encrypted password storage files that are designed to be stored alongside your code in your GIT repository (or wherever else).

You can read more about SecureStore on our website. The associated command-line client for managing the secrets store (creating a new store, adding, removing, and updating secrets) can also be found in this repository.

SecureStore API

The API for using SecureStore is primarily self-documenting and intentionally kept small. The primary interface is via an instance of SecretsManager, which can only be created from scratch via SecretsManager::new(..) or loaded from an existing on-disk store via SecretsManager::load(..).

In the usual case, a SecureStore is created and updated via the command line, and the SecureStore API is only used at runtime to retrieve and decrypt secrets individually. A SecureStore is decrypted via either a password or a keyfile, and both the API and the command line interface provide a means of creating a password-encrypted store but exporting a keyfile for use by the application at runtime.

Sample usage

As an example of its usage, including a brief demonstration of ssclient, the CLI companion to this library (also available via and installable with cargo), can be seen below:

# First, install ssclient, the SecureStore CLI interface
~> cargo install ssclient

# Use ssclient to create a new store with password-based encryption,
# and export the derived keyfile so we can use the SecureStore API
# in a passwordless fashion.
~> ssclient create secrets.json --export-key secrets.key
Password: ***********
Confirm password: ***********

# Add a secret to the store. When -s/--store is not specified,
# defaults to secrets.json
~>  ssclient set foo EXtRAsuPErSECRET
Password: ***********

Back in the world of code, we can now use the SecureStore API from this crate to interface with the secrets file we just created, and selectively decrypt its contents with either the password we used at the time the store was created or the in a passwordless manner by means of the keyfile we exported that contains the key derived from our password:

use securestore::{KeySource, SecretsManager};

fn get_api_key() -> String {
    let sman = SecretsManager::load("secrets.json",
    let api_key = sman.get("foo").unwrap();

    assert_eq!("EXtRAsuPErSECRET", api_key.as_str());
    return api_key;

The SecureStore API also includes the relevant APIs for creating new stores; adding, removing, and updating secrets; exporting keyfiles; and everything else typically done with the ssclient CLI companion (which is built on this crate for maximum dogfooding).

Encryption details

SecureStore intentionally does not expose the cryptography innards as part of its API, the particulars of the cryptography algorithms used are considered hard-coded dependent on the schema version. The format itself is written to be forward-compatible such that if and when a need arises for a change in the underlying cryptography format, it can be done in a manner transparent to the API consumer.

It is important that the choice of cryptographic primitives be made taking into account the availability of the chosen algorithms across different languages and platforms, as SecureStore is intended to be an open format with cross-compatible implementations available in different languages supporting many different environments. A conscious decision has been made to also reduce the need for third party dependencies where possible. For the current SecureStore schema (v3), an authenticated variant of AES-128-CBC is used, with two separately-derived/generated keys being used for the AES encryption and the HMAC-SHA1 authentication rounds. When used with user-supplied passwords, PBKDF2 with 256,000 rounds of SHA1 and a unique seed is used to derive the separate keys; the results of the key-stretching operation are not included in the store and are still considered to be sensitive data interchangeable with the password itself.

At this time, OpenSSL is used for all cryptographic operations (including CSPRNG), but that may be replaced with platform-native dependencies in the future. For more details, please refer to the source code.

License and authorship

The SecureStore crate was originally developed by Mahmoud Al-Qudsi of NeoSmart Technologies and is actively updated and maintained by NeoSmart Technologies and the SecureStore contributors. The SecureStore crate is released under a dual MIT and Apache 2.0 License. Any contributions to this crate are assumed to be licensed likewise; contributions not under the both of these licenses are not being accepted at this time.

See also

Commit count: 0

cargo fmt