Module zerokms

Module zerokms 

Expand description

The zerokms module provides a client for interacting with the ZeroKMS service.

ZeroKMS provides key management and encryption services using CipherStash’s “Vitur” protocol. This client provides a high-level interface for managing keys, granting access and encrypting/decrypting data.

§Key Heirarchy

§Workspaces, Keysets and Clients

ZeroKMS is built around the concept of Keysets and Clients that are encapsulated within a Workspace.

  • Workspaces are the top-level entity that encapsulates all Keysets and Clients.
  • Keysets represent a set of data that is encrypted under the same key heirarchy.
  • Clients are entities that can generate and retrieve keys for one or more keysets.

§Authentication

To use the ZeroKMS client, a valid access token is required. You don’t need to provide this directly: it is handled by the client using one of 2 methods:

  • Stash CLI: You can use the stash CLI to authenticate and store the access token
  • Client Access Key: You can provide a client access key to the client to authenticate

Stash CLI is best for local development and testing, while the client access key is best for production.

§ZeroKMS Client

The ZeroKMS client provides a high-level interface for managing Keysets and Clients in ZeroKMS. It does not provide methods to encrypt or decrypt data. For that, you need to use a ZeroKMSWithClientKey client.

The ZeroKMS client can perform the following operations:

  • Create a new Keyset
  • Grant and Revoke access to a Keyset for a client
  • List all Keysets in a Workspace
  • Enable and Disable a Keyset
  • Modify a Keyset’s name or description
  • Create a new Client for a Keyset
  • List all Clients in a Workspace
  • Revoke (Delete) a Client

§Example: Create a Keyset

use cipherstash_client::zerokms::Error;
use cipherstash_client::config::{EnvSource, ZeroKMSConfig};

#[tokio::main]
async fn main() -> Result<(), Error> {
    let zerokms = ZeroKMSConfig::builder()
        .add_source(EnvSource::new())
        .build()
        .expect("failed to build config")
        .create_client();

    zerokms.create_dataset("my-keyset", "My keyset description").await?;

    Ok(())
}

§ZeroKMSWithClientKey Client

The ZeroKMSWithClientKey is the same as ZeroKMS but with the ability to encrypt and decrypt data. Use it only when you need to perform encryption and decryption operations. If your client only needs to manage Keysets and Clients, use the ZeroKMS client.

The ZeroKMSWithClientKey client can perform the following operations:

  • Encrypt one or many values
  • Decrypt one or many values
  • Save and Load a Keyset’s configuration

§Example: Encrypt and Decrypt

use cipherstash_client::zerokms::{ClientKey, EncryptPayload, Error};
use cipherstash_client::config::{EnvSource, ZeroKMSConfig};

let zerokms = ZeroKMSConfig::builder()
  .add_source(EnvSource::new())
  .client_id("29f4c409-da51-496d-a1b8-cea9a9fd2660")
  .try_with_client_key("e27aaa358784340a822d692a99c12692cd0...")?
  .build_with_client_key()
  .expect("failed to build config")
  .create_client();

let message = b"Hello, World!";
let payload = EncryptPayload::new(message);
let encrypted = zerokms.encrypt_single(payload, None).await?;
let result = zerokms.decrypt_single(encrypted, None, None, None).await?;
assert_eq!(message, result.as_slice());

See also ClientKey and EncryptPayload.

§Specifying Keyset ID

When a client has access only to one keyset, ZeroKMS will automatically use that keyset for encryption and decryption. However, when a client has access to multiple keysets, you need to specify the keyset ID.

use cipherstash_client::zerokms::{ClientKey, EncryptPayload, Error};
use cipherstash_client::config::{EnvSource, ZeroKMSConfig};

use uuid::Uuid;
// Keyset ID for the keyset you want to use
let keyset_id: Uuid = "901C968B-9AA9-453D-B024-B26739E3AC88".parse().unwrap();
let message = b"Hello, World!";
let payload = EncryptPayload::new(message);
let encrypted = zerokms.encrypt_single(payload, Some(keyset_id)).await?;
let result = zerokms.decrypt_single(encrypted, None, None, None).await?;
assert_eq!(message, result.as_slice());

§Descriptors

ZeroKMSWithClientKey includes the concept of a “descriptor” which is a string that describes the data being encrypted. It provides a way to identify the data being encrypted and decrypted which can be used to ensure the data is being used correctly.

Descriptors are included in the “Authenticated Associated Data” (AAD) of the encryption and decryption operations. This means that the descriptor is included in the authentication tag and any tampering with the descriptor will cause the decryption to fail. Descriptors are also used by ZeroKMS to track the usage of keys and data.

§Using Descriptors

A common use for descriptors is to identify the data being encrypted like the table, column and row ID in a database.

let message = b"Kate Smith";
// Descriptor for record with ID 1 in the "users" table and "name" column
let payload = EncryptPayload::new_with_descriptor(message, "users/name/1");
let encrypted = zerokms.encrypt_single(payload, None).await?;
let result = zerokms.decrypt_single(encrypted, None, None, None).await?;

§Adding Encryption Context

You can also include additional context values when encrypting data.

let payload = EncryptPayload::new(b"Kate Smith")
   .with_context(Context::new_tag("users/name/1"));
let encrypted = zerokms.encrypt_single(payload, None).await?;
// **Note**: This will fail because the decryption context doesn't match the encryption context
//let result = zerokms.decrypt_single(encrypted).await?;

// To provide the correct context, you need to include the same context when decrypting:
let payload = encrypted.with_context(Context::new_tag("users/name/1"));
let result = zerokms.decrypt_single(payload, None, None, None).await?;

Modules§

encrypted_record

Structs§

ClientKey
NOTE: Debug is safe to implement because KeySet is opaque.
CreateClientResponse
Response message to a CreateClientRequest.
DataKeyWithTag
DatasetConfig
Struct to manage the config for a given database. At connection time, the Driver will retrieve config from Vitur for the currently connected database
DatasetConfigWithIndexRootKey
DeleteClientResponse
EncryptPayload
EncryptedRecord
Represents an encrypted record for storage in the database. Implements serialization and deserialization so you can use it with any serde-compatible format however convenience methods are provided for CBOR, MessagePack, Hex, and Base85 encoding.
GenerateKeyPayload
The requirements for generating a data key from Vitur.
Keyset
Struct representing a keyset. This is the response to a CreateKeysetRequest and a in a vector in the response to a ListKeysetRequest.
KeysetClient
Response type for a ListClientRequest.
RecordDecryptError
RetrieveKeyPayload
The requirements for retrieving a data key from Vitur.
ViturKeyMaterial
Key material type used in GenerateKeyRequest and RetrieveKeyRequest as well as CreateClientResponse.
WithContext
ZeroKMS

Enums§

ClientKeysetId
Struct representing the keyset ids associated with a client which could be a single keyset or multiple keysets.
Context
Represents a contextual attribute for a data key which is used to “lock” the key to a specific context. Context attributes are included key tag generation which is in turn used as AAD in the final encryption step in the client. Context attributes should never include any sensitive information.
Error

Traits§

Decryptable

Functions§

decrypt
encrypt

Type Aliases§

ZeroKMSWithClientKey