2016-08-12 145 views
2

我试图以编程方式将证书导出到带有私钥的p12,而不必先将其导入到证书存储区。添加私钥到X509证书,然后导出到p12在c#

我试图复制的流程如下:

  1. 在Mac上创建一个使用钥匙串证书签名请求。
  2. 使用此命令可以使用 Apple门户为iOS应用程序创建配置证书。
  3. 然后,我下载新的.cer文件,Apple从我的csr生成 。
  4. 通常情况下,您要做的是双击.cer,然后 将导入到KeyChain Access中,并与创建的原始私钥一起出现,并与 一同出现。
  5. 然后,您可以右键单击新证书条目并将其作为.p12导出为 。

我需要复制c#中的最后2个步骤。我有一个来自Apple的.cer,我拥有公钥和私钥,并且我需要以这种方式应用私钥,以便当我以编程方式将其导出为p12时,它与我在上面手动执行的操作相匹配。

我可以导入.CER像这样:

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

但是,当我用一个比较一下我手动创建了钥匙链的不匹配,即:

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

有可能的当然是我的理解如何这一切工作的问题:)

我已经尝试使用BouncyCastle库来做到这一点,但下面的代码在最后的输出没有做任何事情。

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; 
        } 
       } 
      } 
     } 

任何人都可以请指点我在正确的方向吗?

编辑:我做了一个更改,看起来很有前途,因为键的长度现在几乎匹配。我现在通过BouncyCastle的导出P12像这样:

看来使用随机生成的字节来执行操作(见新SecuredRandom()),我现在很困惑,如何发生解密,如果它是随机化的?

谢谢。

+1

ios?还是macOS? .NET Core或Mono?你做了什么来生产你认为不匹配的PFX? (请注意,PFX中有一个随机IV,因此在相同内容上生成两个PFX仍会产生不同的结果)。 – bartonjs

+0

这是一个使用.NET生成PFX的iOS应用程序。我不明白你关于随机性的最后一点。当我使用.NET生成PFX时,每次都会返回相同的字符串。 –

+1

单数。我刚刚在Windows Server 2012 R2上使用.NET Framework 4.6.2进行了检查,并且在同一个对象上调用X509Certificate2.Export(X509ContentType.Pkcs12,“”)两次产生不同的输出(相同长度,不同值),无论它是公共+私人配对证书或公共专用证书。 – bartonjs

回答

1

首先我要感谢上面的bartonjs帮助解决这个问题。不同的长度让我以不同的方式思考这个问题。

我上面的编辑解决了它。我假设通过拨打电话:

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

它会将密钥设置到链中的证书中。相反,我不得不将它们导出,像这样:

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. 
    } 
} 

现在我有一个附加证书和私钥的P12,这一切与苹果的推送通知系统的工作原理。

相关问题