locked
consume java web api that needs client certificate in .net RRS feed

  • Question

  • User447822198 posted

    Hi every body,

    we use .NET framework ( website ,windows forms) in our company , I need to consume a wep api from another company which is built using java, and they need to authenticate the client using certificates 

    the company API interface is simple, they use a REST technology over https with JSON data exchange, the asked to send Exchange certificate:  "We need you to send us a public key of your SSL certificate.  If you don't have a commercial one, you can issue a self signed one (Note: if you use java you can use the 'keytool' utility). Then we will install your certificate as a trusted peer so that we accept requests from you."

    I send them a public key for a self signed certificate generated from IIS (X.509 base 64 encoded), and they send me a sample java code for API CALL

    package com.bisan.proj.act;
    
    import java.io.FileInputStream;
    import java.io.InputStream;
    import java.io.InputStreamReader;
    import java.io.OutputStream;
    import java.net.URL;
    import java.security.KeyStore;
    import java.util.ArrayList;
    import java.util.HashMap;
    import java.util.List;
    import java.util.Map;
    
    import javax.net.ssl.HttpsURLConnection;
    import javax.net.ssl.KeyManagerFactory;
    import javax.net.ssl.SSLContext;
    import javax.net.ssl.SSLSocketFactory;
    import com.google.gson.Gson;
    
    public class ApiTest_currency {
    
      private static final String myKeyStore = ""; //TODO this is your private key store.
      private static final String myKeyPass = "";//TODO keystore password
    
      private static final String account = ""; //TODO bisan account
      private static final String user = ""; //TODO user
      private static final String password = ""; //TODO password
    
      private static SSLSocketFactory sslFactory = null;
    
      private static SSLSocketFactory getFactory() throws Exception {
        if (sslFactory == null) {
          KeyStore clientKeyStore = KeyStore.getInstance(KeyStore.getDefaultType());
          clientKeyStore.load(new FileInputStream(myKeyStore),
              myKeyPass.toCharArray());
          KeyManagerFactory kmf = KeyManagerFactory.getInstance(KeyManagerFactory
              .getDefaultAlgorithm());
          kmf.init(clientKeyStore, myKeyPass.toCharArray());
          SSLContext ctx = SSLContext.getInstance("TLS");
          ctx.init(kmf.getKeyManagers(), null, null);
          sslFactory = ctx.getSocketFactory();
        }
        return sslFactory;
      }//getFactory
    
      public static void main(String[] args) throws Exception {
        System.out.println(createRequest());
        URL url = new URL("https://gw.bisan.com/api/" + account);
        HttpsURLConnection connection = (HttpsURLConnection) url.openConnection();
        connection.setSSLSocketFactory(getFactory());
        connection.setRequestProperty("Content-Type", "application/json");
        connection.setDoInput(true);
        connection.setDoOutput(true);
    
        //set the request
        OutputStream out = connection.getOutputStream();
        out.write(createRequest().getBytes());
        out.close();
        int status = connection.getResponseCode();
        System.out.println(status + " " + connection.getResponseMessage());
        
        if (status == 200)
          handleResponse(connection.getInputStream());
      }//main
      
      /* JSON Request
       * {  
       *    "user"      : "test", 
       *    "password"  : "12345",
       *    "command"   : "table",
       *    "table"     : "currency",
       *    "filters"   : [ {"field"    : "code",
       *                     "operation": "!=",
       *                     "value"    : "01" }
       *                  ],
       * 
       *    "fields"    : ["symbol", "rate"]
       * }
       *
       */
          
      private static String createRequest() {
        Map<String, Object> request = new HashMap<String, Object>();
        request.put("user", user);
        request.put("password", password);
        request.put("command", "table");
        request.put("table", "currency");
    
        ArrayList filters = new ArrayList();
        Map f1 = new HashMap();
        f1.put("field", "code");
        f1.put("operation", "!=");
        f1.put("value", "01");
        filters.add(f1);
        request.put("filters", filters);
    
        ArrayList fields = new ArrayList();
    //    fields.add("code");
    //    fields.add("name");
        fields.add("symbol");
        fields.add("rate");
        request.put("fields", fields);
    
        Gson gson = new Gson();
        return gson.toJson(request);
      }//createRequest
      
      
      /* JSON Reply
       * {
       *    "command" : "table",
       *    "table"   : "currency",
       *    "error"   : "",
       *    "filters" : [ { "field"     : "code", 
       *                    "operation" : "!=",
       *                    "value"     : "01" }
       *                ],
       * 
       *    "fields"  : [ "symbol", "rate"],
       * 
       *    "rows":   [ {"symbol":"USD" ,"rate":"3.86000"},
       *                {"symbol":"JD"  ,"rate":"5.41000"},
       *                {"symbol":"4"   ,"rate":"0.70900"}
       *              ]
       * }
       *
       */
        
      private static void handleResponse(InputStream in) {
        Gson gson = new Gson();
        Map reply = gson.fromJson(new InputStreamReader(in), Map.class);
        System.out.println("\nerror: " + reply.get("error"));
        if (reply.get("error") != null)
          return;
        List<Map> rows = (List<Map>) reply.get("rows");
        System.out.println("rows " + rows.size());
        for (Map m : rows) 
          System.out.println(m.get("symbol") + " " + m.get("rate"));
      }//handleResponse
      
    }//class
    
    

    I served the net to find the equivalent code for sending Client Request with Certificate in .NET but I get lost in articles, I can't distinguish between X509Certificate and X509Certificate2 which one to use and the path of my private key, should I only provide the path, or locate it from the store (MMC) 

    my code Trial 

    using System;
    using System.Net;
    using System.Security.Cryptography.X509Certificates;
    
    class Program
    {
        class MyWebClient : WebClient
        {
    
            // private ssl key info
            string myKeyStore = @"C:Key.pfx";
            string myKeyPass = ""; //password
           protected override WebRequest GetWebRequest(Uri address)
            {
                HttpWebRequest request = (HttpWebRequest)base.GetWebRequest(address);
                X509Certificate cert2 = new X509Certificate(myKeyStore, myKeyPass);
                request.ClientCertificates.Add(cert2);
                return request;
            }
        }
        static void Main(string[] args) 
    
            {
            // Bisan Demo Account
            string account = "";
            string user = "";
            string Bisanpassword = "";
    
            var client = new MyWebClient();    
            var data = client.DownloadString("https://gw.bisan.com/api/" + account);
            Console.WriteLine(data);
            }
        }
        
    
        

    but this didn't work 

    any help please

    Thursday, November 8, 2018 8:33 AM

All replies

  • User-943250815 posted

    It is not clear what is not working, Java code mention TLS, and since TLS comes before Certificate Authentication, perhaps your problem can be related to TLS instead of certificate.

    If you problem is related to TLS negotiation, you should set ServicePointManager.SecurityProtocol to proper TLS version. If you have to work with Tls12 suggest you use .Net 4.6.2

    ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12 // Tls12 just as an example
    var data = client.DownloadString("https://gw.bisan.com/api/" + account);



    Friday, November 9, 2018 12:33 AM