Signed Messages (TryHackMe)

My Dearest Hacker,
LoveNote built it's reputation on trust. Every message, every action, signed and verified by the system itself. LoveNoe claims that no message can be forged, no identity faked.
Yet an internal leak suggests the platform may be trusting something it shouldn't. With Valentine's Day fast approaching, the consequences of a broken trust system could be disastrous.
You can find the web application here:
http://MACHINE_IP:5000
nmap -p- -sV <IP_Address>
Starting Nmap 7.80 ( https://nmap.org ) at 2026-02-14 11:38 GMT
mass_dns: warning: Unable to open /etc/resolv.conf. Try using --system-dns or specify valid servers with --dns-servers
mass_dns: warning: Unable to determine any DNS servers. Reverse DNS is disabled. Try using --system-dns or specify valid servers with --dns-servers
Nmap scan report for 10.48.134.69
Host is up (0.0014s latency).
Not shown: 65533 closed ports
PORT STATE SERVICE VERSION
22/tcp open ssh OpenSSH 8.9p1 Ubuntu 3ubuntu0.13 (Ubuntu Linux; protocol 2.0)
5000/tcp open http Werkzeug httpd 2.0.2 (Python 3.10.12)
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel
Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 9.75 seconds
gobuster dir -u http://<IP_Address>:5000 -w /usr/share/wordlists/dirb/common.txt -x php,html,txt
gobuster dir -u http://<IP_Address>:5000 -w /usr/share/wordlists/dirb/common.txt -x php,html,txt,js
===============================================================
Gobuster v3.6
by OJ Reeves (@TheColonial) & Christian Mehlmauer (@firefart)
===============================================================
[+] Url: http://10.48.134.69:5000
[+] Method: GET
[+] Threads: 10
[+] Wordlist: /usr/share/wordlists/dirb/common.txt
[+] Negative Status codes: 404
[+] User Agent: gobuster/3.6
[+] Extensions: js,php,html,txt
[+] Timeout: 10s
===============================================================
Starting gobuster in directory enumeration mode
===============================================================
/about (Status: 200) [Size: 15206]
/compose (Status: 302) [Size: 218] [--> http://10.48.134.69:5000/login]
/dashboard (Status: 302) [Size: 218] [--> http://10.48.134.69:5000/login]
/debug (Status: 200) [Size: 11342]
/login (Status: 200) [Size: 10999]
/logout (Status: 302) [Size: 208] [--> http://10.48.134.69:5000/]
/messages (Status: 200) [Size: 12929]
/register (Status: 200) [Size: 12509]
Progress: 23070 / 23075 (99.98%)
===============================================================
Finished
===============================================================
curl -i http://<IP_Address>:5000
</head>
<body>
<nav class="navbar">
<div class="nav-container">
<a href="/" class="nav-brand">LoveNote</a>
<ul class="nav-links">
<li><a href="/">Home</a></li>
<li><a href="/messages">Messages</a></li>
<li><a href="/verify">Verify</a></li>
<li><a href="/login">Login</a></li>
<li><a href="/register">Register</a></li>
<li><a href="/about">About</a></li>
</ul>
</div>
</nav>
<div class="hero">
<h1>Send Love Securely</h1>
<p>Professional PKI-based messaging platform for Valentine's Day. Every message digitally signed with RSA-2048 encryption.</p>
<div class="hero-buttons">
<a href="/register" class="hero-btn">Get Started</a>
<a href="/about" class="hero-btn secondary">Learn More</a>
</div>
</div>
<div class="container">
<div class="stats-grid">
<div class="stat-card">
<div class="stat-number">1</div>
<div class="stat-label">Registered Users</div>
</div>
<div class="stat-card">
<div class="stat-number">1</div>
<div class="stat-label">Messages Sent</div>
</div>
<div class="stat-card">
<div class="stat-number">2048</div>
<div class="stat-label">Bit RSA Keys</div>
</div>
</div>
<div class="features-grid">
<div class="feature-card">
<div class="feature-icon">
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
<rect x="3" y="11" width="18" height="11" rx="2" ry="2"></rect>
<path d="M7 11V7a5 5 0 0 1 10 0v4"></path>
</svg>
</div>
<h3 class="feature-title">Digital Signatures</h3>
<p class="feature-desc">Every message is cryptographically signed using RSA-2048 to ensure authenticity and prevent tampering.</p>
</div>
<div class="feature-card">
<div class="feature-icon">
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
<path d="M22 11.08V12a10 10 0 1 1-5.93-9.14"></path>
<polyline points="22 4 12 14.01 9 11.01"></polyline>
</svg>
</div>
<h3 class="feature-title">Verify Authenticity</h3>
<p class="feature-desc">Verify any message's signature to confirm it was sent by the claimed sender and hasn't been modified.</p>
</div>
<div class="feature-card">
<div class="feature-icon">
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
<path d="M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z"></path>
</svg>
</div>
<h3 class="feature-title">Public Messages</h3>
<p class="feature-desc">Share love messages publicly or send private encrypted notes to specific recipients.</p>
</div>
</div>
<div class="recent-messages">
<h2 style="margin-bottom: 1.5rem; font-size: 1.8rem;">Recent Public Messages</h2>
<div class="message-item">
<div class="message-header">
<span class="message-from">admin</span>
<span class="message-time">2026-02-14 11:36:05</span>
</div>
<div class="message-subject">Welcome to LoveNote</div>
<div class="message-preview">Welcome to LoveNote! Send encrypted love messages this Valentine's Day. Your communications are secured with industry-standard RSA-2048 digital signat...</div>
</div>
<div style="text-align: center; margin-top: 1.5rem;">
<a href="/messages" class="btn btn-secondary">View All Messages</a>
</div>
</div>
</div>
<footer class="footer">
<div class="footer-container">
<div class="footer-section">
<h3>LoveNote</h3>
<p>Secure messaging for Valentine's Day. Protected by RSA-2048 digital signatures ensuring authenticity and integrity.</p>
</div>
<div class="footer-section">
<h3>Platform</h3>
<ul class="footer-links">
<li><a href="/">Home</a></li>
<li><a href="/messages">Public Messages</a></li>
<li><a href="/verify">Verify Signatures</a></li>
<li><a href="/about">About</a></li>
</ul>
</div>
<div class="footer-section">
<h3>Security</h3>
<ul class="footer-links">
<li><a href="/about#encryption">Encryption Details</a></li>
<li><a href="/about#pki">PKI Infrastructure</a></li>
<li><a href="/about#privacy">Privacy Policy</a></li>
</ul>
</div>
</div>
<div class="footer-bottom">
© 2026 LoveNote. All rights reserved.
</div>
</footer>
</body>
</html>
Account created successfully! Welcome, jane doe.
Account Created Successfully!
Welcome, jane doe! Your cryptographic keypair has been generated.
Important: Save Your Keys
Your keys are stored securely on our server, but we recommend saving a backup. Your private key is used to sign messages and should be kept confidential. Your public key can be shared with anyone who wants to verify your signatures.
Public Key
Share this key publicly. Others use it to verify your message signatures.
-----BEGIN PUBLIC KEY-----
MFswDQYJKoZIhvcNAQEBBQADSgAwRwJAF/5dSxFrIfzloal791F42tpl3gfy677Z
zgdxh3DnMH9BoQnGblYKrD1mCIqcfS7V6ipvZGFNDbtKW3OsGpb5/wIDAQAB
-----END PUBLIC KEY-----
Private Key
Keep this secret! This key signs your messages and proves you are the sender.
-----BEGIN PRIVATE KEY-----
MIIBUQIBADANBgkqhkiG9w0BAQEFAASCATswggE3AgEAAkAX/l1LEWsh/OWhqXv3
UXja2mXeB/LrvtnOB3GHcOcwf0GhCcZuVgqsPWYIipx9LtXqKm9kYU0Nu0pbc6wa
lvn/AgMBAAECQAvNdjrtEJQhgRvq8S4Rh6+waxezNU2+DgoJI1GKuk7ijEu+fOrs
d4UtO6QzTA8Kn8Y/nFttZEV9ueeRzdgT2jECICjDySKO+WAu6zmi7jikBAZNBnrx
BatHcy1Kf+L1Z16DAiEAlq2d1GmF+KGW1xV+yL5CBhj+Ah3eJs9du8uZMzy1ndUC
ICDp69WGYR1i5LP1tKhw7Xr06B2Ny4j+uKVB+L4UbLDnAiAHq37FOTnglhkfibCS
d1zVAqCraunL//I9hPefbA+yoQIgDxxxN1afI7J8gWw22XuOJt9jFj+kdkk95KxI
NnKEA5o=
-----END PRIVATE KEY-----
they said that username admin is reserved maybe we could check if we can use admin’s session token to test
POST /compose HTTP/1.1
Host: 10.48.134.69:5000
Content-Length: 36
Cache-Control: max-age=0
Accept-Language: en-GB,en;q=0.9
Origin: http://10.48.134.69:5000
Content-Type: application/x-www-form-urlencoded
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/130.0.6723.70 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7
Referer: http://10.48.134.69:5000/compose
Accept-Encoding: gzip, deflate, br
Cookie: session=eyJ1c2VybmFtZSI6ImxvdmVub2UifQ.aZBjbw.1Ig-lSG9EO3IeuIr9fNwJrukECQ
Connection: keep-alive
to_user=admin&subject=gh&message=ttt
System Debug Logs
[2026-02-06 14:23:15] Development mode: ENABLED
[2026-02-06 14:23:15] Using deterministic key generation
[2026-02-06 14:23:15] Seed pattern: {username}_lovenote_2026_valentine
[DEBUG] Seed converted to bytes for cryptographic processing
[DEBUG] Seed hashed using SHA256 to produce large numeric material
[DEBUG] Prime derivation step 1:
[DEBUG] Converting SHA256(seed) into a large integer
[DEBUG] Checking consecutive integers until a valid prime is reached
[DEBUG] Prime p selected
[DEBUG] Prime derivation step 2:
[DEBUG] Modifying seed with PKI-related constant (SHA256(seed + b"pki"))
[DEBUG] Hashing modified seed with SHA256
[DEBUG] Converting hash into a large integer
[DEBUG] Checking consecutive integers until a valid prime is reached
[DEBUG] Prime q selected
[2026-02-06 14:23:16] RSA modulus generated from p à q
[2026-02-06 14:23:16] RSA-2048 key pair successfully constructed
[2026-02-06 14:23:17] Public and private keys saved to disk
Development Notice
This debug endpoint shows internal system logs from the key generation service. The logs reveal implementation details that should not be exposed in production.
#!/usr/bin/env python3
"""
Sign messages or create sessions as admin using recovered private key
"""
import hashlib
from cryptography.hazmat.primitives import hashes
from cryptography.hazmat.primitives.asymmetric import padding
from cryptography.hazmat.primitives import serialization
from cryptography.hazmat.backends import default_backend
import sys
def load_private_key(filename):
"""Load private key from PEM file"""
with open(filename, 'rb') as f:
private_key = serialization.load_pem_private_key(
f.read(),
password=None,
backend=default_backend()
)
return private_key
def sign_message(private_key, message):
"""Sign a message using RSA private key with PSS padding"""
message_bytes = message.encode('utf-8')
# Sign using PSS padding (as mentioned in the app)
signature = private_key.sign(
message_bytes,
padding.PSS(
mgf=padding.MGF1(hashes.SHA256()),
salt_length=padding.PSS.MAX_LENGTH
),
hashes.SHA256()
)
# Convert to hex
signature_hex = signature.hex()
return signature_hex
def main():
print("[*] Loading admin's private key...")
private_key = load_private_key("admin_private.pem")
print("[+] Private key loaded successfully!\n")
if len(sys.argv) > 1:
message = ' '.join(sys.argv[1:])
else:
message = input("Enter message to sign as admin: ")
print(f"\n[*] Signing message: '{message}'")
signature = sign_message(private_key, message)
print("\n" + "="*70)
print("MESSAGE SIGNATURE (hex):")
print("="*70)
print(signature)
print("="*70)
print("\n[+] You can use this signature to verify the message on /verify")
print(f" Username: admin")
print(f" Message: {message}")
print(f" Signature: {signature}")
if __name__ == "__main__":
main()





