Exporting a certificate without its private key and password-protect the output? Beware, there is a serious trap!

So you have an instance of an X509Certificate2 (or X509Certificate) that you want to export as a byte array – and you want to exclude the private key – and encrypt the output using a password.

You have found the Export method of the certificate class which takes one of the X509ContentType enum values and an optional password. The MSDN help informs that you must choose between X509ContentType.Cert, X509ContentType.SerializedCert and X509ContentType.Pkcs12 for the export to work. You also find out (by experimenting or googling) that exporting using X509ContentType.Cert produces a serialized certificate without the private key – just what you want! Hooray!

Now you specify a password and think you’re OK.

Fail. You are not. The password is actually ignored.

If you try this:

The resulting byte arrays a, b and c will have the exact same content, even though you specified different passwords! (And it behaves the same if you use the SecureString class.)

Personally I would expect the Export method to throw an exception when specifying X509ContentType.Cert together with a password (other than null). That would give me, as a developer, a clear sign that I am trying to use an unsupported parameter combination which gives me a chance to try to figure out a work-around. As it is now I am lead to believe that the output content is in fact encrypted.

It is also possible to recreate the certificate again from the byte array giving any password:

Both certX and certY above will be correctly reconstructed.

Here is a simple solution you can use to export a certificate without its private key and encrypt the exported bytes:

Now calling this method, specifying two different passwords and asking not to include the private key…

…generates two byte arrays d and e that are different. Further on, if you try to recreate it you must specify the correct password.

The certZ will be correctly reconstructed, but the second try (with wrong password) will throw a CryptographicException with the message “The specified network password is not correct.