logo Home C++ Home Server
**Keeping up with C++** This (part of the) blog is mostly meant as a dump for me to put solutions to problems I had a hard time finding solutions to, in the hope that it then helps other people (and future-me) find the solutions faster. # Using letsencrypt with QSslSocket Aug 31, 2018 Recently, I had to implement safe online communication in C++ and Qt with an online server. Obviously, QSslSocket on the client side and a modified QTcpServer (like the one by Rich Moore (maintainer of Qt Network) over at [his github](https://github.com/richmoore/qt-examples/tree/master/httpserver)) is the way to go here. The basic setup was quickly implemented but securing it correctly was a bit more of a challenge than expected and took quite a bit of googling as I’m not an expert on SSL and/or network security (so also take the advice here with a grain of salt ;)). In the end I think I have a pretty good and actually easy setup, so I wanted to share it here. First of all, I wanted to use a real certificate from a CA and not a self-signed one. As I’m currently on a budget [Let’s Encrypt](https://letsencrypt.org/) is a perfect choice there. It took me about 5 minutes to read the instructions, install it on my server, and generate the first certificates. To use those certificates I added the following code to an `init()` method in my SslServer: ``` cpp QFile certFile("/etc/letsencrypt/live//cert.pem"); if( !certFile.open( QIODevice::ReadOnly ) ) { qCritical() << "Unable to open the certificate!!!"; return false; } m_cert = QSslCertificate( &certFile ); if( m_cert.isNull() ) { qCritical() << "Certificate was not valid!"; return false; } QFile keyFile("/etc/letsencrypt/live//privkey.pem"); if( !keyFile.open( QIODevice::ReadOnly ) ) { qCritical() << "Unable to open the key!!!"; return false; } m_key = QSslKey( &keyFile, QSsl::Rsa ); if( m_key.isNull() ) { qCritical() << "Key was not valid!"; return false; } ``` `m_cert` and `m_key` are member variables for the certificate and private key. Unfortunately that means, that you have to either start your server as root or make the key and certificate readable for your program. The “cleanest” way I found was to create a new group like `sslUsers` and add every user that needs access to it and use `chown` to make the files accessible by that group. After that, I added the following code to the `incommingConnection()` method of the server just before the `addPendingConnection()` and `socket->startServerEncryption()`: ``` cpp socket->setLocalCertificate( m_cert ); socket->setPrivateKey( m_key ); ``` The last thing you have to do after all this is to package your client with the `chain.pem` also found in `/etc/letsencrypt/live//` and load it into the `QSslSocket` before establishing the connection like this: ``` cpp QFile chain("chain.pem"); if( chain.open( QIODevice::ReadOnly ) ) { QSslCertificate chainCert( &chain ); if( !chainCert.isNull() ) socket->addCaCertificate( chainCert ); else qWarning() << "Chain certificate is invalid."; } else qWarning() << "Unable to read chain certificate."; ``` Now you can establish a secure connection without ever using `QSslSocket::ignoreSslErrors()`. I hope this little entry helped you in some way. If it didn’t or you have some comments, please let me know! If it did help you, let me know too! :)