Une version open-source minimaliste de Seecret.it — frontend en vanilla JavaScript, backend en PHP + SQLite (un seul fichier). Aucun framework, aucun NPM, aucune dépendance Composer. À déployer en 30 secondes sur n’importe quel hébergement mutualisé.
💡 Cette version est volontairement épurée. Pour les fonctionnalités complètes (upload de fichiers, comptes utilisateurs, statistiques, extensions Thunderbird/navigateur, QR Codes Wi-Fi, etc.), utilisez le service hébergé seecret.it.
- Chiffrement AES-GCM 256 bits côté client (Web Crypto API native)
- Lien à usage unique : le secret est détruit dès la première lecture (transaction SQLite atomique)
- Expiration configurable : 5 min / 1h / 1j / 7j / 30j
- Mot de passe optionnel avec dérivation PBKDF2 (600 000 itérations, SHA-256) — OWASP 2023
- Gate anti-robot (case à cocher + bouton) pour éviter le déclenchement par les previews de liens (Discord, Slack, WhatsApp, etc.)
- Modèle zéro-knowledge : la clé de déchiffrement ne quitte jamais le navigateur
Le serveur ne stocke que le ciphertext. La clé (ou le sel PBKDF2 si mot de passe) reste dans le fragment # de l'URL — partie qui, par spécification HTTP, n'est jamais envoyée au serveur.
Conséquence : même si la base est compromise, personne ne peut déchiffrer les secrets stockés sans posséder l'URL complète.
https://votre-domaine.tld/view.html#i=abc12_xy&v=1&p=0&k=BASE64KEY
└─────────────┬─────────────┘
Cette partie reste côté client
- HTML / CSS / Vanilla JavaScript — aucun framework
- Bootstrap 5 (CSS, en local)
- SweetAlert2 (en local)
- Web Crypto API (natif navigateur)
- PHP ≥ 8.0 + extension
pdo_sqlite(paquetphp-sqlite3sur Debian/Ubuntu)
git clone https://github.com/Seecret-it/seecret.it.git
cd seecret.it
# Lancer en local
php -S localhost:8000Ou pointer le DocumentRoot Apache/Nginx vers ce dossier. Le répertoire data/ est créé automatiquement au premier appel — vérifiez juste que l'utilisateur PHP a les droits d'écriture dessus.
seecret.it/
├── index.html Page de création
├── view.html Page de lecture
├── api.php API REST : POST (créer) / GET (lire + détruire)
├── data/
│ ├── .htaccess Bloque l'accès direct à seecrets.sqlite
│ └── .gitignore Ignore le .sqlite (ne pas commiter la BDD)
├── css/
│ ├── bootstrap.min.css
│ ├── sweetalert.css
│ └── style.css Thème seecret.it (cyan #4ac4f3 + turquoise #1aebd6)
└── js/
├── bootstrap.bundle.min.js
├── sweetalert.js
├── crypto.js AES-GCM + PBKDF2 (Web Crypto API)
├── app.js Logique page de création
└── view.js Logique page de lecture
POST /api.php
Content-Type: application/json
{
"ciphertext": "base64url",
"expires_in": 86400
}Réponse :
{ "id": "abc12_xy", "expires_at": 1746790000 }GET /api.php?id=abc12_xyRéponse (le secret est immédiatement supprimé de la base) :
{ "ciphertext": "base64url" }Si déjà lu / expiré / inexistant : 404.
Les secrets expirés sont déjà purgés paresseusement à chaque requête. Pour purger même en l'absence de trafic :
0 * * * * sqlite3 /path/to/data/seecrets.sqlite "DELETE FROM seecrets WHERE expires_at < strftime('%s','now');"| Scénario | Résultat |
|---|---|
| Serveur compromis (lecture BDD seule) | ✅ Aucun secret déchiffrable — la clé n'y est jamais |
Fuite du fichier seecrets.sqlite |
✅ Que des ciphertexts AES-GCM 256, incassables sans la clé |
| Logs serveur exposés | ✅ Les fragments # ne sont pas loggés (jamais transmis HTTP) |
| IP loggées dans le rate-limit | ✅ Stockées en hash SHA-256 avec sel quotidien |
| Lecteur légitime consulte le lien | ✅ Secret détruit après lecture (transaction atomique SQLite) |
| Spam de création / brute-force ID | ✅ Rate-limit 20 POST + 60 GET par minute par IP |
| Saturation disque | ✅ Plafond global de 50 000 secrets (MAX_TOTAL_SECRETS) |
| Aperçu de lien par bots messagerie | ✅ Gate anti-robot avant fetch |
| CSRF cross-origin form POST | ✅ Refus si Content-Type ≠ application/json |
| URL avec clé reste dans l'historique | ✅ history.replaceState après lecture réussie |
| Clickjacking via iframe | ✅ X-Frame-Options: DENY + CSP frame-ancestors 'none' |
| Injection XSS via ciphertext malveillant | ✅ Validation regex [A-Za-z0-9_-]+, CSP stricte, textContent |
| URL complète interceptée avant lecture | |
| Force brute sur mot de passe | |
| MITM sans HTTPS | .htaccess) |
Cette version a été auditée. Mesures appliquées :
Cryptographie
- AES-GCM 256 bits côté client (chiffrement authentifié)
- IV 12 octets random unique par secret
- PBKDF2 SHA-256 avec 600 000 itérations (OWASP 2023)
- Clés générées via
crypto.subtle.generateKey(CSPRNG natif)
API PHP
- Toutes les requêtes en prepared statements PDO (zéro SQL injection)
- Validation stricte des entrées (regex
[A-Za-z0-9_-]+, bornes de taille) Content-Type: application/jsonobligatoire sur POST (mitigation CSRF cross-origin)- Rate-limit par IP hashée (SHA-256 + sel quotidien) — 20 POST / 60 GET par minute
- Cap de 50 000 secrets max (DoS disque)
- Messages d'erreur génériques, exceptions loggées via
error_loguniquement - Transaction SQLite
BEGIN IMMEDIATEpour la lecture-puis-destruction atomique
Headers HTTP
Content-Security-Policystricte (script-src 'self', frame-ancestors 'none')X-Content-Type-Options: nosniffX-Frame-Options: DENYReferrer-Policy: no-referrerPermissions-Policy: interest-cohort=(), camera=(), microphone=(), geolocation=()Cache-Control: no-storesur l'API
Apache .htaccess
- Bloque l'accès aux fichiers cachés (
.git,.env, etc.) - Bloque
.sqlite,.log,.bak,.md - Désactive le listing de répertoire
- HSTS et redirection HTTPS en commentaire (à activer en prod)
Côté client
textContentpartout (jamaisinnerHTML) → pas de XSS via secret déchiffréescapeHtmlsur les URL injectées dans SweetAlerthistory.replaceStateaprès lecture → la clé disparaît de l'historique- Gate anti-bot avant déchiffrement
Cette version est volontairement minimaliste. Elle n'inclut pas :
- Upload de fichiers (uniquement du texte)
- Comptes utilisateurs et historique
- Statistiques d'accès (date, IP, navigateur, pays)
- Liens à
Nvues configurables (uniquement 1 vue ici) - Générateur de QR Codes Wi-Fi
- Générateur de mots de passe
- Extensions Thunderbird / navigateur
- API d'authentification avec clés
Pour ces fonctionnalités, utilisez la version SaaS : seecret.it.
- 🌐 Service hébergé : https://seecret.it
- 📄 CGV : https://seecret.it/fr/cgv
- 🔐 Politique de confidentialité : https://seecret.it/fr/privacy-policy
- 📰 Blog : https://seecret.it/blog
- 🔧 Générateur QR Wi-Fi : https://seecret.it/fr/qrcode_wifi
- 🔑 Générateur de mots de passe : https://seecret.it/fr/password-generator
security · password-sharing · encrypted-links · privacy · cybersecurity · zero-knowledge · self-hosted · aes-gcm · php · sqlite · vanilla-javascript · open-source
Développé pour simplifier le partage de données sensibles et améliorer les pratiques de sécurité au quotidien. Seecret.it évolue constamment — de nouvelles intégrations et fonctionnalités arrivent régulièrement.
PRs et issues bienvenues ! 🚀
