· Marc Morel · Engineering · 8 min de lecture

Trois tortues suffisent peut-être : des clés SSH liées au matériel sur macOS

La sécurité ne se termine jamais sur une racine de confiance inconditionnelle ; elle s'arrête là où la couche suivante cesse d'être rentable. Pour les clés SSH sur un Mac, trois couches suffisent, et l'une d'elles est déjà dans votre portable.

Une carte du monde plate posée sur trois tortues bleues empilées, la plus grande en bas marquée Silicium avec une icône de puce

Des tortues jusqu’en bas

Une vieille histoire raconte une conférence d’astronomie. Alors que l’orateur termine d’expliquer que la Terre tourne autour du Soleil, une vieille dame dans l’assistance objecte poliment : le monde, dit-elle, est une assiette plate posée sur le dos d’une tortue géante. Quand on lui demande sur quoi repose la tortue, elle n’hésite pas. « Ce sont des tortues jusqu’en bas. »

Les ingénieurs sécurité connaissent bien cette réponse. Un secret est protégé par un mot de passe, le mot de passe par un coffre, le coffre par une session, la session par un appareil, et l’appareil par celui qui l’a provisionné. Chaque protection repose sur une autre, et la question « qu’est-ce qui protège ça ? » n’aboutit jamais à une réponse finale et inconditionnelle.

La question utile n’est donc pas de savoir où se trouve la dernière tortue. Il n’y en a pas. C’est de combien de tortues avons-nous besoin avant que la suivante ne vaille plus le coup. Pour les clés SSH sur un Mac, la réponse est trois.

Le problème de la première tortue que la plupart d’entre nous utilisent

La plupart des développeurs s’authentifient encore sur GitHub avec une clé privée stockée dans un fichier : ~/.ssh/id_ed25519, souvent sans passphrase, parfois copiée d’une machine à l’autre, occasionnellement commitée par accident dans un dépôt de dotfiles.

Ce fichier est lisible par tous les processus qui tournent sous votre compte utilisateur. Une dépendance malveillante dans un script de build, une extension d’éditeur compromise ou un outil en ligne de commande vérolé n’a besoin d’aucun exploit pour la voler : il suffit de lire un fichier et de l’envoyer quelque part. Une fois copiée, la clé fonctionne depuis n’importe quelle machine au monde, silencieusement, jusqu’à ce que quelqu’un s’en aperçoive et la révoque. Une passphrase n’aide que tant que la clé est chiffrée au repos. Un agent qui garde la clé déchiffrée toute la journée offre le même matériel à tout ce qui peut parler à son socket.

La faiblesse n’est pas la cryptographie. C’est que le secret est portable. Tout ce qui peut le lire peut devenir vous.

Trois tortues

Une conception saine de l’identité SSH d’un développeur nécessite trois couches, chacune répondant à une question différente.

Tortue un : la clé ne peut pas quitter l’appareil. La clé privée est générée à l’intérieur d’un matériel dédié et n’existe jamais en mémoire principale, sur disque ou dans une sauvegarde. Un malware peut demander au matériel de signer quelque chose, mais il ne peut pas emporter la clé pour l’utiliser ailleurs. Cela transforme un problème de vol en un problème d’usage abusif sur cette machine, ce qui est considérablement plus restreint.

Tortue deux : chaque usage requiert un humain. Chaque signature exige un acte explicite de la personne au clavier : une empreinte digitale, pas une session en cache. Un malware qui demande au matériel de signer déclenche une invite que l’utilisateur n’attendait pas. L’usage silencieux devient un usage visible.

Tortue trois : la partie de confiance peut révoquer. GitHub ne détient que la clé publique. Si le portable est perdu, volé ou mis au rebut, retirer cette clé publique du compte met fin à l’identité immédiatement. La durée de vie de la clé est liée à celle de l’appareil, et le service garde le dernier mot.

Une quatrième tortue est toujours disponible : une chaîne de démarrage durcie, un appareil attesté, un jeton matériel dans un coffre-fort. Chacune ajoute du coût et de la friction, et chacune protège contre un attaquant qui a déjà vaincu les trois premières. Pour la plupart des équipes d’ingénierie, trois couches bien choisies ferment les chemins d’attaque réalistes, et la quatrième est là où l’effort cesse d’être rentable.

La Secure Enclave est la tortue un, et Touch ID la tortue deux

Chaque Mac Apple Silicon, ainsi que les Mac Intel dotés d’une puce T2, contient une Secure Enclave : un coprocesseur isolé avec sa propre mémoire et son propre firmware, conçu pour que les clés générées à l’intérieur ne puissent pas être extraites, même par le système d’exploitation. Touch ID y est relié directement. L’enclave peut exiger une empreinte vérifiée avant d’effectuer une opération avec une clé donnée.

Jusqu’à récemment, utiliser l’enclave pour SSH impliquait des agents tiers comme Secretive, qui reste un choix solide sur les versions plus anciennes de macOS. Depuis macOS Tahoe, le système fournit les briques nativement :

  • sc_auth crée des identités adossées à la Secure Enclave via CryptoTokenKit.
  • /usr/lib/ssh-keychain.dylib implémente l’interface security key provider d’OpenSSH, la même interface qu’OpenSSH utilise pour les jetons FIDO2 comme une YubiKey. Pour OpenSSH, le Mac ressemble simplement à une clé de sécurité matérielle intégrée.

Le type de clé obtenu est sk-ecdsa-sha2-nistp256@openssh.com, que GitHub accepte à la fois pour l’authentification et la signature de commits.

La mise en place pour GitHub

1. Créer l’identité dans la Secure Enclave. Le type de clé p-256-ne signifie que la clé est générée dans l’enclave et n’est pas exportable. -t bio exige Touch ID à chaque usage.

Terminal window
sc_auth create-ctk-identity -l github -k p-256-ne -t bio
sc_auth list-ctk-identities -t ssh # vérifier que l'identité existe

Évitez la variante exportable p-256. Elle chiffre la clé avec l’enclave au lieu de la générer dans l’enclave, ce qui revient à renoncer à la tortue un.

2. Récupérer le handle de la clé pour OpenSSH.

Terminal window
cd ~/.ssh
ssh-keygen -w /usr/lib/ssh-keychain.dylib -K -N ""
mv id_ecdsa_sk_rk id_github_enclave
mv id_ecdsa_sk_rk.pub id_github_enclave.pub

Le fichier « privé » ainsi écrit n’est pas la clé privée. C’est une référence vers la clé détenue par l’enclave, et elle est inutile sur toute autre machine. Conservez-le quand même ; OpenSSH en a besoin pour adresser la clé.

3. Enregistrer la clé publique sur GitHub. Ajoutez id_github_enclave.pub dans Settings → SSH and GPG keys comme clé d’authentification, ou avec la CLI GitHub :

Terminal window
gh ssh-key add ~/.ssh/id_github_enclave.pub --title "MacBook enclave $(date +%Y-%m)"

4. Faire pointer OpenSSH vers l’enclave. Dans ~/.ssh/config :

Host github.com
User git
IdentityFile ~/.ssh/id_github_enclave
IdentitiesOnly yes
SecurityKeyProvider /usr/lib/ssh-keychain.dylib

IdentitiesOnly empêche SSH de proposer toute autre clé qu’il trouverait. SecurityKeyProvider lui indique de demander la signature à l’enclave.

5. Tester.

Terminal window
ssh -T git@github.com

Touch ID devrait vous solliciter, et GitHub devrait vous saluer par votre nom d’utilisateur. À partir de là, chaque git fetch, pull et push en SSH demande votre empreinte.

6. Optionnel : signer les commits avec le même matériel. Exportez le provider pour que tous les outils OpenSSH le trouvent, y compris le ssh-keygen que Git appelle pour signer. Puis configurez Git :

Terminal window
echo 'export SSH_SK_PROVIDER=/usr/lib/ssh-keychain.dylib' >> ~/.zprofile
git config --global gpg.format ssh
git config --global user.signingkey ~/.ssh/id_github_enclave.pub
git config --global commit.gpgsign true

Ajoutez la même clé publique une seconde fois sur GitHub, en tant que clé de signature. Vos commits apparaissent alors comme vérifiés, et chaque signature porte la même garantie que vos connexions : elle a été faite sur ce Mac, par quelqu’un avec ce doigt.

L’exploiter sans regrets

Lier la clé au matériel change quelques habitudes :

  • Prévoir la perte avant qu’elle n’arrive. Une clé qui ne peut pas quitter l’appareil meurt avec lui. Enregistrez une seconde clé liée au matériel : l’enclave d’un autre Mac, ou un jeton FIDO2 rangé en lieu sûr. Révoquez l’ancienne clé le jour où une machine est perdue ou retirée.
  • S’attendre à une invite par signature. Les scripts qui ouvrent de nombreuses connexions SSH solliciteront de nombreuses fois. Regroupez les opérations, ou réutilisez une connexion authentifiée avec ControlMaster auto et un ControlPersist court dans le bloc github.com. Le multiplexage assouplit légèrement la tortue deux : des processus locaux peuvent emprunter la connexion ouverte jusqu’à son expiration, donc gardez une fenêtre courte.
  • Vérifier que l’enclave est vraiment dans la boucle. Dans une machine virtuelle sans enclave, l’outillage peut tout de même créer une identité. Créez les clés sur le Mac physique, et vérifiez que Touch ID sollicite réellement avant de faire confiance à la configuration.
  • Garder les anciennes clés honnêtes. Une fois la clé de l’enclave fonctionnelle, supprimez les clés fichier de GitHub et de ~/.ssh. Une clé forte à côté d’une clé faible n’est pas plus forte que la faible.

Ce qui change

La vieille dame de l’histoire n’avait pas tort : chaque fondation repose sur quelque chose. L’erreur serait d’en conclure qu’on ne peut faire confiance à rien tant que la dernière tortue n’a pas été trouvée. L’ingénierie de sécurité, c’est l’art de choisir où s’arrêter, délibérément, et de savoir pourquoi.

Pour les identités SSH, trois couches font le travail :

  • une clé qui ne peut pas quitter le matériel ;
  • une empreinte pour chaque usage ;
  • un service qui peut révoquer en un clic.

Chacune ferme un chemin que les autres laissent ouvert, et toutes les trois existent déjà sur le portable devant vous.

Partager :
Retour