trelent_hyok/lib.rs
1//! Hold Your Own Key (HYOK) encryption service.
2//!
3//! This library provides a flexible system for managing encrypted data using
4//! customer-managed encryption keys. It supports:
5//!
6//! - Multiple key management services (AWS KMS, Azure Key Vault)
7//! - Custom encryption strategies
8//! - Key caching and persistence
9//! - Type-safe data handling
10//!
11//! The library follows the envelope encryption pattern where data is encrypted
12//! with Data Encryption Keys (DEKs) which are themselves protected by
13//! Customer Managed Keys (CMKs).
14
15pub mod cache;
16pub mod cmk;
17pub mod dek;
18pub mod error;
19mod held_data;
20mod builder;
21pub use builder::*;
22
23pub use held_data::*;
24
25use crate::dek::generator::DEKGenerator;
26use crate::dek::persistence::DEKPersistService;
27use crate::dek::scope::WithScope;
28use crate::dek::DEK;
29use crate::encryption::EncryptionStrategy;
30use crate::error::encryption::EncryptionError;
31use crate::error::generator::PersistError;
32use futures_util::TryFutureExt;
33use std::sync::Arc;
34
35/// Main service for managing encrypted data using the HYOK pattern.
36///
37/// This service coordinates:
38/// - Data Encryption Key (DEK) generation
39/// - Key persistence and caching
40/// - Encryption/decryption operations
41/// - Scope-based key management
42///
43/// # Type Parameters
44///
45/// * `S` - The encryption strategy used for data protection
46///
47/// # Example
48/// ```no_run
49/// use hyokashi::{HYOKServiceBuilder, EncryptionStrategy};
50///
51///
52/// let service = HYOKServiceBuilder::new()
53/// .with_fixed_length_generator(32)
54/// .with_aws_cmk(kms_client, "alias/my-key", algorithm)
55/// .with_aws_persistence(secrets_client)
56/// .build(encryption_strategy)?;
57///
58/// // Encrypt some data
59/// let held = service.hold_value(data, "my-scope".into(), metadata).await?;
60///
61/// // Decrypt the data
62/// let plain = service.release_value(held, "my-scope".into(), metadata).await?;
63///
64/// ```
65pub struct HYOKService<S: EncryptionStrategy> {
66 pub(crate) persist_service: Arc<DEKPersistService>,
67 pub(crate) generator: DEKGenerator,
68 pub(crate) strategy: S,
69}
70
71impl<S: EncryptionStrategy<EncryptionData = ED> + Send + Sync, ED: Send> HYOKService<S> {
72 /// Creates a new HYOK service instance.
73 ///
74 /// # Arguments
75 ///
76 /// * `persist_service` - Service for key persistence and caching
77 /// * `generator` - Strategy for generating new DEKs
78 /// * `strategy` - Strategy for encrypting/decrypting data
79 pub fn new(
80 persist_service: Arc<DEKPersistService>,
81 generator: DEKGenerator,
82 strategy: S
83 ) -> Self {
84 Self {
85 persist_service,
86 generator,
87 strategy,
88 }
89 }
90
91 /// Decrypts an object using its scope to locate the appropriate DEK.
92 ///
93 /// # Arguments
94 ///
95 /// * `obj` - The encrypted object to decrypt
96 ///
97 /// # Type Parameters
98 ///
99 /// * `T` - The encrypted object type
100 /// * `C` - The decrypted object type
101 ///
102 /// # Errors
103 ///
104 /// Returns an `EncryptionError` if:
105 /// - DEK retrieval fails
106 /// - Decryption fails
107 /// - Type conversion fails
108 pub async fn release_object<T, C>(&self, obj: &T) -> Result<C, EncryptionError>
109 where T: ReleaseHeldObject<C, S> + WithScope
110 {
111 let scope = obj.get_scope();
112 let dek = self
113 .prep_dek(scope)
114 .map_err(|e|
115 EncryptionError::new(format!("Could not prep DEK, Error: {:?}", e))
116 ).await?;
117 let result = obj.release_object(dek.into(), &self.strategy).await;
118 result
119 }
120
121 /// Decrypts a held value using the provided scope and metadata.
122 ///
123 /// # Arguments
124 ///
125 /// * `val` - The encrypted value to decrypt
126 /// * `scope` - The scope identifier for locating the DEK
127 /// * `encryption_data` - Additional metadata needed for decryption
128 ///
129 /// # Errors
130 ///
131 /// Returns an `EncryptionError` if:
132 /// - DEK retrieval fails
133 /// - Decryption fails
134 pub async fn release_value(
135 &self,
136 val: HeldValue,
137 scope: String,
138 encryption_data: ED
139 ) -> Result<Vec<u8>, EncryptionError> {
140 let dek = self
141 .prep_dek(scope)
142 .map_err(|e|
143 EncryptionError::new(format!("Could not prep DEK, Error: {:?}", e))
144 ).await?;
145 let result = val.release(dek.into(), &self.strategy, encryption_data).await;
146 result
147 }
148
149 /// Encrypts data using a DEK associated with the provided scope.
150 ///
151 /// # Arguments
152 ///
153 /// * `val` - The data to encrypt
154 /// * `scope` - The scope identifier for key management
155 /// * `encryption_data` - Additional metadata needed for encryption
156 ///
157 /// # Errors
158 ///
159 /// Returns an `EncryptionError` if:
160 /// - DEK retrieval or generation fails
161 /// - Encryption fails
162 pub async fn hold_value(
163 &self,
164 val: Vec<u8>,
165 scope: String,
166 encryption_data: ED
167 ) -> Result<HeldValue, EncryptionError> {
168 let dek = self
169 .prep_dek(scope)
170 .map_err(|e|
171 EncryptionError::new(format!("Could not prep DEK, Error: {:?}", e))
172 ).await?;
173 Held(val, dek.into(), &self.strategy, encryption_data).await
174 }
175
176 /// Retrieves or generates a DEK for the specified scope.
177 ///
178 /// # Arguments
179 ///
180 /// * `scope` - The scope identifier for the DEK
181 ///
182 /// # Returns
183 ///
184 /// The DEK associated with the scope, generating and persisting
185 /// a new one if none exists.
186 ///
187 /// # Errors
188 ///
189 /// Returns a `PersistError` if:
190 /// - Key retrieval fails
191 /// - Key generation fails
192 /// - Key persistence fails
193 pub async fn prep_dek(&self, scope: String) -> Result<DEK, PersistError> {
194 let fetch_result = self.persist_service.fetch_dek(scope.clone()).await;
195 let final_result = match fetch_result {
196 Ok(dek) => Ok(dek.into()),
197 _ => {
198 let dek = self.generator
199 .new_dek()
200 .map_err(|e|
201 PersistError::Error(format!("Could not generate key, Error: {:?}", e))
202 )?;
203 self.persist_service.save_dek(scope.clone(), dek.clone()).await?;
204 Ok(dek.into())
205 }
206 };
207 final_result
208 }
209}