Back to Secure Share

How Secure Share works

A plain-language overview first, with technical detail available when you want it. Secure Share encrypts in your browser and shares only what is needed to deliver a one-time reveal.

The short version: the server stores encrypted blobs, not your plaintext and not your decryption key. The link works once, then the record is deleted.

At a glance

Private by default

Encryption and decryption happen client-side with Web Crypto before any secret is sent over the network.

Single-use reveal

Successful retrieval burns the record. Expired secrets are blocked at expiry and purged by scheduled cleanup.

Optional password layer

A password adds a second factor. The server verifies proof material, not your raw password.

Abuse resistance

Failed reveal attempts trigger temporary lockouts and eventual burn to limit guessing windows.

Choose your depth

Quick understanding

Read the cards above and the bold headings in each journey step below. You will understand what happens and what stays private.

Technical understanding

Read the full journey rows and open the deep-dive sections for algorithm choices, verifyHash, peppering, and lockout controls.

How a secret moves through Secure Share

Each step starts with plain language. Open technical details only when you want the lower-level cryptography and verification flow.

1

Create

You
Enter secret and optional password.
Browser
Generates key material and encrypts your text before upload.
Server
Receives encrypted payload and retrieval metadata only.
Technical details

Generates random baseKey (32 bytes) + salt (16 bytes), derives derivedKey = PBKDF2(passwordOrSynthetic, salt, 1,000,042), builds finalKey = SHA-256(baseKey || derivedKey), encrypts with AES-256-GCM, and computes verifyHash.

2

Package + Share

You
Share the link and, if used, share password separately.
Browser
Packs key data into the URL fragment (#...).
Server
Does not receive fragment contents — browsers do not include the fragment in HTTP requests.
Technical details

Fragment carries packed v2 data: id + baseKey + salt + flags. Server-side create record contains id + ciphertext + verifyHash + expiresIn. Fragment data is client-handled.

3

Verify + Reveal

You
Recipient opens link and enters password if required.
Browser
Rebuilds key material, verifies, then decrypts locally.
Server
Checks proof material and returns ciphertext once.
Technical details

Client submits verifyHash = SHA-256(derivedKey). Stored value is pepper-protected: v1.HMAC-SHA256(verifyHash, VERIFY_HASH_PEPPER). Verification uses constant-time comparison before one-time release.

4

Burn + Expire

You
View and copy the revealed secret.
Browser
Shows plaintext locally; nothing is re-uploaded after decrypt.
Server
Deletes after reveal and applies expiry/lockout protections.
Technical details

Successful retrieval burns the record. Expired secrets are blocked at expiry check and purged by scheduled cleanup. Failed attempts trigger lockout windows and eventual burn to limit brute-force budgets.

Deep dive (expand as needed)

Cryptography choices

Encryption uses AES-256-GCM for confidentiality and integrity. Password-based derivation uses PBKDF2-SHA256 with 1,000,042 iterations, plus a random 16-byte salt.

When a password is used, Secure Share combines random key material with the password-derived key using finalKey = SHA-256(baseKey || derivedKey). Decryption requires URL fragment data and the correct password path.

What is in the link fragment

The link stores packed binary v2 data in #fragment: version + UUID + key + salt + flags. It is fixed length (66 bytes before Base64URL encoding).

The fragment is processed in-browser and is not included in HTTP request paths, helping keep key material out of server logs.

verifyHash, pepper, and lockout behavior

The client computes verifyHash = SHA-256(derivedKey), where derivedKey comes from PBKDF2 using either the user password or a synthetic password for non-password shares.

Before saving, the server protects that value with a secret environment pepper: stored = v1.HMAC-SHA256(verifyHash, VERIFY_HASH_PEPPER). During retrieval, submitted verifyHash is HMAC-wrapped and compared in constant time. Failed attempts trigger lockouts and eventual burn.

Trust boundaries and limitations

The service cannot protect against endpoint compromise (malware, clipboard leaks, captured screenshots), weak passwords, or link forwarding to unintended recipients.

Use a strong password, send link and password over different channels when possible, and choose shorter expiry windows for sensitive secrets.

Common user questions

What should I send?

API keys, recovery codes, credentials, and one-time notes. Keep messages under 512 characters.

Can Nodeblue read my secret?

No plaintext and no decryption key are stored server-side. The system stores encrypted payloads and retrieval metadata only.

What if someone gets the link?

Without a password they may unlock non-password links. For sensitive content, use password protection and share password separately.

What blocks bots and abuse?

Create requests use Turnstile checks; retrieval attempts are lockout-protected and secrets are burned after repeated failures.

Development Approach

Secure Share was built with coding AI assistants as development tools, not as a substitute for engineering judgement. Product direction, architecture, security boundaries, and final implementation decisions were reviewed and directed by Ben Cooper.

The goal was deliberate execution over speed: clear trust boundaries, auditable behaviour, and plain-language transparency around what the service can and cannot see.