Getting started
Cargo.toml:
[dependencies]
kms-aead = { version = "0.30", features = ["gcp-kms-encryption", "aws-lc"] }
The crate has no default features. A build makes three choices, and they do not constrain each other:
- the KMS providers, any number of them, or none for AEAD without a KMS;
- the TLS root store and the TLS crypto provider of each provider that has a choice;
- the crypto backends that run the AEAD algorithms, one or more.
Features
KMS providers:
gcp-kms-encryption: Google Cloud KMS, with the native TLS roots of the system. Be aware it also turns on native-tls in reqwest, so in the same build the Azure provider uses native-tls whatever its TLS feature;gcp-kms-encryption-webpki: Google Cloud KMS with the bundled WebPKI roots;gcp-kms-encryption-base: Google Cloud KMS without a TLS root store or crypto provider. The application enables them with its owngcloud-sdkfeatures, such astls-rootsortls-webpki-roots, and the crate does not build without one;aws-kms-encryption: AWS KMS;azure-kms-encryption: Azure Key Vault and Managed HSM, with rustls and the aws-lc-rs crypto provider. Other TLS variants, choose one:azure-kms-encryption-tls-aws-lc-rs, the same asazure-kms-encryption;azure-kms-encryption-tls-no-provider, rustls with the crypto provider the application installs. The application must install a process-default rustlsCryptoProviderbefore creating the provider, otherwise rustls panics;azure-kms-encryption-native-tls, the platform TLS library;
hashicorp-vault-transit-kms-encryption: HashiCorp Vault Transit, with the system root certificates and the aws-lc-rs crypto provider. To choose them, enable one root store and one crypto provider instead:hashicorp-vault-transit-kms-encryption-tls-rootsorhashicorp-vault-transit-kms-encryption-tls-webpki;hashicorp-vault-transit-kms-encryption-tls-aws-lc-rsorhashicorp-vault-transit-kms-encryption-tls-ring.
The local KMS provider, LocalKmsProvider, is in every build and needs no feature.
Crypto backends, see Crypto backends:
ring: the ring library;aws-lc: the aws-lc-rs library;aws-lc-fips: the aws-lc-rs library on the AWS-LC FIPS module. Needs CMake and Go to build;rustcrypto: the pure Rust RustCrypto crates, no C compiler needed.
Other features:
deterministic: deterministic encryption with AES-SIV, see Deterministic encryption;legacy-formats: reads the layouts written by 0.29 and earlier. Deprecated, see Formats;serde:SerializeandDeserializeforEncrypted, as bytes, forKmsAeadErrorPublicGenericDetailsand forSecretValue;serde-json:Json, a typed field’s plaintext of any serde type, stored as its JSON;postgres:ToSqlandFromSqlof postgres-types forEncrypted, asBYTEA, for tokio-postgres;sqlx: sqlx’s PostgreSQL traits forEncrypted, asBYTEA, without a sqlx runtime or TLS stack.
See Typed fields.
Choosing a backend
The default features of the four cloud providers already build aws-lc-rs for TLS, so aws-lc is
the backend that adds no second crypto library to a provider build. ring and rustcrypto work
with every provider too, and a build may enable several backends at once. Each feature adds a type
to kms_aead::backends, Ring, AwsLc or RustCrypto, and every type that seals or encrypts
takes one as its backend type parameter:
fn example() -> kms_aead::KmsAeadResult<()> {
use kms_aead::backends::AwsLc;
use kms_aead::{AeadAlgorithm, AeadCipher};
let cipher = AeadCipher::<AwsLc>::new(AeadAlgorithm::Aes256Gcm)?;
let _ = cipher;
Ok(())
}
There is no default backend. Code generic over the backend bounds it with B: AeadBackend and
nothing else, see Crypto backends.
Feature rules
The crate refuses some feature combinations at compile time with compile_error!:
- a provider feature without a backend feature fails with “kms-aead needs a crypto backend for its KMS providers: enable “ring”, “aws-lc”, “aws-lc-fips” or “rustcrypto”“;
- HashiCorp Vault Transit needs exactly one of
-tls-rootsand-tls-webpki, and exactly one of-tls-aws-lc-rsand-tls-ring.hashicorp-vault-transit-kms-encryptionalready enables-tls-rootsand-tls-aws-lc-rs, so combine the other variants withhashicorp-vault-transit-kms-encryption-baseinstead; - Azure needs exactly one of
azure-kms-encryption-tls-aws-lc-rs(orazure-kms-encryption),azure-kms-encryption-tls-no-providerandazure-kms-encryption-native-tls.
The aws-lc-rs feature that aws-lc and aws-lc-fips enable is not a backend choice: enabled
alone, the aws-lc-rs build fails. Use aws-lc or aws-lc-fips.
A build without any backend feature compiles, and LocalKmsProvider is in it, but nothing that
seals or encrypts can be constructed, since no type implements AeadBackend.
First example
The local KMS needs no cloud account, so it is the quickest way to try the library. An ephemeral KEK lives as long as the process:
use kms_aead::backends::Ring;
use kms_aead::formats::Envelope;
use kms_aead::providers::{LocalKekId, LocalKmsProvider};
use kms_aead::{Encrypted, KmsAeadEnvelope};
use secret_vault_value::SecretValue;
#[tokio::main(flavor = "current_thread")]
async fn main() -> kms_aead::KmsAeadResult<()> {
let provider = LocalKmsProvider::<Ring>::ephemeral(LocalKekId::try_from("example".to_string())?)?;
let envelope = KmsAeadEnvelope::<LocalKmsProvider<Ring>, Ring>::new(provider)?;
let aad = b"orders/1042";
let secret = SecretValue::from("4111 1111 1111 1111");
let encrypted: Encrypted<SecretValue, Envelope> = envelope.encrypt(aad, &secret).await?;
let decrypted: SecretValue = envelope.decrypt(aad, &encrypted).await?;
assert_eq!(decrypted, secret);
Ok(())
}
To move to a cloud KMS, replace the provider, see KMS providers. The rest of the code stays the same.
MSRV
The minimum supported Rust version is 1.99, for every feature.