diff --git a/frontends/web/app.py b/frontends/web/app.py index 1d25fc4..40c6ee7 100644 --- a/frontends/web/app.py +++ b/frontends/web/app.py @@ -525,8 +525,10 @@ def _register_stegasoo_routes(app: Flask) -> None: return render_template( "admin/users.html", users=users, + user_count=len(users), max_users=MAX_USERS, can_create=can_create_user(), + current_user=get_current_user(), ) @app.route("/admin/users/new", methods=["GET", "POST"]) @@ -639,7 +641,72 @@ def _register_stegasoo_routes(app: Flask) -> None: return render_template("stego/generate.html", generated=False, has_qrcode=_HAS_QRCODE) - # ── Encode (placeholder — full route migration is Phase 1b) ─── + # ── Generate QR + Key download routes ─────────────────────── + + @app.route("/generate/qr/") + @login_required + def generate_qr(token): + if not _HAS_QRCODE: + return "QR code support not available", 501 + file_info = temp_storage.get_temp_file(token) + if not file_info: + return "Token expired or invalid", 404 + if file_info.get("type") != "rsa_key": + return "Invalid token type", 400 + try: + key_pem = file_info["data"].decode("utf-8") + compress = file_info.get("compress", False) + qr_png = generate_qr_code(key_pem, compress=compress) + return send_file(io.BytesIO(qr_png), mimetype="image/png", as_attachment=False) + except Exception as e: + return f"Error generating QR code: {e}", 500 + + @app.route("/generate/qr-download/") + @login_required + def generate_qr_download(token): + if not _HAS_QRCODE: + return "QR code support not available", 501 + file_info = temp_storage.get_temp_file(token) + if not file_info: + return "Token expired or invalid", 404 + if file_info.get("type") != "rsa_key": + return "Invalid token type", 400 + try: + key_pem = file_info["data"].decode("utf-8") + compress = file_info.get("compress", False) + qr_png = generate_qr_code(key_pem, compress=compress) + return send_file( + io.BytesIO(qr_png), mimetype="image/png", + as_attachment=True, download_name="soosef_rsa_key_qr.png", + ) + except Exception as e: + return f"Error generating QR code: {e}", 500 + + @app.route("/generate/download-key", methods=["POST"]) + @login_required + def download_key(): + key_pem = request.form.get("key_pem", "") + password = request.form.get("key_password", "") + if not key_pem: + flash("No key to download", "error") + return redirect(url_for("generate")) + if not password or len(password) < 8: + flash("Password must be at least 8 characters", "error") + return redirect(url_for("generate")) + try: + private_key = load_rsa_key(key_pem.encode("utf-8")) + encrypted_pem = export_rsa_key_pem(private_key, password=password) + key_id = secrets.token_hex(4) + filename = f"soosef_key_{private_key.key_size}_{key_id}.pem" + return send_file( + io.BytesIO(encrypted_pem), mimetype="application/x-pem-file", + as_attachment=True, download_name=filename, + ) + except Exception as e: + flash(f"Error creating key file: {e}", "error") + return redirect(url_for("generate")) + + # ── Encode (placeholder — full route migration is Phase 2) ─── @app.route("/encode", methods=["GET", "POST"]) @login_required diff --git a/frontends/web/templates/admin/users.html b/frontends/web/templates/admin/users.html index f6fe5e5..d3c520c 100644 --- a/frontends/web/templates/admin/users.html +++ b/frontends/web/templates/admin/users.html @@ -1,9 +1,95 @@ {% extends "base.html" %} -{% block title %}Users — SooSeF Admin{% endblock %} + +{% block title %}Manage Users - Stegasoo{% endblock %} + {% block content %} -

User Management

-
- - Admin user management will be migrated from stegasoo's auth system. +
+
+
+
+
+ + User Management +
+
+ {{ user_count }} / {{ max_users }} users +
+
+
+ {% if can_create %} + + {% else %} +
+ + Maximum of {{ max_users }} users reached. +
+ {% endif %} + +
+ + + + + + + + + + + {% for user in users %} + + + + + + + {% endfor %} + +
UsernameRoleCreatedActions
+ + {{ user.username }} + {% if user.id == current_user.id %} + You + {% endif %} + + {% if user.is_admin %} + + Admin + + {% else %} + User + {% endif %} + + {{ user.created_at[:10] if user.created_at else 'Unknown' }} + + {% if user.id != current_user.id %} +
+ +
+
+ +
+ {% else %} + - + {% endif %} +
+
+
+ +
+
{% endblock %} diff --git a/frontends/web/templates/stego/generate.html b/frontends/web/templates/stego/generate.html index 1038bf5..34c52ca 100644 --- a/frontends/web/templates/stego/generate.html +++ b/frontends/web/templates/stego/generate.html @@ -1,10 +1,533 @@ {% extends "base.html" %} -{% block title %}Generate — SooSeF{% endblock %} + +{% block title %}Generate Credentials - Stegasoo{% endblock %} + {% block content %} -

Generate Credentials

-

Generate secure passphrases, PINs, and RSA key pairs.

-
- - Stegasoo credential generator UI will be migrated here. +
+
+
+
+
Generate Credentials
+
+
+ {% if not generated %} + +
+
+ + +
+ {{ min_passphrase_words }} (~33 bits) + {{ default_passphrase_words }} words (~44 bits) + 12 (132 bits) +
+
+ + Recommended: {{ recommended_passphrase_words }}+ words for good security +
+
+ +
+ +
SECURITY FACTORS (select at least one)
+ +
+
+
+ + +
+
+ + +
+
+ +
+
+ + +
+
+ + +
+
+
+ + +
+ + +
+
+

+ +

+
+
+

+ Channel keys create private encoding channels. Only users with the same key can decode each other's images. + Learn more +

+ +
+ + + + +
+
+ + After generating, configure this key in your server's environment or use Custom channel mode when encoding/decoding. +
+
+
+
+
+ + {% else %} + +
+ + Memorize these credentials! They will not be shown again. +
Do not screenshot or save to an unencrypted file. +
+ + {% if pin %} +
+
STATIC PIN
+
+
+
+ {% for digit in pin %} + {{ digit }} + {% endfor %} +
+
+ + +
+
+
+
+ {% endif %} + +
+
+ PASSPHRASE +
+ +
+
+ {{ passphrase }} +
+ +
+ + + +
+
+ + +
+
+
+ Memory Story +
+
+

+ +

+
+ + This story is generated from your passphrase to help you remember it. + The words appear in order within the narrative. +
+ +
+
+
+ +
+ + ({{ words_per_passphrase }} words = ~{{ passphrase_entropy }} bits entropy) + +
+
+ + {% if rsa_key_pem %} +
+
RSA PRIVATE KEY ({{ rsa_bits }} bits)
+ + + +
+ +
+
{{ rsa_key_pem }}
+ +
+ + +
+
+ +
+ + +
+
+ +
+
+
+ The downloaded file will be password-protected (AES-256 encrypted). +
+
+ + {% if has_qrcode and qr_token %} + +
+
+

+ Scan this QR code to transfer the RSA key to another device. +
Warning: This is the unencrypted private key! +

+
+ RSA Key QR Code +
+
+ + Download QR Code + + +
+
+ + Security note: The QR code contains your unencrypted private key. + Only scan in a secure environment. Consider using the password-protected download instead. +
+
+
+ {% endif %} +
+
+ {% endif %} + +
+
SECURITY SUMMARY
+
+
+
+
Passphrase
+
{{ passphrase_entropy }} bits
+
{{ words_per_passphrase }} words
+
+
+ {% if pin_entropy %} +
+
+
PIN
+
{{ pin_entropy }} bits
+
+
+ {% endif %} + {% if rsa_entropy %} +
+
+
RSA
+
{{ rsa_entropy }} bits
+
+
+ {% endif %} +
+
+
Total
+
{{ total_entropy }} bits
+
+
+
+
+ + reference photo entropy (~80-256 bits) +
+
+ + + {% endif %} +
+
+ + {% if not generated %} +
+
+
About Credentials
+
    +
  • + Passphrase is a single phrase you use each time +
  • +
  • + PIN is static and adds another factor both parties must know +
  • +
  • + RSA key adds asymmetric cryptography for additional security +
  • +
  • + You need at least one of PIN or RSA key (or both) +
  • +
+
+
+ {% endif %} +
+ + +{% endblock %} + +{% block scripts %} + + +{% if generated %} + +{% endif %} {% endblock %} diff --git a/frontends/web/templates/stego/tools.html b/frontends/web/templates/stego/tools.html index f9b06e8..02781b2 100644 --- a/frontends/web/templates/stego/tools.html +++ b/frontends/web/templates/stego/tools.html @@ -1,10 +1,1207 @@ {% extends "base.html" %} -{% block title %}Tools — SooSeF{% endblock %} + +{% block title %}Tools - Stegasoo{% endblock %} + {% block content %} -

Tools

-

Image analysis, capacity checking, EXIF stripping, and more.

-
- - Stegasoo tools UI will be migrated here. +
+
+
+ +
+
+ + +
+ +
+ +
+ + + + +
+
+ + +
+ +
+ + + +
+
+ +
+
+ +
+ + Drop image or click to browse +
+
+ Preview +
image.jpg
+
--
+
+ +
+
+ + + + +
+
+ +
+
+ +
+ + Drop image or click to browse +
+
+ Preview +
image.jpg
+
--
+
+ +
+
+ + + + +
+
+ + +
+
+ +
+ + Drop image or click to browse +
+
+ Preview +
image.jpg
+
--
+
+ +
+
+ + + + +
+
+
+ + + + +
+
+
+ +
+ + Drop image or click to browse +
+
+
+ Preview +
+
+ +
+ +
+
image.jpg
+
--
+
+
+ + + + +
+
+ + + 85% +
+
+ +
+ + Drop image or click to browse +
+
+ Preview +
image.jpg
+
--
+
+ +
+
+ + + + +
+
+ + + + + 90% +
+
+ +
+ + Drop image or click to browse +
+
+ Preview +
image.jpg
+
--
+
+ +
+
+ + +
+ Analyze + Capacity Calculator +
+
+ + +
+ + + +
+
+
Capacity Calculator
+ Check how much data can be hidden +
+
+
+ + Drop an image to analyze +
+
+
+ Dimensions + -- +
+
+ Megapixels + -- +
+
+ LSB Capacity + -- +
+
+ DCT Capacity + -- +
+
+
+
+ +
+
+ + + + +
+
+
EXIF Viewer
+ View image metadata +
+
+
+ + Drop an image to view metadata +
+
+
+ +
+
+ + No metadata found +
+
+
+
+ + +
+
+ + + + +
+
+
Strip Metadata
+ Remove all EXIF data +
+
+
+ + Drop an image to strip +
+
+
+ Original Size + -- +
+
+ Output Format + PNG +
+
+ + All metadata will be removed from the image. +
+
+
+
+ + +
+
+ + + + +
+
+
Rotate / Flip
+ Transform image orientation +
+
+
+ + Drop an image to transform +
+
+
+ Original + -- +
+
+ Rotation + +
+
+ Flipped + None +
+ + +
+
+
+ + +
+
+ + + + +
+
+
JPEG Compression
+ Test compression quality +
+
+
+ + Drop an image to compress +
+
+
+ Original + -- +
+
+ Compressed + -- +
+
+ Reduction + -- +
+
+
+
+ + +
+
+ + + + +
+
+
Format Convert
+ Convert between formats +
+
+
+ + Drop an image to convert +
+
+
+ Original + -- +
+
+ Output + PNG +
+
+ New Size + -- +
+
+
+
+ + +
+
+
+
+
+
{% endblock %} + +{% block scripts %} + +{% endblock %}