2017-05-01 11 views
0

Ich habe einen exportierten RSAParameters privaten Schlüssel, den ich in einen anderen Computer importieren möchte. Ich kann neue Schlüssel in den lokalen Computer oder Benutzer-Container speichern, aber ich stecke fest, einen bestehenden Schlüssel zu importieren.RSA CngKey importieren und in MicrosoftSoftwareKeyStorageProvider speichern

Der folgende Code generiert ein neues Schlüsselpaar, und ich weiß, ich könnte nur einen neuen Schlüssel direkt in den Container generieren - aber ich möchte in der Lage sein, einen einzelnen Schlüssel zu generieren und den gleichen Schlüssel in eine Handvoll anderer zu importieren Computers.

Wie kann ich entweder einen RSAParameters oder eine XML-Zeichenkette (entweder eins) nehmen und diese in einen lokalen Benutzer- (oder Maschinen-) Container importieren?

public async Task<KeyGenerationResult> GenerateNewKeyAsync(int keySize) 
    { 
     var csp = new RSACng(keySize); 

     var privKey = await Task.Run(() => csp.ExportParameters(includePrivateParameters: true)); 
     var pubKey = csp.ExportParameters(includePrivateParameters: false); 

     var pubKeyString = exportKeyToString(pubKey); 
     var privKeyString = exportKeyToString(privKey); 

     return new KeyGenerationResult 
     { 
      PrivateKey = privKey, 
      PublicKey = pubKey, 
      PrivateKeyCleartext = privKeyString, 
      PublicKeyCleartext = pubKeyString 
     }; 
    } 

    private static string exportKeyToString(RSAParameters key) 
    { 
     string keyString; 
     var sw = new StringWriter(); 
     var xs = new XmlSerializer(typeof(RSAParameters)); 
     xs.Serialize(sw, key); 
     keyString = sw.ToString(); 
     return keyString; 
    } 

    public void SavePrivateKeyToLocalMachine(RSAParameters privateKey, string keyName) 
    { 
     //Stuck here. :(
    } 

CngKey.Import() nimmt ein byte [] und das sieht vielversprechend aus, aber ich habe nicht in der Lage gewesen, eine Methode zu erstellen die byte [], dass CngKey.Import() erfordert zu finden.

 var d = new RSACryptoServiceProvider(); 
     d.ImportParameters(privateKey); 
     var keyBlob = d.ExportCspBlob(true); 
     var key = CngKey.Import(keyBlob, CngKeyBlobFormat.Pkcs8PrivateBlob); 

Das hat mir ein Byte wird [], aber unabhängig davon, was CngKeyBlobFormat ich verwende, erhalte ich eine Ausnahme. Ich stecke fest.

UPDATE

fand ich einen Weg, um ein byte [] mit

var cp = new CngKeyCreationParameters(); 
cp.KeyUsage = CngKeyUsages.AllUsages; 
cp.ExportPolicy = CngExportPolicies.AllowPlaintextExport | CngExportPolicies.AllowExport | CngExportPolicies.AllowArchiving | CngExportPolicies.AllowPlaintextArchiving; 
cp.Parameters.Add(new CngProperty("Length", BitConverter.GetBytes(keySize), CngPropertyOptions.None)); 
var key = CngKey.Create(CngAlgorithm.Rsa, null, cp); 
var bytes = key.Export(CngKeyBlobFormat.{I have tried them all}); 

Und dieser Code sieht zu bekommen, wie es sollte mir das Byte lassen importieren []

/* try to save this key to the local user container */ 
var keyParameters = new CngKeyCreationParameters() 
{ 
    KeyCreationOptions = CngKeyCreationOptions.OverwriteExistingKey, 
    Provider = CngProvider.MicrosoftSoftwareKeyStorageProvider, 
    KeyUsage = CngKeyUsages.AllUsages, 
    ExportPolicy = CngExportPolicies.AllowPlaintextExport 
}; 
keyParameters.KeyCreationOptions = CngKeyCreationOptions.None; 
keyParameters.Parameters.Add(new CngProperty("Length", BitConverter.GetBytes(keySize), CngPropertyOptions.None)); 
keyParameters.Parameters.Add(new CngProperty(blobType.Format, bytes, CngPropertyOptions.None)); 

var newKey = CngKey.Create(CngAlgorithm.Rsa, "MyTestName", keyParameters); 

... aber noch einmal, keine Würfel. Es ist egal, was CngKeyBlobFormat ich versuche, sie alle geben mir Ausnahmen und ich kann den Schlüssel nicht in einen lokalen Schlüsselspeicheranbieter importieren.

Welchen magischen Mix aus Einstellungen und Parametern benötige ich, damit dies funktioniert?

+0

Welche Ausnahmen erhielten Sie genau? Dies würde nicht nur den Menschen helfen, sondern auch Ihre Frage (und vor allem Ihre Lösung!) Für Menschen, die sich mit dem gleichen Problem konfrontiert sehen, besser erkennen lassen. –

Antwort

1

Nun, ich habe es endlich funktioniert. Hier ist der Code, wie er sich schließlich beruhigt hat.

public class KeyGenerationResult 
{ 
    public RSAParameters PublicKey { get; set; } 
    public string PublicKeyCleartext { get; set; } 
    public string PrivateKeyCleartext { get; set; } 
    public byte[] PrivateBytes { get; set; } 
    public int KeySize { get; set; } 
    public CngKeyBlobFormat BlobFormat { get; set; } 
} 

    public async Task<KeyGenerationResult> GenerateNewKeyAsync(int keySize) 
    { 
     var cp = new CngKeyCreationParameters(); 
     cp.KeyUsage = CngKeyUsages.AllUsages; 
     cp.ExportPolicy = CngExportPolicies.AllowPlaintextExport | CngExportPolicies.AllowExport | CngExportPolicies.AllowArchiving | CngExportPolicies.AllowPlaintextArchiving; 
     cp.Parameters.Add(new CngProperty("Length", BitConverter.GetBytes(keySize), CngPropertyOptions.None)); 
     var key = await Task.Run(() => CngKey.Create(CngAlgorithm.Rsa, null, cp)).ConfigureAwait(false); 
     var blobType = CngKeyBlobFormat.GenericPrivateBlob; 
     var bytes = await Task.Run(() => key.Export(blobType)).ConfigureAwait(false); 

     var rsa = new RSACng(key); 
     var pubKey = rsa.ExportParameters(includePrivateParameters: false); 
     var pubKeyString = exportKeyToString(pubKey); 

     return new KeyGenerationResult 
     { 
      PublicKey = pubKey, 
      PrivateKeyCleartext = Convert.ToBase64String(bytes), 
      PublicKeyCleartext = pubKeyString, 
      PrivateBytes = bytes, 
      BlobFormat = blobType, 
      KeySize = keySize 
     }; 
    } 

    private static string exportKeyToString(RSAParameters key) 
    { 
     string keyString; 
     var sw = new StringWriter(); 
     var xs = new XmlSerializer(typeof(RSAParameters)); 
     xs.Serialize(sw, key); 
     keyString = sw.ToString(); 
     return keyString; 
    } 

    public void SavePrivateKeyToLocalMachine(KeyGenerationResult keyData, string keyName) 
    { 
     var myKSP = CngProvider.MicrosoftSoftwareKeyStorageProvider; 
     const bool MachineKey = false; 

     if (!CngKey.Exists(keyName, myKSP)) 
     { 
      var keyParams = new CngKeyCreationParameters 
      { 
       ExportPolicy = CngExportPolicies.AllowPlaintextExport, 
       KeyCreationOptions = (MachineKey) ? CngKeyCreationOptions.MachineKey : CngKeyCreationOptions.None, 
       Provider = myKSP 
      }; 
      keyParams.Parameters.Add(new CngProperty("Length", BitConverter.GetBytes(keyData.KeySize), CngPropertyOptions.None)); 
      keyParams.Parameters.Add(new CngProperty(keyData.BlobFormat.Format, keyData.PrivateBytes, CngPropertyOptions.None)); 

      CngKey.Create(CngAlgorithm.Rsa, keyName, keyParams); 
     } 
     else 
     { 
      throw new CryptographicException($"The key with the name '{keyName}' already exists!"); 
     } 
    } 
+0

Als Referenz, ich glaube, das war die Inspiration für diese Antwort: https://social.msdn.microsoft.com/Forums/vstudio/en-US/467485eb-1249-406e-86c8-289eb42bd51b/net-cng-full- backup-recovery-von-rsa-keypair-cngkeyimport-cngkeyblobformat-? forum = netfxbcl –

Verwandte Themen