Search Unity

  1. Megacity Metro Demo now available. Download now.
    Dismiss Notice
  2. Unity support for visionOS is now available. Learn more in our blog post.
    Dismiss Notice

HTTPS certificate validation only works when using .net 4.6 and ServicePointManager doesnt work

Discussion in 'Scripting' started by nilsk123, Dec 12, 2017.

  1. nilsk123

    nilsk123

    Joined:
    Dec 13, 2016
    Posts:
    19
    I'm developing a program which has to verify the server we're talking to is actually the correct server. To do this we've implemented certificate pinning, meaning we store a local copy of the servers public certificate and compare it to the one the server provides at runtime. This should make sure we're communicating with the right hostname and rule out a man in the middle kind of attack.

    To set this up I followed the example available at https://www.owasp.org/index.php/Certificate_and_Public_Key_Pinning#.Net

    The code in this example is really straight forward and easy to implement. The only change I needed to make was to compare the entire certificate instead of just the public key. This did not work however, I always get a TlsException: The authentication or decryption has failed, even if the validationcallback always returns true. I added some log statements in the callback and as far as i can tell it doesn't even get called.

    To get it working, in the end, I had to change the scripting backend to .net 4.6 (lucky shot!). The ServicePointManager still doesn't seem to have an effect, but if i add a callback manually to a request it works and compares the certificates successfully. Find the working code attached below. I would prefer however to use the servicepointmanager, does anyone know why it doesn't work?

    Code (csharp):
    1. public class CertPinTest : MonoBehaviour {
    2.     private string apiURL = "https://api.xxxxxxxx.com";
    3.     private X509Certificate2 cert;
    4.     // Use this for initialization
    5.     void Start () {
    6.         cert = new X509Certificate2(Path.Combine(Application.streamingAssetsPath, "xxxxx.cer"));
    7.         HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create(apiURL);
    8.         request.Method = "POST";
    9.         request.Headers.Add("X-Api-Key", "xxxxxxxxxxxxx");
    10.         request.ServerCertificateValidationCallback += CertificateValidationCallback;
    11.         request.GetResponse();
    12.     }
    13.     public bool CertificateValidationCallback(object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors)
    14.     {
    15.         return certificate.Equals(cert);
    16.     }
    17. }