PQC Dual USB Library
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.15.6: This release patches multiple vulnerabilities found during a full code audit. Users on v0.15.5 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.
Overview
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.
️ Architecture Overview
┌─────────────────────────────────────────────────────────────┐
│ 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 │ │
│ └──────────────┘ └──────────────┘ │
└─────────────────────────────────────────────────────────────┘
Key Features
Post-Quantum Security
- 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
Dual USB Architecture
- 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
️ Security Features
- 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
Developer-Friendly
- 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
Installation
pip install pqcdualusb
Backend Dependencies
The 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.
Quick Start Guide
This example demonstrates the end-to-end process of creating and managing a secure dual USB backup using the library's functions.
Basic Usage
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}")
Complete Example with Error Handling
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.")
Security Properties
Cryptographic Stack
| 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 |
Security Workflow
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)
API Reference
Core Functions
init_dual_usb(token, primary_mount, backup_mount, passphrase)
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_token(token, primary_mount, backup_mount, passphrase, prev_rotation)
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_dual_setup(primary_mount, backup_mount, passphrase)
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_from_backup(backup_file, restore_primary, passphrase)
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)
Use Cases
1. Cryptocurrency Wallet Protection
Securely store master private keys across two USB devices with quantum-resistant encryption.
2. Enterprise Key Management
Manage encryption keys for organizational data with audit logging and rotation capabilities.
3. Password Manager Master Key
Protect the master encryption key for password management systems with redundant backups.
4. Secure Document Storage
Encrypt and backup sensitive documents with post-quantum security guarantees.
5. Hardware Security Module (HSM) Backup
Create offline backups of HSM keys with tamper-evident logging.
Advanced Configuration
Custom Argon2id Parameters
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)
)
Secure Memory Wiping
from pqcdualusb.crypto import secure_wipe
sensitive_data = bytearray(b"secret-data")
# Use the data...
secure_wipe(sensitive_data) # Automatically wipes on deletion
Documentation
For comprehensive documentation including:
- Architecture diagrams (interactive Mermaid diagrams on GitHub)
- Detailed API reference
- Security analysis
- Contribution guidelines
- Threat model
Visit the GitHub Repository.
Contributing
Contributions are welcome! Please see the CONTRIBUTING.md file for guidelines.
Security
For security vulnerabilities, please email Johnsonajibi@gmail.com instead of using the issue tracker.
See SECURITY.md for our security policy.
License
This project is licensed under the MIT License. See the LICENSE file for details.
Acknowledgments
- NIST for standardizing post-quantum cryptography algorithms
- Open Quantum Safe (OQS) project for the
liboqslibrary - The cryptography community for ongoing research and development
Support
- Documentation: GitHub Repository
- Issues: GitHub Issues
- Email: Johnsonajibi@gmail.com
Metadata
Release files for pqcdualusb 0.15.6
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| pqcdualusb-0.15.6.tar.gz | 69.9 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| pqcdualusb-0.15.6-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 122.2 kB
Release files / pqcdualusb-0.15.6.tar.gz
| Download URL | pqcdualusb-0.15.6.tar.gz |
|---|---|
| Size | 69.9 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
6e3ee61195f57d25723d7f0e5554f33f4cbbfdabb6655f4eff1d74ab29bdb694
|
|
BLAKE2b-256 checksum How to use checksums |
b4dcdf80e88cc3e826d6a7c60531cf1346b186322b873740bfb4125b58f5b5b4
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.11.9
|
Release files / pqcdualusb-0.15.6-py3-none-any.whl
| Download URL | pqcdualusb-0.15.6-py3-none-any.whl |
|---|---|
| Size | 52.3 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
bcc6204abfd77251ea64a2d90caac8b2b83931027e7666ec7844dc2efa037c6c
|
|
BLAKE2b-256 checksum How to use checksums |
ee7bb11695094edcd0f41eb7744fb8fb830026387d153f458e42b1a04b83c7f3
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.11.9
|