[FIXED] SSL Cert issued by Windows CA, exported by OpenSSL works on Windows but not Android

Issue

I’m setting up a pipeline for an android device to request a certificate like so:

var subjectName = $"CN={GetFQDN()},O=My Org,OU=Test,T=Test,ST=OK,C=US";

            // Create new Object for Issuer and Subject
            var subject = new X509Name(subjectName);

            // Generate the key Value Pair, which in our case is a public Key
            var random = new SecureRandom();
            const int strength = 2048;
            var keyGenerationParameters = new KeyGenerationParameters(random, strength);

            var keyPairGenerator = new RsaKeyPairGenerator();
            keyPairGenerator.Init(keyGenerationParameters);
            AsymmetricCipherKeyPair subjectKeyPair = keyPairGenerator.GenerateKeyPair();

            //PKCS #10 Certificate Signing Request
            
            Pkcs10CertificationRequest csr = new Pkcs10CertificationRequest("SHA1WITHRSA", subject, subjectKeyPair.Public, null, subjectKeyPair.Private);

            //Convert BouncyCastle CSR to .PEM file.
            StringBuilder CSRPem = new StringBuilder();
            PemWriter CSRPemWriter = new PemWriter(new StringWriter(CSRPem));
            CSRPemWriter.WriteObject(csr);
            CSRPemWriter.Writer.Flush();

            //get CSR text
            var CSRtext = CSRPem.ToString();

            // Write content into a Txt file
            using (StreamWriter f = new StreamWriter(Path.Combine(System.Environment.GetFolderPath(System.Environment.SpecialFolder.ApplicationData), @"MyCsr.txt"), false))
            {
                f.Write(CSRtext);
            }
            CSRPem = new StringBuilder();
            CSRPemWriter = new PemWriter(new StringWriter(CSRPem));
            CSRPemWriter.WriteObject(subjectKeyPair.Private);
            CSRPemWriter.Writer.Flush();
            CSRtext = CSRPem.ToString();

            using (StreamWriter f = new StreamWriter(Path.Combine(System.Environment.GetFolderPath(System.Environment.SpecialFolder.ApplicationData), @"PrivateKey.pem"), false))
            {
                f.Write(CSRtext);
            }

The csr is sent to a Windows CA server, then the resulting .cer is combined with the private key using the following openssl command (on Windows 11):

openssl pkcs12 -export -in myCer.cer -inkey myKey.pem -out myPfx.pfx

Regardless of what the password is set to, including blank, the certificate will install correctly on any Windows PC but says incorrect password on any Android device, when installing through the system dialogue. When trying to decode the .pfx programmatically, like:

Application.Context.Assets.Open("newCert.pfx").CopyTo(mmstream);
                  byte[] b = mmstream.ToArray();

                var myCert = new X509Certificate2(b, String.Empty);

I get the following error:

System.Security.Cryptography.CryptographicException: Unable to decode certificate. ---> System.Security.Cryptography.CryptographicException: `MonoBtlsPkcs12.Import` failed.

It seems like Android may be using a different algorithm to encrypt using the password by default? But every post I’ve found about exporting to Android from openssl just uses the default arguments.

Solution

Looks like Android accepts certs I generate with 32 bit openssl and not 64 bit. Unsure why this is.

openssl pkcs12 -export -in myCer.cer -inkey myKey.pem -out myPfx.pfx

worked fine in 32 bit openssl

Answered By – eleviness

Answer Checked By – Dawn Plyler (Easybugfix Volunteer)

Leave a Reply

(*) Required, Your email will not be published