Dart https request with ssl certificate please

后端 未结 2 1424
无人及你
无人及你 2020-12-17 04:19

I have the following Javascript code which works fine when I run it with nodejs. However, I would like to write something similar that works with Dart. I\'ve gone through th

2条回答
  •  被撕碎了的回忆
    2020-12-17 04:56

    It is possible to use a client certificates with dart:io HTTPS requests. However it is a bit complicated due to the way SSL/TLS is implemented in Dart.

    Dart uses the Mozilla NSS library for SSL/TLS. NSS stores all its keys and certificates in a database. The SecureSocket.initialize call is used to select the NSS database to use. If no database is specified the builtin database will be used. The builtin database contains only trusted root certificates.

    To work with client certificates you need to create a NSS database with your certificates and keys. The database is manipulated using the NSS certutil tool, which is documented here:

    https://developer.mozilla.org/en-US/docs/Mozilla/Projects/NSS/Reference/NSS_tools_:_certutil

    This example creates a database with three certificates, a self signed CA, a server certificate for localhost and a client certificate. Use testtest as the password.

    $ mkdir certdb
    $ certutil -N -d sql:certdb
    $ certutil -S -s "CN=Example CA" -n my-ca-cert -x -t "TCu,u,u" -5 sslCA -m 1234 -d sql:certdb
    

    Answer 9 and N

    $ certutil -S -s "CN=localhost" -n my-server-cert -c "my-ca-cert" -t "u,u,u" -m 730 -d sql:certdb
    $ certutil -S -s "CN=sgjesse" -n my-client-cert -c "my-ca-cert" -t "Pu,u,u" -m 731 -d sql:certdb
    

    Then you can run this server:

    import "dart:async";
    import "dart:io";
    
    void serve() {
      HttpServer.bindSecure('localhost',
                            8080,
                            certificateName: 'my-server-cert',
                            requestClientCertificate: true).then((server) {
        server.listen((HttpRequest request) {
          if (request.certificate != null) {
            print('Client certificate ${request.certificate.subject}');
          } else {
            print('No client certificate');
          }
          request.response.write("Hello");
          request.response.close();
        });
      });
    }
    
    void InitializeSSL() {
      var testPkcertDatabase = Platform.script.resolve('certdb').toFilePath();
      SecureSocket.initialize(database: testPkcertDatabase,
                              password: 'testtest');
    }
    
    void main() {
      InitializeSSL();
      serve();
    }
    

    And this client:

    import "dart:async";
    import "dart:io";
    
    void request() {
      HttpClient client = new HttpClient();
      client.getUrl(Uri.parse("https://localhost:8080/"))
          .then((request) => request.close())
          .then((response) {
            print('Subject: ${response.certificate.subject}');
            print('Issuer: ${response.certificate.issuer}');
            return response.transform(UTF8.decoder).join('');
          })
         .then(print);
    }
    
    void InitializeSSL() {
      var testPkcertDatabase = Platform.script.resolve('certdb').toFilePath();
      SecureSocket.initialize(database: testPkcertDatabase,
                              password: 'testtest');
    }
    
    void main() {
      InitializeSSL();
      request();
    }
    

    And hopefully the client will present the client certificate. However this relies on NSS picking the client certificate, and I am not sure of the rules for this. If you use a SecureSocket you can chose the client certificate explicitly, but that is currently not possible for HTTPS, see https://code.google.com/p/dart/issues/detail?id=8872.

    Here is a client which uses SecureSocket:

    import "dart:async";
    import "dart:io";
    
    void request() {
      SecureSocket.connect('localhost',
                           8080,
                           sendClientCertificate: true,
                           certificateName: 'my-client-cert').then((socket) {
        socket.write("GET / HTTP/1.0\r\n\r\n");
        socket.listen(print);
      });
    }
    
    void InitializeSSL() {
      var testPkcertDatabase = Platform.script.resolve('certdb').toFilePath();
      SecureSocket.initialize(database: testPkcertDatabase,
                              password: 'testtest');
    }
    
    void main() {
      InitializeSSL();
      request();
    }
    

    Hope that helps.

提交回复
热议问题