I'm having difficulty loading an X509Certificate2
from XML, using the FromXmlString
method. The exception I'm getting is m_safeCertContext is an invalid handle.
System.Security.Cryptography.CryptographicException occurred
HResult=-2146233296
Message=m_safeCertContext is an invalid handle.
Source=System
StackTrace:
at System.Security.Cryptography.X509Certificates.X509Certificate2.get_HasPrivateKey()
at System.Security.Cryptography.X509Certificates.X509Certificate2.get_PrivateKey()
...
To create the XML, I'm loading the .pfx
file and using ToXmlString
;
var certificate = new X509Certificate2(
@"D:\public_privatekey.pfx",
(string)null,
X509KeyStorageFlags.Exportable
);
var exportedPrivate = certificate.PrivateKey.ToXmlString(true);
This generate XML which starts like this...
<RSAKeyValue><Modulus>y0iuejYHYajI...
To recreate the certificate, I'm using...
var certificate = new X509Certificate2();
certificate.PrivateKey.FromXmlString(xml);
Where xml
is a string containing the XML content.
The exception is thrown on the FromXmlString
call.
I'm new to using certificates, but my best guess is that the .pfx
contains both public and private keys, and possibly some other important data, and that I need all of that in order to have a valid X509 certificate.
However I couldn't find ToXmlString
and FromXmlString
on the X509Certificate2
directly. How should I do this? Thanks for any advice.
An X.509 certificate is described in a structured binary format called ASN.1/DER encoding. ASN.1 is a language to describe the contents of the certificate and DER is the encoding of the contents that comply with that ASN.1 structure.
Encoding your in-memory certificate separately from the private key can be done using the Export
method using the content type X509ContentType.Cert
. You can also export the certificate and private key back into a "pfx" by specifying Pfx
or Pkcs12
. If you require XML then you can encode the byte array result using base 64. You can then store it into an XML CDATA element.
Usually a private key is also stored in a binary PKCS#8 container format, also defined using ASN.1 / DER. Microsoft has however chosen to store the key into a Microsoft-proprietary XML format by default.