2

do you know by any chance why the badCertificateCallback is being called? The certificate (that dart is claiming to be invalid) is exactly the same that I have set up as trusted certificate (the equality check is true!).

import 'dart:convert';
import 'dart:io';
import 'dart:typed_data';

import 'package:http/http.dart' as http;
import 'package:http/io_client.dart';

final PEM = new File(
  '../server_keys/cert.pem',
).readAsBytesSync();

Future<http.Response> listDir(String path) async {
  SecurityContext context = new SecurityContext(withTrustedRoots: false);

  context.setTrustedCertificatesBytes(PEM);

  print("context setup");
  final httpClient = HttpClient(context: context);

  httpClient.badCertificateCallback = ((cert, host, port) {
    print("In bad certificate callback.");
    print('Subject: ${cert.subject}');
    print('Issuer: ${cert.issuer}');
    print('Expires: ${cert.endValidity}');
    print('Host: ${host}');
    print('Port: ${port}');
    return String.fromCharCodes(PEM) == cert.pem;
  });

  print("get url");

  final client = IOClient(httpClient);
  print("POSTING");
  return client
      .post(
        Uri.parse('https://127.0.0.1:5000/list'),
        headers: <String, String>{
          'Content-Type': 'application/json; charset=UTF-8',
        },
        body: jsonEncode(<String, String>{
          'path': path,
        }),
      )
      .timeout(const Duration(seconds: 5));
}

void main() async {
  await listDir("admin/user/test").then((response) {
    print(response.body);
  });
  print("finished");
}

Furthermore, this is working just fine:

curl -v --cacert ../server_keys/cert.pem https://127.0.0.1:5000/list

Maybe you can give me an hint.

Further information:

Here is the certificate:

-----BEGIN CERTIFICATE-----
MIIE0jCCAroCEQCpB3UQ/DdGjoFQykLNzSJcMA0GCSqGSIb3DQEBDQUAMCcxETAP
BgNVBAoMCFhZWkNsb3VkMRIwEAYDVQQDDAkxMjcuMC4wLjEwHhcNMjIwNjE3MTI1
ODM2WhcNMzIwNjE0MTI1ODM2WjAnMREwDwYDVQQKDAhYWVpDbG91ZDESMBAGA1UE
AwwJMTI3LjAuMC4xMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAq8Hg
MaLMUzrDFb5SkpkwpT/0uVX0DL7XUEOgo8QPGWHD5OtM4CGbafF3nW0vdjYWXAhr
RUcqaq/NNu5Z715QvZwdR9jeXs/M4cPJ9/em/4AjvrhaQxJd2pvIr/Tajaw/yqOF
Sw7MT01v4Xszd7ImKeDYcwhyZYo5CdwCUj8lCo4cwq4pRUOGGuUXZiYJzIognC6v
E+UT0Lo/zoDebvc6JUXJ43meH8FxYqGkHHEE+vXwoxyxw64C+fglW4sbMfnrYUmr
EfzOL0DHwygFyl6TIZEM8w+5vXIm4vims6lYEtnlVo0eB+Wj6Y0QPhaA3giTcioX
f6tZYdIx2cRXzRaKujG/iJN+U4N2m/kXidJmkl0Uir+H6YerWdGSLWY7saeuR14i
X5VPVH/zenjbjCAWqQUyp9bvphpBERSmhQWrwVOFqdeqIgHOxn81DCFCEnzNLTMH
+svL8lTF1Q0PSiNB4Rf95TpnhjAGEtk24EE/aJw+uDgPaM9XyIYYSzdcCL2t5EL9
CUz8Lc19Iq6TlKsIPnQdDYFetmzSJaWnxNwyvjLGd3uLbF8CJOm8MQEANTOmImLz
ZFlgH/LXxm/gSngcjxIQYW+d8FbrpWu6RBHF43jxOxLZYx16fcTt/QM1cASsIHuI
kcy9sKvzBsStUqMyLRbuKfF/lAOovDuBwvvzIMECAwEAATANBgkqhkiG9w0BAQ0F
AAOCAgEACQR6Sup+hjY3Jz2EDjeVDoWsliDrtwtZ7T+igTrQbeT1gIiaIf4soJjw
RqQsZXMdFDCHsGI7eneI6wM2L03kXu7CSTL04TYDhr/2ykqjolha1KZ4W6oNlxGr
fqPdVsdo/NpyXn3b/XxtrPQnHRfZUN8OrlCn8wG0fNb6BFVEvPajcayuJdgS2qmn
5Umc66D6LqsuODOu+6URdQApFQYI+nAKQinFDUuNLnIpusaF7QG9r/Mf+m1ADNF+
WvBt594u0XSzR5+dXA0V60nfLxcC8YMqDtQ1bmbYukJRQEoarREJawI4OUYutLu2
XulnUM4sqUnbgAthaO8i5kHWp6iYjnX6B0+COyABBLqiyXu6w0nLMQzv9hekDDaN
CvhDf9BOtLrbFRnZJqxWKITxZw9U58yEeBgIXFQviYUL81tcWk8QyOBrocNBohMz
C+SypMIGPL21+Xv87MwMk/ied5J4V0rY93NOC+MDC6mTbJ1EOr/XEs+TxTu8AnDt
0EhjzXlPj4G100fmaP9BHjMPy8ReSy09bzAU4GPs8dAl7x6aNutyi39E7WeUgJNm
Odv4Wz7LwxX3t/cWkgSoKFT5DuDpBlafbI7ACWCjVe5mgd7cx75mv6pMTqJI8fEA
/OW44WN6IaLHyjG8BeHEt1yVld9RbCeyUY7A4cx94wwpD7TfPlI=
-----END CERTIFICATE-----

Here is the python flask server code (now with localhost):

import os
from flask import Flask, jsonify
import ssl

app = Flask(__name__)

@app.route("/list", methods = ['POST', 'GET'])
def list_route():
    return jsonify(isError= False,
                    message= "Success",
                    statusCode= 200,
                    data={
                        "path": "hihi"
                    }), 200


if __name__ == "__main__":  
    server_keys = {
        "url": "localhost",
        "cert_file": "server_keys/cert.pem",
        "key_file": "server_keys/key.pem",
    }
    os.system("openssl req -x509 -nodes -new -sha256 -days 390 -newkey rsa:4096 -keyout server_keys/key.pem -out server_keys/cert.pem -subj '/C=de/CN=localhost'")
    context = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)    
    context.load_cert_chain(server_keys["cert_file"], server_keys["key_file"])    
    app.run(debug=True, ssl_context=context, host=server_keys["url"], port="5000")

It is working with curl:

curl -v --cacert ../server_keys/cert.pem https://localhost:5000/list

But still not for me with dart (using Intel Mac OSX Monetary).

Flo
  • 23
  • 4
  • Does this answer your question? [how-to-solve-flutter-certificate-verify-failed-error-while-performing-a-post-req](https://stackoverflow.com/a/69481863/2828341) – lepsch Jun 17 '22 at 12:38
  • Using: ``` SecurityContext.defaultContext.setTrustedCertificatesBytes(PEM); final httpClient = HttpClient(); ``` gives me the same behavior :( – Flo Jun 17 '22 at 12:50
  • Does the certificate match the URL, i.e. has this certificate a subject alternative name for 127.0.0.1? Could you please provide the full certificate so one could have a look at the certificate details? Specifically, does the certificate has basic constraints CA:true or CA:false? – Steffen Ullrich Jun 17 '22 at 12:54
  • I have not deliberately added any constraints. I added the certificate to the question. – Flo Jun 17 '22 at 13:11

1 Answers1

1

Looks like you've stumbled upon a bug on Dart. There is an open issue about this exact problem. It only appears on macOS but on Windows/Linux/Android it works flawlessly...

Below is the command to generate the keys in bash. I've tested the script on my own and it works on Windows but fails on macOS.

openssl req -x509 -out localhost.crt -keyout localhost.key \
  -newkey rsa:2048 -nodes -sha256 -subj '/CN=localhost' -extensions EXT \
  -config <(printf "[dn]\nCN=localhost\n[req]\ndistinguished_name = dn\n[EXT]\nsubjectAltName=DNS:localhost\nkeyUsage=digitalSignature\nextendedKeyUsage=serverAuth")
lepsch
  • 8,927
  • 5
  • 24
  • 44
  • could you share with me how you created the certificate? For me I still get the same "CERTIFICATE_VERIFY_FAILED" error even with localhost... Do I create the keys in a wrong way? e.g. I just tried this: openssl req -x509 -newkey rsa:2048 -nodes -out server_keys/cert.pem -keyout server_keys/key.pem -days 731 -sha256 -subj "/CN=localhost" – Flo Jun 17 '22 at 17:47
  • I've added the info to the answer itself. Please take a look – lepsch Jun 17 '22 at 18:17
  • thank you very much. I just tested it but somehow the dart code is just timing out on me :( What OS are you using? Curl is working again without issue... – Flo Jun 20 '22 at 18:44
  • Testing on macOS the problem also shows for me (I was testing on Windows). Looks like you've stumbled upon a bug on Dart. Please check my answer again with the updated info. – lepsch Jun 20 '22 at 21:56