source : docs/operations/warrant-canary.md · versionné
Warrant canary — procédure
- Version : 1.0.0
- Date : 2026-04-24
- Issue GitHub : #82
- Références : cahier des charges § 7 ; runbook incident § F3
Principe
Le warrant canary est une déclaration signée mensuellement affirmant que le collectif n'a pas été contraint par une demande légale à mettre en place une backdoor, installer un mouchard, ou autre. Si la signature cesse de se renouveler, c'est un signal sans mot : on informe sans violer un ordre de bâillon légal.
Ce qui est promis (et comment)
La déclaration cible :
- ✅ Aucune demande légale forçant à modifier les systèmes, installer
une backdoor, ou rompre la promesse Zero-Knowledge. - ✅ Aucun membre du core team personnellement contraint.
Elle NE promet PAS :
- Qu'aucune requête légale standard (mandat vers un hébergeur, par
exemple) n'a été reçue — ces requêtes sont traitées dans le cadre strict de la loi et documentées agrégément dans les transparency reports trimestriels.
Architecture
Clé de signature
- Paire hybride ECDSA P-384 + Dilithium-3 dédiée au canary.
- Générée en cérémonie hors-ligne, stockée dans le même coffre HSM que
la CA racine (3-of-5 shards). - Clé publique publiée dans /public/canary/public-key.hybrid et fingerprint affiché sur /transparency.
Stockage du canary
- Fichier texte
/public/canary/current.txtversionné dans le repo
public GitHub (lecture seule). - Format : ``` OmbrysWeb warrant canary As of YYYY-MM-DD, OmbrysWeb collective has received no legal order forcing a backdoor, surveillance device, or breach of Zero-Knowledge.
No core team member has been personally coerced.
Previous signature date : YYYY-MM-DD Next signature expected : YYYY-MM-DD (+30 days window) Hybrid signature (hex) : <ecdsa_p384_der_hex>||<dilithium3_hex> Public key fingerprint : <sha384 truncated 12 bytes, hex separators> `` - Un current.txt.sig` contient la signature seule, détachée.
Cadence
- Renouvelé le 1er de chaque mois (± 72h de tolérance).
- Si aucune signature n'arrive dans les 7 jours après la date attendue,
une alerte Matrix est envoyée au canal #ombrys-general. - Si aucune signature n'arrive dans les 30 jours, le canary est considéré comme "tombé" — page /transparency affiche un bandeau rouge explicite.
Procédure mensuelle
Jour J
- Un membre du core team physique access au HSM hors-ligne.
- Allume la machine air-gap dédiée à la signature canary.
- Exécute
scripts/sign-canary.sh:
- Lit
docs/transparency/canary-template.txt. - Remplace
{{DATE}},{{PREV_DATE}},{{NEXT_DATE}}avec des
dates calculées dynamiquement. - Signe avec la clé hybride sur le HSM. - Produit current.txt + current.txt.sig + current.txt.sha256. 4. Transfère les 3 fichiers sur clé USB jetable (format ext4 chiffré LUKS, clé jetée après). 5. Sur une machine en ligne : commit + push dans le repo privé Forgejo → miroir GitHub public met à jour /public/canary/* dans les quelques minutes qui suivent. 6. Notification Matrix E2EE #ombrys-core : "Canary signé pour <mois>, valid jusqu'au <date>".
En cas d'impossibilité de signer librement
NE PAS signer un faux canary.
- Laisser la date passer sans nouveau commit.
- Le site
/transparencyaffichera le delta. Les utilisateurs
attentifs le remarqueront. 3. Si possible (et sans violer l'éventuel gag order) : notifier les membres via le canal dégradé Briar du core team. 4. La déclaration suivante (quand légalement possible) documente le "silence" et ses circonstances dans la mesure du permis.
Scripts
scripts/sign-canary.sh
#!/usr/bin/env bash
# À exécuter sur la machine air-gap dédiée.
# Requiert : openssl, liboqs CLI (ou crate ombrys-pq-cli en M6+),
# accès HSM PKCS#11 pour ECDSA P-384.
set -euo pipefail
readonly TEMPLATE="docs/transparency/canary-template.txt"
readonly OUT_DIR="apps/web/public/canary"
# Date logic
now="$(date -u +%Y-%m-%d)"
prev="$(date -u -d '-1 month' +%Y-%m-%d 2>/dev/null || date -u -v-1m +%Y-%m-%d)"
next="$(date -u -d '+1 month' +%Y-%m-%d 2>/dev/null || date -u -v+1m +%Y-%m-%d)"
# Render
mkdir -p "${OUT_DIR}"
sed -e "s/{{DATE}}/${now}/" \
-e "s/{{PREV_DATE}}/${prev}/" \
-e "s/{{NEXT_DATE}}/${next}/" \
"${TEMPLATE}" > "${OUT_DIR}/current.txt"
# Sha256 pour vérification rapide
shasum -a 256 "${OUT_DIR}/current.txt" | awk '{print $1}' > "${OUT_DIR}/current.txt.sha256"
# Signature ECDSA P-384 via HSM
openssl dgst -sha384 -sign "$HSM_ECDSA_KEY_URI" \
"${OUT_DIR}/current.txt" > "${OUT_DIR}/current.txt.ecdsa.sig"
# Signature Dilithium-3 via liboqs CLI (M6+)
# oqs-sign --algo ml-dsa-65 --key "$HSM_DILITHIUM_KEY_URI" \
# --input "${OUT_DIR}/current.txt" \
# --output "${OUT_DIR}/current.txt.dilithium.sig"
# Bundle hybride v1
# cat \
# <(printf '\x01') \
# <(printf "%04x" "$(wc -c < current.txt.ecdsa.sig)" | xxd -r -p) \
# "${OUT_DIR}/current.txt.ecdsa.sig" \
# "${OUT_DIR}/current.txt.dilithium.sig" \
# > "${OUT_DIR}/current.txt.sig"
echo "[canary] signed for ${now}, next expected ${next}"
echo "[canary] commit + push via Forgejo → miroir GitHub"Template
Placer un template docs/transparency/canary-template.txt avec les placeholders {{DATE}}, {{PREV_DATE}}, {{NEXT_DATE}}.
Vérification côté utilisateur
Un utilisateur peut vérifier le canary :
curl -sf https://<domaine>/canary/current.txt > canary.txt
curl -sf https://<domaine>/canary/current.txt.sig > canary.sig
curl -sf https://<domaine>/canary/public-key.hybrid > pk.hybrid
# Verification hybrid (outil `ombrys-verify-canary` fourni, voir cli/)
ombrys-verify-canary --key pk.hybrid --msg canary.txt --sig canary.sig
# → "OK" si les deux signatures (ECDSA + Dilithium) valident.Surveillance automatisée
Un cron côté infra surveille /canary/current.txt :
- Si le fichier n'est pas mis à jour dans la fenêtre attendue → alerte
Matrix E2EE à #ombrys-core. - Si le sha256 ne correspond plus à une signature valide → alerte. - Dashboard Grafana interne (WireGuard only) affiche l'historique.
Changelog
- 2026-04-24 : procédure initiale. Première signature attendue au go-live M7.