docs: transfert de secret sans exposition (RSA-OAEP)

This commit is contained in:
2026-07-18 08:33:20 +00:00
parent f68dc326d9
commit ce1e83b5fe
+67
View File
@@ -0,0 +1,67 @@
# Transferer un secret entre deux machines sans jamais l'exposer
Cas d'usage vecu (18/07/2026) : deplacer `HERMES_PERSO_OPENROUTER_KEY` du NAS (`hermes-platform/.env`)
vers le VPS Contabo (`hermes-nabil/data/.env`), alors que **aucun canal direct NAS -> VPS n'existe**
(SSH NAS->VPS non fonctionnel, Tailscale userspace sur Synology) et que le seul lien commun est
l'agent (Claude), dont le contexte de conversation ne doit **jamais** contenir un secret en clair.
## Principe : chiffrement asymetrique, la cle privee ne bouge pas
Seuls transitent par l'agent la **cle publique** (non sensible) et le **ciphertext** (opaque).
Le secret n'apparait en clair a aucun moment dans la conversation, ni dans un log, ni dans un
historique shell. La cle privee est **detruite immediatement apres usage** (secret de transit jetable).
## Procedure (RSA-3072 + OAEP-SHA256)
### 1. Machine destinataire — generer la paire, publier la cle publique
```bash
umask 077; mkdir -p ~/.transit && cd ~/.transit
openssl genpkey -algorithm RSA -pkeyopt rsa_keygen_bits:3072 -out priv.pem
openssl rsa -in priv.pem -pubout -out pub.pem
chmod 600 priv.pem
cat pub.pem # seule sortie affichee : non sensible
```
### 2. Machine source — extraire sans afficher, chiffrer
```bash
umask 077; mkdir -p /tmp/transit && cd /tmp/transit
cat > pub.pem <<'PEM'
<coller la cle publique>
PEM
grep -m1 "^MA_VARIABLE=" /chemin/.env | cut -d= -f2- | tr -d '"'\''' | tr -d '\r\n' > secret.bin
echo "longueur=$(wc -c < secret.bin)" # controle SANS afficher la valeur
openssl pkeyutl -encrypt -pubin -inkey pub.pem \
-pkeyopt rsa_padding_mode:oaep -pkeyopt rsa_oaep_md:sha256 \
-in secret.bin -out secret.enc
shred -u secret.bin
base64 -w0 secret.enc # ciphertext opaque, transitable
```
### 3. Destinataire — dechiffrer, injecter, tout detruire
```bash
cd ~/.transit
base64 -d secret.b64 > secret.enc
openssl pkeyutl -decrypt -inkey priv.pem \
-pkeyopt rsa_padding_mode:oaep -pkeyopt rsa_oaep_md:sha256 \
-in secret.enc -out secret.bin
echo "longueur=$(wc -c < secret.bin)" # doit egaler celle de la source
ENV=~/projet/data/.env
[ -n "$(tail -c1 $ENV)" ] && echo >> $ENV # garantir un saut de ligne final
grep -v '^MA_VARIABLE=' $ENV > $ENV.tmp && mv $ENV.tmp $ENV # idempotence
{ printf 'MA_VARIABLE='; cat secret.bin; printf '\n'; } >> $ENV
chmod 600 $ENV
shred -u secret.bin secret.enc secret.b64 priv.pem pub.pem; rmdir ~/.transit
```
Puis cote source : `rm -rf /tmp/transit`.
## Regles
- **Jamais** `echo $SECRET`, `cat .env`, ni un `grep` qui imprime la valeur. Controler par
**longueur** (`wc -c`) et **prefixe booleen** (`head -c 6 f | grep -q '^sk-or-' && echo oui`).
- Piege : `${#VAR}` sur le *nom* de variable renvoie la longueur du **nom**. Indirection obligatoire :
`eval v=\${VAR}; echo ${#v}`.
- RSA-3072 + OAEP-SHA256 : charge utile max ~318 octets — largement suffisant pour une cle API.
Au-dela (fichier, keystore) : chiffrer le fichier en AES puis chiffrer la cle AES en RSA.
- Cle privee **jetable et detruite** apres l'operation : meme si le ciphertext reste dans un
historique, il devient indechiffrable (forward secrecy artisanale).
- Ne dispense pas de la regle generale : un secret reellement expose en clair = **rotation immediate**.