A comprehensive Python library for post-quantum cryptographic dual USB backup operations with advanced hardware security features and side-channel attack countermeasures.
SECURITY NOTICE — v0.1.5: This release patches multiple vulnerabilities found during a full code audit. Users on v0.1.4 or earlier should upgrade immediately:
pip install --upgrade pqcdualusbFixes: path traversal in
validate_path(), weakened scrypt KDF (n=2**15), timing leak in constant-time comparison, OverflowError in side-channel dummy ops, error-message information disclosure, backup restore using wrong KDF parameters, and dead hybrid key domain separator.
NOTE: This is a library package designed to be imported into your applications. For full documentation, diagrams, and architecture details visit the GitHub Repository.
The PQC Dual USB Library provides a robust, enterprise-grade solution for securing data against threats from both classical and quantum computers. It offers a functional API for developers to integrate post-quantum cryptography (PQC) into applications requiring secure data storage, especially for scenarios involving redundant backups on physical devices like USB drives.
The library is designed with a "secure-by-default" philosophy, automatically handling complex security operations like side-channel attack mitigation, secure memory management, and hybrid cryptographic schemes.
┌─────────────────────────────────────────────────────────────┐
│ YOUR APPLICATION │
└─────────────────────┬───────────────────────────────────────┘
│ Import & Use
▼
┌─────────────────────────────────────────────────────────────┐
│ pqcdualusb Library │
├─────────────────────────────────────────────────────────────┤
│ storage.py │ High-level API (init, rotate, verify) │
│ backup.py │ Backup creation and restoration │
│ crypto.py │ Classical crypto (AES-256-GCM, Argon2id) │
│ pqc.py │ Post-quantum crypto (Kyber, Dilithium) │
│ device.py │ USB device validation │
│ audit.py │ Tamper-evident logging │
└─────────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────┐
│ Physical Storage (USB Drives) │
│ ┌──────────────┐ ┌──────────────┐ │
│ │ PRIMARY USB │ │ BACKUP USB │ │
│ │ • Token │◄────────────►│ • Token │ │
│ │ • State │ Redundant │ • State │ │
│ │ • Backup │ │ • Backup │ │
│ └──────────────┘ └──────────────┘ │
└─────────────────────────────────────────────────────────────┘
- NIST-standardized algorithms: Kyber1024 (KEM) and Dilithium3 (signatures)
- Hybrid encryption: Combines classical AES-256-GCM with post-quantum KEMs
- Future-proof: Protection against both classical and quantum computer attacks
- Split secret design: Data is secured across two physical USB devices
- Redundant storage: Automatic synchronization between primary and backup drives
- Atomic operations: Ensures data integrity even during power failures
- Secure memory: Automatic wiping of sensitive data from RAM
- Side-channel resistance: Constant-time operations to prevent timing attacks
- Strong KDF: Argon2id protects passphrases against brute-force attacks
- Tamper-evident logging: Comprehensive audit trail of all security events
- Simple API: Clean, functional interface with minimal boilerplate
- Type hints: Full type annotations for better IDE support
- Comprehensive tests: Extensive test suite ensures reliability
- Cross-platform: Works on Windows, Linux, and macOS
pip install pqcdualusbThe library requires at least one PQC backend. Choose one:
Option 1: Python backend (Recommended for most users)
pip install pqcdualusb[pqc]Option 2: High-performance Rust backend
For advanced users who need maximum performance. See the GitHub README for Rust setup instructions.
This example demonstrates the end-to-end process of creating and managing a secure dual USB backup using the library's functions.
from pathlib import Path
from pqcdualusb.storage import init_dual_usb, rotate_token, verify_dual_setup
from pqcdualusb.backup import restore_from_backup
# Define your USB drive paths
primary_usb = Path("/media/usb1") # Adjust to your system
backup_usb = Path("/media/usb2") # Adjust to your system
# Your secret data (e.g., encryption key, master password)
secret_data = b"my-super-secret-master-key"
passphrase = "a-very-strong-and-unique-passphrase"
# 1. Initialize the dual USB backup system
init_info = init_dual_usb(
token=secret_data,
primary_mount=primary_usb,
backup_mount=backup_usb,
passphrase=passphrase
)
print(f" Initialized: {init_info['primary']}, {init_info['backup']}")
# 2. Verify the backup integrity
is_valid = verify_dual_setup(
primary_mount=primary_usb,
backup_mount=backup_usb,
passphrase=passphrase
)
print(f" Backup verified: {is_valid}")
# 3. Rotate the secret (e.g., periodic key rotation)
new_secret = b"my-new-rotated-master-key"
rotate_info = rotate_token(
token=new_secret,
primary_mount=primary_usb,
backup_mount=backup_usb,
passphrase=passphrase,
prev_rotation=0 # Increment on each rotation
)
print(f" Token rotated to rotation #{rotate_info['rotation']}")
# 4. Restore from backup (disaster recovery)
restore_path = Path("/media/usb_restore")
restored_token, _ = restore_from_backup(
backup_file=Path(rotate_info['backup']),
restore_primary=restore_path,
passphrase=passphrase
)
print(f" Restored to: {restored_token}")import os
from pathlib import Path
import tempfile
import shutil
# Import the necessary functions from the library
from pqcdualusb.storage import init_dual_usb, rotate_token
from pqcdualusb.backup import restore_from_backup
from pqcdualusb.crypto import verify_backup
from pqcdualusb.exceptions import (
PassphraseMismatchError,
BackupVerificationError,
DeviceNotFoundError
)
# --- Setup: Create temporary directories to simulate USB drives ---
# In a real application, these paths would point to your actual USB drives.
tmp_dir = Path(tempfile.mkdtemp(prefix="pqc_usb_demo_"))
primary_path = tmp_dir / "PRIMARY"
backup_path = tmp_dir / "BACKUP"
primary_path.mkdir()
backup_path.mkdir()
print(f" Simulating USB drives:\n Primary: {primary_path}\n Backup: {backup_path}\n")
# --- Core Variables ---
passphrase = "a-very-strong-and-unique-passphrase"
initial_secret = os.urandom(64) # 512-bit secret
try:
# 1. Initialize the Dual USB Backup
print("Step 1: Initializing the dual USB backup...")
init_info = init_dual_usb(
token=initial_secret,
primary_mount=primary_path,
backup_mount=backup_path,
passphrase=passphrase
)
print(f" Initialization complete.")
print(f" Primary: {init_info['primary']}")
print(f" Backup: {init_info['backup']}\n")
# 2. Verify the Backup Integrity
print("Step 2: Verifying the backup file...")
is_valid = verify_backup(
Path(init_info['backup_file']),
passphrase,
initial_secret
)
if is_valid:
print(" Backup integrity verified successfully.\n")
else:
raise BackupVerificationError("Backup verification failed!")
# 3. Rotate the Token with a New Secret
print("Step 3: Rotating the token with a new secret...")
new_secret = os.urandom(64)
rotate_info = rotate_token(
token=new_secret,
primary_mount=primary_path,
backup_mount=backup_path,
passphrase=passphrase,
prev_rotation=0
)
print(f" Token rotation complete.")
print(f" Rotation number: {rotate_info['rotation']}")
print(f" New backup: {rotate_info['backup']}\n")
# 4. Restore from the Latest Backup
print("Step 4: Restoring the secret from the latest backup...")
restore_path = tmp_dir / "RESTORED"
restore_path.mkdir()
restored_token_path, _ = restore_from_backup(
backup_file=Path(rotate_info['backup']),
restore_primary=restore_path,
passphrase=passphrase
)
# Verify that the restored data matches the new secret
restored_data = restored_token_path.read_bytes()
assert restored_data == new_secret, "Restored data doesn't match!"
print(f" Restore successful!")
print(f" Restored to: {restored_token_path}")
print(f" Data verified: {len(restored_data)} bytes match.\n")
except PassphraseMismatchError:
print(" Error: Incorrect passphrase provided.")
except BackupVerificationError as e:
print(f" Error: Backup verification failed - {e}")
except DeviceNotFoundError as e:
print(f" Error: USB device not found - {e}")
except Exception as e:
print(f" Unexpected error: {e}")
finally:
# --- Cleanup ---
shutil.rmtree(tmp_dir)
print(" Cleanup complete.")| Component | Algorithm | Purpose |
|---|---|---|
| Key Derivation | Argon2id | Protects passphrase from brute-force attacks |
| Symmetric Encryption | AES-256-GCM | Fast, authenticated encryption for data |
| Post-Quantum KEM | Kyber1024 | Quantum-resistant key encapsulation |
| Post-Quantum Signature | Dilithium3 | Quantum-resistant digital signatures |
| HMAC | HMAC-SHA256 | Additional integrity verification |
User Passphrase
│
▼
┌─────────────┐
│ Argon2id │ ← Memory-hard KDF
└──────┬──────┘
│
▼
Master Key (256-bit)
│
├─────────────────────┐
│ │
▼ ▼
┌──────────────┐ ┌──────────────┐
│ AES-256-GCM │ │ Kyber1024 │
│ Classical │ │ Post-Quantum │
└──────┬───────┘ └──────┬───────┘
│ │
└──────────┬──────────┘
│
▼
Encrypted Secret
│
▼
┌─────────────────────────────┐
│ Dilithium3 │
│ Digital Signature │
└─────────────────────────────┘
│
▼
USB Storage (Dual)
Initialize a new dual USB backup system.
Parameters:
token(bytes): The secret data to protect (32-128 bytes recommended)primary_mount(Path): Path to the primary USB drivebackup_mount(Path): Path to the backup USB drivepassphrase(str): User passphrase for encryption
Returns: Dictionary with initialization information
Rotate the secret with a new value.
Parameters:
token(bytes): The new secret dataprimary_mount(Path): Path to the primary USB drivebackup_mount(Path): Path to the backup USB drivepassphrase(str): User passphrase (must match initialization)prev_rotation(int): Previous rotation number
Returns: Dictionary with rotation information
Verify the integrity of the dual USB setup.
Parameters:
primary_mount(Path): Path to the primary USB drivebackup_mount(Path): Path to the backup USB drivepassphrase(str): User passphrase
Returns: True if verification passes, False otherwise
Restore data from a backup file.
Parameters:
backup_file(Path): Path to the backup filerestore_primary(Path): Path where to restore the primary tokenpassphrase(str): User passphrase
Returns: Tuple of (restored_token_path, state_data)
Securely store master private keys across two USB devices with quantum-resistant encryption.
Manage encryption keys for organizational data with audit logging and rotation capabilities.
Protect the master encryption key for password management systems with redundant backups.
Encrypt and backup sensitive documents with post-quantum security guarantees.
Create offline backups of HSM keys with tamper-evident logging.
from pqcdualusb.crypto import derive_key
# High-security settings (slower but more secure)
key = derive_key(
passphrase="my-passphrase",
salt=b"random-salt-32-bytes",
time_cost=4, # Default: 3
memory_cost=65536 # Default: 65536 (64 MB)
)from pqcdualusb.crypto import secure_wipe
sensitive_data = bytearray(b"secret-data")
# Use the data...
secure_wipe(sensitive_data) # Automatically wipes on deletionFor comprehensive documentation including:
- Architecture diagrams (interactive Mermaid diagrams on GitHub)
- Detailed API reference
- Security analysis
- Contribution guidelines
- Threat model
Visit the GitHub Repository.
Contributions are welcome! Please see the CONTRIBUTING.md file for guidelines.
For security vulnerabilities, please email Johnsonajibi@gmail.com instead of using the issue tracker.
See SECURITY.md for our security policy.
This project is licensed under the MIT License. See the LICENSE file for details.
- NIST for standardizing post-quantum cryptography algorithms
- Open Quantum Safe (OQS) project for the
liboqslibrary - The cryptography community for ongoing research and development
- Documentation: GitHub Repository
- Issues: GitHub Issues
- Email: Johnsonajibi@gmail.com