pub struct RefreshableCipher<C> { /* private fields */ }Expand description
An AEAD cipher that holds a hot-swappable inner cipher behind an
ArcSwap.
This is the pure mechanism layer — it knows how to atomically swap the inner cipher by re-invoking a factory closure. Concurrent refresh attempts are serialised so that only one factory call runs at a time; waiters that arrive while a refresh is in flight adopt the result.
Policy concerns (TTL, failure backoff) are handled by
ScheduledRefreshCipher, which wraps the
same mechanism.
This allows runtime rotation of encryption keys (e.g. from a KMS or secret manager) without restarting the application.
For emitting, go through the selector API
(select_cipher /
select_sealer), which hands back a frozen
snapshot. Using the type directly as an AeadEncryptor takes a fresh snapshot
per call, so reading metadata and then encrypting can straddle a rotation — the
hazard the selector exists to prevent (see composing crypto
strategies); the bare impl exists
only for composition and erasure.
All clones share the same underlying state, so a refresh performed through
any clone is visible to all others — a single RefreshableCipher can be
cloned into a sealer and an unsealer while one handle is kept for refresh.
Implementations§
Source§impl<C: Debug + MaybeSendSync + 'static> RefreshableCipher<C>
impl<C: Debug + MaybeSendSync + 'static> RefreshableCipher<C>
Sourcepub async fn refresh(&self) -> Result<bool, Error>
pub async fn refresh(&self) -> Result<bool, Error>
Refreshes the cipher by re-invoking the factory and atomically swapping the inner value.
Concurrent callers are serialised — only one factory call runs at a time. If another task already refreshed while this one was waiting for the lock, the new value is adopted without a redundant fetch.
Returns Ok(true) if new key material was fetched by this call, or
Ok(false) if another task already refreshed concurrently.
§Errors
Returns an error if the factory call fails.
Sourcepub fn builder<I1>() -> RefreshableCipherBuilder<C, I1>where
I1: Fn() -> Pin<Box<dyn MaybeSendFuture<Output = Result<C, Error>>>> + MaybeSendSync + 'static,
pub fn builder<I1>() -> RefreshableCipherBuilder<C, I1>where
I1: Fn() -> Pin<Box<dyn MaybeSendFuture<Output = Result<C, Error>>>> + MaybeSendSync + 'static,
Creates a new RefreshableCipher using the given factory.
The factory is called immediately to produce the initial cipher. The
same factory is called on subsequent refreshes via
refresh.
§Errors
Returns an error if the initial factory call fails.
Trait Implementations§
Source§impl<C: AeadEncryptor + 'static> AeadCipherSelector for RefreshableCipher<C>
impl<C: AeadEncryptor + 'static> AeadCipherSelector for RefreshableCipher<C>
Source§fn select_cipher(&self) -> MaybeSendBoxFuture<'_, Arc<dyn AeadEncryptor>>
fn select_cipher(&self) -> MaybeSendBoxFuture<'_, Arc<dyn AeadEncryptor>>
Source§impl<C: AeadDecryptor + 'static> AeadDecryptor for RefreshableCipher<C>
impl<C: AeadDecryptor + 'static> AeadDecryptor for RefreshableCipher<C>
Source§fn cipher_match(&self, m: &CipherMatch<'_>) -> Option<KeyMatchStrength>
fn cipher_match(&self, m: &CipherMatch<'_>) -> Option<KeyMatchStrength>
Source§fn decrypt<'a>(
&'a self,
cipher_match: Option<&'a CipherMatch<'a>>,
nonce: &'a [u8],
ciphertext: &'a [u8],
tag: &'a [u8],
aad: &'a [u8],
) -> MaybeSendBoxFuture<'a, Result<Vec<u8>, DecryptError>>
fn decrypt<'a>( &'a self, cipher_match: Option<&'a CipherMatch<'a>>, nonce: &'a [u8], ciphertext: &'a [u8], tag: &'a [u8], aad: &'a [u8], ) -> MaybeSendBoxFuture<'a, Result<Vec<u8>, DecryptError>>
Source§fn try_refresh(&self) -> MaybeSendBoxFuture<'_, bool>
fn try_refresh(&self) -> MaybeSendBoxFuture<'_, bool>
JwsVerifier::try_refresh. Read moreSource§impl<C: AeadEncryptor + 'static> AeadEncryptor for RefreshableCipher<C>
impl<C: AeadEncryptor + 'static> AeadEncryptor for RefreshableCipher<C>
Source§fn enc_algorithm(&self) -> Cow<'_, str>
fn enc_algorithm(&self) -> Cow<'_, str>
A256GCM).Source§fn encrypt<'a>(
&'a self,
plaintext: &'a [u8],
aad: &'a [u8],
) -> MaybeSendBoxFuture<'a, Result<AeadOutput, Error>>
fn encrypt<'a>( &'a self, plaintext: &'a [u8], aad: &'a [u8], ) -> MaybeSendBoxFuture<'a, Result<AeadOutput, Error>>
Source§impl<C: AeadEncryptor + 'static> AeadSealerSelector for RefreshableCipher<C>
impl<C: AeadEncryptor + 'static> AeadSealerSelector for RefreshableCipher<C>
Source§fn select_sealer(&self) -> MaybeSendBoxFuture<'_, Arc<dyn AeadSealer>>
fn select_sealer(&self) -> MaybeSendBoxFuture<'_, Arc<dyn AeadSealer>>
Source§impl<C: AeadDecryptor + 'static> AeadUnsealer for RefreshableCipher<C>
impl<C: AeadDecryptor + 'static> AeadUnsealer for RefreshableCipher<C>
Source§fn unseal<'a>(
&'a self,
cipher_match: Option<&'a CipherMatch<'a>>,
bundle: &'a [u8],
aad: &'a [u8],
) -> MaybeSendBoxFuture<'a, Result<Vec<u8>, DecryptError>>
fn unseal<'a>( &'a self, cipher_match: Option<&'a CipherMatch<'a>>, bundle: &'a [u8], aad: &'a [u8], ) -> MaybeSendBoxFuture<'a, Result<Vec<u8>, DecryptError>>
AeadSealer::seal. Read more