Skip to content

X509Certificate2(X509Certificate) missing #15713

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

Closed
tmds opened this issue Nov 14, 2015 · 11 comments
Closed

X509Certificate2(X509Certificate) missing #15713

tmds opened this issue Nov 14, 2015 · 11 comments

Comments

@tmds
Copy link
Member

tmds commented Nov 14, 2015

I am using SslStream with a userCertificateValidationCallback. The callback is passed a X509Certificate which I would like to convert to a X509Certificate2. The constructor to convert the certificate is missing/not yet implemented.

Somewhat related: perhaps SslStream should pass a X509Certificate2 instead of a X509Certificate to the userCertificateValidationCallback?

@davidsh
Copy link
Contributor

davidsh commented Nov 14, 2015

/cc: @ericstj @weshaggard @stephentoub @CIPop @SidharthNabar @terrajobst @mconnew

Related: #15708.

I don't think it is possible to upconvert an X509Certificate to an X509Certificate2. The other way works since X509Certificate2 derives from X509Certificate.

Actually, we are considering changing the API signature of what SslStream takes to use X509Certificate2 in a manner similar to how WinHttpHandler.ServerCertificateCallback takes a Func which uses X509Certificate2. However, doing a change like that will break .NET Desktop API source compat. But it is something we are discussing.

@davidsh
Copy link
Contributor

davidsh commented Nov 14, 2015

/cc: @bartonjs

@tmds
Copy link
Member Author

tmds commented Nov 14, 2015

desktop framework allows conversion via X509Certificate2(X509Certificate)

@bartonjs
Copy link
Member

@morganbr It seems like a reasonable thing to me, was there a reason for leaving it out of the contract that you can recall?

@tmds
Copy link
Member Author

tmds commented Nov 16, 2015

From my use-case with SslStream I've noticed another interesting thing. The validation callback with signature X509Certificate is passed a X509Certificate2 (on windows desktop and windows coreclr).
The SslStream.RemoteCertificate on both frameworks is a X509Certificate. I found it a bit strange that this isn't the same instance.

@CIPop
Copy link
Contributor

CIPop commented Nov 16, 2015

@bartonjs We've had the same problem during the implementation for SslStream. Since X509Certificate is deprecated but it is locked down by the Desktop API surface, the implementation in CoreFX forces all certificates to be X509Certificate2 and will throw if a cast from X509Certificate to X509Certificate2 is not possible.

@tmds As a workaround, in CoreFX (at least for Windows) it's safe to cast to an X509Certificate2.

@morganbr
Copy link
Contributor

The conversion constructor and copy constructor have a very nasty side effect on desktop that we didn't want to have in Core -- they necessarily both have handles to the same underlying native object. That means we can't handle things like deleting ephemeral keys or changing properties correctly on both objects.

@tmds
Copy link
Member Author

tmds commented Nov 17, 2015

@CIPop my comment and your comment above are saying something different
I think the certificate passed to the validation callback is actually a X509Certificate2 but this isn't so for SslStream.RemoteCertificate.
Are you sure both are of type X509Certificate2?

@tmds
Copy link
Member Author

tmds commented Dec 3, 2015

Running this code:

        public async Task AsyncMain()
        {
            TcpClient client = new TcpClient();
            await client.ConnectAsync("www.google.com", 443);
            SslStream sslStream = new SslStream(client.GetStream(), false, (sender, certificate, chain, errors) =>
            {
                Console.WriteLine($"Callback certificate type is {certificate.GetType()}");
                return true;
            });
            await sslStream.AuthenticateAsClientAsync("test");
            Console.WriteLine($"RemoteCertificate type is {sslStream.RemoteCertificate.GetType()}");
            Console.Read();
        }
        public void Main(string[] args)
        {
            AsyncMain().Wait();
        }

Gives the same output on .NET Framework and .NET Core:

Callback certificate type is System.Security.Cryptography.X509Certificates.X509Certificate2
RemoteCertificate type is System.Security.Cryptography.X509Certificates.X509Certificate

@bartonjs
Copy link
Member

@tmds There are a couple workarounds that you could utilize:

  • Since this is a public-key-only certificate: new X509Certificate2(cert.Export(X509ContentType.Cert))
  • If you believed it to be a certificate from the Windows certificate store, and you wanted to access the FriendlyName or Archived properties: new X509Certificate2(cert.Handle) (Note that this would lose the private key on Unix)
    • These two properties would be the only benefit of using the handle constructor over the byte[] constructor, and the byte-based one avoids the side effects that @morganbr referenced.
  • If you have an X509Certificate(1) instance and need access to the private key, and it's not exportable, there's no way to solve that right now.
    • Hence pursuing instantiators of X509Certificate(1) and changing them to X509Certificate2.

But, hopefully, I can just get the object type upgrade change through :).

@bartonjs
Copy link
Member

bartonjs commented Jan 5, 2016

Since the only instantiator of X509Certificate (non-2) objects in Core has been removed; I'm going to close this issue. If you find that you are still encountering problems you can't work around, please reopen.

@bartonjs bartonjs closed this as completed Jan 5, 2016
@bartonjs bartonjs removed their assignment Nov 15, 2016
@msftgits msftgits transferred this issue from dotnet/corefx Jan 31, 2020
@msftgits msftgits added this to the 1.0.0-rc2 milestone Jan 31, 2020
@ghost ghost locked as resolved and limited conversation to collaborators Jan 4, 2021
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

No branches or pull requests

6 participants