Open BillBaird opened 4 years ago
Hi @BillBaird thanks for your feedback. I would love to get this support this, get this to work on OSX, problem is, I have no idea about OSX. I will start looking into this, and build up my knowlegde, so this will work. If you make any progress, have have more pointers, PRs, I would be very grateful.
Greetings Damien
Hello @damienbod. I have been pulling my hair out trying to get one implementation to work on Windows, OSX, and Linux and although I am not working on it directly, have had some insight. My focus has been on ECDsa keys and chain of trust creating a PFX file (PCKS#12).
Stumbling on your CreateCertificateWithPrivateKey in PemDecoder, I saw Pkcs12Builder for the first time. Indeed, it is new in .net core 3.0. I saw your comment on OpenSSL requiring a file to have a mac. From there, I noticed this little caveat at the end of the remarks section in https://docs.microsoft.com/en-us/dotnet/api/system.security.cryptography.pkcs.pkcs12builder.sealwithmac?view=dotnet-plat-ext-3.1.
The hash algorithm used on a fresh installation of Windows 7 when exporting via X509Certificate.Export as a PKCS#12 PFX is SHA1 with an iteration count of 2000. Due to collision problems with SHA1, Microsoft recommends a security model based on SHA256 or better; however, some PFX readers may only support SHA1.
Since my goal was to create a PFX containing the full chain of trust, but only the private key from the leaf certificate, I used Pkcs12Builder and that comment to create the following Export routine:
/// <summary>
/// Exports one or more certificates in PKCS12 format representing a chain of trust. The certificates should start with the leaf
/// node of the trust tree working their way up to the root CA.
///
/// Note that this implementation is for ECDsa keys.
/// </summary>
/// <param name="privateKeyPassword">A password used to shroud the private key of the leaf certificate</param>
/// <param name="pkcs12Password">A password using to seal the exported PKCS12 bytes</param>
/// <param name="cert">A set of one or more certificates with the leaf node (the one which for which the private key should be included) given first.</param>
public static byte[] ExportTrustChainWithPrivateKey(string privateKeyPassword, string pkcs12Password, params X509Certificate2[] cert)
{
var builder = new Pkcs12Builder();
var contents = new Pkcs12SafeContents();
for (int i = 0; i < cert.Length; i++)
{
contents.AddCertificate(cert[i]);
if (i == 0)
contents.AddShroudedKey(cert[i].GetECDsaPrivateKey(), privateKeyPassword, new PbeParameters(PbeEncryptionAlgorithm.TripleDes3KeyPkcs12, HashAlgorithmName.SHA1, 2000));
}
builder.AddSafeContentsUnencrypted(contents);
// OpenSSL requires the file to have a mac, without mac this will run on Windows but not on Linux
// See hash algorithm comment at the end of
// https://docs.microsoft.com/en-us/dotnet/api/system.security.cryptography.pkcs.pkcs12builder.sealwithmac?view=dotnet-plat-ext-3.1
// SHA1 is used since using SHA2565 here does not work on OSX.
builder.SealWithMac(pkcs12Password, HashAlgorithmName.SHA1, 2000);
return builder.Encode();
}
This is all new to me, so I don't know if what I've done here is "correct", but it works identically on Windows, OSX, and Linux (and I'll soon be trying to use these in Xamarin), which was my goal.
I can't commit to any PRs right now, but if I can carve out some time I'll try to get to them. I'm thankful that Pkcs12Builder exists (along with a whole new set of related classes), but I feel like we're pioneers in that there are no examples, etc. out there and MS's docs are not real useful (the one little caveat in the remarks was the most useful thing I found).
Thanks for your library. I never would have made it this far without it. Bill
I've been trying to get this working on OSX. A few issues are easily handled, such as OSX's lack of support for "FriendlyName". However, I've been unable to get the ImportExportTests to execute properly.
The ImportExportTests.ImportExportECPrivateKeyPublicKeyPairPem test fails on these lines:
with the error
Similar issues occur on the tests
ImportExportRsaPrivateKeyPublicKeyPairPem
andImportExportSingleChainedECPrivateKeyPublicKeyPairPem
, always on the callimportExport.CreateCertificateWithPrivateKey
.Any chance of getting this library to work on OSX? This is the only real issue that I've run into with it.