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