2016-08-12 2 views
2

Ich versuche, ein Zertifikat mit seinem privaten Schlüssel in ein p12 zu exportieren, ohne es zuerst in einen Zertifikatspeicher importieren zu müssen.Privater Schlüssel zu X509-Zertifikat vor dem Export zu p12 in c hinzufügen #

Der Fluss I zu replizieren versuchen ist wie folgt:

  1. Auf einem Mac eine Zertifikatsignierungsanforderung Schlüsselanhänger mit erstellen.
  2. Verwenden Sie diese Option, um ein Bereitstellungszertifikat für iOS-Apps mit dem Apple-Portal zu erstellen.
  3. Ich lade dann die neue .cer-Datei herunter, die Apple von meinem csr generiert hat.
  4. Normalerweise, was Sie dann tun würden ist Doppelklick auf die. CER und es würde in KeyChain Access importieren und erscheinen mit und als Teil des ursprünglichen privaten Schlüssels, der erstellt wurde.
  5. Sie können dann mit der rechten Maustaste auf den neuen Zertifikatseintrag klicken und als .p12 exportieren.

Ich muss die letzten 2 Schritte in C# replizieren. Ich habe einen .cer von Apple, ich habe die öffentlichen und privaten Schlüssel und ich muss den privaten Schlüssel irgendwie so anwenden, dass, wenn ich es programmatisch als p12 exportiere, es dem entspricht, den ich manuell oben mache.

kann ich die cer importieren wie so:

X509Certificate2 originalCert = new X509Certificate2(@"c:\temp\aps.cer"); 
//then export it like so 
byte[] p12 = originalCert.Export(X509ContentType.Pkcs12, "password"); 

Aber wenn ich es mit dem einen vergleiche ich manuell erstellen aus KeyChain es nicht übereinstimmen, dh:

byte[] p12Bytes = File.ReadAllBytes(@"c:\temp\manual.p12"); 
    string manual = Convert.ToBase64String(p12Bytes); 
    string generated = Convert.ToBase64String(p12); 
    Assert.IsTrue(manual == generated);//this fails 

Es kann von natürlich ein Problem mit meinem Verständnis, wie das alles funktioniert :)

Ich habe versucht, die BouncyCastle-Bibliotheken, dies zu tun, aber der folgende Code tut nichts zur Ausgabe am Ende.

Org.BouncyCastle.X509.X509Certificate cert = Org.BouncyCastle.Security.DotNetUtilities.FromX509Certificate(originalCert); 
X509CertificateEntry[] chain = new X509CertificateEntry[1]; 
X509CertificateEntry entry = new X509CertificateEntry(cert); 
     chain[0] = entry; 

     AsymmetricKeyEntry keyPair; 
     using (StreamReader reader = File.OpenText(@"c:\temp\EXPORTED PRIVATE KEY.p12")) 
     { 
      Pkcs12Store store = new Pkcs12Store(reader.BaseStream, "Password".ToCharArray()); 
      foreach (string n in store.Aliases) 
      { 
       if (store.IsKeyEntry(n)) 
       { 
        AsymmetricKeyEntry key = store.GetKey(n); 

        if (key.Key.IsPrivate) 
        { 
         keyPair = key; 
         pfx.SetKeyEntry("TEST CERT", key, chain); 
         break; 
        } 
       } 
      } 
     } 

Kann jemand bitte mich in die richtige Richtung?

EDIT: Ich habe eine weitere Änderung gemacht, die vielversprechend aussieht, wie die Längen der Schlüssel jetzt fast übereinstimmen. Ich bin Export jetzt die p12 über BouncyCastle wie so:

Es zufällig erzeugten Bytes zu verwenden, scheint die Operation durchzuführen (siehe neuen SecuredRandom()) und ich bin jetzt verwirrt, wie die Entschlüsselung, wenn sie auftritt ist etwas zufällig?

Danke.

+1

ios? Oder macOS? .NET Core oder Mono? Und was hast du getan, um den PFX zu produzieren, der deiner Meinung nach nicht zusammenpasst? (Beachten Sie, dass es im PFX eine zufällige IV gibt, sodass zwei PFX-Generationen mit demselben Inhalt immer noch andere Ergebnisse liefern). – bartonjs

+0

Es ist eine iOS App mit .NET, um den PFX zu generieren. Ich verstehe deinen letzten Punkt bezüglich der Zufälligkeit nicht. Wenn ich den PFX mit .NET erzeuge, wird jedes Mal dieselbe Zeichenfolge zurückgegeben. –

+1

ungerade. Ich habe gerade mit .NET Framework 4.6.2 auf Windows Server 2012 R2 überprüft, und X509Certificate2.Export (X509ContentType.Pkcs12, "") zweimal auf das gleiche Objekt ruft unterschiedliche Ausgabe (gleiche Länge, unterschiedliche Werte), ob es eine öffentliche sein + Privates Paar oder nur öffentliches Paar. – bartonjs

Antwort

1

Zuerst möchte ich bartonjs oben für seine Hilfe bei der Lösung dieses Problems danken. Die unterschiedlichen Längen haben mich dazu gebracht, anders darüber nachzudenken.

Meine Bearbeitung oben löste es. Ich nahm an, dass, indem ich anrief:

pfx.SetKeyEntry("MyKey", key, chain); 

es würde den Schlüssel in die Bescheinigungen in der Kette einstellen.Stattdessen musste ich sie wie so exportieren:

using (MemoryStream stream = new MemoryStream()) 
{ 
    pfx.Save(stream, "Password".ToCharArray(), new SecureRandom());//The SecureRandom must be responsible for the different strings/lengths when re-generated. 
    using (BinaryReader reader = new BinaryReader(stream)) 
    { 
     byte[] p12 = stream.ToArray(); 
     //then I can save this off somewhere - in my case the db. 
    } 
} 

Jetzt habe ich ein p12 mit einem Zertifikat und einen privaten Schlüssel befestigt ist und es funktioniert alles mit Apples Push-Benachrichtigungssystem.

Verwandte Themen