Skip to main content

CtEngine

Struct CtEngine 

Source
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,

Source

pub const fn new() -> Self

Creates a new constant-time-oriented decoder engine.

Source

pub const fn is_padded(&self) -> bool

Returns whether this constant-time-oriented decoder expects padded input.

Source

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());
Source

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"));
Source

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.

Source

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));
Source

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.

Source

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");
Source

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.

Source

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"));
Source

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"));
Source

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");

Trait Implementations§

Source§

impl<A: Clone, const PAD: bool> Clone for CtEngine<A, PAD>

Source§

fn clone(&self) -> CtEngine<A, PAD>

Returns a duplicate of the value. Read more
1.0.0 (const: unstable) · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl<A: Copy, const PAD: bool> Copy for CtEngine<A, PAD>

Source§

impl<A: Debug, const PAD: bool> Debug for CtEngine<A, PAD>

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl<A: Default, const PAD: bool> Default for CtEngine<A, PAD>

Source§

fn default() -> CtEngine<A, PAD>

Returns the “default value” for a type. Read more
Source§

impl<A, const PAD: bool> Display for CtEngine<A, PAD>

Source§

fn fmt(&self, formatter: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl<A: Eq, const PAD: bool> Eq for CtEngine<A, PAD>

Source§

impl<A: PartialEq, const PAD: bool> PartialEq for CtEngine<A, PAD>

Source§

fn eq(&self, other: &CtEngine<A, PAD>) -> bool

Tests for self and other values to be equal, and is used by ==.
1.0.0 (const: unstable) · Source§

fn ne(&self, other: &Rhs) -> bool

Tests for !=. The default implementation is almost always sufficient, and should not be overridden without very good reason.
Source§

impl<A, const PAD: bool> StructuralPartialEq for CtEngine<A, PAD>

Auto Trait Implementations§

§

impl<A, const PAD: bool> Freeze for CtEngine<A, PAD>

§

impl<A, const PAD: bool> RefUnwindSafe for CtEngine<A, PAD>
where A: RefUnwindSafe,

§

impl<A, const PAD: bool> Send for CtEngine<A, PAD>
where A: Send,

§

impl<A, const PAD: bool> Sync for CtEngine<A, PAD>
where A: Sync,

§

impl<A, const PAD: bool> Unpin for CtEngine<A, PAD>
where A: Unpin,

§

impl<A, const PAD: bool> UnsafeUnpin for CtEngine<A, PAD>

§

impl<A, const PAD: bool> UnwindSafe for CtEngine<A, PAD>
where A: UnwindSafe,

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
Source§

impl<T> ToString for T
where T: Display + ?Sized,

Source§

fn to_string(&self) -> String

Converts the given value to a String. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.