Contexte et limitation initiale

La bibliothèque swift-nio-ssh implémente le protocole SSH en Swift mais, depuis la version 0.15.0, elle ne propose que les algorithmes modernes ed25519 et les courbes ecdsa. Cette décision, explicitée par les mainteneurs, repose sur la préférence pour les primitives récentes et sur la dépréciation de ssh-rsa avec SHA‑1 depuis OpenSSH 8.8 (2021). Cependant, les instances Amazon EC2 continuent de délivrer des paires de clés PKCS#1 RSA .pem créées avant 2021, ce qui empêche les outils qui s’appuient sur ~/.ssh/ d’établir une connexion.

Architecture du module et contraintes d’extension

Le type NIOSSHPrivateKey encapsule la clé dans un enum BackingKey interne :

extension NIOSSHPrivateKey {
    internal enum BackingKey {
        case ed25519(Curve25519.Signing.PrivateKey)
        case ecdsaP256(P256.Signing.PrivateKey)
        // ...
    }
}

Les propriétés backingKey et son initialiseur sont respectivement internal et private. Aucun protocole public n’est prévu pour ajouter un nouveau cas, ce qui oblige à modifier le code source du module et donc à créer un fork.

Implémentation du support RSA

Le fork introduit huit fichiers : le manifeste Package.swift qui importe _RSA.Signing depuis CryptoExtras, cinq sources sous Sources/NIOSSH/ et un test adapté. Le point critique réside dans la différence entre le blob de clé et le nom d’algorithme transmis dans la requête publickey. Pour ed25519 et les courbes ecdsa, les deux chaînes sont identiques, mais pour RSA le blob porte le tag ssh-rsa tandis que le champ algorithm name doit indiquer rsa-sha2-256 ou rsa-sha2-512 (RFC 8332). Le fork ajoute la propriété suivante :

internal var signatureAlgorithmName: String.UTF8View {
    switch self.backingKey {
    case .rsa:
        return Self.rsaSHA512SignatureAlgorithm
    case .ed25519, .ecdsaP256, .ecdsaP384, .ecdsaP521, .certified:
        return self.keyPrefix
    }
}

Cette valeur est écrite à deux endroits : dans SSHMessages.swift (message sur le fil) et dans UserAuthSignablePayload.swift (buffer signé). Si les deux écritures divergent, le serveur reçoit un paquet syntaxiquement correct mais rejette la clé sans indication précise, rendant le diagnostic difficile. Le fork introduit un test qui compare les deux buffers byte à byte, garantissant leur cohérence.

Choix de l’algorithme et maintenance du fork

Le fork propose systématiquement rsa-sha2-512 sans négociation, car swift-nio-ssh ne parse pas le message SSH_MSG_EXT_INFO contenant la liste server-sig-algs. Cette option est compatible avec toutes les versions d’OpenSSH post‑7.2 (2016), couvrant ainsi la majorité des serveurs ciblés par des visualiseurs de logs. Le code est annoté avec le préfixe LOGRAKER FORK, ce qui permet de repérer rapidement les modifications lors d’un rebase sur la branche upstream. Un test de sérialisation compare le blob public généré avec la sortie de ssh-keygen -y, assurant la conformité au format SSH officiel.

Le principal risque réside dans la perte de mises à jour de sécurité : un paquet SwiftPM local ne signale pas les correctifs upstream. L’auteur recommande d’interroger régulièrement les advisory GitHub d’Apple :

gh api repos/apple/swift-nio-ssh/security-advisories \
  --jq '.[] | "\(.severity) \(.ghsa_id) \(.summary)"'

En conclusion, le fork répond à un besoin opérationnel concret – l’accès à des machines dont les clés sont RSA – mais introduit une dette de maintenance. Si la bibliothèque ajoute nativement RSA, le fork pourra être retiré sans impact.