Cryptography

How to MD5-hash file in C++ using OpenSSL

#include <openssl/md5.h>
#include <openssl/evp.h>
#include <fstream>
#include <iostream>

std::string HashFileMD5(const std::string& filename) {
    std::ifstream file(filename, std::ios::binary);
    if (!file) {
        throw std::runtime_error("Failed to open file: " + filename);
    }

    EVP_MD_CTX* md5Context = EVP_MD_CTX_new();
    EVP_MD_CTX_init(md5Context);
    EVP_DigestInit_ex(md5Context, EVP_md5(), nullptr);

    const size_t bufferSize = 4096;
    char buffer[bufferSize];
    while (!file.eof()) {
        file.read(buffer, bufferSize);
        EVP_DigestUpdate(md5Context, buffer, file.gcount());
    }

    std::array<uint8_t, 16> result;
    EVP_DigestFinal_ex(md5Context, result.data(), nullptr);
    file.close();

    EVP_MD_CTX_free(md5Context);

    return convertToHex(result);
}

 

Posted by Uli Köhler in C/C++, Cryptography

How to compute SHA256 of std::string (hex or binary) using OpenSSL

This code uses the OpenSSL library to compute the SHA256 hash of a given std::string. Two variants are provided, one of them computing a binary hash (returning a std::array<uint8_t, 32>), the other computing a hex hash (returning a std::string).

#include <string>
#include <openssl/sha.h>

template<typename T>
std::string convertToHex(const T& binaryResult)
{
    std::ostringstream ss;
    ss << std::hex << std::setfill('0');
    for (unsigned int i = 0; i < binaryResult.size(); ++i) {
        ss << std::setw(2) << static_cast<unsigned>(binaryResult.at(i));
    }

    return ss.str();
}

std::array<uint8_t, 32> computeSHA256(const std::string& input) {
    std::array<uint8_t, 32> hash{};

    EVP_MD_CTX* mdctx = EVP_MD_CTX_new();
    const EVP_MD* md = EVP_sha256();

    EVP_DigestInit_ex(mdctx, md, nullptr);
    EVP_DigestUpdate(mdctx, input.c_str(), input.length());
    EVP_DigestFinal_ex(mdctx, hash.data(), nullptr);

    EVP_MD_CTX_free(mdctx);
    return hash;
}

std::string computeSHA256Hex(const std::string& input) {
    auto hash = computeSHA256(input);
    return convertToHex(hash);
}

Compile using

g++ -o main main.cpp -lcrypto -lssl

 

Posted by Uli Köhler in C/C++, Cryptography

How to export GPG public key to file using the command line

gpg --armor -o MyKey.gpg --export [Key ID or fingerprint]

For example, with fingerprint

gpg --armor -o MyKey.gpg --export AA15942077B73AE65E88FB4BCFC41606DD8C212E

with (short) key ID:

gpg --armor -o MyKey.gpg --export DD8C212E
Posted by Uli Köhler in Cryptography

How to fix OpenVPN ‘failed to find GID for group openvpn’

Problem:

In your OpenVPN server logs you see this error message

failed to find GID for group openvpn

followed by a server restart (Exiting due to fatal error).

Solution:

Run this command to add the OpenVPN group:

sudo groupadd openvpn

In most cases, you’ll see this in your server log after doing that:

failed to find UID for user openvpn
Exiting due to fatal error

In that case, refer to our previous post on How to fix OpenVPN “failed to find UID for user openvpn”

Posted by Uli Köhler in Cryptography, Linux

How to fix OpenVPN ‘failed to find UID for user openvpn’

Problem:

In your OpenVPN server logs you see this error message

failed to find UID for user openvpn

followed by a server restart (Exiting due to fatal error).

Solution:

Run this command to add the openvpn user and add that user to the openvpn group:

sudo useradd openvpn -g openvpn
Posted by Uli Köhler in Cryptography, Linux

How to generate Diffie-Hellman (DH) parameters using OpenSSL

Problem:

For our webserver or VPN server, you want to use unique Diffie-Hellman parameters but you don’t know how to generate the .pem file using OpenSSL.

Solution:

Use this command to generate the parameters and save them in dhparams.pem:

openssl dhparam -out dhparams.pem 4096

This command generates Diffie-Hellman parameters with 4096 bits. This provides good security while still providing a very reasonable performance for modern devices. Depending on your preferred level of Paranoia you might want to increase the number of bits even more.

Note that even for “only” 4096 bits generating the parameters will usually take a couple of minutes. Larger parameter sizes might take many hours to days to generate. Ensure that you are generating the parameters on a fast computer and not on your Raspberry Pi or similar!

Posted by Uli Köhler in Cryptography, Linux

GPG symmetric encryption: Passphrase on command line

Problem:

You want to use GnuPG’s –symmetric encryption, but instead of interactively entering the password you want to use a command line argument with the cleartext password.

Solution:

Use --batch --yes --passphrase <passphrase>:

gpg --symmetric --batch --yes --passphrase 12345 <input file>

Note that this is potentially insecure as it’s way easier to find out the command line parameters of running programs than intercepting the inputs of the interactive input dialog. Therefore, use this strategy only if neccessary.

Posted by Uli Köhler in Cryptography

How to automatically renew Let’s Encrypt certbot certs on Ubuntu

New: Our new post How to install automated certbot/LetsEncrypt renewal in 30 seconds features an updated procedure using systemd and an automated installer.

On Ubuntu, you can easily setup a daily job that tries to renew almost-expired Let’s Encrypt certificates.

Create /etc/cron.daily/renewcerts:

#!/bin/bash
certbot renew
service nginx reload

After that, sudo chmod a+x /etc/cron.daily/renewcerts.

Now you should verify that the script would actually run:

run-parts --test -v /etc/cron.daily

should print, among other lines, this line:

/etc/cron.daily/renewcerts

IMPORTANT: You still need to run certbot renew manually every 1-2 months to check if there are any errors that might prevent certs from being renewed.

NOTE: Since the script is calling service nginx reload, you need to ensure that your nginx config files are not left in a broken state for too long if you edit them. Use sudo nginx -t to check for errors after you edit them. Also note that if you make nginx config changes, the script might unintentionally apply them to your productive HTTP/HTTPS server!

Posted by Uli Köhler in Cryptography, Linux

How to build libsodium (NaCl) DEB packages

Problem:

You want to create a binary DEB package of libsodium. However, there is no official DEB package available for the latest version.

Continue reading →

Posted by Uli Köhler in Cryptography, Linux

C/C++ Base64 codec using libtomcrypt

Problem:

In C/C++ you want to encode/decode something from/to Base64. libtomcrypt is WTFPL-licensed and therefore provides a good choice for both commercial and non-commercial projects.

Continue reading →

Posted by Uli Köhler in C/C++, Cryptography