An end-to-end Python project that detects regions of interest (ROI) in images, encrypts only those regions using modern cryptography, and reconstructs the image after decryption for correctness verification.
Built for the Cryptography course.
Instead of encrypting an entire image, this pipeline:
- Detects ROI areas (contour-based or face-based).
- Extracts ROI pixels only.
- Generates or derives an AES-256 key:
- RSA mode (default): generates a random AES key and wraps it with the recipient's RSA public key.
- Password mode: derives a key from a password using PBKDF2-HMAC-SHA256.
- Encrypts ROI bytes using AES-256-GCM (default) or AES-256-CBC + HMAC-SHA256.
- Signs metadata with the encryptor's RSA private key (RSA mode) for non-repudiation.
- Stores encrypted payload + metadata (mask, shape, encrypted AES key or salt, etc.).
- Verifies digital signature, decrypts, and reconstructs the original image.
- Reports performance and security metrics (NPCR/UACI, timing, ROI ratio, etc.).
- Selective encryption: encrypts only ROI pixels, reducing encryption workload.
- Hybrid RSA + AES encryption: RSA-OAEP wraps the AES session key (no shared password needed).
- Digital signatures: RSA-PKCS1v15 signs metadata for non-repudiation.
- Password mode: PBKDF2-HMAC-SHA256 key derivation available as fallback.
- Multiple ROI methods:
global,adaptive,otsu,face. - Face detection fallback: when no faces are detected, the entire image is encrypted as a safety net.
- Authenticated encryption: AES-GCM with optional AAD binding, or AES-CBC with Encrypt-then-MAC.
- Correct NPCR/UACI metrics: measured against actual AES ciphertext, not visual placeholders.
- Built-in self-tests in
key_manager.pyandencryption.py.
| File | Purpose |
|---|---|
main.py |
Full ROI encryption pipeline CLI and orchestration |
roi_detector.py |
ROI detection, thresholding, contouring, face detection |
key_manager.py |
Salt generation, PBKDF2 key derivation, KDF parameter handling |
encryption.py |
AES-GCM / AES-CBC+HMAC encryption/decryption + packet helpers |
rsa_manager.py |
RSA key pair generation, OAEP key wrapping, digital signatures |
keys/ |
Generated RSA key pair (auto-created on first run) |
outputs/ |
Generated outputs (masks, encrypted image, metadata, etc.) |
- Python 3.9+
- Packages:
numpy,opencv-python,matplotlib,pycryptodome
pip install numpy opencv-python matplotlib pycryptodome# First run auto-generates RSA keys in keys/
python main.py --image photo.jpgpython main.py --generate-keyspython main.py --image photo.jpg --key-mode password --password "StrongPass@123"# Use face detection with CBC mode
python main.py --image photo.jpg --method face --mode CBC
# Change visual fill for encrypted ROI
python main.py --image photo.jpg --fill blur
# Run wrong-password rejection demo (password mode)
python main.py --image photo.jpg --key-mode password --wrong-password-test
# Speed vs security tradeoff table
python main.py --image photo.jpg --key-mode password --iteration-sweep| Argument | Default | Description |
|---|---|---|
--image / -i |
demo images | Input image path(s) |
--key-mode |
rsa |
rsa (hybrid encryption) or password (PBKDF2) |
--public-key |
keys/public.pem |
RSA public key PEM path |
--private-key |
keys/private.pem |
RSA private key PEM path |
--generate-keys |
- | Generate RSA key pair and exit |
--password / -p |
- | Encryption password (password mode only) |
--method / -m |
otsu |
ROI method: global, adaptive, otsu, face |
--mode |
GCM |
AES mode: GCM or CBC |
--iterations / -n |
100000 |
PBKDF2 iterations (password mode only) |
--fill |
black |
Visual fill: black, blur, noise |
--min-area |
500 |
Minimum contour area for ROI filtering |
--output / -o |
outputs |
Output directory |
Encryption:
1. Generate random 32-byte AES key
2. Encrypt AES key with recipient's RSA public key (RSA-OAEP)
3. Encrypt ROI with AES key
4. Sign metadata with sender's RSA private key
5. Store: encrypted AES key + ciphertext + signature
Decryption:
1. Verify metadata signature with sender's public key
2. Decrypt AES key with recipient's RSA private key
3. Decrypt ROI with AES key
This is the same approach used by TLS, PGP, and S/MIME.
Encryption:
1. Generate random salt
2. Derive AES key from password via PBKDF2-HMAC-SHA256
3. Encrypt ROI with AES key
4. Store: salt + iterations + ciphertext
Decryption:
1. Re-derive AES key from same password + stored salt
2. Decrypt ROI
The pipeline reports both crypto and visual NPCR/UACI:
- NPCR/UACI (crypto): measured against actual AES ciphertext bytes interpreted as pixel values. This is the correct measurement for evaluating cipher quality.
- NPCR/UACI (visual): measured against the display fill (black/blur/noise). This is what you see on screen but does not reflect cipher quality.
- RSA mode avoids the shared-password problem entirely.
- Digital signatures provide non-repudiation (proof of who encrypted).
- Face detection falls back to full-image encryption when no faces are found, preventing accidental data exposure.
- Prefer AES-GCM whenever possible.
- Keep private keys secure. The
keys/directory is for learning only.
Warning: The default
keys/directory stores private keys in plaintext on disk. In a production system, use a hardware security module (HSM) or a key management service. This project is for educational use.
This project is a working academic demonstration. For production deployment, the following integrations would be appropriate:
The RSA public keys could be wrapped in X.509 certificates, enabling identity verification through a Certificate Authority (CA) trust chain. This is how HTTPS establishes identity - the browser trusts a CA, the CA vouches for the server's public key. For this project, each user's public key would be bound to their identity via a signed certificate.
The metadata JSON could be packaged as a signed JWT (JSON Web Token) with standard claims (iss, iat, exp, sub). This would make the metadata interoperable with any JWT library in any language, and the exp claim could enforce time-limited access to encrypted images.
The generate_key_pair() and key storage functions could be replaced with calls to AWS KMS, Azure Key Vault, or GCP Cloud KMS. These services provide hardware-backed key storage, automatic key rotation, fine-grained access control, and audit logs - none of which a local keys/ directory can offer.
The Haar cascade face detector (Viola-Jones, 2001) could be replaced with MTCNN, RetinaFace, or MediaPipe for higher accuracy and per-detection confidence scores. The fallback-to-full-image mechanism would then trigger based on confidence thresholds rather than binary presence/absence.
- ROI quality depends on image characteristics and chosen threshold method.
- Haar cascade face detection has limited accuracy on non-frontal faces.
- UACI values may deviate from ideal 33.5% depending on image content and ROI size, since AES ciphertext statistics depend on plaintext distribution.
- This is an educational pipeline, not a hardened production system.