Home > Software engineering >  CERTIFICATE_VERIFY_FAILED although it should be valid?
CERTIFICATE_VERIFY_FAILED although it should be valid?

Time:06-25

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).

CodePudding user response:

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")
  • Related