-
Notifications
You must be signed in to change notification settings - Fork 5.9k
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
[Breaking change]: X509Certificate2, X509Certificate constructors and X509Certificate2Collection.Import are obsolete for binary and file content #41662
Comments
The content and messaging of this should get sign-off from @bartonjs first. |
I tweaked the message a little bit, LGTM. |
@bartonjs reading dotnet/runtime#91763 it looks like the Authenticode pieces were cut, is the intention for those to keep using Here's code from the SDK where we use this and I had to suppress: |
Also there's quite a lot of code that uses the approach shown in https://stackoverflow.com/questions/72096812/loading-x509certificate2-from-pem-file-results-in-no-credentials-are-available/72101855#72101855 to export+import a cert to workaround some Windows issue, is that contuing to work with export+X509CertificateLoader.LoadCertificate ? |
More or less. For anyone still using that ctor, but expecting a certain content type, the recommendation is to do something like if (X509Certificate2.GetCertContentType(input) != X509ContentType.TheOneIExpect)
{
throw new CryptographicException();
}
#pragma warning disable SYSLIB0057
X509Certificate2 cert = new(input);
#pragma warning restore |
Yeah, just now it's |
Ok. It's a bit sad that we have to suppress the warning for the Authenticode case but so be it :) |
As per recommendation from dotnet/docs#41662 (comment)
As per recommendation from dotnet/docs#41662 (comment)
@bartonjs HI Jeremy, i believe that question you quoted was in reference to PEM files. How do we get an x509Certificate2Collection for a PEM file with multiple certs/keys that has been read in and is now in a byte[]? Thanks. |
@ScotMac If you actually mean PEM when you say PEM, then that's X509Certificate2Collection.ImportFromPem, which is not being marked as obsolete. If you meant PFX when you said PEM, that's X509CertificateLoader.LoadPkcs12Collection. |
Oh, I slightly lied. The Collection ImportFromPem won't import private keys. There's no API for loading multiple certificates and multiple private keys from PEM. Only PFX supports multiple private keys. |
@bartonjs Thanks Jeremy. Yes, it appears that API will only read in public key certs. Is there no .NET API for parsing PEM data that contains at least one private key, and possibly multiple public key certs? Thus providing a way to get the key/certs necessary to estabish an mTLS connection (including the validation of the server cert), without using MCS (cert stores). |
And yes, i meant PEM. But thanks for that p12 load function, since we are currently using x509Certificate2Collection.Import() for p12, which appears to be obsoleted by this notice. |
@bartonjs Hi Jeremy, it appears that the replacement functions you suggested, LoadPkcs12 and LoadPkcs12Collection, are part of the nuget package Microsoft.Bcl.Cryptography. Are there any plans to make them "built-in" to .NET? Also, Microsoft.Bcl.Cryptography original purpose was to add support in older .NET versions that didn't have the newer cryptography support. That is not the case here, where this is instead Core functionality for .NET that was obsoleted. |
They are built in to .NET 9. You don't need the package if you are targeting .NET 9+. Microsoft.Bcl.Cryptography is only needed if you want the API down level, which might make multi-targeting easier. |
What is the recommended way of replacing the now obsolete Because |
Same problem here... |
For extracting "Authenticode" things, the new cert loader does not currently handle that. You should
This comment from the preview 7 release notes shows an example: https://github.com/dotnet/core/blob/main/release-notes/9.0/preview/preview7/libraries.md#changes-to-x509-certificate-loading But, essentially: X509ContentType actualType = X509Certificate2.GetCertContentType(data);
if (actualType != X509ContentType.Authenticode)
{
throw new CryptographicException();
}
#pragma warning disable SYSLIB0057
using X509Certificate2 cert = new X509Certificate2(data);
#pragma warning restore SYSLIB0057
// use cert |
@vcsjones how is it possible that there isn't an alternative that doesn't involve making use of the deprecated API and adding a supress? 💩 |
Yes, exactly what we need. I way to load all the certificates in a particular cert store file, both for PEM and P12. |
Mostly because we thought almost no one was using that particular aspect of the API. That has proven incorrect. (However, no one has yet asked for any of the other formats that we dropped). It also turns out the feature is |
You'll have to test the file yourself and then route it either to X509CertificateLoader.LoadPkcs12Collection or X509Certificate2Collection.ImportFromPem. Hint: A PFX will always start with the byte 0x30, and a PEM sequence never will (assuming you're not trying to do a hybrid PEM/binary thing). I don't forsee us adding any more "content-sniffing" loaders, at least not in the cryptography space. |
What namespace is X509CertificateLoader supposed to be in? I can't find it anywhere... EDIT: Found it |
@bartonjs Sorry, if i wasn't clear. I meant separate files. ie, an API for loading multiple certs in a p12 file into a X509Certificate2Collection, and a separate API for loading multiple certs in a PEM file into a x509Certificate2collection. |
OK, so for a PEM file, Jeremy's suggestion was X509Certificate2Collection.ImportFromPem(ReadOnlySpan). However, the problem with that API is that it will only load the public certs in the file (hence the fact that it doesn't take a password). From the doc page for it: "PEM-encoded items with a CERTIFICATE PEM label will be imported. PEM items with other labels will be ignored." However, it does give us half the work needed: the public key certs. So then, can we use the following to get the private key (password protected) cert: X509Certificate2.CreateFromEncryptedPemFile() So, then a combination of the above two methods might solve my problem, for PEM encoded files, giving me the public certs and the private key cert. |
This means that we are going to have this warning supress until dotnet 10 is released? Assuming that this case will be taken into account in 10 of course .... |
Description
The constructors on
X509Certificate
andX509Certificate2
that accept content as abyte[]
,ReadOnlySpan<byte>
, or astring
file path have been marked obsolete.The
Import
method and all overloads onX509Certificate2Collection
have also been marked obsolete.Version
.NET 9 Preview 7
Previous behavior
Developers could use those APIs without an obsolete warning.
New behavior
Affected APIs will receive an obsolete compilation warning with SYSLIB0057.
Type of breaking change
Reason for change
The affected APIs supported loading certificates in multiple formats. For example,
new X509Certificate2(data)
would load a certificate from abyte[]
called data. This data could be one of any supported format, including X.509, PKCS7, or PKCS12/PFX.While this was easy to use, it created issues where user-supplied data is passed with a different format than intended. This may allow loading PKCS12 where only X.509 content was intended to be loaded, or create interoperability issues from handling the data in different ways.
Recommended action
Developers should use a different API to load certificate content, depending on the intended content type.
A new class called
X509CertificateLoader
can be used to load X.509 or PKCS12 content.X509CertificateLoader.LoadCertificate
andX509CertificateLoader.LoadCertificateFromFile
can be used.X509CertificateLoader.LoadPkcs12
,X509CertificateLoader.LoadPkcs12FromFile
,X509CertificateLoader.LoadPkcs12Collection
, andX509CertificateLoader.LoadPkcs12CollectionFromFile
can be used.SignedCms
from theSystem.Security.Cryptography.Pkcs
package can be used to inspect certificates in PKCS7 content.If you are uncertain about the content type you are loading,
X509Certificate2.GetCertContentType
can be used to determine the content type and call the appropriate API.You may also suppress the obsoletion using
#pragma warning disable SYSLIB0057
and#pragma warning restore SYSLIB0057
around the affected code to continue using the legacy certificate loading APIs.The
Microsoft.Bcl.Cryptography
package suppliesX509CertificateLoader
for .NET Framework and .NET Standard.Feature area
Cryptography
Affected APIs
Affected Doc IDs:
M:System.Security.Cryptography.X509Certificates.X509Certificate2.#ctor(System.Byte[])
M:System.Security.Cryptography.X509Certificates.X509Certificate2.#ctor(System.ReadOnlySpan{System.Byte})
M:System.Security.Cryptography.X509Certificates.X509Certificate2.#ctor(System.String)
M:System.Security.Cryptography.X509Certificates.X509Certificate2.#ctor(System.Byte[],System.Security.SecureString)
M:System.Security.Cryptography.X509Certificates.X509Certificate2.#ctor(System.Byte[],System.String)
M:System.Security.Cryptography.X509Certificates.X509Certificate2.#ctor(System.String,System.Security.SecureString)
M:System.Security.Cryptography.X509Certificates.X509Certificate2.#ctor(System.String,System.String)
M:System.Security.Cryptography.X509Certificates.X509Certificate2.#ctor(System.Byte[],System.Security.SecureString,System.Security.Cryptography.X509Certificates.X509KeyStorageFlags)
M:System.Security.Cryptography.X509Certificates.X509Certificate2.#ctor(System.Byte[],System.String,System.Security.Cryptography.X509Certificates.X509KeyStorageFlags)
M:System.Security.Cryptography.X509Certificates.X509Certificate2.#ctor(System.ReadOnlySpan{System.Byte},System.ReadOnlySpan{System.Char},System.Security.Cryptography.X509Certificates.X509KeyStorageFlags)
M:System.Security.Cryptography.X509Certificates.X509Certificate2.#ctor(System.String,System.ReadOnlySpan{System.Char},System.Security.Cryptography.X509Certificates.X509KeyStorageFlags)
M:System.Security.Cryptography.X509Certificates.X509Certificate2.#ctor(System.String,System.Security.SecureString,System.Security.Cryptography.X509Certificates.X509KeyStorageFlags)
M:System.Security.Cryptography.X509Certificates.X509Certificate2.#ctor(System.String,System.String,System.Security.Cryptography.X509Certificates.X509KeyStorageFlags)
M:System.Security.Cryptography.X509Certificates.X509Certificate.#ctor(System.Byte[])
M:System.Security.Cryptography.X509Certificates.X509Certificate.#ctor(System.String)
M:System.Security.Cryptography.X509Certificates.X509Certificate.#ctor(System.Byte[],System.Security.SecureString)
M:System.Security.Cryptography.X509Certificates.X509Certificate.#ctor(System.Byte[],System.String)
M:System.Security.Cryptography.X509Certificates.X509Certificate.#ctor(System.String,System.String,System.Security.Cryptography.X509Certificates.X509KeyStorageFlags)
M:System.Security.Cryptography.X509Certificates.X509Certificate.#ctor(System.String,System.Security.SecureString)
M:System.Security.Cryptography.X509Certificates.X509Certificate.#ctor(System.String,System.String)
M:System.Security.Cryptography.X509Certificates.X509Certificate.#ctor(System.Byte[],System.Security.SecureString,System.Security.Cryptography.X509Certificates.X509KeyStorageFlags)
M:System.Security.Cryptography.X509Certificates.X509Certificate.#ctor(System.Byte[],System.String,System.Security.Cryptography.X509Certificates.X509KeyStorageFlags)
M:System.Security.Cryptography.X509Certificates.X509Certificate.#ctor(System.String,System.Security.SecureString,System.Security.Cryptography.X509Certificates.X509KeyStorageFlags)
M:System.Security.Cryptography.X509Certificates.X509Certificate.#ctor(System.String,System.String,System.Security.Cryptography.X509Certificates.X509KeyStorageFlags)
M:System.Security.Cryptography.X509Certificates.X509Certificate2Collection.Import(System.Byte[])
M:System.Security.Cryptography.X509Certificates.X509Certificate2Collection.Import(System.ReadOnlySpan{System.Byte})
M:System.Security.Cryptography.X509Certificates.X509Certificate2Collection.Import(System.ReadOnlySpan{System.Byte})
M:System.Security.Cryptography.X509Certificates.X509Certificate2Collection.Import(System.Byte[],System.String,System.Security.Cryptography.X509Certificates.X509KeyStorageFlags)
M:System.Security.Cryptography.X509Certificates.X509Certificate2Collection.Import(System.ReadOnlySpan{System.Byte},System.ReadOnlySpan{System.Char},System.Security.Cryptography.X509Certificates.X509KeyStorageFlags)
M:System.Security.Cryptography.X509Certificates.X509Certificate2Collection.Import(System.ReadOnlySpan{System.Byte},System.String,System.Security.Cryptography.X509Certificates.X509KeyStorageFlags)
M:System.Security.Cryptography.X509Certificates.X509Certificate2Collection.Import(System.String,System.ReadOnlySpan{System.Char},System.Security.Cryptography.X509Certificates.X509KeyStorageFlags)
M:System.Security.Cryptography.X509Certificates.X509Certificate2Collection.Import(System.String,System.String,System.Security.Cryptography.X509Certificates.X509KeyStorageFlags)
"M:System.Security.Cryptography.X509Certificates.X509Certificate.CreateFromSignedFile(System.String)
Associated WorkItem - 292111
The text was updated successfully, but these errors were encountered: