pub struct CtEngine<A, const PAD: bool> { /* private fields */ }Expand description
A zero-sized constant-time-oriented Base64 decoder.
§Security
For ordinary secret-bearing inputs, prefer
Self::decode_slice_clear_tail, Self::decode_buffer, or
Self::decode_in_place_clear_tail. For shared-memory,
enclave-adjacent, HSM-style, or multi-principal deployments where
another component can observe caller-owned output during the call, use
Self::decode_slice_staged_clear_tail with a private staging buffer
so malformed input cannot transiently write decoded bytes into the
public output buffer before the final error gate.
Implementations§
Source§impl<A, const PAD: bool> CtEngine<A, PAD>where
A: Alphabet,
impl<A, const PAD: bool> CtEngine<A, PAD>where
A: Alphabet,
Sourcepub const fn is_padded(&self) -> bool
pub const fn is_padded(&self) -> bool
Returns whether this constant-time-oriented decoder expects padded input.
Sourcepub fn validate_result(&self, input: &[u8]) -> Result<(), DecodeError>
pub fn validate_result(&self, input: &[u8]) -> Result<(), DecodeError>
Validates input without writing decoded bytes.
This uses the same constant-time-oriented symbol mapping and opaque
malformed-input error behavior as
Self::decode_slice_clear_tail. Input length, padding length, and
final success or failure remain public.
§Examples
use base64_ng::ct;
ct::STANDARD.validate_result(b"aGVsbG8=").unwrap();
assert!(ct::STANDARD.validate_result(b"aGVsbG8").is_err());Sourcepub fn validate(&self, input: &[u8]) -> bool
pub fn validate(&self, input: &[u8]) -> bool
Returns whether input is valid for this constant-time-oriented
decoder.
This is a convenience wrapper around Self::validate_result.
§Examples
use base64_ng::ct;
assert!(ct::URL_SAFE_NO_PAD.validate(b"-_8"));
assert!(!ct::URL_SAFE_NO_PAD.validate(b"+/8"));Sourcepub fn decoded_len(&self, input: &[u8]) -> Result<usize, DecodeError>
pub fn decoded_len(&self, input: &[u8]) -> Result<usize, DecodeError>
Returns the exact decoded length for valid input.
This uses the same constant-time-oriented validation policy as
Self::validate_result before returning a length. Input length,
padding length, and final success or failure remain public.
Sourcepub fn decode_slice_clear_tail(
&self,
input: &[u8],
output: &mut [u8],
) -> Result<usize, DecodeError>
pub fn decode_slice_clear_tail( &self, input: &[u8], output: &mut [u8], ) -> Result<usize, DecodeError>
Decodes input into output and clears all bytes after the
decoded prefix.
If decoding fails, the entire output buffer is cleared before the error is returned. Use this variant for sensitive payloads where partially decoded bytes from rejected input should not remain in the caller-owned output buffer.
§Security: Transient Plaintext Window
Decoded bytes are written to output progressively during the
fixed-shape decode loop before malformed-input detection is
complete. On error, the entire output is wiped before returning,
but a concurrent same-process observer with access to output
during the call may observe transient partial plaintext from valid
leading quanta. For shared-memory, enclave-adjacent, HSM-style, or
multi-principal deployments where even transient writes are
unacceptable, use Self::decode_slice_staged_clear_tail with a
private staging buffer.
§Examples
use base64_ng::ct;
let mut output = [0xff; 8];
let written = ct::STANDARD
.decode_slice_clear_tail(b"aGk=", &mut output)
.unwrap();
assert_eq!(&output[..written], b"hi");
assert!(output[written..].iter().all(|byte| *byte == 0));Sourcepub fn decode_slice_staged_clear_tail(
&self,
input: &[u8],
output: &mut [u8],
staging: &mut [u8],
) -> Result<usize, DecodeError>
pub fn decode_slice_staged_clear_tail( &self, input: &[u8], output: &mut [u8], staging: &mut [u8], ) -> Result<usize, DecodeError>
Decodes through caller-provided private staging before copying into
output.
This variant is for shared-memory or sandboxed deployments where
the caller-owned output buffer must not contain transient decoded
bytes from malformed input. The staging buffer must be at least
the decoded length of input and must not be shared with
untrusted concurrent observers. On success, decoded bytes are
copied from staging into output; on error, both buffers are
cleared before returning.
Input length, final success or failure, and decoded length remain public.
Sourcepub fn decode_buffer<const CAP: usize>(
&self,
input: &[u8],
) -> Result<DecodedBuffer<CAP>, DecodeError>
pub fn decode_buffer<const CAP: usize>( &self, input: &[u8], ) -> Result<DecodedBuffer<CAP>, DecodeError>
Decodes input into a stack-backed buffer.
This uses the same constant-time-oriented scalar decoder as
Self::decode_slice_clear_tail and clears the internal backing
array before returning an error.
§Examples
use base64_ng::ct;
let decoded = ct::STANDARD.decode_buffer::<5>(b"aGVsbG8=").unwrap();
assert_eq!(decoded.as_bytes(), b"hello");Sourcepub fn decode_vec(&self, input: &[u8]) -> Result<Vec<u8>, DecodeError>
pub fn decode_vec(&self, input: &[u8]) -> Result<Vec<u8>, DecodeError>
Decodes input into an owned byte vector.
This uses the same constant-time-oriented scalar decoder as
Self::decode_slice_clear_tail. If decoding fails, the allocated
output buffer is cleared before the error is returned.
Use Self::decode_secret for secret-bearing payloads that should stay
on the crate’s redacted, drop-wiping buffer path. Use
Self::decode_secret_staged for shared-memory, enclave-adjacent,
HSM-style, or multi-principal deployments where even transient writes
into the final heap allocation are unacceptable.
Sourcepub fn decode_secret(&self, input: &[u8]) -> Result<SecretBuffer, DecodeError>
pub fn decode_secret(&self, input: &[u8]) -> Result<SecretBuffer, DecodeError>
Decodes input into a redacted owned secret buffer.
This is the recommended heap-owning CT decode path for secret-bearing
payloads. It decodes with Self::decode_vec and then wraps the result
in SecretBuffer, which redacts formatting and clears initialized
bytes plus spare vector capacity on drop.
§Security: Transient Plaintext Window
This function uses the non-staged CT decode path. Decoded bytes are
written transiently into the heap allocation before the final error
gate. On error, the allocation is wiped before returning, but a
concurrent same-process observer with access to that allocation during
the call may observe transient partial plaintext. For shared-memory,
enclave-adjacent, HSM-style, or multi-principal deployments where even
transient writes into the final heap allocation are unacceptable, use
Self::decode_secret_staged with a stack-backed private staging
capacity large enough for the decoded value.
§Examples
use base64_ng::ct;
let decoded = ct::STANDARD.decode_secret(b"aGVsbG8=").unwrap();
assert!(decoded.constant_time_eq_public_len(b"hello"));Sourcepub fn decode_secret_staged<const STAGE: usize>(
&self,
input: &[u8],
) -> Result<SecretBuffer, DecodeError>
pub fn decode_secret_staged<const STAGE: usize>( &self, input: &[u8], ) -> Result<SecretBuffer, DecodeError>
Decodes input into a redacted owned secret buffer through private
stack staging.
STAGE must be at least the decoded length of input. Decoded bytes
are written to a stack-backed staging buffer first and copied into the
returned heap buffer only after the full constant-time-oriented decode
succeeds. On error, both staging and heap output buffers are wiped before
returning.
This is the preferred owned decode API for shared-memory, enclave-adjacent, HSM-style, or multi-principal deployments where the final heap allocation must not contain transient partial plaintext from rejected input.
§Examples
use base64_ng::ct;
let decoded = ct::STANDARD
.decode_secret_staged::<5>(b"aGVsbG8=")
.unwrap();
assert!(decoded.constant_time_eq_public_len(b"hello"));Sourcepub fn decode_in_place_clear_tail<'a>(
&self,
buffer: &'a mut [u8],
) -> Result<&'a mut [u8], DecodeError>
pub fn decode_in_place_clear_tail<'a>( &self, buffer: &'a mut [u8], ) -> Result<&'a mut [u8], DecodeError>
Decodes buffer in place and clears all bytes after the decoded
prefix.
If decoding fails, the entire buffer is cleared before the error is returned.
§Security: Transient Plaintext Window
This in-place API writes decoded bytes into buffer during the
fixed-shape decode loop before malformed-input detection is
complete. On error, the entire buffer is wiped before returning,
but concurrent same-process observers with access to the same memory
can observe transient partial plaintext. Use
Self::decode_slice_staged_clear_tail with a private staging
buffer when shared-memory or enclave-adjacent deployments cannot
tolerate that window.
§Examples
use base64_ng::ct;
let mut buffer = *b"aGk=";
let decoded = ct::STANDARD.decode_in_place_clear_tail(&mut buffer).unwrap();
assert_eq!(decoded, b"hi");