Self signed certificates and HttpClient

ArcheoneArcheone ✭✭FRMember ✭✭

Hello,

I use a Self signed certificate in my android app.

I have lib in PCL which use HttpClient for all the request.
For windows phone App I have only to add to trusted store like below :

        async Task AddCertificateInTrustedRootAuthorities(string certificatePath)
       {
                   Uri certificateUri = new Uri(certificatePath);
                   var certificateFile = await StorageFile.GetFileFromApplicationUriAsync(certificateUri);
                   IBuffer certBlob = await FileIO.ReadBufferAsync(certificateFile);
                   var certificate = new Certificate(certBlob);
                   // Get access to the TrustedRootCertificationAuthorities for your own app (not the system one)
                   var trustedStore = CertificateStores.TrustedRootCertificationAuthorities;
                   // Add the certificate to the TrustedRootCertificationAuthorities store for your app
                   trustedStore.Add(certificate);
        }

And after that when I use my HttpClient just work with my https links.

But for Android I add the certificate in the KeyStore. And after that only the socket factory I create have this certificate enable.>
How to give it to my HttpClient?

        void AddCertificate(int certificateId, int id)
       {
        var certificateFactory = CertificateFactory.GetInstance("X.509");
        string keyStoreType = KeyStore.DefaultType;
        KeyStore keyStore = KeyStore.GetInstance(keyStoreType);
        keyStore.Load(null, null);


        Certificate certificate;
        using (var stream = Application.Context.Resources.OpenRawResource(certificateId))
            certificate = certificateFactory.GenerateCertificate(stream);
        keyStore.SetCertificateEntry("ca" + id, certificate);

        string tmfAlgorithm = TrustManagerFactory.DefaultAlgorithm;
        TrustManagerFactory tmf = TrustManagerFactory.GetInstance(tmfAlgorithm);
        tmf.Init(keyStore);


        // Create a TrustManager that trusts the CAs in our KeyStore
        var trustManagerFactory = TrustManagerFactory.GetInstance(TrustManagerFactory.DefaultAlgorithm);
        trustManagerFactory.Init(keyStore);
        // Create an SSLContext that uses our TrustManager

        var ctx = SSLContext.GetInstance("TLS");
        ctx.Init(null, tmf.GetTrustManagers(), null);

        // apply the new context
        var socketFactory = ctx.SocketFactory;
       }

If we can't how do you do to use webservice with self signed certificates?

Posts

  • CheesebaronCheesebaron mod DKInsider, University mod

    You know real certificates are practically free or very cheap? Why not just use a real one?

  • ArcheoneArcheone ✭✭ FRMember ✭✭

    My customer want only use this type of certificates... :'(

  • CheesebaronCheesebaron mod DKInsider, University mod

    If you are not using a special handler such as ModernHttpClient then you should be able to use ServicePointManager:
    https://msdn.microsoft.com/en-us/library/system.net.servicepointmanager.servercertificatevalidationcallback(v=vs.110).aspx

  • ArcheoneArcheone ✭✭ FRMember ✭✭

    I try to validate/invalidate the certificate with the ServicePointManager but the CN name is not exactly the same on the server. The CN has the name of the URL of the server :'(.

    For the windows 8 App with the first code I posted, it's work liked a charm. But for the android version I didn't found anything which work with the HttpClient from Mono.Android.

    If someone have solve this problem^^, I will be happy to know how he do that.

  • SKallSKall ✭✭✭✭ USMember ✭✭✭✭

    Surely you can solve whether the certificate is from a source you trust. It should have a serial number and the CN can be matched as you probably should know which servers you're connecting to.

            System.Net.ServicePointManager.ServerCertificateValidationCallback +=
                (sender, cert, chain, sslPolicyErrors) =>
            {
                if (cert == null || !cert.Subject.StartsWith("CN=server.this.that")) return false;
    
                System.Diagnostics.Debug.WriteLine(cert.GetSerialNumberString());
                System.Diagnostics.Debug.WriteLine(cert.Issuer);
                System.Diagnostics.Debug.WriteLine(cert.Subject);
                return true;
            };
    

    Are you sure there's not enough static information in the certificate to determine if you should return true or false?

Sign In or Register to comment.