.Net client authentication setup using HttpWebRequ

2019-07-25 12:57发布

问题:

This is more about how to get HttpWebRequest to work or even if HttpWebRequest is the right implementation. I've let my C# and .Net skill lapse the past few year, so I hope I can be forgiven for that.

I trying to hit a secure web service that requires client authentication. I have four certs to hit this with.

• Root Certificate • Intermediate Root Certificate • Device Certificate • Private Key

The server is Java and these certs are in .jks form trustore and keystore. I pulled them into .pem files.

So, I failed on the C# client side, so I thought I'd write a little Python snippet to make sure at least the server side is working as expected. Twenty minutes later, I'm making secure posts. Here's that code:

# Keys
path = "C:\\path\\"
key = path + "device.pem"
privkey = path + "device_privkey.pem"
CACerts = path + "truststore.concat" # root & intermediate cert


def post():
    url = "/url"
    headers = {'Content-Type': 'application/xml'}

    ## This section is HTTPSConnection

    context = ssl.SSLContext(ssl.PROTOCOL_TLS)
    context.verify_mode = ssl.CERT_OPTIONAL

    context.load_cert_chain(key, privkey, password='password')
    context.verify_mode = ssl.CERT_NONE
    context.load_verify_locations(CACerts)

    conn = http.client.HTTPSConnection(host, port=8080, context=context)
    conn.request("POST", url, registrationBody, headers)

    response = conn.getresponse()

    regresp = response.read()

The concat certificate is the concatenation of the root and intermediate certificates.

Are you with me?

Now to my C#/.Net headache.

This my attempt. I clearly don't know what I'm doing here.

    public async Task POSTSecure(string pathname, string body)
    {
        string path = "C:\\path";
        string key = path + "device.pem";
        string privkey = path + "device_privkey.pem";
        string CACerts1 = path + "vtn_root.pem";
        string CACerts2 = path + "vtn_int.pem";

        try
        {
            // Create certs from files
            X509Certificate2 keyCert = new X509Certificate2(key);
            X509Certificate2 rootCert = new X509Certificate2(CACerts1);
            X509Certificate2 intCert = new X509Certificate2(CACerts2);

            HttpWebRequest request = (System.Net.HttpWebRequest)System.Net.WebRequest.Create("https://" + host + ":" + port + pathname);
            ServicePoint currentServicePoint = request.ServicePoint;

            // build the client chain?
            request.ClientCertificates.Add(keyCert);
            request.ClientCertificates.Add(rootCert);
            request.ClientCertificates.Add(intCert);

            Console.WriteLine("URI: {0}", currentServicePoint.Address);

            // This validates the server regardless of whether it should
            request.ServerCertificateValidationCallback = ValidateServerCertificate;

            request.Method = "POST";
            request.ContentType = "application/xml";
            request.ContentLength = body.Length;

            using (var sendStream = request.GetRequestStream())
            {
                sendStream.Write(Encoding.UTF8.GetBytes(body), 0, body.Length);
            }

            var response = (HttpWebResponse)request.GetResponse();
        }
        catch (Exception e)
        {
            Console.WriteLine("Post error.");
        }
    }

Thanks for any help or a pointer to a decent tutorial.

[Edit] More info. On the server side, the debugging points to an empty client certificate chain. This is right after it reports serverhello done.

回答1:

Okay, I think I was pretty close in the original, but I solved it this way:

            request.ClientCertificates = new X509Certificate2Collection(
                                new X509Certificate2(
                                    truststore,
                                    password));

The "trustore" file is a .p12 containing the certificates listed above. The .p12 truststore can be created from the .jks truststore through keytool and openssl. Lots of info out there on how to do that.