0

One of my customers is getting a CERTIFICATE_VERIFY_FAILER error when the app attempts an https post to our production API service. The service is signed with a valid CA. It has only been reported by one person so far.

Error from exception: HandshakeException: Handshake error in client (OE Error: CERTIFICATE_VERIFY_FAILER: self signed certificate in certificate chain (handshake.cc:352))

The customer did a factory reset, but it didn't fix it. They are using the app on a Samsung S6. They have two other phones on the same wifi that works fine. The issue occurs both on wifi and cell data. I tried upgrading to the latest version of flutter (v1.6.3-pre.15). They are still reporting the issue. I've been unable to reproduce this on an emulator. Also the app is working on other Samsung S6 devices.

I also verified the ssl cert using https://www.sslshopper.com/ssl-checker.html#hostname=prod.mapdot.net

Here is the code that is throwing the exception:

  static Future<String> mapDotSignIn(String usr, String pass) async {
    final url = ApiHelper.RootUrl + "Login/Login";
    try {
      Map<String, dynamic> json = new Map<String, dynamic>();
      json['user'] = usr;
      json['pass'] = pass;

      var jsonStr =jsonEncode(json);

      var resp = await http.post(url,
          headers: {"Content-Type": "application/json"}, body: jsonStr);

      Map<String, dynamic> respMap = jsonDecode(resp.body);
      return respMap['token'];
    } catch (e) {
      return 'Error: ' + e.toString();
    }
  }

I was considering adding ..badCertificateCallback to the call, but I'd rather avoid that unless there is no other way. Any ideas what might cause this?

Brad
  • 71
  • 2
  • 2
  • No idea what's happening, but there's a good argument to implement the callback anyway, so that you can implement pinning. Rather than letting the stack validate that the server's certificate matches the hostname, is signed by someone it recognises and all the expiration dates look good, it gives you the server's certificate to look at yourself. Since it's your certificate, and this is the one and only certificate that should ever be presented by the server, you can validate it by comparing its signature hash. This is probably a stronger check that the hostname check. See SO Qs about SSL pin – Richard Heap May 25 '19 at 11:38
  • Of course, this probably won't help with this particular phone, as you will no doubt find that the certificate it's getting is NOT your server's certificate. And that's probable down to some VPN or proxy it's going through. Naturally, you should not allow a connection unless it is to your server. You may end up having to tell this one use that their configuration isn't supported. – Richard Heap May 25 '19 at 11:42
  • See https://stackoverflow.com/questions/51323603/how-to-do-ssl-pinning-via-self-generated-signed-certificates-in-flutter and https://stackoverflow.com/questions/54726406/how-can-i-do-public-key-pinning-in-flutter/54838348#54838348 – Richard Heap May 25 '19 at 13:28
  • Thanks for the comments. I had similar thoughts regarding the ssl pinning. What really bugs me about this issue is she isn't seeing other issues with the phone. If something is changing the certs I would expect most applications on the device to be breaking. What kills me even more was that a factory reset didn't fix it. I suspect this is some kind of defect in Flutter or Dart. I just upgraded the http package from http: ^0.12.0+1 to http: ^0.12.0+2. I hope that will fix it, but I doubt it will based on the change log. – Brad May 25 '19 at 13:42
  • 1
    Correct. Changing that won't matter. The error you see is coming from deep in the boringssl layer. Not from the dart code. – Richard Heap May 25 '19 at 14:34
  • Is it possible to output the certificate chain? That might give some insight as to what's going on. – Brad May 25 '19 at 15:16

0 Answers0