We should be able to choose security protocol as strong as possible.
At present, there is line in runtime file: _https://github.com/dart-lang/sdk/blob/master/runtime/bin/security_context.cc_ which sets protocol to version TLS1.0.
(:825) SSL_CTX_set_min_proto_version(ctx, TLS1_VERSION); // cannot be changed from dart
Please, add option to choose minimal protocol version from Dart SecurityContext.
@sortie
Hmm. That's not good enough.
Wikipedia says "In October 2018, Apple, Google, Microsoft, and Mozilla jointly announced they would deprecate TLS 1.0 and 1.1 in March 2020.[11]" so we should think about that as well.
I'll need some time to understand this code a bit better and what incompatibilities/breaking changes might occur if we change this or expose it in Dart. Could be interesting to a do an SSL labs test with a dart client / server and see exactly what they allow.
Just as info.
We have following piece of code (sample), which worked well, until June this year, when specification for web service had changed, and now is only allowed to use TLS1.2 protocol. This had led us to error SSLV3_ALERT_HANDSHAKE_FAILURE(tls_record.cc:586).
SecurityContext context = new SecurityContext(withTrustedRoots: true)
..setTrustedCertificates('tls_connection_cert')
..usePrivateKey('private_cert.p12', password: 'password');
await SecureSocket.connect("service_host", 9002, context: context).then((socket) {
print('Connected to: '${socket.remoteAddress.address}:${socket.remotePort}');
socket.destroy();
});
Since project is Flutter based, we quickly turn to Platform channel options, and at the moment we are calling native solutions. Java example:
KeyManager[] privateCert; // private_cert.p12
TrustManager[] publicCert; // tls_connection_cert
SSLContext ssl = SSLContext.getInstance("TLSv1.2");
ssl.init(privateCert.getKeyManagers(), publicCert.getTrustManagers(), null);
SSLSocket socket = (SSLSocket)ssl.getSocketFactory().createSocket("service_host", 9002);
socket.startHandshake();
socket.close();
We have probe with Wireshark tool. Using vanilla dart:io in a standalone app, Dart sends a 1.2 Client Hello inside a 1.0 header, offering 15 cipher suites. On Java side there is 1.2 header with 45 chiper suites.
Our particular server chooses TLS_DHE_RSA_WITH_AES_256_GCM_SHA384 (0x009f) chiper, which is not present in those 15 choices, that Dart send in its Client Hello.
None, I was afraid I raised โbadโ question. This was before I deep dive into Dart source code to find reason of the problem.
How / When can I enable TLS 1.2 in Dart? Browsers are complaining about the standart settings.
@ferhatb @yjbanov @jonahwilliams - is this going to impact our developer workflow for flutter web?
I'm not quite sure what the implications would be for the tool, fyi @zanderso
/cc @aarongreen for advice about what the right thing to do here is:
https://github.com/dart-lang/sdk/blob/master/runtime/bin/security_context.cc#L808
Hi all,
I too was having issues handshaking from my Flutter app with an IOT message broker that supported a minimum TLS v1.2 connection. Whilst searching for an explanation, I found https://github.com/dart-lang/sdk/issues/37157, https://github.com/dart-lang/sdk/issues/37173 and https://github.com/dart-lang/sdk/issues/41061 which are similar issues discussing problems connecting via TLS with Dart. From what I understand, it appears that the connection message headers are TLS v1.0 conform, meaning my server rejected the request as insecure.
In addition, https://github.com/dart-lang/sdk/issues/35462 discusses issues with using the setTrustedCertificates() method from the dart:io library. This lead me to the following TLS/SSL with Dart article that ultimately helped me solve my issue. I have included code snippets of both the solution and what I had previously been doing wrong below. I hope this helps anyone else struggling with this issue and saves you the time and head-scratching that I went through โฐ
pubspec.yaml
...
assets:
# Add the required certificates to your bundle. Note: Your personal use-case may be different,
# so just make sure to have a reference somewhere to the certificates required to negotiate a
# secure connection.
#
# The certificate_chain.pem file contains the required client certificate together with the root
# authority certificate. Note: order is important. The client certificate must come before the
# root authority in this file! Mine looks something like this:
#
# -----BEGIN CERTIFICATE-----
# Paste your client certificate here
# -----END CERTIFICATE-----
# -----BEGIN CERTIFICATE-----
# Paste your root authority certificate here
# -----END CERTIFICATE-----
#
- assets/path_to_certificates/certificate_chain.pem
- assets/path_to_certificates/private.pem
client.dart
...
// Obtain the raw byte data of the certificate chain and private key file contents
ByteData certificateChain = await rootBundle.load("assets/path_to_certificates/certificate_chain.pem");
ByteData privateKey = await rootBundle.load("assets/path_to_certificates/private.pem");
final context = SecurityContext.defaultContext;
context.useCertificateChainBytes(certificateChain.buffer.asUint8List());
context.usePrivateKeyBytes(privateKey.buffer.asUint8List());
await SecureSocket.connect(host, port, context: context)
// Party time ๐
...
The following code results in a HandshakeException SSLV3_ALERT_BAD_CERTIFICATE(tls_record.cc:587)
pubspec.yaml
...
assets:
# The root CA and client certificates were previously separate. The solution was to combine
# them into a single certificate chain (see above)
- assets/path_to_certificates/root_ca_cert.pem
- assets/path_to_certificates/client_cert.pem
- assets/path_to_certificates/private.pem
client.dart
...
// Obtain the raw byte data of the client & root CA certificates and private key file contents
ByteData rootCACertificate = await rootBundle.load("assets/path_to_certificates/root_ca_cert.pem");
ByteData clientCertificate = await rootBundle.load("assets/path_to_certificates/client_cert.pem");
ByteData privateKey = await rootBundle.load("assets/path_to_certificates/private.pem");
final context = SecurityContext.defaultContext;
context.setClientAuthoritiesBytes(clientCertificate.buffer.asUint8List());
context.setTrustedCertificatesBytes(rootCACertificate.buffer.asUint8List())
context.usePrivateKeyBytes(privateKey.buffer.asUint8List());
await SecureSocket.connect(host, port, context: context)
// HandshakeException ๐ฅ
...
Hi all,
I too was having issues handshaking from my Flutter app with an IOT message broker that supported a minimum TLS v1.2 connection. Whilst searching for an explanation, I found #37157, #37173 and #41061 which are similar issues discussing problems connecting via TLS with Dart. From what I understand, it appears that the connection message headers are TLS v1.0 conform, meaning my server rejected the request as insecure.
In addition, #35462 discusses issues with using the setTrustedCertificates() method from the dart:io library. This lead me to the following TLS/SSL with Dart article that ultimately helped me solve my issue. I have included code snippets of both the solution and what I had previously been doing wrong below. I hope this helps anyone else struggling with this issue and saves you the time and head-scratching that I went through โฐ
Solution ๐
pubspec.yaml
... assets: # Add the required certificates to your bundle. Note: Your personal use-case may be different, # so just make sure to have a reference somewhere to the certificates required to negotiate a # secure connection. # # The certificate_chain.pem file contains the required client certificate together with the root # authority certificate. Note: order is important. The client certificate must come before the # root authority in this file! Mine looks something like this: # # -----BEGIN CERTIFICATE----- # Paste your client certificate here # -----END CERTIFICATE----- # -----BEGIN CERTIFICATE----- # Paste your root authority certificate here # -----END CERTIFICATE----- # - assets/path_to_certificates/certificate_chain.pem - assets/path_to_certificates/private.pemclient.dart
... // Obtain the raw byte data of the certificate chain and private key file contents ByteData certificateChain = await rootBundle.load("assets/path_to_certificates/certificate_chain.pem"); ByteData privateKey = await rootBundle.load("assets/path_to_certificates/private.pem"); final context = SecurityContext.defaultContext; context.useCertificateChainBytes(certificateChain.buffer.asUint8List()); context.usePrivateKeyBytes(privateKey.buffer.asUint8List()); await SecureSocket.connect(host, port, context: context) // Party time ๐ ...Erroneous code (for reference only of what didn't work as expected) โ
The following code results in a HandshakeException SSLV3_ALERT_BAD_CERTIFICATE(tls_record.cc:587)
pubspec.yaml
... assets: # The root CA and client certificates were previously separate. The solution was to combine # them into a single certificate chain (see above) - assets/path_to_certificates/root_ca_cert.pem - assets/path_to_certificates/client_cert.pem - assets/path_to_certificates/private.pemclient.dart
... // Obtain the raw byte data of the client & root CA certificates and private key file contents ByteData rootCACertificate = await rootBundle.load("assets/path_to_certificates/root_ca_cert.pem"); ByteData clientCertificate = await rootBundle.load("assets/path_to_certificates/client_cert.pem"); ByteData privateKey = await rootBundle.load("assets/path_to_certificates/private.pem"); final context = SecurityContext.defaultContext; context.setClientAuthoritiesBytes(clientCertificate.buffer.asUint8List()); context.setTrustedCertificatesBytes(rootCACertificate.buffer.asUint8List()) context.usePrivateKeyBytes(privateKey.buffer.asUint8List()); await SecureSocket.connect(host, port, context: context) // HandshakeException ๐ฅ ...
You are a hero.
i need this badly right now
Most helpful comment
How / When can I enable TLS 1.2 in Dart? Browsers are complaining about the standart settings.