QR functionality (sorta).
This commit is contained in:
@@ -30,6 +30,20 @@ from stegasoo import (
|
||||
FilePayload,
|
||||
)
|
||||
|
||||
# QR Code utilities
|
||||
try:
|
||||
from stegasoo.qr_utils import (
|
||||
extract_key_from_qr_file,
|
||||
generate_qr_code,
|
||||
has_qr_read, has_qr_write,
|
||||
can_fit_in_qr, needs_compression,
|
||||
)
|
||||
HAS_QR = True
|
||||
except ImportError:
|
||||
HAS_QR = False
|
||||
has_qr_read = lambda: False
|
||||
has_qr_write = lambda: False
|
||||
|
||||
|
||||
# ============================================================================
|
||||
# CLI SETUP
|
||||
@@ -177,34 +191,36 @@ def generate(pin, rsa, pin_length, rsa_bits, words, output, password, as_json):
|
||||
@click.option('--embed-file', '-e', type=click.Path(exists=True), help='Embed a file (binary)')
|
||||
@click.option('--phrase', '-p', required=True, help='Day phrase')
|
||||
@click.option('--pin', help='Static PIN')
|
||||
@click.option('--key', '-k', type=click.Path(exists=True), help='RSA key file')
|
||||
@click.option('--key-password', help='RSA key password')
|
||||
@click.option('--key', '-k', type=click.Path(exists=True), help='RSA key file (.pem)')
|
||||
@click.option('--key-qr', type=click.Path(exists=True), help='RSA key from QR code image')
|
||||
@click.option('--key-password', help='RSA key password (for encrypted .pem files)')
|
||||
@click.option('--output', '-o', type=click.Path(), help='Output file (default: auto-generated)')
|
||||
@click.option('--date', 'date_str', help='Date override (YYYY-MM-DD)')
|
||||
@click.option('--quiet', '-q', is_flag=True, help='Suppress output except errors')
|
||||
def encode_cmd(ref, carrier, message, message_file, embed_file, phrase, pin, key, key_password, output, date_str, quiet):
|
||||
def encode_cmd(ref, carrier, message, message_file, embed_file, phrase, pin, key, key_qr, key_password, output, date_str, quiet):
|
||||
"""
|
||||
Encode a secret message or file into an image.
|
||||
|
||||
Requires a reference photo, carrier image, and day phrase.
|
||||
Must provide either --pin or --key (or both).
|
||||
Must provide either --pin or --key/--key-qr (or both).
|
||||
|
||||
For text messages, use -m or -f or pipe via stdin.
|
||||
For binary files, use -e/--embed-file.
|
||||
RSA key can be provided as a .pem file (--key) or QR code image (--key-qr).
|
||||
|
||||
\b
|
||||
Examples:
|
||||
# Text message
|
||||
# Text message with PIN
|
||||
stegasoo encode -r photo.jpg -c meme.png -p "apple forest thunder" --pin 123456 -m "secret"
|
||||
|
||||
# Text from file
|
||||
stegasoo encode -r photo.jpg -c meme.png -p "words" --pin 123456 -f message.txt
|
||||
# With RSA key file
|
||||
stegasoo encode -r photo.jpg -c meme.png -p "words" -k mykey.pem -m "secret"
|
||||
|
||||
# Embed a binary file (PDF, ZIP, etc.)
|
||||
# With RSA key from QR code image
|
||||
stegasoo encode -r photo.jpg -c meme.png -p "words" --key-qr keyqr.png -m "secret"
|
||||
|
||||
# Embed a binary file
|
||||
stegasoo encode -r photo.jpg -c meme.png -p "words" --pin 123456 -e secret.pdf
|
||||
|
||||
# Pipe text
|
||||
echo "secret" | stegasoo encode -r photo.jpg -c meme.png -p "words" --pin 123456
|
||||
"""
|
||||
# Determine what to encode
|
||||
payload = None
|
||||
@@ -223,14 +239,35 @@ def encode_cmd(ref, carrier, message, message_file, embed_file, phrase, pin, key
|
||||
else:
|
||||
raise click.UsageError("Must provide message via -m, -f, -e, or stdin")
|
||||
|
||||
# Load key if provided
|
||||
# Load key if provided (from .pem file or QR code image)
|
||||
rsa_key_data = None
|
||||
rsa_key_from_qr = False
|
||||
|
||||
if key and key_qr:
|
||||
raise click.UsageError("Cannot use both --key and --key-qr. Choose one.")
|
||||
|
||||
if key:
|
||||
rsa_key_data = Path(key).read_bytes()
|
||||
elif key_qr:
|
||||
if not HAS_QR or not has_qr_read():
|
||||
raise click.ClickException(
|
||||
"QR code reading not available. Install: pip install pyzbar\n"
|
||||
"Also requires system library: sudo apt-get install libzbar0"
|
||||
)
|
||||
key_pem = extract_key_from_qr_file(key_qr)
|
||||
if not key_pem:
|
||||
raise click.ClickException(f"Could not extract RSA key from QR code: {key_qr}")
|
||||
rsa_key_data = key_pem.encode('utf-8')
|
||||
rsa_key_from_qr = True
|
||||
if not quiet:
|
||||
click.echo(f"Loaded RSA key from QR code: {key_qr}")
|
||||
|
||||
# QR code keys are never password-protected
|
||||
effective_key_password = None if rsa_key_from_qr else key_password
|
||||
|
||||
# Validate security factors
|
||||
if not pin and not rsa_key_data:
|
||||
raise click.UsageError("Must provide --pin or --key (or both)")
|
||||
raise click.UsageError("Must provide --pin or --key/--key-qr (or both)")
|
||||
|
||||
try:
|
||||
ref_photo = Path(ref).read_bytes()
|
||||
@@ -243,7 +280,7 @@ def encode_cmd(ref, carrier, message, message_file, embed_file, phrase, pin, key
|
||||
day_phrase=phrase,
|
||||
pin=pin or "",
|
||||
rsa_key_data=rsa_key_data,
|
||||
rsa_password=key_password,
|
||||
rsa_password=effective_key_password,
|
||||
date_str=date_str,
|
||||
)
|
||||
|
||||
@@ -278,37 +315,63 @@ def encode_cmd(ref, carrier, message, message_file, embed_file, phrase, pin, key
|
||||
@click.option('--stego', '-s', required=True, type=click.Path(exists=True), help='Stego image')
|
||||
@click.option('--phrase', '-p', required=True, help='Day phrase')
|
||||
@click.option('--pin', help='Static PIN')
|
||||
@click.option('--key', '-k', type=click.Path(exists=True), help='RSA key file')
|
||||
@click.option('--key-password', help='RSA key password')
|
||||
@click.option('--key', '-k', type=click.Path(exists=True), help='RSA key file (.pem)')
|
||||
@click.option('--key-qr', type=click.Path(exists=True), help='RSA key from QR code image')
|
||||
@click.option('--key-password', help='RSA key password (for encrypted .pem files)')
|
||||
@click.option('--output', '-o', type=click.Path(), help='Save decoded content to file')
|
||||
@click.option('--quiet', '-q', is_flag=True, help='Output only the content (for text) or suppress messages (for files)')
|
||||
@click.option('--force', is_flag=True, help='Overwrite existing output file')
|
||||
def decode_cmd(ref, stego, phrase, pin, key, key_password, output, quiet, force):
|
||||
def decode_cmd(ref, stego, phrase, pin, key, key_qr, key_password, output, quiet, force):
|
||||
"""
|
||||
Decode a secret message or file from a stego image.
|
||||
|
||||
Must use the same credentials that were used for encoding.
|
||||
Automatically detects whether content is text or a file.
|
||||
RSA key can be provided as a .pem file (--key) or QR code image (--key-qr).
|
||||
|
||||
\b
|
||||
Examples:
|
||||
# Decode and print text
|
||||
# Decode with PIN
|
||||
stegasoo decode -r photo.jpg -s stego.png -p "apple forest thunder" --pin 123456
|
||||
|
||||
# Decode and save (auto-detect type)
|
||||
stegasoo decode -r photo.jpg -s stego.png -p "words" --pin 123456 -o output.txt
|
||||
# Decode with RSA key file
|
||||
stegasoo decode -r photo.jpg -s stego.png -p "words" -k mykey.pem
|
||||
|
||||
# Quiet mode for piping text
|
||||
stegasoo decode -r photo.jpg -s stego.png -p "words" --pin 123456 -q | less
|
||||
# Decode with RSA key from QR code image
|
||||
stegasoo decode -r photo.jpg -s stego.png -p "words" --key-qr keyqr.png
|
||||
|
||||
# Save output to file
|
||||
stegasoo decode -r photo.jpg -s stego.png -p "words" --pin 123456 -o output.txt
|
||||
"""
|
||||
# Load key if provided
|
||||
# Load key if provided (from .pem file or QR code image)
|
||||
rsa_key_data = None
|
||||
rsa_key_from_qr = False
|
||||
|
||||
if key and key_qr:
|
||||
raise click.UsageError("Cannot use both --key and --key-qr. Choose one.")
|
||||
|
||||
if key:
|
||||
rsa_key_data = Path(key).read_bytes()
|
||||
elif key_qr:
|
||||
if not HAS_QR or not has_qr_read():
|
||||
raise click.ClickException(
|
||||
"QR code reading not available. Install: pip install pyzbar\n"
|
||||
"Also requires system library: sudo apt-get install libzbar0"
|
||||
)
|
||||
key_pem = extract_key_from_qr_file(key_qr)
|
||||
if not key_pem:
|
||||
raise click.ClickException(f"Could not extract RSA key from QR code: {key_qr}")
|
||||
rsa_key_data = key_pem.encode('utf-8')
|
||||
rsa_key_from_qr = True
|
||||
if not quiet:
|
||||
click.echo(f"Loaded RSA key from QR code: {key_qr}")
|
||||
|
||||
# QR code keys are never password-protected
|
||||
effective_key_password = None if rsa_key_from_qr else key_password
|
||||
|
||||
# Validate security factors
|
||||
if not pin and not rsa_key_data:
|
||||
raise click.UsageError("Must provide --pin or --key (or both)")
|
||||
raise click.UsageError("Must provide --pin or --key/--key-qr (or both)")
|
||||
|
||||
try:
|
||||
ref_photo = Path(ref).read_bytes()
|
||||
@@ -320,7 +383,7 @@ def decode_cmd(ref, stego, phrase, pin, key, key_password, output, quiet, force)
|
||||
day_phrase=phrase,
|
||||
pin=pin or "",
|
||||
rsa_key_data=rsa_key_data,
|
||||
rsa_password=key_password,
|
||||
rsa_password=effective_key_password,
|
||||
)
|
||||
|
||||
if result.is_file:
|
||||
|
||||
Reference in New Issue
Block a user