docs: transfert de secret sans exposition (RSA-OAEP)
This commit is contained in:
@@ -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**.
|
||||
Reference in New Issue
Block a user