Bug 1660 - Creating an X509Certificate2 from a serialized PKCS#12 byte[] causes an exception
Summary: Creating an X509Certificate2 from a serialized PKCS#12 byte[] causes an excep...
Status: RESOLVED FIXED
Alias: None
Product: Android
Classification: Xamarin
Component: Mono runtime / AOT Compiler ()
Version: 1.0
Hardware: PC Windows
: --- normal
Target Milestone: ---
Assignee: Bugzilla
URL:
Depends on:
Blocks:
 
Reported: 2011-10-24 10:49 UTC by Nate Yocom
Modified: 2013-05-23 14:34 UTC (History)
4 users (show)

Tags:
Is this bug a regression?: ---
Last known good build:


Attachments
monodroid solution that fails (507.81 KB, application/zip)
2011-10-24 10:49 UTC, Nate Yocom
Details
mono windows version of the same code, this works (496.61 KB, application/zip)
2011-10-24 10:51 UTC, Nate Yocom
Details


Notice (2018-05-24): bugzilla.xamarin.com is now in read-only mode.

Please join us on Visual Studio Developer Community and in the Xamarin and Mono organizations on GitHub to continue tracking issues. Bugzilla will remain available for reference in read-only mode. We will continue to work on open Bugzilla bugs, copy them to the new locations as needed for follow-up, and add the new items under Related Links.

Our sincere thanks to everyone who has contributed on this bug tracker over the years. Thanks also for your understanding as we make these adjustments and improvements for the future.


Please create a new report on Developer Community or GitHub with your current version information, steps to reproduce, and relevant error messages or log files if you are hitting an issue that looks similar to this resolved bug and you do not yet see a matching new report.

Related Links:
Status:
RESOLVED FIXED

Description Nate Yocom 2011-10-24 10:49:54 UTC
Created attachment 759 [details]
monodroid solution that fails

I’m porting an app that uses a System.Net.HttpWebRequest with client certificates, and I’ve found that I can’t seem to create a System.Security.Cryptography.X509Certificates.X509Certificate2 from a serialized PKCS#12 byte[].   I’ve created the byte[] using Bouncycastle’s Pkcs12Store.Save() method, and creating an X509Certifcate2 object from this seems to work fine in windows (using the byte[] constructor).  With monodroid though I get an exception when constructing:

byte[] bits = …. Pkcs#12 stuff …
X509Certificate2 foo = new X509Certificate2(bits);

System.Security.Cryptography.CryptographicException: Unable to decode certificate. ---> System.Security.Cryptography.CryptographicException: Input data cannot be coded as a valid certificate. ---> System.NotSupportedException: Undefined length encoding.

I've created minimal example projects using mono for windows, and vs2010+monodroid for android, I'll attach.
Comment 1 Nate Yocom 2011-10-24 10:51:19 UTC
Created attachment 760 [details]
mono windows version of the same code, this works
Comment 2 Jonathan Pryor 2011-11-01 22:50:08 UTC
It looks like it works on mono/Windows because mono is using CryptoAPI; If I use it on OSX, I get the same exception that you see on Mono for Android:

Unhandled Exception: System.Security.Cryptography.CryptographicException: Unable to decode certificate. ---> System.Security.Cryptography.CryptographicException: Input data cannot be coded as a valid certificate. ---> System.NotSupportedException: Undefined length encoding.
Comment 3 Sebastien Pouliot 2011-11-02 08:21:18 UTC
Jon, the sample code won't work on Mono/Windows (but MS.NET/Windows) since CryptoAPI is not used by Mono.

Nate, the ASN.1 decoder used by Mono does not support undefined length encoding. Sadly it's not a simple fix since it would require to rework everything ASN.1-based in Mono and would break existing APIs.

I suggest you use the classes included in Mono.Security.dll (it's shipped with MonoDroid) if you want to create certificates from managed code. This will ensure the ASN.1 content always have it's length properly calculated (and set) which makes it easier to consume by any tools (including Mono). An alternative is to "fix" (it may already have such option) BouncyCastle not to generated such structures.

You can have a look at 'makecert' to see how you can create certificate using the API provided by Mono.
https://github.com/mono/mono/blob/master/mcs/tools/security/makecert.cs
Comment 4 Nate Yocom 2011-11-02 10:10:11 UTC
Thank you Sebastien, to be clear, I need an System.Security.Cryptography.X509Certificates.X509Certificate2 which has both public and private keys that I can provide to the System.Web.HttpWebRequest.  

makecert.cs appears to create a Mono.Security flavor X509 certificate structure.  Are you suggesting I can serialize this as pkcs12 and de-serialize it again as a System.Security.Cryptography.X509Certificates.X509Certificate2? or that there is a way to create an System.Security.Cryptography.X509Certificates.X509Certificate2 directly?  Or am I just reading the namespaces wrong and makecert.cs does exactly what I need? :)
Comment 5 Sebastien Pouliot 2011-11-02 11:03:06 UTC
yes, makecert.cs source code (bottom) shows how to create a PKCS#12 file (but you could keep all that into memory). 

Once you have the PKCS#12 structure (file or memory) you'll be able to instantiate a X509Certificate2 from it - and it will include both the certificate and the private key.
Comment 6 Jonathan Pryor 2011-11-17 17:41:33 UTC
@Nate: Are you still having this problem after Sebastien's workaround?

Thanks,
 - Jon
Comment 7 Nate Yocom 2011-11-21 18:58:17 UTC
To be honest I have not tried it - for other reasons the effort underway was taken up through other means and I have not had a chance to focus on this again.  However, in reading the makecert code I am confident this is sufficiently resolved (though I am a bit disappointed that the ASN1 decoder would fail on valid ASN1 :/).  

I appreciate your and Sebastien's help, please resolve this bug however necessary.
Comment 8 Miguel de Icaza [MSFT] 2013-05-23 14:34:44 UTC
Closing for now