TLS/SSL connection using Self-Signed Certificates with Dart and Flutter

Muhammad Tabish Khanday
5 min readMar 13, 2022

--

https://www.thesslstore.com/

Have you ever wanted to use self-signed SSL/TLS certificates in your Flutter application?

I did. ✋

I wanted to build a Flutter application that needed to communicate with the remote server working on an encrypted (SSL/TLS) socket.

Using TLS and managing a CA is an advanced topic. Initially, I researched a lot on this topic but I didn’t get any answer to my question 😔

But after spending a couple of months, finally, I got the answer and I was so excited because all the hard work paid off eventually 😀. I wanted to share my research with the #FlutterCommunity so that everybody will get benefit from my research.

Enough with the background story behind this article. Now, let's dive deep into this…

What is a TLS/SSL?

SSL stands for Secure Sockets Layer and, in short, it’s the standard technology for keeping an internet connection secure and safeguarding any sensitive data that is being sent between two systems, preventing criminals from reading and modifying any information transferred, including potential personal details. The two systems can be a server and a client (for example, a shopping website and browser) or server to server (for example, an application with personally identifiable information or with payroll information).

It does this by making sure that any data transferred between users and sites, or between two systems remain impossible to read. It uses encryption algorithms to scramble data in transit, preventing hackers from reading it as it is sent over the connection. This information could be anything sensitive or personal which can include credit card numbers and other financial information, names, and addresses.

TLS (Transport Layer Security) is just an updated, more secure, version of SSL. We still refer to our security certificates as SSL because it is a more commonly used term.

HTTPS (HyperText Transfer Protocol Secure) appears in the URL when a website is secured by an SSL certificate. The details of the certificate, including the issuing authority and the corporate name of the website owner, can be viewed by clicking on the lock symbol on the browser bar.

How does SSL/TLS Work?

Web servers and web browsers rely on the Secure Sockets Layer (SSL) protocol to help users protect their data during transfer by creating a uniquely encrypted channel for private communications over the public Internet. Each SSL Certificate consists of a key pair as well as verified identification information. When a web browser (or client) points to a secured website, the server shares the public key with the client to establish an encryption method and a unique session key. The client confirms that it recognizes and trusts the issuer of the SSL Certificate. This process is known as the “SSL handshake” and it begins a secure session that protects message privacy, message integrity, and server security.

How to establish SSL/TLS connection using self-signed certificates from the Flutter Application?

In this article, we will establish a connection with the remote Docker Server using an encrypted (SSL/TLS) connection from our Flutter Application.

By default, Docker runs through a non-networked UNIX socket. It can also optionally communicate using SSH or a TLS (HTTPS) socket.

Step 1: Expose the Docker Server with an encrypted (SSL/TLS) socket

For exposing the remote Docker Server with an encrypted socket, Follow this documentation:

Step 2: Copy certificates to your workspace

After Step1 is completed, copy these certificates to your workspace:

  1. ca.pem (Certificate Authority/ CA Certificate)
  2. cert.pem (Client Certificate/ SSL Certificate)
  3. key.pem (Client Key/ SSL Key)

Step 3: Test the connection

Now, you can test the connection using these certificates and keys using the curl command-line tool

curl https://[DOCKER_SERVER_IP]:2376/images/json \
--cert cert.pem \
--key key.pem \
--cacert ca.pem

Output:

Step 4: Create a Flutter Application to connect with the encrypted (SSL/TLS) Docker Server using these self-signed certificates.

The Dart VM supports TLS/SSL out of the box. You can use Dart to connect to
HTTPS resources, as well as create HTTPS servers.

Dart uses BoringSSL (instead of OpenSSL), as its
secure networking library. The Chrome browser, and Chromium, have already moved
to BoringSSL, and Dart is following their lead.

The BoringSSL library is a fork of OpenSSL and is created and maintained by
Google. It is smaller and more aggressively updated and maintained. The
management of certificates and keys, using PEM files, is easier to understand
than the security database used by NSS.

Dart HttpClient

An HTTP client for communicating with an HTTP server.

Sends HTTP requests to an HTTP server and receives responses. Maintains state, including session cookies and other cookies, between multiple requests to the same server.

An HttpClient can make the HTTPS requests, connecting to the server using the TLS (SSL) secure networking protocol. Https scheme will work automatically if the server’s certificate is signed by root CA on the default list of well-known tested CA’s compiled by Mozilla.

In order to add a custom CA, or to send a client certificate to the server that requests one, pass SecurityContext object as the optimal parameter/ context argument to the HttpClient constructor.

SecurityContext

The object contains the certificates to trust when making a secure client connection, and the certificate chain and private key to serving from a secure server.

The SecureSocket and SecureServerSocket classes take a SecurityContext as an argument to their connect and bind methods.

Certificates and keys can be added to a SecurityContext from either PEM or PKCS12 containers.

SecurityContext({bool withTrustedRoots = true});

Creates a new SecurityContext.

By default, the created SecurityContext contains no keys or certificates. These can be added by calling the methods of this class.

If withTrustedRoots is passed as true, the SecurityContext will be seeded by the trusted root certificates provided as explained below. To obtain a SecurityContext containing trusted root certificates, SecurityContext.defaultContext is usually sufficient and should be used instead. However, if the SecurityContext containing the trusted root certificates must be modified per-connection, then withTrustedRoots should be used.

setTrustedCertificatesBytes method

Add a certificate to the set of trusted X509 certificates used by SecureSocket client connections.

useCertificateChainBytes method

Sets the chain of X509 certificates served by SecureServerSocket when making secure connections, including the server certificate.

usePrivateKeyBytes method

Sets the private key for a server certificate or client certificate.

Now, let's get into the coding part of the application:

Dependencies:

File: main.dart

File: home_page.dart

Output:

As you can see in this screenshot, our Flutter Application has successfully connected with the remote encrypted(SSL/TLS) Docker Server using the self-signed certificates. Yay👏👏

That’s all for this article, Hope You learned Something from here.

Thanks, everyone for reading. I’ll be back with some new articles very soon, thanks!

Muhammad Tabish Khanday

LinkedIn: https://www.linkedin.com/in/mtabishk/

--

--