Skip to main content

pd_cipher

PD.Cipher SDK

A Rust SDK for token-based encryption that enables privacy-preserving computations on structured data.

Overview

The PD.Cipher SDK provides a comprehensive set of tools for encrypting and decrypting tokenized data. Its core feature is adaptive token truncation, a form of deterministic encryption that significantly reduces the size of encrypted tokens while preserving the patterns required for machine learning.

Architecture

The SDK is built on a few key architectural principles:

  • Async API: The main PDCipher struct provides async methods that enable efficient token encryption without blocking the runtime.
  • Provider-Based Storage: A StorageProvider trait allows users to implement custom storage backends (e.g., for Redis, RocksDB, or cloud storage), enabling the SDK to scale beyond the memory of a single machine.
  • Pattern Preservation: Deterministic encryption ensures identical tokens always produce identical ciphertexts, enabling ML on encrypted data.

Quick Start

use pd_cipher::{PDCipher, config::CipherConfig, EncryptionAlgorithm, KeyGenerator};

# #[tokio::main(flavor = "current_thread")]
# async fn main() -> pd_cipher::Result<()> {
// 1. Use the builder for clear, validated configuration
let config = CipherConfig::builder()
.algorithm(EncryptionAlgorithm::default()) // XChaCha20Poly1305
.build()?;

// 2. Generate a key
let key = KeyGenerator::generate_key(config.algorithm)?;

// 3. Your input data as tokens
let tokens = vec!["Alice", "sends", "money", "to", "Bob", "Alice"];

// 4. Encrypt tokens
let (encrypted_tokens, context) = PDCipher::encrypt(&tokens, &key, &config).await?;

// Pattern preservation: "Alice" appears twice and maps to the same cipher token
assert_eq!(encrypted_tokens[0], encrypted_tokens[5]);

// 5. Decrypt when needed
let token_refs: Vec<&str> = encrypted_tokens.iter().map(|s| s.as_str()).collect();
let decrypted = PDCipher::decrypt(&token_refs, &context, &key).await?;
assert_eq!(tokens, decrypted);
# Ok(())
# }

Features

  • parallel (enabled by default): Enables parallel processing support via the rayon crate.
  • lookup (enabled by default): Enables the storage provider system for lookup tables.
  • io: Enables I/O providers for file-based operations.

Functions

algorithm

Sets the encryption algorithm.

Arguments

  • algorithm - The encryption algorithm to use

Example

use pd_cipher::config::CipherConfig;
use pd_cipher::keys::EncryptionAlgorithm;

let config = CipherConfig::builder()
.algorithm(EncryptionAlgorithm::XChaCha20Poly1305)
.build()
.expect("Valid configuration");
pub fn algorithm(...)

kdf_iterations

Sets the number of PBKDF2 iterations for key derivation.

Arguments

  • iterations - Number of iterations (must be >= 100,000)

Example

use pd_cipher::config::CipherConfig;

let config = CipherConfig::builder()
.kdf_iterations(1_000_000)
.build()
.expect("Valid configuration");
pub fn kdf_iterations(...)

enable_parallelism

Enables or disables parallel processing.

Arguments

  • enabled - Whether to enable parallel processing

Example

use pd_cipher::config::CipherConfig;

let config = CipherConfig::builder()
.enable_parallelism(false)
.build()
.expect("Valid configuration");
pub fn enable_parallelism(...)

max_token_count

Sets the maximum number of tokens allowed in a single operation.

Arguments

  • max_count - Maximum token count (must be > 0)

Example

use pd_cipher::config::CipherConfig;

let config = CipherConfig::builder()
.max_token_count(500_000)
.build()
.expect("Valid configuration");
pub fn max_token_count(...)

max_token_size

Sets the maximum size of a single token in bytes.

Arguments

  • max_size - Maximum token size in bytes (must be > 0)

Example

use pd_cipher::config::CipherConfig;

let config = CipherConfig::builder()
.max_token_size(8192)
.build()
.expect("Valid configuration");
pub fn max_token_size(...)

password_length_range

Sets the password length constraints.

Arguments

  • min_length - Minimum password length (must be >= 1)
  • max_length - Maximum password length (must be >= min_length)

Example

use pd_cipher::config::CipherConfig;

let config = CipherConfig::builder()
.password_length_range(12, 256)
.build()
.expect("Valid configuration");
pub fn password_length_range(...)

with_progress_callback

Sets a progress callback function.

The callback receives (current, total) progress updates during encryption operations.

Arguments

  • callback - Function to call with progress updates

Example

use pd_cipher::config::CipherConfig;

let config = CipherConfig::builder()
.with_progress_callback(|current, total| {
println!("Progress: {:.1}%", 100.0 * current as f64 / total as f64);
})
.build()
.expect("Valid configuration");
pub fn with_progress_callback<...>(...)

text_output

Sets the output strategy for text tokens.

Arguments

  • strategy - The strategy to use for text token output

Example

use pd_cipher::config::{CipherConfig, TextOutputStrategy};

let config = CipherConfig::builder()
.text_output(TextOutputStrategy::FixedShortest)
.build()
.expect("Valid configuration");
pub fn text_output(...)

numeric_output

Sets the output strategy for numeric tokens.

Arguments

  • strategy - The strategy to use for numeric token output

Example

use pd_cipher::config::{CipherConfig, NumericOutputStrategy};

let config = CipherConfig::builder()
.numeric_output(NumericOutputStrategy::Plain)
.build()
.expect("Valid configuration");
pub fn numeric_output(...)

min_truncation_length

Sets the minimum truncation length for adaptive token truncation.

Arguments

  • min_length - Starting length for truncation attempts (default: 4)

Example

use pd_cipher::config::CipherConfig;

let config = CipherConfig::builder()
.min_truncation_length(6)
.build()
.expect("Valid configuration");
pub fn min_truncation_length(...)

truncation_step_size

Sets the truncation step size for adaptive token truncation.

Arguments

  • step_size - Increment when collision detected (default: 2)

Example

use pd_cipher::config::CipherConfig;

let config = CipherConfig::builder()
.truncation_step_size(3)
.build()
.expect("Valid configuration");
pub fn truncation_step_size(...)

truncation_settings

Sets the truncation parameters for adaptive token truncation.

Arguments

  • min_length - Starting length for truncation attempts (default: 4)
  • step_size - Increment when collision detected (default: 2)

Example

use pd_cipher::config::CipherConfig;

let config = CipherConfig::builder()
.truncation_settings(6, 3)
.build()
.expect("Valid configuration");
pub fn truncation_settings(...)

plt_segments

Sets the number of PLT segments.

Arguments

  • segments - Number of segments for piecewise linear transformation

Example

use pd_cipher::config::CipherConfig;

let config = CipherConfig::builder()
.plt_segments(128)
.build()
.expect("Valid configuration");
pub fn plt_segments(...)

plt_slope_range

Sets the PLT slope range.

Arguments

  • min - Minimum slope value (must be positive)
  • max - Maximum slope value (must be > min)

Example

use pd_cipher::config::CipherConfig;

let config = CipherConfig::builder()
.plt_slope_range(0.5, 1.5)
.build()
.expect("Valid configuration");
pub fn plt_slope_range(...)

plt_value_range

Sets the PLT value range.

Arguments

  • min - Minimum expected input value
  • max - Maximum expected input value

Example

use pd_cipher::config::CipherConfig;

let config = CipherConfig::builder()
.plt_value_range(-1e9, 1e9)
.build()
.expect("Valid configuration");
pub fn plt_value_range(...)

build

Builds the configuration with validation.

Returns

A validated CipherConfig instance.

Errors

Returns CipherError::ValidationError if any parameter is invalid.

Example

use pd_cipher::config::CipherConfig;
use pd_cipher::keys::EncryptionAlgorithm;

let config = CipherConfig::builder()
.algorithm(EncryptionAlgorithm::Aes256Gcm)
.kdf_iterations(800_000)
.build()
.expect("Valid configuration");
pub fn build(...)

is_encrypted

Check if this strategy applies encryption.

pub fn is_encrypted(...)

format

Format a hash according to this strategy.

Arguments

  • hash - The full hash to format
  • min_length - The minimum length required for uniqueness

Returns

The formatted output string.

pub fn format(...)

is_encrypted

Check if this strategy applies encryption.

pub fn is_encrypted(...)

builder

Creates a new builder for constructing a CipherConfig.

Example

use pd_cipher::config::CipherConfig;
use pd_cipher::keys::EncryptionAlgorithm;

let config = CipherConfig::builder()
.algorithm(EncryptionAlgorithm::Aes256Gcm)
.kdf_iterations(800_000)
.build()
.expect("Valid configuration");
pub fn builder(...)

validate

Validates the configuration parameters.

Ensures all parameters are within acceptable ranges and combinations are valid for secure operation.

Errors

Returns CipherError::ValidationError if any parameter is invalid.

pub fn validate(...)

validate_password

Validates a password against this configuration's constraints.

Arguments

  • password - The password to validate

Errors

Returns CipherError::ValidationError if the password doesn't meet requirements.

pub fn validate_password(...)

validate_tokens

Validates a token collection against this configuration's constraints.

Arguments

  • tokens - The tokens to validate

Errors

Returns CipherError::ValidationError if tokens don't meet requirements.

pub fn validate_tokens(...)

to_json

Serializes the configuration to JSON.

Note: The progress callback is not included in serialization.

Errors

Returns CipherError::SerializationError if serialization fails.

pub fn to_json(...)

from_json

Deserializes configuration from JSON.

The resulting configuration will have no progress callback set.

Arguments

  • json - JSON string containing the configuration

Errors

Returns CipherError::DeserializationError if deserialization fails.

pub fn from_json(...)

from_tokens

Creates a new Plaintext from a vector of tokens.

Arguments

  • tokens - A vector of Tokens.

Errors

Returns CipherError::InvalidPlaintext if the token list is empty.

pub fn from_tokens(...)

tokens

Returns a slice of the plaintext tokens.

pub fn tokens(...)

token_count

Returns the number of tokens in the plaintext.

pub fn token_count(...)

new

Creates a new token classifier.

pub fn new(...)

classify

Classifies a token as either numeric or string.

This method provides explicit control flow for token type determination, avoiding the anti-pattern of using parse failure as a branching mechanism.

Arguments

  • token - The raw token bytes to classify

Returns

  • Ok(TokenType::Numeric(value)) if the token is a valid number
  • Ok(TokenType::String(bytes)) if the token is not numeric

Errors

Returns an error if the token is empty or invalid UTF-8 that can't be processed.

pub fn classify(...)

classify_batch

Batch classification of multiple tokens.

Arguments

  • tokens - Iterator of raw token bytes

Returns

Vector of classified tokens with their types.

pub fn classify_batch<...>(...)

new

Creates a new async adaptive truncation engine.

pub fn new(...)

build_lookup_table

Pass 1: Analyze dataset and build lookup table.

This method processes all tokens to determine optimal truncation lengths that avoid collisions while minimizing token size.

pub fn build_lookup_table<...>(...)

determine_target_width

Determines the target width for all tokens based on the strategy.

pub fn determine_target_width(...)

generate_tokens

Pass 2: Generate truncated tokens based on analysis.

pub fn generate_tokens<...>(...)

finalize

Finalizes the builder and returns metadata.

pub fn finalize(...)

new

Creates a new numeric processor with PLT configuration.

pub fn new(...)

new

Creates a new string processor.

pub fn new(...)

create_processor

Creates the appropriate processor based on token type.

pub fn create_processor(...)

generate_key

Generate a new cryptographic key for the specified algorithm.

This method creates a new key using the operating system's cryptographically secure random number generator.

Arguments

  • algorithm - The symmetric algorithm for which to generate a key.

Errors

Returns CipherError::RngError if the random number generator fails.

pub fn generate_key(...)

derive_from_password

Derive a cryptographic key from a password using PBKDF2.

This method derives a key from a password using PBKDF2 with HMAC-SHA256. The derived key includes the salt and iteration count, allowing it to be recreated from the same password later.

Arguments

  • password - The password to derive the key from.
  • salt - The salt for key derivation. If None, a random salt will be generated.
  • iterations - The number of PBKDF2 iterations to use.
  • algorithm - The symmetric algorithm for which to generate a key.

Returns

A Key object containing the derived key data and the derivation parameters.

Example

use pd_cipher::{KeyGenerator, EncryptionAlgorithm};

# fn example() -> pd_cipher::Result<()> {
use pd_cipher::constants::PBKDF2_DEFAULT_ITERATIONS;

// Derive a key from a password
let key = KeyGenerator::derive_from_password(
"secure-password",
None, // Generate random salt
PBKDF2_DEFAULT_ITERATIONS,
EncryptionAlgorithm::Aes256Gcm
)?;

// The key contains both the derived key material and the salt
let derivation_info = key.derivation_info().unwrap();
assert_eq!(derivation_info.iterations, PBKDF2_DEFAULT_ITERATIONS);
# Ok(())
# }
pub fn derive_from_password(...)

key_size

Returns the required key size for the algorithm in bytes.

pub fn key_size(...)

id

Get the key's unique identifier.

pub fn id(...)

validate

Validates the key against the requirements of a given algorithm.

pub fn validate(...)

size

Get the key size in bytes.

pub fn size(...)

derivation_info

Get the key derivation info if this key was derived from a password.

pub fn derivation_info(...)

new

Creates a new file system key provider.

The specified directory will be created if it doesn't exist. Default file permissions are set to 0o600 (owner read/write only).

Arguments

  • key_directory - Directory to store key files

Errors

Returns CipherError::IoError if directory creation fails.

Example

use pd_cipher::keys::providers::filesystem::FileSystemKeyProvider;
use std::path::Path;

# fn example() -> pd_cipher::Result<()> {
let provider = FileSystemKeyProvider::new(Path::new("./my-keys"))?;
# Ok(())
# }
pub fn new<...>(...)

set_file_permissions

Sets the file permissions for stored key files.

Arguments

  • permissions - Unix file permissions (e.g., 0o600 for owner read/write only)

Example

use pd_cipher::keys::providers::filesystem::FileSystemKeyProvider;
use std::path::Path;

# fn example() -> pd_cipher::Result<()> {
let mut provider = FileSystemKeyProvider::new(Path::new("./keys"))?;
provider.set_file_permissions(0o640)?; // Owner read/write, group read
# Ok(())
# }
pub fn set_file_permissions(...)

disable_file_permissions

Disables explicit file permission setting.

Uses system defaults for file creation.

pub fn disable_file_permissions(...)

key_directory

Returns the key storage directory.

pub fn key_directory(...)

new

Creates a new empty in-memory key provider.

Example

use pd_cipher::keys::providers::memory::InMemoryKeyProvider;

let provider = InMemoryKeyProvider::new();
pub fn new(...)

with_keys

Creates a new provider with initial keys.

Arguments

  • initial_keys - Vector of (key_id, key, metadata) tuples

Example

use pd_cipher::keys::providers::{memory::InMemoryKeyProvider, KeyMetadata};
use pd_cipher::keys::{EncryptionAlgorithm, KeyGenerator};

# fn example() -> pd_cipher::Result<()> {
let key = KeyGenerator::generate_key(EncryptionAlgorithm::Aes256Gcm)?;
let metadata = KeyMetadata {
id: "test-key".to_string(),
algorithm: EncryptionAlgorithm::Aes256Gcm,
created_at: 1234567890,
description: Some("Initial key".to_string()),
};

let initial_keys = vec![("test-key".to_string(), key, metadata)];
let provider = InMemoryKeyProvider::with_keys(initial_keys);
# Ok(())
# }
pub fn with_keys(...)

key_count

Returns the number of keys currently stored.

Example

use pd_cipher::keys::providers::memory::InMemoryKeyProvider;

let provider = InMemoryKeyProvider::new();
assert_eq!(provider.key_count(), 0);
pub fn key_count(...)

clear

Clears all stored keys.

Example

use pd_cipher::keys::providers::{KeyProvider, memory::InMemoryKeyProvider};
use pd_cipher::keys::EncryptionAlgorithm;

# fn example() -> pd_cipher::Result<()> {
let mut provider = InMemoryKeyProvider::new();

// Add some keys
let key = provider.generate_key(EncryptionAlgorithm::Aes256Gcm)?;
provider.store_key("key1", key, None)?;

assert_eq!(provider.key_count(), 1);
provider.clear();
assert_eq!(provider.key_count(), 0);
# Ok(())
# }
pub fn clear(...)

new

Creates a new normalization component with default settings.

Default settings:

  • Trim whitespace: true
  • Normalize case: false
  • Unicode normalization: true
pub fn new(...)

with_settings

Creates a normalization component with custom settings.

pub fn with_settings(...)

new

Creates a new validation component with default settings.

pub fn new(...)

with_limits

Creates a validation component with custom limits.

pub fn with_limits(...)

new

Creates a new filter component with no filters.

pub fn new(...)

with_min_size

Sets minimum token size filter.

pub fn with_min_size(...)

with_max_size

Sets maximum token size filter.

pub fn with_max_size(...)

exclude_pattern

Adds a pattern to exclude from tokens.

pub fn exclude_pattern(...)

include_pattern

Adds a pattern that tokens must contain to be included.

pub fn include_pattern(...)

new

Creates a new transform component.

Arguments

  • name - Name for this transformation component
  • transform_fn - Function to apply to each token
pub fn new<...>(...)

new

Creates a new empty pipeline.

Example

use pd_cipher::pipeline::Pipeline;

let pipeline = Pipeline::new();
pub fn new(...)

with_limit

Creates a new pipeline with a custom component limit.

Arguments

  • max_components - Maximum number of components allowed

Example

use pd_cipher::pipeline::Pipeline;

let pipeline = Pipeline::with_limit(10);
pub fn with_limit(...)

add_component

Adds a component to the end of the pipeline.

Components are executed in the order they are added.

Arguments

  • component - The component to add

Errors

Returns CipherError::ValidationError if the component limit is exceeded.

Example

use pd_cipher::pipeline::Pipeline;
use pd_cipher::pipeline::components::NormalizationComponent;

# fn example() -> pd_cipher::Result<()> {
let mut pipeline = Pipeline::new();
pipeline.add_component(Box::new(NormalizationComponent::new()))?;
# Ok(())
# }
pub fn add_component(...)

insert_component

Inserts a component at a specific position in the pipeline.

Arguments

  • index - Position to insert the component
  • component - The component to insert

Errors

Returns CipherError::ValidationError if index is out of bounds or component limit is exceeded.

pub fn insert_component(...)

remove_component

Removes a component at the specified index.

Arguments

  • index - Index of the component to remove

Returns

The removed component, or None if index is out of bounds.

pub fn remove_component(...)

component_count

Returns the number of components in the pipeline.

pub fn component_count(...)

component_names

Returns the names of all components in order.

pub fn component_names(...)

process

Processes tokens through the entire pipeline.

Each component processes the output of the previous component in sequence.

Arguments

  • tokens - Input tokens to process

Returns

The final processed tokens after all components have been applied.

Errors

Returns the first error encountered during processing.

Example

use pd_cipher::pipeline::Pipeline;
use pd_cipher::pipeline::components::NormalizationComponent;

# fn example() -> pd_cipher::Result<()> {
let mut pipeline = Pipeline::new();
pipeline.add_component(Box::new(NormalizationComponent::new()))?;

let tokens = vec![" Hello World ".as_bytes().to_vec()];
let processed = pipeline.process(&tokens)?;
# Ok(())
# }
pub fn process(...)

clear

Clears all components from the pipeline.

pub fn clear(...)

is_empty

Returns whether the pipeline is empty (has no components).

pub fn is_empty(...)

serialize_key

Serializes a Key object to a byte vector.

This method converts an encryption key into a binary format suitable for secure storage.

Security Warning

Serialized keys contain sensitive cryptographic material. Always store them in a secure, access-controlled location.

pub fn serialize_key(...)

deserialize_key

Deserializes a Key object from a byte slice.

This method reconstructs an encryption key from its serialized representation.

Security Note

Only deserialize keys from trusted sources.

pub fn deserialize_key(...)

validate_key

Validate a Key against the requirements of a specific algorithm.

Arguments

  • key - The cryptographic key to validate
  • algorithm - The encryption algorithm to validate against

Errors

Returns CipherError::InvalidKey if the key doesn't meet algorithm requirements.

Examples

use pd_cipher::keys::{KeyGenerator, EncryptionAlgorithm};
use pd_cipher::validation::Validator;

# fn example() -> pd_cipher::Result<()> {
let key = KeyGenerator::generate_key(EncryptionAlgorithm::Aes256Gcm)?;
Validator::validate_key(&key, EncryptionAlgorithm::Aes256Gcm)?;
# Ok(())
# }
pub fn validate_key(...)

validate_ciphertext_format

Validate the format of a raw byte slice as potential encrypted data. This is a high-level check that verifies minimum size requirements.

pub fn validate_ciphertext_format(...)

backend

Creates a backend error from any error type

pub fn backend<...>(...)

not_found

Creates a not found error with context

pub fn not_found<...>(...)

invalid_data

Creates an invalid data error with context

pub fn invalid_data<...>(...)

prefix_exists

Checks if a prefix exists in the current table. This is used during the build phase for collision detection.

pub fn prefix_exists(...)

new

Creates a new empty lookup table with the given configuration.

pub fn new(...)

insert

Adds a mapping from full hash to truncated token and plaintext.

Arguments

  • full_hash - The complete hash of the plaintext token
  • truncated - The truncated representation
  • plaintext - The original plaintext value
pub fn insert(...)

len

Returns the number of unique tokens in the table.

pub fn len(...)

is_empty

Returns true if the table is empty.

pub fn is_empty(...)

finalize_metadata

Updates metadata after analysis is complete.

pub fn finalize_metadata(...)

new

Creates new metadata with the given configuration.

pub fn new(...)

record_collision

Records a collision during truncation analysis.

pub fn record_collision(...)

record_token_length

Records the length of a truncated token.

pub fn record_token_length(...)

average_token_length

Returns the average truncated token length.

pub fn average_token_length(...)

efficiency_summary

Returns a summary of the truncation efficiency.

pub fn efficiency_summary(...)

new

Creates a new transformer with the specified parameters.

Arguments

  • key - Encryption key for seeding the PRNG
  • num_segments - Number of piecewise segments
  • slope_min - Minimum slope value (must be positive)
  • slope_max - Maximum slope value (must be > slope_min)
  • min_val - Minimum expected input value
  • max_val - Maximum expected input value

Panics

Panics if parameters are invalid (e.g., slope_min less than or equal to 0, min_val greater than or equal to max_val)

pub fn new(...)

transform

Transforms a numerical value using the piecewise linear transformation.

Arguments

  • value - The numeric value to transform

Returns

The transformed value, preserving order relationships

Example

# use pd_cipher::encryptors::numerical::PiecewiseLinearTransformer;
let key = b"secret_key";
let plt = PiecewiseLinearTransformer::new(key, 64, 0.8, 1.2, -1e6, 1e6);

let x = 10.0;
let y = 20.0;
let tx = plt.transform(x);
let ty = plt.transform(y);

assert!(tx < ty); // Order preserved
pub fn transform(...)

can_transform

Checks if a value can be transformed.

Arguments

  • value - The value to check

Returns

true if the value can be transformed (now accepts all f64 values including special values)

pub fn can_transform(...)

num_segments

Returns the number of segments in this transformer.

pub fn num_segments(...)

encrypt

Encrypts text tokens, preserving patterns for ML analysis.

This is the primary method for encrypting data with PD.Cipher. It takes plaintext tokens and produces deterministic cipher tokens that preserve patterns while protecting content. Identical plaintext tokens always map to identical cipher tokens, enabling machine learning and analytics on encrypted data.

Uses the built-in InMemoryStorageProvider for simplicity.

Examples

use pd_cipher::{PDCipher, config::CipherConfig, KeyGenerator};

# #[tokio::main(flavor = "current_thread")]
# async fn main() -> pd_cipher::Result<()> {
let config = CipherConfig::default();
let key = KeyGenerator::generate_key(config.algorithm)?;

// Encrypt user data while preserving patterns
let tokens = vec!["alice@email.com", "bob@email.com", "alice@email.com"];
let (encrypted_tokens, context) = PDCipher::encrypt(&tokens, &key, &config).await?;

// Pattern preserved: duplicate tokens produce duplicate cipher tokens
assert_eq!(encrypted_tokens[0], encrypted_tokens[2]);
assert_ne!(encrypted_tokens[0], encrypted_tokens[1]);
# Ok(())
# }

Machine Learning with Output Strategies

use pd_cipher::{PDCipher, config::{CipherConfig, TextOutputStrategy, NumericOutputStrategy}, KeyGenerator};

# #[tokio::main(flavor = "current_thread")]
# async fn main() -> pd_cipher::Result<()> {
// Configure for ML: encrypt schema but keep numbers plain
let config = CipherConfig::builder()
.text_output(TextOutputStrategy::Variable) // Encrypt column names
.numeric_output(NumericOutputStrategy::Plain) // Keep numbers plain for ML
.build()?;

let key = KeyGenerator::generate_key(config.algorithm)?;

// Dataset with schema and values
let tokens = vec!["age", "35", "income", "75000", "score", "0.85"];
let (encrypted_tokens, context) = PDCipher::encrypt(&tokens, &key, &config).await?;

// Schema is encrypted, numbers remain plain for ML computation
assert_ne!(encrypted_tokens[0], "age"); // "age" is encrypted
assert_eq!(encrypted_tokens[1], "35"); // Numbers remain plain
assert_ne!(encrypted_tokens[2], "income"); // "income" is encrypted
assert_eq!(encrypted_tokens[3], "75000"); // Numbers remain plain
# Ok(())
# }
pub fn encrypt(...)

decrypt

Decrypts tokens using the provided context and key.

This method reverses the encryption process, converting cipher tokens back to their original plaintext form. It requires the same key that was used for encryption and the context returned from the encrypt operation.

Uses the built-in InMemoryStorageProvider for simplicity.

Examples

use pd_cipher::{PDCipher, PDContext, config::CipherConfig, KeyGenerator};

# #[tokio::main(flavor = "current_thread")]
# async fn main() -> pd_cipher::Result<()> {
let config = CipherConfig::default();
let key = KeyGenerator::generate_key(config.algorithm)?;

// First encrypt some data
let original = vec!["sensitive", "data", "sensitive"];
let (encrypted_tokens, context) = PDCipher::encrypt(&original, &key, &config).await?;

// Later decrypt it back
let tokens_refs: Vec<&str> = encrypted_tokens.iter().map(|s| s.as_str()).collect();
let decrypted = PDCipher::decrypt(&tokens_refs, &context, &key).await?;
assert_eq!(original, decrypted);
# Ok(())
# }
pub fn decrypt(...)

to_bytes

Serializes the context to bytes for storage.

pub fn to_bytes(...)

from_bytes

Deserializes context from bytes.

pub fn from_bytes(...)

verify_format

Verifies the context format version is supported.

pub fn verify_format(...)

Constants

VERSION

Current version of the PD.Cipher SDK.

This version string is automatically synchronized with the version specified in Cargo.toml and follows semantic versioning.

pub const VERSION: ...