dotnet / runtime

.NET is a cross-platform runtime for cloud, mobile, desktop, and IoT apps.
https://docs.microsoft.com/dotnet/core/
MIT License
15.25k stars 4.73k forks source link

cannot validate certificate for 192.168.1.200 because it doesn't contain any IP SANs #74161

Closed ComptonAlvaro closed 2 years ago

ComptonAlvaro commented 2 years ago

I have created the certificate for the server using easy-rsa 3.

Then I create the X509Certificate2 in this way.

    string miStrCertificado = File.ReadAllText("certificados/server.crt");
    string miStrKey = File.ReadAllText("certificados/server.key");
    X509Certificate2 miCertficadoX509 = X509Certificate2.CreateFromPem(miStrCertificado, miStrKey);

    X509Certificate2 miCertificado2 = new X509Certificate2(miCertficadoX509.Export(X509ContentType.Pkcs12));

But when I try to connect with the client (grpcui in this case) that try to connect to the server using the IP, I get the error: "cannot validate certificate for 192.168.1.200 because it doesn't contain any IP SANs".

In this case the server and the client runs in the same computer.

If I try to connect using localhost instead of the IP, I can connect using this certificates. So it seems that the certificates are created correctly but I need to set the SAN field if I want to connect using the IP.

So how could i set this field or how is the best way to create the self-signed certificates?

Thanks.

ghost commented 2 years ago

Tagging subscribers to this area: @dotnet/area-system-security, @vcsjones See info in area-owners.md if you want to be subscribed.

Issue Details
I have created the certificate for the server using easy-rsa 3. Then I create the X509Certificate2 in this way. ``` string miStrCertificado = File.ReadAllText("certificados/server.crt"); string miStrKey = File.ReadAllText("certificados/server.key"); X509Certificate2 miCertficadoX509 = X509Certificate2.CreateFromPem(miStrCertificado, miStrKey); X509Certificate2 miCertificado2 = new X509Certificate2(miCertficadoX509.Export(X509ContentType.Pkcs12)); ``` But when I try to connect with the client (grpcui in this case) that try to connect to the server using the IP, I get the error: "cannot validate certificate for 192.168.1.200 because it doesn't contain any IP SANs". In this case the server and the client runs in the same computer. If I try to connect using localhost instead of the IP, I can connect using this certificates. So it seems that the certificates are created correctly but I need to set the SAN field if I want to connect using the IP. So how could i set this field or how is the best way to create the self-signed certificates? Thanks.
Author: ComptonAlvaro
Assignees: -
Labels: `area-System.Security`
Milestone: -
bartonjs commented 2 years ago

I don't know how you'd create it correctly with easy-rsa, since that's not a tool I'm familiar with.

If you wanted to create it in code:

X509Certificate2 miCertificado2;

using (RSA key = RSA.Create(2048))
{
    CertificateRequest req = new CertificateRequest(
        "CN=localhost",
        key,
        HashAlgorithmName.SHA256,
        RSASignaturePadding.Pkcs1);

    req.CertificateExtensions.Add(
        new X509KeyUsageExtension(X509KeyUsageFlags.DigitalSignature, false));

    req.CertificateExtensions.Add(
        new X509EnhancedKeyUsageExtension(
            new OidCollection{
                new Oid("1.3.6.1.5.5.7.3.1", null),
            },
            false));

    req.CertificateExtensions.Add(
        new X509BasicConstraintsExtension(false, false, 0, false));

    SubjectAlternativeNameBuilder sanBuilder = new SubjectAlternativeNameBuilder();
    sanBuilder.AddIpAddress(IPAddress.Parse("192.168.1.200"));
    // optional
    sanBuilder.AddIpAddress(IPAddress.Loopback);
    sanBuilder.AddIpAddress(IPAddress.IPv6Loopback);
    sanBuilder.AddDnsName("localhost");

    req.CertificateExtensions.Add(sanBuilder.Build());

    X509Certificate2 miCertificadoX509 = req.CreateSelfSigned(
        DateTimeOffset.UtcNow,
        DateTimeOffset.UtcNow.AddMonths(1));

    using (miCertificadoX509)
    {
        miCertificado2 = new X509Certificate2(miCertificadoX509.Export(X509ContentType.Pkcs12));
    }
}
ComptonAlvaro commented 2 years ago

I have use easy-rsa 3.1.0 and it works. It assign the IP as SAN to the server certificate and then I can connect using grpui running in the local computer or in another computer (in a virtual machine).

vcsjones commented 2 years ago

Since it sounds like updating the tool resolved the issue I am going to close this out.