-
Notifications
You must be signed in to change notification settings - Fork 4.8k
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
Error exporting https certificate on macOS Sonoma 14.4 #99735
Comments
Also facing the same issue. Removing Edit: Ah, the issue is with exporting the private |
Ok. I've found a workaround.
Next, use
When prompted for a password, just press Return/Enter. Then you need to further split the
And the
It's not very straight-forward, but it seems like |
You can also generate the self-signed SSL certificate for localhost and key using openssl:
Only that NuGet package is deprecated, |
@thj-dk I guess the main thing that the dotnet cert is supposed to add over that is that it's trusted by the system. (Which, yes, you could manually trust the cert generated via openssl as well.) |
Yep, the in-box version of The call in question appears to be https://github.com/dotnet/aspnetcore/blob/702ba39ace967037a3f726765732e3e63f80907e/src/Shared/CertificateGeneration/CertificateManager.cs#L506 Unfortunately, Apple appears to use that error code for a number of different conditions, making it hard to debug by inspection. We may need to pull in https://github.com/dotnet/runtime for their understanding of the PAL. |
I tried pulling out the important calls from dev-certs. Does this throw the same exception? using System.Security.Cryptography;
using System.Security.Cryptography.X509Certificates;
using var store = new X509Store(StoreName.My, StoreLocation.CurrentUser);
store.Open(OpenFlags.ReadOnly);
var certs = store.Certificates.OfType<X509Certificate2>().ToList();
var cert = certs.Single(c => c.FriendlyName == "ASP.NET Core HTTPS development certificate");
var key = cert.GetRSAPrivateKey()!;
var eyBytes = key.ExportEncryptedPkcs8PrivateKey(string.Empty, new PbeParameters(PbeEncryptionAlgorithm.Aes256Cbc, HashAlgorithmName.SHA256, 1)); I'd ask for a copy of the cert, but exporting seems to be the crux of the issue. 😆 |
Huh, a colleague happened to be on 14.3 and it didn't repro there, but it did start failing in this way after upgrading to 14.4. Didn't see that coming. |
Self-contained repro using System.Security.Cryptography;
using System.Security.Cryptography.X509Certificates;
using System.Text;
var cert = Repro.CreateCertificate();
var key = cert.GetRSAPrivateKey()!;
var eyBytes = key.ExportEncryptedPkcs8PrivateKey(string.Empty, new PbeParameters(PbeEncryptionAlgorithm.Aes256Cbc, HashAlgorithmName.SHA256, 1));
public class Repro
{
internal const int CurrentAspNetCoreCertificateVersion = 2;
internal const string AspNetHttpsOid = "1.3.6.1.4.1.311.84.1.1";
internal const string AspNetHttpsOidFriendlyName = "ASP.NET Core HTTPS development certificate";
private const string ServerAuthenticationEnhancedKeyUsageOid = "1.3.6.1.5.5.7.3.1";
private const string ServerAuthenticationEnhancedKeyUsageOidFriendlyName = "Server Authentication";
private const string LocalhostHttpsDnsName = "localhost";
private const string LocalhostHttpsDistinguishedName = "CN=" + LocalhostHttpsDnsName;
public const int RSAMinimumKeySizeInBits = 2048;
public static X509Certificate2 CreateCertificate()
{
// shims
var notBefore = DateTime.Now;
var notAfter = DateTime.Now + TimeSpan.FromDays(365);
var Subject = LocalhostHttpsDistinguishedName;
var AspNetHttpsCertificateVersion = CurrentAspNetCoreCertificateVersion;
var subject = new X500DistinguishedName(Subject);
var extensions = new List<X509Extension>();
var sanBuilder = new SubjectAlternativeNameBuilder();
sanBuilder.AddDnsName(LocalhostHttpsDnsName);
var keyUsage = new X509KeyUsageExtension(X509KeyUsageFlags.KeyEncipherment | X509KeyUsageFlags.DigitalSignature, critical: true);
var enhancedKeyUsage = new X509EnhancedKeyUsageExtension(
new OidCollection() {
new Oid(
ServerAuthenticationEnhancedKeyUsageOid,
ServerAuthenticationEnhancedKeyUsageOidFriendlyName)
},
critical: true);
var basicConstraints = new X509BasicConstraintsExtension(
certificateAuthority: false,
hasPathLengthConstraint: false,
pathLengthConstraint: 0,
critical: true);
byte[] bytePayload;
if (AspNetHttpsCertificateVersion != 0)
{
bytePayload = new byte[1];
bytePayload[0] = (byte)AspNetHttpsCertificateVersion;
}
else
{
bytePayload = Encoding.ASCII.GetBytes(AspNetHttpsOidFriendlyName);
}
var aspNetHttpsExtension = new X509Extension(
new AsnEncodedData(
new Oid(AspNetHttpsOid, AspNetHttpsOidFriendlyName),
bytePayload),
critical: false);
extensions.Add(basicConstraints);
extensions.Add(keyUsage);
extensions.Add(enhancedKeyUsage);
extensions.Add(sanBuilder.Build(critical: true));
extensions.Add(aspNetHttpsExtension);
var certificate = CreateSelfSignedCertificate(subject, extensions, notBefore, notAfter);
return certificate;
}
internal static X509Certificate2 CreateSelfSignedCertificate(
X500DistinguishedName subject,
IEnumerable<X509Extension> extensions,
DateTimeOffset notBefore,
DateTimeOffset notAfter)
{
using var key = CreateKeyMaterial(RSAMinimumKeySizeInBits);
var request = new CertificateRequest(subject, key, HashAlgorithmName.SHA256, RSASignaturePadding.Pkcs1);
foreach (var extension in extensions)
{
request.CertificateExtensions.Add(extension);
}
var result = request.CreateSelfSigned(notBefore, notAfter);
return result;
RSA CreateKeyMaterial(int minimumKeySize)
{
var rsa = RSA.Create(minimumKeySize);
if (rsa.KeySize < minimumKeySize)
{
throw new InvalidOperationException($"Failed to create a key with a size of {minimumKeySize} bits");
}
return rsa;
}
}
} |
Thanks for the self-contained repro @amcasey. I'll take a look. |
Smaller repro: [Fact]
public static void TestMe()
{
using RSA rsa = RSA.Create(2048);
CertificateRequest req = new CertificateRequest("CN=potato", rsa, HashAlgorithmName.SHA256, RSASignaturePadding.Pkcs1);
using X509Certificate2 cert = req.CreateSelfSigned(DateTime.Now, DateTime.Now.AddDays(1));
using RSA key = cert.GetRSAPrivateKey()!;
byte[] pkcs8 = key.ExportEncryptedPkcs8PrivateKey("potato", new PbeParameters(PbeEncryptionAlgorithm.Aes256Cbc, HashAlgorithmName.SHA256, 1));
} |
Bigger, but simpler repro. Basically, exporting an key that was created from a SecIdentityRef is broken. This is not unique to RSA, happens with ECDsa, too. using System.Security.Cryptography;
using System.Security.Cryptography.X509Certificates;
string certContent = """
-----BEGIN CERTIFICATE-----
MIICozCCAYugAwIBAgIJAMxONl7kijUmMA0GCSqGSIb3DQEBCwUAMBExDzANBgNV
BAMTBnBvdGF0bzAeFw0yNDAzMTQwMTAwMzVaFw0yNDAzMTUwMTAwMzVaMBExDzAN
BgNVBAMTBnBvdGF0bzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALii
le9egQ3vTfx6FVi3Zrq6PAmy+8VVocVrMXhwP064LRTYSHMFdwG0LGUr2rFhbbFx
x4q3DizbHB1RpkhDVJ+IkfSdGg8c8BeBq+C8Th5Vr+91CsqocCVsZxpJRWdZfcAl
Znzueo1jxh+CjnZAHYhKk0SJXrZCQrcWcy+W7CuX7SPc9nS/ZaMwXf7bb/V+kbnM
h+dhbMV6xj94Du0rEpMzVnAzxs14iLMtbW/eyLhHpf4iL/z4n4/52aoNfi/psx76
ZYq346cnSNGhEjY80Gj+4MR7g2iVt1YmZXR0/H00NqxzVP5k/k7nILBKHYzeV0aa
ODXtiDJDiwTmslq1B+0CAwEAATANBgkqhkiG9w0BAQsFAAOCAQEAC/aKrVV3hkwI
ETpsIW0+wkJyA2ABIkMiuNma3clipe4xnldTNJpJ86luRUTkP9BorR+AaBQersYp
YJ+r3niIdqlX7DN9n9/981asFp7QaFVJpb8/YXhPTcGUCS91QiFHdLk94qz+YKra
iHbtKnabNt/gLjRLEnh7TTNP3VTZhZJbfFLVG2pQaDgMhh3EAOAD84moKx8hOESl
TWjI1MLWwkWeNVuRU2qy4p69gquMzPWPOy8HISw5EtvslOee++m5/vBvoxXKh3IW
1NMFqbWTQfJoqWuEjS183UvDMBm4zrNnB+dlHP+WsAqK+P0D6OIotL91rlj15VsD
O9QoWGtUFA==
-----END CERTIFICATE-----
-----BEGIN RSA PRIVATE KEY-----
MIIEowIBAAKCAQEAuKKV716BDe9N/HoVWLdmuro8CbL7xVWhxWsxeHA/TrgtFNhI
cwV3AbQsZSvasWFtsXHHircOLNscHVGmSENUn4iR9J0aDxzwF4Gr4LxOHlWv73UK
yqhwJWxnGklFZ1l9wCVmfO56jWPGH4KOdkAdiEqTRIletkJCtxZzL5bsK5ftI9z2
dL9lozBd/ttv9X6RucyH52FsxXrGP3gO7SsSkzNWcDPGzXiIsy1tb97IuEel/iIv
/Pifj/nZqg1+L+mzHvplirfjpydI0aESNjzQaP7gxHuDaJW3ViZldHT8fTQ2rHNU
/mT+TucgsEodjN5XRpo4Ne2IMkOLBOayWrUH7QIDAQABAoIBAA7MRHPrJoZGo1Y5
4FXxhbuvsJ9UDPRCWk/E49yOiIW8uADsmxU8P08aZkLUj+JOwqMpu++ySgyjzLN3
3LnRdanp9k1n6FOvmCRA1GpTxUy5RZDNrWf+iysgrqcaGhnVVRa47fzTg0HWQ5CO
dEW7ep0hYaoTpXePmiJrm59D5hlR4IcYyFAVvnr0iRi3huGALJAUrsMUs4EYr4tq
+URCKm70nPEwjTmL/CsNNHYiCTsyyJ9/p4Yms1DugP1nVQeR0iqMBnqDzvBsOnp4
Df8PRZoQek+MA24txNzeFYLzKKKqSVUvUrdgFfegoxYdwucGaJYSpf0Yx7MHOIvO
qsVFA2kCgYEA9cbbl+lcnUkJQznHtcKf7B0NDZC5xIbsMMdoee/aadGYz81UHPM/
p29f0YSP3a8IbohXrZiimHW3FkZfp4wwPthx+bQ8ubuP1isjB5bzi2pzK4HFbi7h
YL/7yKuV2SpCUc4gUm4osxAP44SEd6edkTZCdTd7uAjYuIzSDxm4CAkCgYEAwFCp
4YrPeBVRWpBHncRUVW8iMB48A+4leUHB/5vQaH9d0+yDTy3JClEP3ycleR6/bSfS
O7LtXE9yWwedGaeov/4EjSoa/3l61dvlM3igxk7dsw7c2M839xP2LSQC6VnHtyuA
VDOzMZY039d9xmGywhWgqI/cg7KAKWNBTFQsUcUCgYA5fJ7mZGYOQAQTnlMxF2nS
j2T7NEvPRQO/0RSF2O1MbQMCL/OppdfQsQNHfWstHgCp4egoKZh2cqo1YpaDGQ47
1OKr1lWR1+Yn4QUbhFpI1MhFd+AXCo4a1CzvXfr5xaGngsAap7uLTol43Qki96iq
S3e19RlSDXerivyjHY/nCQKBgQCqhVt8TtaTBWPzR0cZDsIwVrAbtlNEsN6tW68m
dAQhA/4wMOBlTpWZ/jJyjYVelfLqWIrCwG5SkWc2a9PSsaShSBzFBnaV3CMciTP7
pZP5Amj1odIUs/hNrndzoyCpxB+fvIS3JHhZGXScnbg6NNqJ2R9xFs5SP+3/xLBb
e68oeQKBgEx+wgLUpZjaFVFYNnKKGAZLpFIw0FL2BpDWR1PcdyOvz0h98lHJmoWs
K1Z7U/hITZKK9tnuCAqL2nHdwTX21VlHvCOCLhL4pVYzNkdJ4N9XX5c4yMyj9fSt
KSi7b25K/R2GwWfs7cuqjIzcxGS2kDZbt8DUvmQ7qC2yXjxSzCcR
-----END RSA PRIVATE KEY-----
""";
using X509Certificate2 c = X509Certificate2.CreateFromPem(certContent, certContent);
using RSA r = c.GetRSAPrivateKey()!;
r.ExportParameters(true); |
I just hit this as well Sonoma 14.4. |
I think I got a fix. Doing validation. |
The gist of the problem is that Apple changed the error code returned here Line 144 in b181ed5
Instead of errSecPassphraseRequired, we are getting errSecInvalidKeyAttributeMask back, so our error handling doesn't happen. |
We're also affected by this issue in Dev Proxy, and it's preventing us from inspecting HTTPS traffic. Can't wait to try the fix. Thank you so much for patching it so quickly! 👏 |
Reopened for backports. |
This has been fixed. The fix will be available in 8.0.4, 7.0.18, and 6.0.29. Since back ports are complete, I am going to close this out. |
Where can I get 8.0.4? |
It is not released yet. It will be part of the April release of .NET, which I think is in the next week or two. |
@johndobrien In the meantime, you could use the solution mentioned here temporarily, #99735 (comment) |
My God this issue has been driving me crazy for last 2 hours, thanks finally for this |
Something changed in macOS 14.4 (compared to 14.3) that caused PEM cert export to start raising
Interop+AppleCrypto+AppleCFErrorCryptographicException: The operation couldn’t be completed. (OSStatus error -67738 - CSSM Exception: -2147415780 CSSMERR_CSP_INVALID_KEYATTR_MASK)
.The original repro uses
dotnet dev-certs
to generate and export a self-signed cert aspnetcore uses during local development, but I've included a self-contained repro below.[Original description below]
Is there an existing issue for this?
Describe the bug
Generating https development certificates using this commands throws an exception.
Full output:
.NET Version
8.0.201
Anything else?
The text was updated successfully, but these errors were encountered: