Project Overview
This Python application enables secure data transfer by embedding encrypted payloads inside images using least-significant-bit (LSB) steganography. It combines RSA and ECDSA cryptography for confidentiality and integrity, and offers both a desktop GUI and command-line interface for encrypted file exchange over FTP.
Why This Project Exists
- Protects sensitive files against interception and tampering
- Hides both the fact of communication (steganography) and the content (encryption)
- Simplifies secure peer-to-peer transfers with a user-friendly GUI and scriptable CLI
Main Features
- LSB image steganography for covert data embedding
- RSA hybrid encryption (AES+RSA) for payload confidentiality
- ECDSA signatures for payload integrity verification
- Encrypted FTP transfer between two hosts
- Dual interfaces: CLI for automation, PyQt5-based GUI for desktop use
Typical Use Cases
- Embedding classified documents inside innocuous images for email delivery
- Securely synchronizing backups between remote machines over FTP
- Automating secure file drops in CI/CD pipelines via scripts
- Exchanging confidential data in low-trust network environments
Application Interfaces
Command-Line Interface
Use the CLI for headless operation or integration into scripts:
# Embed and encrypt a file into an image
python cli.py embed \
--input secret.pdf \
--output stego.png \
--rsa-public peer_pub.pem \
--aes-key-size 256
# Extract and decrypt the embedded file
python cli.py extract \
--input stego.png \
--output recovered.pdf \
--rsa-private my_priv.pem
# Transfer stego image over FTP
python cli.py ftp-send \
--host ftp.example.com \
--user alice \
--password redacted \
--file stego.png
Graphical User Interface
Launch the desktop application for interactive secure transfers:
python gui.py
- Select source files and target images via file dialogs
- Manage RSA/ECDSA key pairs in-app
- Monitor encrypted FTP transfers with real-time status updates
Getting Started
This section guides you from zero to your first success with image steganography and cryptography tools.
Environment Requirements
- Python ≥ 3.8
- pip
- Pillow
- cryptography
- tkinter (usually bundled with Python; on Debian/Ubuntu:
sudo apt-get install python3-tk
)
Installing Dependencies
- Clone the repository:
git clone https://github.com/Anknorx/Secure-Data-Transfer-with-image-steganography-RSA-ECDSA-.git cd Secure-Data-Transfer-with-image-steganography-RSA-ECDSA-
- Install Python packages:
pip install --upgrade pip pip install Pillow cryptography
Running the Application
Launch the GUI
python codes/main.py
- Opens a window with options for LSB steganography, RSA-enhanced and ECC-enhanced encoding/decoding.
- Use File → Open to select images, Encode or Decode, then Save results.
Launch the CLI
python codes/digi.py
- Interactive prompts guide you through:
- Choosing operation:
encode-image
,decode-image
,encrypt-message
,decrypt-message
, etc. - Selecting RSA key size or ECC curve.
- Specifying input/output file paths.
- Choosing operation:
Quick Start: Hello World
Embed “Hello, World!” in an image, then decode it back.
- Prepare a cover image
cover.png
in the repo root. - Encode text into the image:
Result:python codes/digi.py # Select operation: encode-image # Enter path to cover image: cover.png # Enter output image path: stego.png # Enter message: Hello, World! # Choose encryption: none
stego.png
contains your hidden message. - Decode from the stego image:
Output:python codes/digi.py # Select operation: decode-image # Enter path to stego image: stego.png # Choose decryption: none
Decoded message: Hello, World!
You now have a working steganography workflow. Explore RSA/ECC options and the GUI for advanced use cases.
Usage Guide
This guide walks you through two interfaces for secure data transfer using image steganography: a simple Tkinter UI for selecting and sharing image files, and a CLI menu for LSB, RSA-enhanced LSB, and ECC signature embedding.
Sending Images to the Data Sharing Folder
Provide users with a minimal UI to pick up to five images (JPEG, PNG, GIF) and copy them into a configurable “data sharing” directory.
Code Example
import tkinter as tk
from tkinter import filedialog, messagebox
import shutil
import os
DATA_FOLDER = "data" # Update to your target directory
def open_files():
file_paths = filedialog.askopenfilenames(
title="Select up to 5 images",
filetypes=[("Image files", "*.jpg;*.jpeg;*.png;*.gif")]
)
if not file_paths:
return # User cancelled
if len(file_paths) > 5:
messagebox.showerror("Error", "You can only select up to 5 images.")
return
os.makedirs(DATA_FOLDER, exist_ok=True)
try:
for src in file_paths:
filename = os.path.basename(src)
dst = os.path.join(DATA_FOLDER, filename)
shutil.copy(src, dst)
messagebox.showinfo(
"Success",
f"Saved {len(file_paths)} files to '{DATA_FOLDER}'"
)
except Exception as e:
messagebox.showerror("Error", f"Failed to save files: {e}")
# UI Setup
root = tk.Tk()
root.title("Save Images to Data Sharing Folder")
root.geometry("400x200")
select_button = tk.Button(
root,
text="Select Images (Up to 5)",
command=open_files,
width=25,
height=2
)
select_button.pack(pady=40)
root.mainloop()
Practical Usage
- Set
DATA_FOLDER
to your network-shared or local directory. - Import
open_files()
in your app or run it standalone. - The script auto-creates
DATA_FOLDER
if missing. - Adjust
filetypes
to support other formats. - Handle edge cases (no selection, too many files, I/O errors).
Tips
- Restrict by total size:
total_size = sum(os.path.getsize(p) for p in file_paths) if total_size > MAX_BYTES: ...
- For headless servers, replace
messagebox
with logging. - Verify write permissions on network paths before copying.
CLI Interface and Command Flow
Use digi.py
to embed or extract messages via pure LSB, LSB+RSA, or ECC-based signatures in PNG images. Ensure Python 3 and required modules (opencv-python
, rsa
, ecc
) are installed.
1. Starting the Script
python digi.py
Top-level menu:
- Press
1
for LSB Technique - Press
2
for LSB + RSA Technique - Press
3
for ECC Signature Technique - Type
quit
to exit
2. LSB Technique (Option 1)
Menu:
Encrypt
– embed a secret messageDecrypt
– extract a hidden messageback
– return to main menu
Basic flow:
Enter Command: Encrypt
Enter File Path: path/to/input.png
Enter output filename: output.png
Enter the secret message: Top secret
Internally:
from LSB_Technique import encode
encoded = encode(image_name="path/to/input.png", code_message="Top secret")
import cv2
cv2.imwrite("output.png", encoded)
To decrypt:
Enter Command: Decrypt
Enter File Path: output.png
Decoded message: Top secret
3. LSB + RSA Technique (Option 2)
Menu:
n
/e
/d
– redefine RSA parametersEncrypt
– embed and encrypt payloadDecrypt
– extract and decrypt payloadback
– return
Redefine modulus n
:
Enter Command: n
current n = 3233
Enter a value for n: 3613
Redefine public exponent e
(recalculates d
):
from rsa import gcd, modInverse, phi
d = modInverse(e, phi(n))
Encrypt/decrypt calls:
from rsa import Encrypt, Decrypt
Encrypt("input.png") # outputs enc_input.png
Decrypt("enc_input.png")
4. ECC Signature Technique (Option 3)
Menu:
Encrypt
– embed ECC‐signed payloadDecrypt
– extract and verify signatureback
– return
Usage:
Enter Command: Encrypt
Enter File Path: path/to/input.png
Internally calls:
from ecc import Encrypt1, Decrypt1
Encrypt1("path/to/input.png") # produces enc_input.png
To verify:
Enter Command: Decrypt
Enter File Path: enc_input.png
Signature valid: True
5. Error Handling & Exiting
- Invalid commands print a hint and re-prompt.
- Type
back
to go up one level,quit
to exit. - Keep
digi.py
,LSB_Technique.py
,rsa.py
, andecc.py
in the same directory or PYTHONPATH. - Ensure OpenCV (
cv2
), RSA/ECC modules install without errors.
This menu-driven CLI lets you switch between steganography modes without restarting the script.
Core Concepts & Module Reference
This section covers the internal building blocks of the steganography, RSA and ECDSA modules. Developers can use or extend these routines to embed, encrypt, and sign data within images.
LSB Encoding with OpenCV (encode
/ decode
)
Hide and retrieve ASCII messages inside RGB images by manipulating each pixel’s least significant bit. Uses a five-character sentinel ("====="
) to mark message end.
Function signatures
encode(image_path: str, code_message: str) -> numpy.ndarray
decode(image_path: str) -> str
How it works
- Load image:
img = cv2.imread(image_path)
- Compute capacity = (width × height × 3) ÷ 8 bytes.
- Validate
len(code_message)
≤ capacity; elseValueError
. - Append sentinel
"====="
to the message. - Convert each char to 8-bit binary and flatten bits.
- Iterate pixels in row-major order. For each R, G, B channel, replace LSB with the next message bit.
- Stop when all bits (including sentinel) embed.
- Return modified
numpy.ndarray
; save viacv2.imwrite
.
Example usage
import cv2
from codes.LSB_Technique import encode, decode
# Encode
secret = "Meet at dawn"
stego_array = encode("original.png", secret)
cv2.imwrite("stego.png", stego_array)
# Decode
recovered = decode("stego.png")
print("Recovered message:", recovered)
Practical guidance
- Use lossless formats (PNG, BMP). JPEG destroys LSB data.
- Check printed capacity: catch
ValueError
for oversized messages. - Always include sentinel to detect end of text.
RSA Encryption & Embedding (Encrypt
)
Encrypts user plaintext using RSA (n=493, e=13), then hides ciphertext blocks in an image via the LSB encoder.
Function signature
from codes.rsa import Encrypt
Encrypt(original_image_file: str) -> None
Core steps
- Prompt for plaintext:
plaintext = input("Enter Plaintext: ")
- Map each char to a two-digit code using module’s
letter
andnumber
lists. - Compute ciphertext blocks:
X = [(int(block)**e) % n for block in numC]
. - Open cover image:
img = Image.open(original_image_file)
. - Call
Encode(img, plaintext_length, X)
to embed both length and ciphertext. - Save as
enc_<original_image_file>
.
Code excerpt
# codes/rsa.py
from PIL import Image
from stegan import Encode
n, e = 493, 13
def Encrypt(original_image_file):
plaintext = input("Enter Plaintext: ")
# Map chars → two-digit numbers
numC = [number[letter.index(ch)] for ch in plaintext]
# RSA encryption
X = [(int(block) ** e) % n for block in numC]
print("Ciphertext:", X)
img = Image.open(original_image_file)
img_encoded = Encode(img, len(X), X)
if img_encoded:
out = f"enc_{original_image_file}"
img_encoded.save(out)
print(f"{out} saved!")
Usage example
$ python
>>> from codes.rsa import Encrypt
>>> Encrypt("cover_image.png")
Enter Plaintext: Hello, world!
Ciphertext: [324, 67, …]
enc_cover_image.png saved!
Customization tips
- Change RSA key by updating module-level
n
ande
, and computing private exponentd
. - Extend
letter
/number
lists in parallel to support more characters.
ECDSA Signature & Embedding (Encrypt1
)
Generates an ECDSA signature over user input (SECP256k1), then hides the signature bytes in a cover image.
Function signature
from codes.ecc import Encrypt1
Encrypt1(original_image_file: str) -> str
How it works
- Generate key pair:
private_key = ecdsa.SigningKey.generate(curve=ecdsa.SECP256k1) public_key = private_key.get_verifying_key()
- Read message:
msg = input("ENTER THE TEXT: ")
. - Hash message:
msg_hash = hashlib.sha256(msg.encode()).digest()
. - Sign hash:
signature = private_key.sign(msg_hash)
. - Verify signature:
public_key.verify(signature, msg_hash)
. - Embed signature bytes via
stegan.Encode
. - Save as
sign.png
and returnsignature.hex()
.
Code example
# codes/ecc.py
import hashlib, ecdsa
from PIL import Image
from stegan import Encode
def Encrypt1(original_image_file: str) -> str:
# Key generation
sk = ecdsa.SigningKey.generate(curve=ecdsa.SECP256k1)
vk = sk.get_verifying_key()
# Input and hash
user_text = input("ENTER THE TEXT: ")
msg_hash = hashlib.sha256(user_text.encode()).digest()
# Sign and verify
signature = sk.sign(msg_hash)
vk.verify(signature, msg_hash)
# Embed into image
img = Image.open(original_image_file)
img_encoded = Encode(img, signature, list(signature))
img_encoded.save("sign.png")
return signature.hex()
Usage example
from codes.ecc import Encrypt1
sig_hex = Encrypt1("cover.png")
print("Embedded signature:", sig_hex)
# sign.png created in working directory
Extension tips
- Refactor to pass
message: str
instead of usinginput()
. - Persist or load keys externally for repeatable signatures.
- Ensure stego capacity ≧ signature length.
Development & Contribution Guide
This guide explains the project layout, coding standards, how to add new cryptographic methods, tweak the GUI, and submit pull requests.
Project Layout
Root
├── README.md
├── codes
│ ├── digi.py # CLI for LSB, RSA, ECC operations
│ ├── main.py # tkinter GUI for steganography + crypto
│ └── crypto_methods # (add new modules here)
└── assets # images, icons, sample files
- Keep all Python code in
codes/
. - Place new crypto modules under
codes/crypto_methods/
. - Store UI assets (logos, icons) in
assets/
.
Coding Standards
- Follow PEP8: 4-space indents, snake_case functions, PascalCase classes.
- Include docstrings on all public functions.
- Use Python’s
logging
overprint
for CLI output indigi.py
. - Add type hints for function signatures.
- Run
flake8
andblack --check
before committing.
Example function signature in codes/crypto_methods/rsa.py
:
import rsa
from typing import Tuple
def generate_keys(key_size: int = 2048) -> Tuple[bytes, bytes]:
"""
Generate RSA public and private keys.
Args:
key_size: bit length of the key.
Returns:
(public_key_pem, private_key_pem)
"""
(pub, priv) = rsa.newkeys(key_size)
return (pub.save_pkcs1(), priv.save_pkcs1())
Adding New Cryptographic Methods
- Create module
codes/crypto_methods/aes.py
- Implement interface
Providegenerate_keys()
,encrypt()
,decrypt()
. - Expose in CLI (
codes/digi.py
)- Import your module.
- Extend
--method
choices. - Route calls:
from crypto_methods import aes
METHODS = {
'lsb': stego.lsb,
'rsa': rsa.encrypt_image,
'ecc': ecc.encrypt_image,
'aes': aes.encrypt_image,
}
# In main():
parser.add_argument(
'--method', choices=METHODS.keys(), default='lsb'
)
args = parser.parse_args()
METHODS[args.method](https://github.com/Anknorx/Secure-Data-Transfer-with-image-steganography-RSA-ECDSA-/blob/main/args.input, args.output, args.key)
- Integrate in GUI (
codes/main.py
)- Add a new tab or radio button:
import crypto_methods.aes as aes
# After defining tabs
aes_tab = ttk.Frame(notebook)
notebook.add(aes_tab, text='AES')
# Add controls like other tabs
ttk.Button(aes_tab, text="Select Key", command=aes.load_key).grid(row=0, column=0)
- Wire handlers to call
aes.encrypt_image()
/aes.decrypt_image()
.
Tweaking GUI Layout
The GUI uses tkinter
+ ttk.Notebook
.
Key areas in codes/main.py
:
- Main window
root = tk.Tk() root.title("Secure Image Steganography") root.geometry("800x600")
- Notebook tabs
notebook = ttk.Notebook(root) notebook.pack(expand=True, fill='both')
- Embedding controls
Each tab usesgrid(row, column, padx, pady)
.
To adjust layout, changecolumnspan
,sticky
, or addttk.Frame
containers.
Example: Add status bar at bottom:
status_var = tk.StringVar(value="Ready")
status_bar = ttk.Label(root, textvariable=status_var, relief='sunken', anchor='w')
status_bar.pack(side='bottom', fill='x')
Update status_var.set("Encrypting...")
in handlers for user feedback.
Submitting Pull Requests
- Fork the repository and create a feature branch:
git checkout -b feature/your-feature-name
- Implement changes, run lint & tests:
black . && flake8
- Commit with clear messages:
git commit -m "Add AES encryption support in GUI and CLI"
- Push branch and open a PR against
main
. - In PR description, reference issue (
Fixes #123
), summarize implementation, and include screenshots for GUI changes. - Address review comments and rebase to clean up history:
git rebase -i main
Thank you for contributing to Secure-Data-Transfer-with-image-steganography-RSA-ECDSA!