2017-06-26 10 views
1

Ich habe die folgende Methode, die einen verschlüsselten privaten Schlüssel mit Hüpfburg für C# erstellt:Entschlüsseln Passwort geschützt PEM enthält privaten Schlüssel

public string GetPrivateKey(AsymmetricCipherKeyPair keyPair, string password) 
{ 
    var generator = new Pkcs8Generator(keyPair.Private, Pkcs8Generator.PbeSha1_3DES); 
    generator.IterationCount = 4; 
    generator.Password = password.ToCharArray(); 
    var pem = generator.Generate(); 

    TextWriter textWriter = new StringWriter(); 
    PemWriter pemWriter = new PemWriter(textWriter); 
    pemWriter.WriteObject(pem); 
    pemWriter.Writer.Flush(); 
    string privateKey = textWriter.ToString(); 
    return privateKey; 
} 

die wie folgt aussieht:

-----BEGIN ENCRYPTED PRIVATE KEY----- 
... 
-----END ENCRYPTED PRIVATE KEY----- 

Was ich don‘ Ich weiß, wie man das Passwort verwendet, das zum Verschlüsseln des privaten Schlüssels in meiner Decrypt-Methode verwendet wird. Gerade jetzt, ohne zu wissen, wie man „entschlüsseln“ meine privaten Schlüssel er password, ich die folgende Ausnahme erhalten:

Org.BouncyCastle.OpenSsl.PemException: Problem VERSCHLüSSELT Erzeugen der private Schlüssel: System.NullReferenceException: Objektverweis nicht auf eine Instanz eines Objekts festgelegt. bei Org.BouncyCastle.OpenSsl.PemReader.ReadPrivateKey (PemObject pemObject)

Hier ist der Code für die Methode Decrypt:

public string Decrypt(string base64Input, string privateKey, string password) 
{ 
    var bytesToDecrypt = Convert.FromBase64String(base64Input); 

    //get a stream from the string 
    AsymmetricCipherKeyPair keyPair; 
    var decryptEngine = new Pkcs1Encoding(new RsaEngine()); 

    using (var txtreader = new StringReader(privateKey)) 
    { 
     var obj = new PemReader(txtreader).ReadObject(); 
     keyPair = (AsymmetricCipherKeyPair) obj; 

     decryptEngine.Init(false, keyPair.Private); 
    } 

    var decrypted = Encoding.UTF8.GetString(decryptEngine.ProcessBlock(bytesToDecrypt, 0, bytesToDecrypt.Length)); 
    return decrypted; 
} 
+0

Ich habe einige Tags hinzugefügt und den Titel geändert (etwas präziser, indem ich die Laufzeiteigenschaften in den Fragetext verschoben habe). Ich habe keine BC-Implementierung online gefunden, also hoffe ich, dass dies etwas Aufmerksamkeit erregt - rechtzeitig :) –

Antwort

1

Es scheint mir, dass Sie das privat entschlüsseln, müssen Schlüssel, um es zu benutzen. Momentan wird Ihr Passwort-Parameter nicht verwendet. Leider ist es nicht so einfach herauszufinden, wie das geht.


Hüpfburg, wie viele anderer Java-API, verwenden Sie einen Passwort-Handler, das Kennwort abzuzurufen. Der Grund dafür ist, dass das Programm den Benutzer nur dann nach dem Passwort fragt, wenn es erforderlich ist. Dies ermöglicht dem Programm, das Passwort für die kürzeste Zeit im Speicher zu belassen.

So für die Entschlüsselung zu ermöglichen, verwenden Sie den folgenden Konstruktor:

PemReader(TextReader reader, IPasswordFinder pFinder); 

mit einer Implementierung von IPasswordFinder (Hüpfburg für C# ist in erster Linie ein Java-Port, sonst ein Delegierter wahrscheinlich verwendet worden wäre).


Für Ihre Bequemlichkeit, der Code. Dieser Code rekonstruiert auch das gesamte Schlüsselpaar, nicht nur den privaten Schlüssel.

Aussagen Import:

using Org.BouncyCastle.Crypto; 
using Org.BouncyCastle.Crypto.Generators; 
using Org.BouncyCastle.Crypto.Parameters; 
using Org.BouncyCastle.Crypto.Prng; 
using Org.BouncyCastle.OpenSsl; 
using Org.BouncyCastle.Security; 
using System.IO; 

der Decoder:

private static AsymmetricCipherKeyPair DecodePrivateKey(string encryptedPrivateKey, string password) 
{ 
    TextReader textReader = new StringReader(encryptedPrivateKey); 
    PemReader pemReader = new PemReader(textReader, new PasswordFinder(password)); 
    object privateKeyObject = pemReader.ReadObject(); 
    RsaPrivateCrtKeyParameters rsaPrivatekey = (RsaPrivateCrtKeyParameters)privateKeyObject; 
    RsaKeyParameters rsaPublicKey = new RsaKeyParameters(false, rsaPrivatekey.Modulus, rsaPrivatekey.PublicExponent); 
    AsymmetricCipherKeyPair kp = new AsymmetricCipherKeyPair(rsaPublicKey, rsaPrivatekey); 
    return kp; 
} 

erforderlich Hilfsklasse:

private class PasswordFinder : IPasswordFinder 
{ 
    private string password; 

    public PasswordFinder(string password) 
    { 
     this.password = password; 
    } 


    public char[] GetPassword() 
    { 
     return password.ToCharArray(); 
    } 
} 

Hinweis, die normalerweise sollten Sie nur char[] statt 01 verwendenfür Passwörter wie char[] kann nach Gebrauch gelöscht werden, während string nicht kann.

Jetzt haben Sie die private Schlüssel Entschlüsselung sollte einfach sein.

+0

Einige weitere Tests (zum Beispiel vor dem Umwandeln des Objekts in 'RsaPrivateCrtKeyParameters' würden natürlich auch nicht schaden. –

Verwandte Themen