Skip to main content

Crate doppel

Crate doppel 

Source
Expand description

Secret swapping and streaming restoration for arbitrary byte payloads.

doppel intercepts secrets in outbound payloads, replaces them with structurally-equivalent fakes, and restores the originals in streaming responses.

Three operations form the core workflow:

  1. swap — scan a payload for secrets matching the supplied Patterns, replace each with a fake, and return the swapped payload, encrypted entries, and a session key.
  2. Transmit — send the swapped payload to the external service. Hold the entries and session key locally.
  3. restore — stream the response through the restore function, which replaces fakes with originals using the session key and entries.

For repeated swap calls against the same fixed pattern set, use Detector to pre-build the Aho-Corasick automaton once and reuse it across calls; this avoids rebuilding the automaton on every request.

§Quick start

use doppel::{swap, restore, patterns};

// NOT real credentials — synthetic key matching the Anthropic structural pattern
let payload = b"Authorization: sk-ant-api03-w8bVJRHra9S96i3ios_XhbLgzEBjS6qjPUEgiPrWjN2OeICCY1lwhK3Z35Z_jM89STjqSOxHh6GWGkG2R7uv-AohQLmK9AA";

// 1. Swap: detect and replace the key before sending to an external service
// Note: `patterns::all()` uses ephemeral salts — two separate calls to `swap` with
// the same secret will produce different fakes. For stable fakes across calls,
// use `SecretsFile::to_patterns()`. The `restore` call always works correctly because
// fakes are embedded in the encrypted entries, independent of pattern salts.
let result = swap(payload, &patterns::all()).unwrap();
assert_eq!(result.entries.len(), 1); // one secret detected
assert_ne!(result.payload.as_slice(), payload as &[u8]); // key replaced with a fake

// result.payload     — send to external service (key replaced with a fake)
// result.entries     — keep locally; needed to restore secrets in the response
// result.session_key — keep locally; zeroized on drop

// 2. Restore: recover the original secret from the response stream
let mut response = result.payload.as_slice();
let mut restored = Vec::new();
restore(
    &mut response,
    &mut restored,
    &result.entries,
    &result.session_key,
)
.unwrap();
assert_eq!(restored, payload.as_slice());

Re-exports§

pub use detector::Detector;
pub use patterns::Pattern;
pub use secrets_file::PatternEntry;
pub use secrets_file::SecretsFile;
pub use secrets_file::SecretsFileError;
pub use types::Entry;
pub use types::SessionKey;
pub use types::SwapError;
pub use types::SwapResult;

Modules§

detector
Pre-built detection context for high-throughput use cases.
patterns
Built-in structural patterns and per-call constructor functions.
secrets_file
Patterns file serialization and deserialization (TOML, version 3).
segment
Segment types for structural pattern definitions.
types
Core types: SessionKey, Entry, SwapResult, and error enums.

Structs§

SecretOptions
Options for registered secret registration.

Enums§

RestoreError
Errors returned by restore and restore_stream (async feature).
SecretError
Errors returned by registration.

Functions§

register
Register an arbitrary secret with default options and produce a registered-secret Pattern.
register_with_options
Register an arbitrary secret with explicit options.
restore
Stream input to output incrementally, replacing any fakes found in entries with their original plaintext, decrypted using session_key.
swap
Scan payload for secrets matching patterns, replace each with a structurally-equivalent fake, and return the swapped payload, encrypted entries, and a fresh session key.