Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

X509Certificate2/CommonCrypto: Unable to open PKCS#12 files with no password and valid MAC #23635

Closed
qmfrederik opened this issue Sep 23, 2017 · 6 comments · Fixed by dotnet/corefx#42226
Milestone

Comments

@qmfrederik
Copy link
Contributor

If you have a PKCS#12 file which is not protected with a password, and which does have a MAC entry, opening the file will work on Windows and Linux but fails on Mac (which use CommonCrypto).

This is a regression on macOS as this worked with .NET Core 1.x (when using OpenSSL) and no longer works with .NET Core 2.0.

The following unit test reproduces the behavior:

using System;
using System.Security.Cryptography.X509Certificates;
using Xunit;

namespace temp
{
  public class UnitTest1
  {
    [Fact]
    public void Test1()
    {
      var cert = new X509Certificate("my_pkcs12.pfx");
      Assert.NotNull(cert);
    }
  }
}

The test passes on Windows & Linux but fails on macOS with the following error message:

Failed   certs.UnitTest1.Test1
Error Message:
 Interop+AppleCrypto+AppleCommonCryptoCryptographicException : MAC verification failed during PKCS12 import (wrong password?)
Stack Trace:
   at Interop.AppleCrypto.X509ImportCertificate(Byte[] bytes, X509ContentType contentType, SafePasswordHandle importPassword, SafeKeychainHandle keychain, Boolean exportable, SafeSecIdentityHandle& identityHandle)
   at Internal.Cryptography.Pal.CertificatePal.FromBlob(Byte[] rawData, SafePasswordHandle password, X509KeyStorageFlags keyStorageFlags)
   at System.Security.Cryptography.X509Certificates.X509Certificate..ctor(String fileName, String password, X509KeyStorageFlags keyStorageFlags)
   at System.Security.Cryptography.X509Certificates.X509Certificate..ctor(String fileName)
   at certs.UnitTest1.Test1() in /Users/quamotion/scratch/certs/UnitTest1.cs:line 12

my_pkcs12.pfx can be generated using the following script, use an empty password when prompted:

openssl genrsa -out my_key.key 2048
openssl req -new -key my_key.key -out my_request.csr
openssl x509 -req -days 3650 -in my_request.csr -signkey my_key.key -out my_cert.crt
openssl pkcs12 -keypbe PBE-SHA1-3DES -certpbe PBE-SHA1-3DES -export -in my_cert.crt -inkey my_key.key -out my_pkcs12.pfx -name "my-name"

This is not the same as #18254, that one was about p12 stores where the MAC is absent; in this case there is a valid MAC.

@qmfrederik
Copy link
Contributor Author

/cc @bartonjs

@qmfrederik
Copy link
Contributor Author

@bartonjs Is this a known compatibility issue?
From what I can gather, it's not listed at cross-platform-cryptography.md, so wanted to make sure.

@qmfrederik
Copy link
Contributor Author

qmfrederik commented Sep 26, 2017

As a FYI for others who may hit the same issue, here's code that may act as a workaround based on BouncyCastle.

Pkcs12Store store = new Pkcs12Store();;

using (Stream stream = File.OpenRead(filename))
{
    store.Load(stream, new char[] {});
}

var keyAlias = store.Aliases.Cast<string>().SingleOrDefault(a => store.IsKeyEntry(a));

var key = (RsaPrivateCrtKeyParameters)store.GetKey(keyAlias).Key;
var bouncyCertificate = store.GetCertificate(keyAlias).Certificate;

var certificate = new X509Certificate2(DotNetUtilities.ToX509Certificate(bouncyCertificate));
var parameters = DotNetUtilities.ToRSAParameters(key);

RSACryptoServiceProvider rsa = new RSACryptoServiceProvider();  
rsa.ImportParameters(parameters);

certificate = RSACertificateExtensions.CopyWithPrivateKey(certificate, rsa);

return certificate;

@kae
Copy link

kae commented Oct 2, 2017

Is any triage planned on this issue?

At least bug/non bug decision

@danmoseley
Copy link
Member

cc @bartonjs ..

@bartonjs
Copy link
Member

bartonjs commented Oct 4, 2017

Based on testing I did in the past, Apple cannot read a PFX that contains non-encrypted keys. So while this is a bug, it's probably not something that we would work around in .NET without a very compelling argument (like it being a key distribution model by a government CA, or something like that); but rather something which ideally would be resolved by Apple (https://bugreport.apple.com/, for SecItemImport).

What's the scenario here? Where are these PFX files coming from?

Dotnet-GitSync-Bot referenced this issue in Dotnet-GitSync-Bot/corefx Apr 25, 2019
* Remove file polling only, and leave the COMPlus_* functionality.
* Fix bug/typo introduced with dotnet/coreclr#21718

Signed-off-by: dotnet-bot <dotnet-bot@microsoft.com>
jkotas referenced this issue in dotnet/corefx Apr 26, 2019
* Remove file polling only, and leave the COMPlus_* functionality.
* Fix bug/typo introduced with dotnet/coreclr#21718

Signed-off-by: dotnet-bot <dotnet-bot@microsoft.com>
schaabs referenced this issue in Azure/azure-sdk-for-net Jun 19, 2019
* Adding ClientCertificateCredential to Azure.Idenity

* fixing test assertion

* adding cert with password to work around https://github.com/dotnet/corefx/issues/24225
@msftgits msftgits transferred this issue from dotnet/corefx Jan 31, 2020
@msftgits msftgits added this to the 5.0 milestone Jan 31, 2020
mattleibow added a commit to xamarin/ExposureNotification.Sample that referenced this issue May 25, 2020
@dotnet dotnet locked as resolved and limited conversation to collaborators Dec 20, 2020
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

Successfully merging a pull request may close this issue.

5 participants