2010-06-29 9 views
6

ich in einem Versuch, den folgenden Code bin mit dem Network programmatisch erlaubt Konto Zugriff auf einen Schlüssel haben:Versuch zum Festlegen von Berechtigungen auf einem KeyContainer in C# ist keine Wirkung

var RSA = new RSACryptoServiceProvider(
    new CspParameters() { 
    KeyContainerName = "MyEncryptionKey", 
    Flags = CspProviderFlags.UseExistingKey | CspProviderFlags.UseMachineKeyStore 
}); 

RSA.CspKeyContainerInfo.CryptoKeySecurity.AddAccessRule(
    new System.Security.AccessControl.CryptoKeyAccessRule(
    new SecurityIdentifier(WellKnownSidType.NetworkServiceSid, null), 
    CryptoKeyRights.GenericAll, 
    AccessControlType.Allow 
) 
); 

Dieser Code läuft ohne Fehler, hat aber keine Auswirkungen auf die Berechtigungen des Schlüsselcontainers.

jedoch das Kommandozeilen-Tool mit aspnet_regiis das Gleiche zu tun, funktioniert perfekt:

aspnet_regiis -pa "MyEncryptionKey" "NetworkService" 

Ich bin mit voller Admin-Rechten ausgeführt wird - wenn ich mit diesen Rechten nicht laufen, dann ist eine Ausnahme geworfen. Ich laufe auch als der Benutzer, der anfänglich den Schlüssel erstellt hat.

Der Schlüsselcontainer hat immer folgende Zugriffsregeln:

S-1-5-18   -> LocalSystem 
S-1-5-32-544  -> Administrators 
S-1-5-5-0-135377 -> MyUser 

Mit aspnet_regiis, die SID, S-1-5-20 zu dieser Liste hinzugefügt wird. Ich kann es nicht vom Code beeinflussen.

Ich habe versucht, die Sicherheits-ID aus der Sid im String-Format, sowie mit SetAccessRule anstelle von AddAccessRule.

Irgendwelche Ideen, wie diese ACL-Liste tatsächlich von Code betroffen ist?

Antwort

10

Sie scheinen nicht zu telefonieren. Die Änderungen, die Sie an CryptoKeySecurity vornehmen, werden nicht sofort gespeichert. Sie müssen eine der Methoden Persist(...) verwenden, um die Änderungen tatsächlich zu speichern.

NativeObjectSecurity.Persist Method (String, AccessControlSections)

Es scheint, dass diese API einen eher gewundenen Ansatz folgen der Modifikation. Sie müssen zuerst einen CspParameters erstellen, die erforderlichen Änderungen anwenden und anschließend den Provider anhand dieser Parameter erstellen. Construction ruft ein Update für den Container auf.

var params = new CspParameters 
{ 
    KeyContainerName = "MyEncryptionKey", 
    Flags = CspProviderFlags.UseExistingKey | CspProviderFlags.UseMachineKeyStore  
}; 

params.CryptoKeySecurity.AddAccessRule(
    new System.Security.AccessControl.CryptoKeyAccessRule(
    new SecurityIdentifier(WellKnownSidType.NetworkServiceSid, null), 
    CryptoKeyRights.GenericAll, 
    AccessControlType.Allow 
) 
); 

var RSA = new RSACryptoServiceProvider(params); 
+0

Leider sind alle Persist-Methoden geschützt. –

+0

Offenbar müssen Sie die Sicherheit vor dem Erstellen des Providers mithilfe von CspParameters ändern. Wenn die CspParameters an den RSACryptoServiceProvider übergeben werden, rufen sie eine Persistenz auf. SEHR seltsame Art, eine API zu erstellen, aber laut der Dokumentation scheint es so zu sein, wie es funktioniert. Antwort aktualisiert, um zu reflektieren. – jrista

+4

Das hat mich auf die richtige Spur gebracht. Die CryptoKeySecurity-Eigenschaft, wie oben verwendet, ist null, also Würfe. Sie können eine neue erstellen, aber sie löscht alle Berechtigungen, die bereits vorhanden waren (dies war der erste tatsächliche Effekt, den es hatte, also bin ich jetzt aus meinem Hauptschlüsselspeicher ausgesperrt;). Aber ... wenn Sie den Schlüssel aus dem Keystore erhalten, dann erstellen Sie einen neuen CspParamters, indem Sie die Werte aus der RSA.CspKeyContainerInfo (einschließlich Provider Name & Typ, Containername und CryptoKeySecurity) kopieren, dann können Sie ändern, erstellen Sie einen anderen RSA Schlüsselobjekt mit den cspparameters, und voila, alles fertig. simples ...? –