3.2.2016

foto Petr Bravenec

Petr Bravenec
Twitter: @BravenecPetr
+420 777 566 384
petr.bravenec@hobrasoft.cz

The usual approach to log in to a web applications is to request username and password. This approach is risky when using unsecured HTTP protocol. Anyone listing to your network traffic can easily read your password using application like tcpdump or wireshark.

This is not good. Of course you do not want to give access to your bank account to unknown attacker. We do not produce bank applications but unpleasant may be event just the fact that someone change settings of your home wifi. Therefore, it is good practice to encrypt sensitive network traffic.

Read earlier article about HTTP SSL server for C++ and Qt
SSL support in HTTP server for C++ and Qt

You can find overview of http server here: Our work - Http Server for C++ and Qt

To encrypt the connection the SSL is commonly used. But it can offer you more then just encryption. If you are relying solely on encryption, you were in the same situation as without encryption at all. Attacker's situation becomes little complicated because he cannot use simple tcpdump or wireshark now but against a computer bandit established in the middle of your internet connection you were still powerless. For such a bandit it would be very easy to impersonate your bank. Instead of talking to bank you were talking to intruder, in fact. Your password to you hard-earned money could be compromised on en encrypted channel, too. To avoid such a situation, you need to be sure that you are talking to real bank. In the real world, is's easy - bank is available at its usual location and you can easily recognize bank clerk from masked robber. On the internet you have no such security, but you can secure the connection in another way.

If you want to be sure you are talking to bank, you have to ensure two things:

  • you have to check the bank's id card
  • you have to know how the id card looks like to avoid faked id card

The role of id cards in computer world play SSL certificates and keys. Validity of the id card (know how the id card looks like) ensures certification authorities.

The situation is reversible - the same procedure, thus checking ID card, the bank can verify that you are really you.

It you have verified bank's id and the bank verified your id, it is needless to require passwords. And that's another thing the SSL offers to you. It is possible to log in to the internet application without password.

How to implement SSL certificate login on the server side

Server has few parameters which configure encryption:

[http]
useSSL = true
sslKey = /etc/ssl/private/mysite.bravenec.eu.key.pem
sslCrt = /etc/ssl/private/mysite.bravenec.eu.crt.pem
sslCaCrt = /etc/ssl/private/hobrasoft.crt.pem

Parameter sslKey and sslCrt are sufficient to create encrypted connection. Next parameter sslCaCrt is the certificate which should be used to sign client's certificate to be considered credible.

In the application using Hobrasoft httpd server call method HttpConnection::verified() to ensure that the client's certificate was issued by known certification authority. Class HttpConnection has also other methods to access client's certificate:

  • bool verified() - returns true when the client's certificate is valid and signed with certificate set with sslCaCrt parameter.
  • QSslCertificate peerCertificate() - returns client's certificate.
  • QString commonName() - returns name set in client's certificate. This value can be used to identify the user.

How to set client's certificate in browser

There are a lot of browsers. This is the procedure for Chrome:

  • Open "Options" dialog.
  • Go to "Advanced" section.
  • Click "View Certificates". The Certificate Manager dialog will open up
  • Go to "Your Certificates" tab an click "Import".
  • Select your SSL certificate which should be in PKCS #12 format.
  • When you access web site signed with the same certification authority, select the certificate.

The server application should identify you using your certificate. If you have written the server's controller properly, no username and password should be required.

How to use your client's certificate using curl

Curl is a small utility for accessing HTTP sites from the command line.

Curl requires key and certificate in PEM format:

curl \
    --cacert hobrasoft.crt.pem \
    --cert bravenec.crt.pem \
    --key  bravenec.key.pem \
    -v -X GET https://weblight.bravenec.eu:8099/

How to use client's certificate in Qt application

Qt applications use class QNetworkAccessManger to access http server. The class works asynchronously, each request needs separated instance of QNetworkRequest. The class requires SSL configuration in QSslConfiguration instance:

QNetworkAccesManager *manager = new QNetworkAccessManager()
// ... manager setting - connections to slots...

// Default configuration
QSslConfiguration configuration = QSslConfiguration::defaultConfiguration();

// CA certificates are replaced with own certificate
QList caCertificates;
QFile fileca("hobrasoft.crt.pem");
filecea.open(QIODevice::ReadOnly);
caCertificates << QSslCertificate(fileca);
configuration.setCaCertificates(caCertificates);

// Client's private key 
QFile filekey("bravenec.key.pem");
filekey.open(QIODevice::ReadOnly);
QSslKey key = QSslKey(filekey);
configuration.setPrivateKey(key);

// Client's certificate
QFile filecrt("bravenec.crt.pem");
filecrt.open(QIODevice::ReadOnly);
QSslCertificate crt = QSslCertificate(filecrt);
configuration.setLocalCertificate(crt);

// Create request and attach ssl configuration to it
QNetworkRequest request(QUrl("https://weblight.bravenec.eu:8099"));
request.setSslConfiguration(configuration);

// Pass the request to QNetworkAccessManager
QNetworkReply *reply = manager->get(request);

There is only idicated how to use QNetworkAccessManager. Real use is something more complex.

Note

This procedure will only work if everything is properly set up, certificates are valid and the server exactly matches the name in the certificate.

If you try to connect to http server with different name then set in certificate, then the authentication fail on the client's side. Then you have to suppress the server verification in your code:

configuration.setPeerVerifyMode(QSslSocket::VerifyMone);

You should always catch signal QNetworkAccessManager::sslErrors(QNetworkReply *, QList<QSslError>). Error can be ignored calling QNetworkReply::ignoreSslErrors() in the connecte slot. Please, consider carefully which errors to ignore and ask the user. Ignoring SSL errors can lead to serious security issues.

Conclusion

Authentication by certificate is not common practice in usual web application. I real world the authentication is used for example to access time stamp certification authorities. This case usually requires specialized application.

You can use authentication in situations where various devices are communicating and it is appropriate to avoid user and password management.

Hobrasoft s.r.o. | Contact