Panneau lateral masquable et redimensionnable, plus de types de cles
Le panneau des sessions etait declare Movable|Floatable mais pas Closable : il n'avait donc aucun bouton de fermeture et ne pouvait pas etre masque. Sa largeur plancher etait par ailleurs imposee par son contenu, ce qui empechait de le retrecir vraiment. - ajout de DockWidgetClosable, largeur minimale ramenee a 120 px - bascule par F9, par le menu Affichage, ou par la croix du panneau, les trois restant synchronises - separateur elargi a 6 px et surligne au survol, pour etre attrape facilement Generation de cles : ajout d'ECDSA sur les courbes NIST P-256, P-384 et P-521, en plus d'Ed25519 et RSA. Ed25519 reste le choix par defaut : c'est aussi une courbe elliptique (Curve25519), plus courte et plus rapide, et sans les interrogations qui entourent le choix des parametres des courbes NIST. Chaque type est verifie relisible par paramiko, donc utilisable pour se connecter. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
58
tests/test_keys.py
Normal file
58
tests/test_keys.py
Normal file
@@ -0,0 +1,58 @@
|
||||
"""Generation de cles SSH : tous les types proposes doivent produire une cle
|
||||
relisible par paramiko, donc utilisable pour se connecter."""
|
||||
import sys, pathlib
|
||||
sys.path.insert(0, str(pathlib.Path(__file__).resolve().parent.parent))
|
||||
|
||||
import tempfile
|
||||
from pathlib import Path
|
||||
|
||||
import paramiko
|
||||
|
||||
from app.key_manager import (
|
||||
KeyManager, KEY_TYPE_LABELS, KEY_TYPE_RSA, KEY_TYPE_ED25519, ECDSA_CURVES,
|
||||
)
|
||||
|
||||
tmp = Path(tempfile.mkdtemp())
|
||||
km = KeyManager(registry_path=tmp / "keys.json")
|
||||
|
||||
LOADERS = (paramiko.Ed25519Key, paramiko.ECDSAKey, paramiko.RSAKey)
|
||||
|
||||
|
||||
def recharge(chemin: str, mot_de_passe=None):
|
||||
for loader in LOADERS:
|
||||
try:
|
||||
return loader.from_private_key_file(chemin, password=mot_de_passe)
|
||||
except paramiko.SSHException:
|
||||
continue
|
||||
return None
|
||||
|
||||
|
||||
print(f"{'type':<12} {'libelle':<32} {'algorithme relu':<22} bits")
|
||||
print("-" * 78)
|
||||
for key_type, label in KEY_TYPE_LABELS.items():
|
||||
bits = 2048 if key_type == KEY_TYPE_RSA else 4096
|
||||
entry = km.generate_key(f"test_{key_type}", key_type, rsa_bits=bits, save_dir=tmp)
|
||||
pkey = recharge(entry.private_path)
|
||||
assert pkey is not None, f"{key_type} : cle illisible par paramiko"
|
||||
assert entry.public_key_text.startswith(pkey.get_name()), (entry.public_key_text[:30], pkey.get_name())
|
||||
assert entry.fingerprint.startswith("SHA256:"), entry.fingerprint
|
||||
print(f"{key_type:<12} {label:<32} {pkey.get_name():<22} {pkey.get_bits()}")
|
||||
|
||||
print()
|
||||
print("=== les courbes NIST sont bien distinctes ===")
|
||||
noms = {}
|
||||
for key_type in ECDSA_CURVES:
|
||||
entry = next(k for k in km.keys if k.key_type == key_type)
|
||||
noms[key_type] = recharge(entry.private_path).get_name()
|
||||
print(f" {key_type:<12} -> {noms[key_type]}")
|
||||
assert len(set(noms.values())) == 3, noms
|
||||
|
||||
print()
|
||||
print("=== cle protegee par une passphrase ===")
|
||||
entry = km.generate_key("test_avec_passphrase", KEY_TYPE_ED25519, passphrase="secret", save_dir=tmp)
|
||||
assert recharge(entry.private_path) is None, "sans la passphrase, la cle ne doit pas se charger"
|
||||
assert recharge(entry.private_path, "secret") is not None, "avec la passphrase, elle doit se charger"
|
||||
print(" chargement refuse sans passphrase, accepte avec : OK")
|
||||
|
||||
print()
|
||||
print("GENERATION DE CLES : OK")
|
||||
Reference in New Issue
Block a user