Get the Apple Keychain to find out Bouncy Castle.NET, created by PKCS12 (.p12)

Our organization manages stable iOS applications for several clients, which means working with a large number of different developer identity certificates and issuing notification certificates.

I have had success with the Bouncy Castle C # Crypto API in simplifying the management of certificates and private keys for push notifications , essentially eliminating the need for Keychain for all of our push notification certificates .

I would like to extend this to developer ID certificates. The goal would be to store all the private key and certificate data in a database for each developer identifier. Then, when you need to prepare a new developer or build machine, server-side code can wrap all the certificates and private keys in one p12 archive with one password that can be imported into the target Mac keychain.

Unfortunately, Mac Keychain does not like the p12 files that I generate. This is annoying since I can successfully import these files in Windows Certificate Manager.

The code I use (important parts) is as follows:

private byte[] GetP12Bytes(List<DevIdentity> identities, string password)
{
    Pkcs12Store store = new Pkcs12Store();

    foreach(DevIdentity ident in identities)
    {
        // Easiest to create a Bouncy Castle cert by converting from .NET
        var dotNetCert = new X509Certificate2(ident.CertificateBytes);
        // This method (not shown) parses the CN= attribute out of the cert distinguished name
        string friendlyName = GetFriendlyName(dotNetCert.Subject); 

        // Now reconstitute the private key from saved value strings
        BigInteger modulus = new BigInteger(ident.PrivateKey.Modulus);
        BigInteger publicExponent = new BigInteger(ident.PrivateKey.PublicExponent);
        BigInteger privateExponent = new BigInteger(ident.PrivateKey.Exponent);
        BigInteger p = new BigInteger(ident.PrivateKey.P);
        BigInteger q = new BigInteger(ident.PrivateKey.Q);
        BigInteger dP = new BigInteger(ident.PrivateKey.DP);
        BigInteger dQ = new BigInteger(ident.PrivateKey.DQ);
        BigInteger qInv = new BigInteger(ident.PrivateKey.QInv);
        RsaKeyParameters kp = new RsaPrivateCrtKeyParameters(modulus, publicExponent, privateExponent, p, q, dP, dQ, qInv);
        AsymmetricKeyEntry privateKey = new AsymmetricKeyEntry(kp);

        // Now let convert to a Bouncy Castle cert and wrap it for packaging
        Org.BouncyCastle.X509.X509Certificate cert = DotNetUtilities.FromX509Certificate(dotNetCert);
        X509CertificateEntry certEntry = new X509CertificateEntry(cert);

        // Set the private key and certificate into the store
        store.SetCertificateEntry(friendlyName, certEntry);
        store.SetKeyEntry(ident.PrivateKeyName, privateKey, new X509CertificateEntry[] { certEntry });
    }

    using (MemoryStream ms = new MemoryStream())
    {
        store.Save(ms, password.ToCharArray(), new SecureRandom());
        ms.Flush();
        byte[] p12Bytes = ms.ToArray();
        return p12Bytes;
    }
}

As I said, this works great for importing to Windows, but with a very common error when importing to Mac, Keychain does not work.

, Keychain p12 p12, , .

Mac Keychain, p12 Bouncy Castle PKCS12Store, , Keychain p12, , "1.2.840.113549.1.9.21", (DerOctetString # af8a1d6891efeb32756c12b7bdd96b5ec673e11e).

p12, "1.2.840.113549.1.9.21", .

Google "1.2.840.113549.1.9.21" , , OID PKCS_12_LOCAL_KEY_ID. , Keychain , , , .

Hashtable, CertificateEntry, hashtable. , , , .

, . , ​​API Bouncy Castle? , - . , Keychain p12. , , , .

+3
1

BouncyCastle Pkcs12Store , Friendly Name Local Key ID (, , 1.7, 2011 ). , , , , .

iPhone Pkcs12Store ( ):

var store = new Pkcs12Store();

// pairs is IEnumerable<Tuple<X509Certificate, AsymmetricKeyParameter>>
foreach (var pair in pairs)
{
    var cn = pair.Item1.SubjectDN
         .GetValueList(X509Name.CN).OfType<string>().Single();

    var certEntry = new X509CertificateEntry(pair.Item1);
    store.SetCertificateEntry(cn, certEntry);

    var keyEntry = new AsymmetricKeyEntry(pair.Item2);
    store.SetKeyEntry("Developer Name", keyEntry, new[] { certEntry });
}

store.Save(stream, string.Empty.ToArray(), new SecureRandom());

Keychain Access.app OS X 10.7 , , , . /p >

, , Pkcs12Store LocalKeyId, .

Pkcs12Store .

+1

Source: https://habr.com/ru/post/1791002/


All Articles