
SRO PKCS11 – SSH Agent CNG ist ein souveräner, ultraleichter und abhängigkeitsfreier Windows-Agent, der PKCS#11, SSH-Agent, Pageant und CNG/Smartcard in einer einzigen robusten Binärdatei vereint. Konzipiert für anspruchsvolle Umgebungen, bietet er native Hardware-Kryptographie, Service-/Userland-Isolation und vollständige Smartcard-Unterstützung.
Souveräne Vereinheitlichung PKCS#11 + SSH-Agent + Pageant + CNG/Smartcard
Eine einzige Windows-ausführbare Datei, die vier traditionell getrennte Funktionen vereint:
Souverän. Keine Abhängigkeit von der CRT. Alle Speicheroperationen erfolgen über RtlCopyMemory, RtlZeroMemory, RtlEqualMemory (FreeCRT.h). Unicode überall (natives Win32). Kein malloc, memcpy, strlen, printf.
Sicher. Die privaten Schlüssel werden nie exportiert. Es wird keine PIN übertragen. CNG/KSP verwaltet die native Windows-PIN-Oberfläche. Strenge Isolation von Dienst ↔ Benutzerbereich über gesicherte Pipes.
Minimalistisch. Nur eine Binärdatei. Keine externen DLLs. Keine Registry-Aufblähung. Einfache Installation (regsvr32 oder -install).
Vielseitig. Gleichzeitige Unterstützung von PKCS#11, SSH-Agent, Pageant und WSL2 im selben Prozess.
---``` ┌──────────────────────────────────────────────────────────────┐ │ Clients (Git, VS, WSL, OpenSSH, PuTTY, Firefox) │ └────────────────────────┬─────────────────────────────────────┘ │ ┌───────────────┼───────────────┬─────────────────┐ │ │ │ │ SSH-agent Pageant (WM_COPYDATA) PKCS#11 WSL2 (TCP) │ │ │ │ v v v v ┌──────────────────────────────────────────────────────────────┐ │ Service Stub (session 0, SYSTEM) │ │ - Accepte connexions sur \.\pipe\openssh-ssh-agent │ │ - Crée pipe interne par client (GUID unique) │ │ - Lance helper userland avec token interactif │ │ - Forwarde messages sans manipuler de secrets │ └────────────────────────┬─────────────────────────────────────┘ │ lancé par le service v ┌──────────────────────────────────────────────────────────────┐ │ Helper Userland (session interactive) │ │ - Connecte au pipe interne │ │ - Décode protocole SSH-agent/Pageant │ │ - Invoque CNG/KSP pour signature │ │ - UI PIN native Windows (pas de relay) │ │ - Renvoie signature au service │ │ - Fenêtre Pageant cachée pour WM_COPYDATA │ │ - Listener TCP 127.0.0.1:10022 pour WSL2 │ │ - Tray icon avec menu contextuel │ └────────────────────────┬─────────────────────────────────────┘ │ v ┌──────────────────────────────────────────────────────────────┐ │ CNG/KSP Backend │ │ - NCryptSignHash avec PKCS#1/PSS padding │ │ - Enumération certificats Windows Store │ │ - Filtrage SmartCardOnly / AllowedKSP │ │ - Support RSA + ECDSA (P-256, P-384, P-521) │ │ - Support EdDSA (Ed25519, Ed448) │ │ - Support Brainpool (P256r1, P384r1, P512r1) │ │ - Cache clés + providers (4h timeout) │ └──────────────────────────────────────────────────────────────┘
---
## Ausführungsmodi
### 1. PKCS#11-Modus (automatisch)
Geladen von:
- `ssh -I ssh-agent.exe benutzer@host`
- Firefox (Sicherheitseinstellungen → PKCS#11-Modul laden)
- `pkcs11-tool --module ssh-agent.exe --list-objects`
Stellt die standardmäßigen PKCS#11-Exporte bereit:
- `C_Initialize`, `C_Finalize`, `C_GetInfo`
- `C_GetSlotList`, `C_GetSlotInfo`, `C_GetTokenInfo`
- `C_GetMechanismList`, `C_GetMechanismInfo`
- `C_OpenSession`, `C_CloseSession`, `C_Login`, `C_Logout`
- `C_FindObjectsInit`, `C_FindObjects`, `C_FindObjectsFinal`
- `C_GetAttributeValue`
- `C_SignInit`, `C_Sign`
- `C_VerifyInit`, `C_Verify`
- `C_DecryptInit`, `C_Decrypt`
- `C_GenerateRandom`, `C_SeedRandom`
**Unterstützte Mechanismen (insgesamt 14):**
- `CKM_RSA_PKCS` (roh mit Padding)
- `CKM_RSA_X_509` (roh ohne Padding)
- `CKM_SHA1_RSA_PKCS` (Legacy ssh-rsa)
- `CKM_SHA256_RSA_PKCS` (rsa-sha2-256)
- `CKM_SHA384_RSA_PKCS` (rsa-sha2-384)
- `CKM_SHA512_RSA_PKCS` (rsa-sha2-512)
- `CKM_SHA256_RSA_PKCS_PSS` (RSA-PSS SHA-256)
- `CKM_SHA384_RSA_PKCS_PSS` (RSA-PSS SHA-384)
- `CKM_SHA512_RSA_PKCS_PSS` (RSA-PSS SHA-512)
- `CKM_ECDSA` (roh)
- `CKM_ECDSA_SHA1` (Legacy)
- `CKM_ECDSA_SHA256` (ecdsa-sha2-nistp256/384/521)
- `CKM_ECDSA_SHA384`
- `CKM_ECDSA_SHA512`
### 2. Benutzerland-Agent-Modus (eigenständig)```bash
ssh-agent.exe
\\.\pipe\openssh-ssh-agent in der BenutzersitzungKompatibel mit:
set SSH_AUTH_SOCK=\\.\pipe\openssh-ssh-agent)ssh-agent.exe -install net start SROSSHAgentCNG
### 4. Modus Helper Crypto Userland
- Läuft in Sitzung 0 (SYSTEM)
- Akzeptiert Verbindungen über globalen Pipe
- Erstellt einen internen Pipe pro Client (gesichert durch SID)
- Startet einen Userland-Helper mit `CreateProcessAsUserW`
- Leitet Nachrichten weiter, ohne die Geheimnisse zu berühren
- Helper-Pool mit Timeout 4h (automatische Wiederverwendung)
- LRU-Eviction, wenn Pool voll
**Vorteile:**
- UI-PIN in der Benutzersitzung (nicht in Sitzung 0)
- Kompatibel mit gehärteten Umgebungen
- Strenge Isolation Service ↔ Crypto
- Multi-Benutzer-Multiplexing```bash
ssh-agent.exe -useragent -pipe \\.\pipe\ssh-ksp-helper-{GUID}
Automatisch vom Dienst gestartet:
NCryptSignHash auf (native PIN-Oberfläche)regsvr32 ssh-agent.exe
Erstellt die Schlüssel:
- `HKLM\SOFTWARE\San@sro Inc\PKCS11-SSH-Agent`
- `HKCU\SOFTWARE\San@sro Inc\PKCS11-SSH-Agent`
- `HKCU\SOFTWARE\Mozilla\Firefox\PKCS11Modules\SROSSHAgent`
### Windows-Dienst installieren```bash
ssh-agent.exe -install
net start SROSSHAgentCNG
Hinzufügen zu ~/.bashrc oder ~/.zshrc :```bash
export SSH_AUTH_SOCK="$HOME/.ssh/agent.sock"
if ! pgrep -u $USER socat > /dev/null || [ ! -S "$SSH_AUTH_SOCK" ]; then # Nettoyage préventif rm -f "$SSH_AUTH_SOCK"
# Lancement du bridge en arrière-plan
# Note: Utiliser 127.0.0.1 si mode 'mirrored'
# sinon l'IP du host (ex: 192.168.99.x)
socat UNIX-LISTEN:"$SSH_AUTH_SOCK",fork,unlink-early \
TCP:127.0.0.1:10022 > /dev/null 2>&1 &
fi
### Deinstallieren```bash
regsvr32 /u ssh-agent.exe
ssh-agent.exe -remove
Schlüssel: HKLM\SOFTWARE\San@sro Inc\pkcs11-cng oder HKCU\SOFTWARE\San@sro Inc\pkcs11-cng
Beispiel:``` StoreName = "MY" StoreLocation = "CurrentUser" SmartCardOnly = 1 AllowedKSP = "Microsoft Smart Card Key Storage Provider;YubiKey Smart Card Key Storage Provider" RelaxCheckMode = 0 LogLevel = 2
---
## Unterstützte Protokolle
### SSH-Agent
#### SSH2_AGENTC_REQUEST_IDENTITIES (11)
Anfrage :```
[type=11]
Antwort:``` [type=12][count][key_blob_1][comment_1][key_blob_2][comment_2]...
**key_blob RSA :**```
[len]["ssh-rsa"][len][exponent][len][modulus]
key_blob ECDSA :``` [len]["ecdsa-sha2-nistp256"][len]["nistp256"][len][point]
**key_blob EdDSA :**```
[len]["ssh-ed25519"][len][point]
Anfrage :``` [type=13][len][key_blob][len][data][flags]
**Flags :**
- `0x00` : ssh-rsa (SHA-1, legacy)
- `0x02` : rsa-sha2-256
- `0x04` : rsa-sha2-512
Antwort :```
[type=14][len][signature_blob]
signature_blob :``` [len]["rsa-sha2-256"][len][signature_data]
### Pageant
Kompatibel mit PuTTY via `WM_COPYDATA`:
1. Client erstellt einen gemeinsamen Speicher via `CreateFileMapping`
2. Schreibt die SSH-Agent-Anfrage im Standardformat
3. Sendet `WM_COPYDATA` an das Fenster "Pageant"
4. Liest die Antwort aus dem gemeinsamen Speicher
Format des gemeinsamen Speichers:```
[uint32 length][SSH-agent payload]
TCP Listener auf 127.0.0.1:10022 :
handle_ssh_message()Windows verwaltet das PIN vollständig über CNG/KSP und den Minidriver der Smartcard.
Das Modul speichert niemals die PIN und erhält sie nie zu Gesicht:
PIN-Cache: Wird automatisch von Windows/Minidriver verwaltet (kein Anwendungscache erforderlich).
NCrypt-Flags:
NCRYPT_SILENT_FLAG (keine Benutzeroberfläche)SILENT_FLAG fehlschlägt: Automatischer Wiederholungsversuch mit BenutzeroberflächeSchlüssel-Cache (Timeout 4h):
CNG_KEY_INFO (Handle, Anbieter, Container)Anbieter-Cache (Timeout 4h):
NCRYPT_PROV_HANDLENCryptOpenStorageProvidercng_store_enum_certificates(cfg, callback, user_data);
Filter:
- Verfügbare private Schlüssel
- Autorisierte KSP (wenn `SmartCardOnly`)
- Nicht exportierbare Schlüssel (wenn `SmartCardOnly`)
### Signatur```c
cng_sign_hash(key_info, mechanism, hash, hash_len, signature, &sig_len);
Mécanisme → Padding :
CKM_RSA_PKCS → BCRYPT_PAD_PKCS1CKM_SHA256_RSA_PKCS → BCRYPT_PAD_PKCS1 + BCRYPT_SHA256_ALGORITHMCKM_SHA256_RSA_PKCS_PSS → BCRYPT_PAD_PSS + salt size = hash sizeCKM_ECDSA_SHA256 → Kein Padding (rohe Signatur)RSA :```c cng_cert_get_public_key(cert, modulus, &mod_len, exponent, &exp_len);
**ECDSA :**```c
cng_cert_get_ec_params(cert, params, ¶ms_len); // OID courbe
cng_cert_get_ec_point(cert, point, &point_len); // Point public
Unterstützte Kurven:
nistp256 (OID: 1.2.840.10045.3.1.7), nistp384 (1.3.132.0.34), nistp521 (1.3.132.0.35)brainpoolP256r1, brainpoolP384r1, brainpoolP512r1ed25519 (OID: 1.3.101.112), ed448 (1.3.101.113)Unterstützt Active Directory-Authentifizierung :```c cng_extract_upn_from_certificate(cert, upn, upn_size);
Extrahiert die Erweiterung `szOID_NT_PRINCIPAL_NAME`, um sie als SSH-Kommentar zu verwenden.
---
## Sicherheit
### Private Schlüssel
**Nie exportiert.** Alle kryptografischen Vorgänge werden an CNG/KSP delegiert. `NCryptSignHash` wird mit dem Schlüssel-Handle aufgerufen, niemals mit dem Schlüssel selbst.
### PIN
**Wird ausschließlich von Windows (CNG/KSP/minidriver) verwaltet.**
Das Modul **speichert niemals die PIN** und **sieht sie nie durchlaufen**:
- Die PIN wird niemals an das PKCS#11-Modul übermittelt
- Die PIN-Oberfläche wird vom Minidriver der Smartcard angezeigt
- Der PIN-Cache wird automatisch von Windows/minidriver verwaltet
- Im Servicemodus: Der Userland-Helper (interaktive Sitzung) empfängt die PIN-Oberfläche
**Servicemodus (reiner Passthrough):**
Der Service-Stub macht NUR transparentes Forwarding:
- Client → Service → Helper (SSH-Agent-Nachricht weiterleiten)
- Helper → Service → Client (SSH-Agent-Antwort weiterleiten)
- Der Service parst niemals den Inhalt
- Der Service sieht niemals: PIN, Hash, Signatur, Schlüssel
### Isolation Service ↔ Userland
**Sichere Pipes.** Jede interne Pipe wird:
- Mit einer eindeutigen GUID erstellt
- Mit `FILE_FLAG_FIRST_PIPE_INSTANCE` erstellt
- DACL, die nur den aktuellen Benutzer zulässt
Der Userland-Helper ruft CNG/KSP in der interaktiven Sitzung auf → native PIN-Oberfläche.
### Überwachung (Audit)
**Unicode-Logs.** Alle Ereignisse werden über `utils_log()` protokolliert:
- Client-Verbindungen
- Schlüsselaufzählung
- Signaturanfragen
- CNG/KSP-Fehler
- Agentenkonflikte
**Speicherort:** OutputDebugString + optionale Datei (`utils_set_log_file()`).
---
## Kompatibilität
| Umgebung | Modus | Status |
|------------------------------|------------------------|--------|
| OpenSSH for Windows | Standalone / Service | ✓ |
| Git for Windows | Standalone / Service | ✓ |
| Visual Studio | Standalone / Service | ✓ |
| WSL (npiperelay) | Standalone / Service | ✓ |
| WSL2 (TCP) | Standalone / Service | ✓ |
| PuTTY / plink / pscp | Pageant | ✓ |
| Firefox | PKCS#11 | ✓ |
| OpenSC / pkcs11-tool | PKCS#11 | ✓ |
| ssh -I (OpenSSH) | PKCS#11 | ✓ |
| Gehärtete Umgebungen | Service stub | ✓ |
| SmartCard GIDS | CNG/KSP | ✓ |
| SmartCard PIV | CNG/KSP | ✓ |
| YubiKey | CNG/KSP | ✓ |
| Nitrokey | CNG/KSP | ✓ |
---
## Export öffentlicher Schlüssel
### CLI-Befehl```bash
ssh-agent.exe -exportkey [output.pub]
CryptUIDlgSelectCertificateFromStoreOpenSSH :``` ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQC5... [email protected]
**RFC4716 :**```
---- BEGIN SSH2 PUBLIC KEY ----
Comment: "[email protected]"
AAAAB3NzaC1yc2EAAAADAQABAAABAQC5ABCDEF...
---- END SSH2 PUBLIC KEY ----
Prioritätsreihenfolge für den Kommentar:
TRAY_MODE_USERLAND (grün) :
TRAY_MODE_SERVICE (blau) :
Dynamischer Tooltip :``` SRO SSH-Agent (Userland) 12 keys, 3 clients
Aktualisierung:
- Alle 5 Sekunden
- Bei jeder Client-Verbindung/-Trennung
- Beim Leeren des Caches
### Kontextmenü
**Show Keys...** : Dialog, der alle verfügbaren Schlüssel auflistet```
═══════════════════════════════════════════════
SRO SSH-Agent - Available Keys
═══════════════════════════════════════════════
[01] RSA-2048 - [email protected]
[02] ECDSA-nistp256 - [email protected]
[03] EdDSA-Ed25519 - [email protected]
═══════════════════════════════════════════════
Total: 3 keys
💡 Tip: Use 'Export Public Key' to copy SSH format
Export Public Key... : Öffnet den Auswahldialog und kopiert in die Zwischenablage
Flush & Reload Keys : Leert die Schlüssel-/Provider-Caches und lädt neu
Settings... : Zeigt die aktuelle Konfiguration an``` Current Configuration:
Store Name: MY Store Location: CurrentUser SmartCard Only: Yes Relax Key Usage Check Mode: No Log Level: 2
Edit registry to change: HKLM\SOFTWARE\San@sro Inc\pkcs11-cng
**Exit** : Sauberer Stopp (signalisiert `g_shutdown_event`)
### Dedizierter UI-Thread
- Verstecktes Fenster mit Nachrichtenpumpe
- `GetMessage/DispatchMessage`-Schleife
- Ereignis `g_tray_ready_event` zur Synchronisation
- Automatische Bereinigung (`Shell_NotifyIcon(NIM_DELETE)`)
---
## WSL2-Unterstützung
### Architektur```
┌─────────────────────────────────────────────┐
│ WSL2 (Linux) │
│ - socat UNIX-LISTEN → TCP:127.0.0.1:10022 │
└─────────────────────────────────────────────┘
│
│ TCP
v
┌─────────────────────────────────────────────┐
│ Windows Host │
│ - ssh-agent.exe (listener 127.0.0.1:10022)│
│ - CNG/KSP → Smartcard │
└─────────────────────────────────────────────┘
Sicherheit:
g_wsl2_clients[16]CRITICAL_SECTION pro SlotMirrored-Modus (Windows 11 22H2+):```bash
socat UNIX-LISTEN:"$SSH_AUTH_SOCK",fork,unlink-early
TCP:127.0.0.1:10022 > /dev/null 2>&1 &
**Klassischer NAT-Modus :**```bash
# Récupérer l'IP du host Windows
HOST_IP=$(ip route | grep default | awk '{print $3}')
socat UNIX-LISTEN:"$SSH_AUTH_SOCK",fork,unlink-early \
TCP:$HOST_IP:10022 > /dev/null 2>&1 &
BOOL wsl2_network_start(WORD port, HANDLE shutdown_event); void wsl2_network_stop(void); BOOL wsl2_network_is_running(void); DWORD wsl2_network_get_client_count(void);
## Konflikterkennung
### Erkannte Agenten```c
typedef enum {
AGENT_NONE = 0,
AGENT_OPENSSH_NATIVE, // OpenSSH for Windows (ssh-agent.exe)
AGENT_PAGEANT, // PuTTY Pageant (fenêtre "Pageant")
AGENT_SRO_USERLAND, // SRO SSH-Agent userland
AGENT_SRO_SERVICE, // SRO SSH-Agent service Windows
AGENT_UNKNOWN // Agent inconnu détecté
} AGENT_TYPE;
Natives OpenSSH :
ssh-agent.exe über CreateToolhelp32SnapshotPageant :
FindWindowW(L"Pageant", L"Pageant")SRO Userland :
CreateFileW(\\.\pipe\openssh-ssh-agent)SRO Service :
OpenServiceW(L"SROSSHAgentCNG")SERVICE_RUNNINGWird beim Start angezeigt, wenn ein Konflikt erkannt wird:``` ⚠ SSH Agent Conflict Detected
The following SSH agents are already running: • OpenSSH Native (ssh-agent.exe) • PuTTY Pageant
Running multiple agents may cause conflicts.
Do you want to continue anyway?
[Continue] [Stop conflicting agents] [Exit]
**Actions :**
- **Continue** : Trotzdem starten (Konfliktrisiko)
- **Stop** : Versuche, die Agenten zu stoppen (falls möglich)
- **Exit** : Beenden ohne zu starten
### Öffentliche Funktion```c
BOOL detect_running_agents(AGENT_TYPE* detected_agents, DWORD* count);
BOOL show_agent_conflict_dialog(const AGENT_TYPE* agents, DWORD count);
const WCHAR* agent_type_to_string(AGENT_TYPE agent);
Keine. Die Binärdatei ist eigenständig und lädt nur System-DLLs:
kernel32.dll (immer vorhanden)advapi32.dll (Registry, SCM)crypt32.dll (Zertifikate)ncrypt.dll (CNG)bcrypt.dll (Hashing)wtsapi32.dll (Sitzungen)shell32.dll (Tray-Symbol)ws2_32.dll (Winsock)cryptui.dll (Zertifikatauswahldialog)Kein CRT. Alle Speicheroperationen via RtlCopyMemory, RtlZeroMemory, RtlEqualMemory.
SSH2_AGENTC_*_ENCRYPT).SSH2_AGENTC_ADD_ID_CONSTRAINED.MAX_HELPERS).RelaxCheckMode = 1, um sie zu verwenden.Beiträge sind willkommen! Bitte:
Diese Software ist Eigentum der San@sro inc.
Sie wird nach einem Vertrauenslizenzmodell vertrieben:
• Persönliche & Bildung: Kostenlos und erwünscht.
• Berufliche/kommerzielle Nutzung: Erfordert den Kauf einer Licence de Paix Technique (Technische Friedenslizenz).
Die Nutzung in Unternehmen ohne gültige Lizenz stellt eine Urheberrechtsverletzung dar, trotz des bewussten Fehlens jeglicher technischer Sperren.
Die Weiterverteilung ist unter der Bedingung erlaubt, dass: • die Binärdatei intakt bleibt, • die originale Authenticode-Signatur erhalten bleibt.
Diese Software wird "wie besehen" ohne jegliche Garantie bereitgestellt.
Die vollständige Lizenz (FR + EN) mit Definitionen, Weiterverteilungsbedingungen, Laufzeit, Kündigung und Modalitäten zur Erlangung einer Licence de Paix Technique ist hier verfügbar:
Für alle Anfragen zu Berufslizenzen:
📧 [email protected]
SRO PKCS11 – SSH Agent CNG verarbeitet keinerlei sensible Geheimnisse:
die PIN, privaten Schlüssel und kryptografischen Operationen werden vollständig von Windows (CNG/KSP/Minidriver) verwaltet.
Um einen Fehler, ein anormales Verhalten oder eine potenzielle Schwachstelle zu melden, ist eine Richtlinie zur verantwortungsvollen Offenlegung hier verfügbar:
Sicherheitskontakt:
📧 [email protected]
SRO PKCS11 – SSH Agent CNG
Souverän. Robust. Betriebsbereit.
Eine einzige Binärdatei für alles.
| Wert | Typ | Beschreibung |
|---|
StoreName | REG_SZ | "MY", "Root", usw. (Standard: "MY") |
StoreLocation | REG_SZ | "CurrentUser" oder "LocalMachine" |
Mode | REG_SZ | "All" oder "SmartCard" |
SmartCardOnly | REG_DWORD | 1 = nur Smartcards filtern |
AllowedKSP | REG_SZ | Liste der erlaubten KSP (getrennt durch ";") |
RelaxCheckMode | REG_DWORD | 1 = EKU/KeyUsage/Datumsvalidierung deaktivieren (selbstsigniertes YubiKey PIV) |
LogLevel | REG_DWORD | 0=aus, 1=Fehler, 2=Info, 3=Debug |