-
- Make sure you're using the exact same reference photo file
+
+ Use the exact same reference photo file (byte-for-byte identical)
-
- Use the phrase for the day the message was encoded, not today
+
+ Enter the exact passphrase used during encoding (case-sensitive, spacing matters)
-
+
Provide the same security factors (PIN and/or RSA key) used during encoding
-
- Ensure the stego image hasn't been resized or recompressed
+
+ Ensure the stego image hasn't been resized, cropped, or recompressed
-
- If using an RSA key, make sure the password is correct
+
+ Format compatibility: v3.2.0 cannot decode messages from v3.1.0 (different format)
+
+
+
+ If using an RSA key, verify the password is correct (if key is encrypted)
-
- v3.0: If auto-detection fails, try specifying LSB or DCT mode in Advanced Options
+
+ If auto-detection fails, try specifying LSB or DCT mode in Advanced Options
@@ -309,84 +304,22 @@ document.getElementById('decodeForm')?.addEventListener('submit', function() {
btn.disabled = true;
});
-// Show RSA password field when key is selected (only for .pem files, not QR)
+// Show RSA password field when key is selected
const rsaKeyInput = document.getElementById('rsaKeyInput');
const rsaKeyQrInput = document.getElementById('rsaKeyQrInput');
const rsaPasswordGroup = document.getElementById('rsaPasswordGroup');
-if (rsaKeyInput) {
- rsaKeyInput.addEventListener('change', function() {
- // Show password field only for .pem files
- rsaPasswordGroup.classList.toggle('d-none', !this.files.length);
- // Clear QR input if file is selected
- if (rsaKeyQrInput && this.files.length) {
- rsaKeyQrInput.value = '';
- }
- });
-}
-
-if (rsaKeyQrInput) {
- rsaKeyQrInput.addEventListener('change', function() {
- // Hide password field for QR codes (they're unencrypted)
- rsaPasswordGroup.classList.add('d-none');
- // Clear file input if QR is selected
- if (rsaKeyInput && this.files.length) {
- rsaKeyInput.value = '';
- }
- });
-}
-
-// Day names for date detection
-const dayNames = ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'];
-
-// Detect day AND date from filename - FIXED VERSION
-function detectDayFromFilename(filename) {
- // Match patterns like _20251227 or _2025-12-27
- const compactMatch = filename.match(/_(\d{4})(\d{2})(\d{2})/);
- const dashedMatch = filename.match(/_(\d{4})-(\d{2})-(\d{2})/);
-
- const dateMatch = compactMatch || dashedMatch;
-
- if (dateMatch) {
- const [, year, month, day] = dateMatch;
- const date = new Date(parseInt(year), parseInt(month) - 1, parseInt(day));
- const dayName = dayNames[date.getDay()];
- // Return ISO format date string for the server
- const dateStr = `${year}-${month.padStart(2, '0')}-${day.padStart(2, '0')}`;
-
- console.log('Detected date from filename:', dateStr, 'Day:', dayName);
-
- return {
- dayName: dayName,
- dateStr: dateStr
- };
- }
- return null;
-}
-
-// Update day phrase label AND set hidden date field
-function updateDayLabel(dayName, dateStr) {
- const label = document.getElementById('dayPhraseLabel');
- if (label && dayName) {
- label.innerHTML = `Provide ${dayName}'s Phrase`;
- }
-
- // CRITICAL FIX: Set the hidden date field for the server
- const dateField = document.getElementById('stegoDate');
- if (dateField && dateStr) {
- dateField.value = dateStr;
- console.log('Set stego_date hidden field to:', dateStr);
- }
-
- // Show info alert about detected date
- const dateAlert = document.getElementById('dateDetectedAlert');
- const dateText = document.getElementById('dateDetectedText');
- if (dateAlert && dateText && dateStr) {
- dateText.textContent = `Encoding date detected: ${dateStr} (${dayName})`;
- dateAlert.classList.remove('d-none');
+function checkRsaKeySelected() {
+ const hasFile = (rsaKeyInput && rsaKeyInput.files.length > 0) ||
+ (rsaKeyQrInput && rsaKeyQrInput.files.length > 0);
+ if (rsaPasswordGroup) {
+ rsaPasswordGroup.classList.toggle('d-none', !hasFile);
}
}
+rsaKeyInput?.addEventListener('change', checkRsaKeySelected);
+rsaKeyQrInput?.addEventListener('change', checkRsaKeySelected);
+
// PIN Toggle
document.getElementById('togglePin')?.addEventListener('click', function() {
const input = document.getElementById('pinInput');
@@ -461,7 +394,6 @@ document.querySelectorAll('.drop-zone').forEach(zone => {
const input = zone.querySelector('input[type="file"]');
const label = zone.querySelector('.drop-zone-label');
const preview = zone.querySelector('.drop-zone-preview');
- const isStegoZone = zone.id === 'stegoDropZone';
['dragenter', 'dragover'].forEach(evt => {
zone.addEventListener(evt, e => {
@@ -482,29 +414,12 @@ document.querySelectorAll('.drop-zone').forEach(zone => {
input.files = e.dataTransfer.files;
const file = e.dataTransfer.files[0];
showPreview(file);
-
- // FIXED: Extract both day name AND date string
- if (isStegoZone) {
- const detected = detectDayFromFilename(file.name);
- if (detected) {
- updateDayLabel(detected.dayName, detected.dateStr);
- }
- }
}
});
input.addEventListener('change', function() {
if (this.files && this.files[0]) {
- const file = this.files[0];
- showPreview(file);
-
- // FIXED: Extract both day name AND date string
- if (isStegoZone) {
- const detected = detectDayFromFilename(file.name);
- if (detected) {
- updateDayLabel(detected.dayName, detected.dateStr);
- }
- }
+ showPreview(this.files[0]);
}
});
diff --git a/pyproject.toml b/pyproject.toml
index a8f285f..8741f28 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
[project]
name = "stegasoo"
-version = "3.0.2"
+version = "3.2.0"
description = "Secure steganography with hybrid photo + passphrase + PIN authentication"
readme = "README.md"
license = "MIT"