• Let’s Encrypt is a new Certificate Authority that is automated and free to use. This makes it possible to obtain domain validated (DV) certificates for your domain names as no cost!

    I registered for the closed beta, and got a few of my domain names authorised. This meant that I could now obtain certificates for them. The process was fairly simple. I chose to use the webroot authentication method, which means that the Let’s Encrypt client should be able to place files under my webroot to prove that I control the domain.

    Since my webroot is /var/www I created the /var/www/acme/.well-known/acme-challenge folders for the webroot plugin to use. My web server is Nginx so I placed the following code in the server blocks for the domains I want to obtain certificates for and reloaded the Nginx configuration.

    location ~ ^/\.well-known/acme-challenge {
      root /var/www/acme;
      default_type application/jose+json;

    Now it was time to install and run the Let’s Encrypt client to obtain the certificates. When prompted I used /var/www/acme as the webroot path.

    git clone https://github.com/letsencrypt/letsencrypt
    cd letsencrypt
    ./letsencrypt-auto --agree-dev-preview --server https://acme-v01.api.letsencrypt.org/directory certonly

    So far so good. I now had my certificates under /etc/letsencrypt/live and could configure Nginx to use them. Great! For those who are curious this is my SSL configuration for Nginx:

    ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
    ssl_session_cache shared:SSL:10m;
    ssl_session_timeout 5m;
    ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
    ssl_prefer_server_ciphers on;
    ssl_ecdh_curve secp384r1;
    ssl_dhparam /etc/ssl/dhparams.pem;
    add_header Strict-Transport-Security max-age=31536000;

    The certificates are valid for 90 days, so they need to be renewed fairly often. I wanted to automate this process, so I wrote the following script. Basically it checks all certificates under /etc/letsencrypt/live and if one is about to expire in less than 4 weeks it is automatically renewed. I named this script certrenew.

    if [ ! -d /etc/letsencrypt/live ]; then
      exit 1
    function issueCert {
      /root/.local/share/letsencrypt/bin/letsencrypt certonly --renew-by-default --agree-dev-preview --server https://acme-v01.api.letsencrypt.org/directory --authenticator webroot --webroot-path /var/www/acme $1
    while IFS= read -r -d '' cert; do
      if ! openssl x509 -noout -checkend $((4*7*86400)) -in "${cert}"; then
        subject="$(openssl x509 -noout -subject -in "${cert}" | grep -o -E 'CN=[^ ,]+' | tr -d 'CN=')"
        subjectaltnames="$(openssl x509 -noout -text -in "${cert}" | sed -n '/X509v3 Subject Alternative Name/{n;p}' | sed 's/\s//g' | tr -d 'DNS:' | sed 's/,/ /g')"
        domains="-d ${subject}"
        for name in ${subjectaltnames}; do
          if [ "${name}" != "${subject}" ]; then
            domains="${domains} -d ${name}"
        issueCert "${domains}"
    done < <(find /etc/letsencrypt/live -name cert.pem -print0)
    exit ${exitcode}

    The script can be downloaded here.

    To automate everything I run the following script via cron every day. It calls the certrenew script and if certificates are renewed it reloads the Nginx configuration after the renewal process. This will produce output so you will get an e-mail from the cron daemon when certificates are renewed. If you don't what that then just send the output of certrenew to /dev/null.

    if /usr/local/bin/certrenew; then
      /usr/sbin/nginx -t && systemctl reload nginx
    exit 0

    That's it. Fully automated renewal of Let's Encrypt certificates 🙂

  • Update: I quit using Endomondo some time ago and no longer maintain this script. If it still works, great! If it doesn’t and you can make it work for you, great! If you want to take it and maintain it, feel free to do so.

    Update 2: Stephen Casey has modified this script so it should work again. Please check out his website for a description and a link to the updated script.

    As many people around the world I like to do some exercise now and then, and when that exercise is running I save all my workouts to Endomondo. I have been doing this for over two years now, and have accumulated more than 300 workouts. Recently Endomondo decided to limit the amount of features available for free, and move them to a subscription part of the website. While I have no problems with paying for what I use, I consider it a bad move to start charging for features that used to be free. It doesn’t really affect me that much though, since I never used those features anyway. However, it got me thinking that should Endomondo decide to do something similar in the future, I won’t have the option to switch platform since they hold all my workout data. There is a possibility to export one workout at a time, but Endomondo clearly stated that a mass export function will not be available. I was not satisfied by this so I wrote a script to export all my workouts from Endomondo, and I am posting it here in case some of you want to get all your data back from Endomondo too. After all it’s YOUR data. The script is written in PHP and runs from the command line. For Windows I have put everything needed into a single file. For Linux  and OSX you need to install PHP yourself. Also, in order for the script to work you need to login in one of the following ways:

    1. Put your username and password in a file called secret.txt where the first line is the username and the second line is the password. This does not work with Facebook logins and also requires OpenSSL support in your PHP installation.
    2. Get the cookie used to authenticate you and put the cookie  (everything after “Cookie: ” or the entire line, it doesn’t matter) in a file called cookie.txt. You can get the cookie in several ways: With Wireshark, using Chrome: (F12, reload page in Endomondo, Network, click on one of the resources under headers) or with some extension like TamperData for Firefox.

    If both files exist, username and password authentication takes priority. The script will first download a list of all your workouts, then download the actual workouts. It will remember the the latest workout that was downloaded, so if you run it again at a later point in time, you will only get new workouts. You can modify the function generateFileName to change the filenames of the saved workouts. Disclaimer: This script worked for me. Endomondo can easily change something on their website so this script does not work anymore, so I offer no guarantee that it will work for you. Use this script at your own risk. You can download the script for Linux and OSX or you can download everything needed to run it under Windows. If you’re using Windows you should extract the Endomondo directory from the ZIP file and execute the file run.cmd. For any other OS you should just execute php getworkouts.php.

  • Computer, English Kommentarer lukket til Port Checker: Check if a TCP port is open

    Have you had this problem before? You have started a service listening on some TCP port, and you want to know if it is reachable from the Internet, or if some firewall along the way are blocking the packets. Maybe you’re running the service yourself and testing it from your local network doesn’t tell you anything about reachability from the Internet?

    Whatever the reason is for testing whether or not a TCP port is open from the Internet, here’s a service that can help you do just that: https://portchecker.bytopia.dk/

    It’s really simple to use. Just enter an IP address (IPv4 or IPv6) and a TCP port number and click Check, and the service will tell you if the port is open or closed when accessing it from the Internet.

  • This blog entry is about a small utility I made, which I call VerifiedQR. So read on if you want to know what VerifiedQR is about.

    The short version

    It allows one to store data in a QR code together with a digital signature, so the data can be authenticated by verifying the signature when reading the QR code.

    The longer version

    QR codes are often used for ticketing, especially self-print tickets. To verify the validity of such a ticket, one will normally use one of the following two solutions: Either give the QR reader online access to a database of valid ticket IDs, or preload the reader with all valid ticket IDs. However, both solutions have their disadvantages. Online access is not always (reliably) available, and preloading all valid ticket IDs on the reader prevents you from verifying tickets issued after the preloading has been done.

    The solution which VerifiedQR uses, is to store a digital signature in the QR code together with the data. Hence all readers equipped with the public key can verify that the data in the QR code is correct. Clearly this is nothing new and has been possible for a long time (although I haven’t yet seen it done for data in QR codes). However, for typical signature schemes such as RSA, the size of the signature will be prohibitively large for storage inside a QR code, which can only hold a very limited amount of data and still be easy to read. Another cryptographic solution is to use symmetric key authentication such as HMAC or CBC-MAC, but now anyone with access to a reader can potentially extract the key and forge tickets.

    VerifiedQR uses a type of public key cryptography (BLS signatures based on pairings) to keep the signature size as small as possible while still using public key cryptography. Furthermore, the data is compressed to reduce its size as much as possible. VerifiedQR is a set of Java libraries that allows one to easily generate a QR code storing a list of data items, as well as easily recover and verify data from a QR code.

    Here are some code snippets that demonstrate how it is used. First one must initialise the BLS signature scheme and generate keys. In this example we store them as well:

    BLS bls = new BLS("curve.properties");

    One can (of course) also load keys existing keys. The curve parameters must be the same as when the keys were generated:

    bls = new BLS("curve.properties");

    The data to be stored in the QR code are simply stored as strings in a Vector:

    Vector vec = new Vector();
    vec.add("John Doe");

    It is very simple to generate a 200×200 pixel qr.png file containing the QR code:

    VerifiedQR qr = new VerifiedQR();
    String strData = qr.encodeAndSign(bls, vec);
    qr.generate("qr.png", strData, 200, 200);

    To verify the data, first get the Vector from the QR code data stored in strData:

    Vector vec = qr.decodeAndVerify(bls, strData);

    If verification fails, decodeAndVerify will throw a SignatureException. Also note that for verification one does not have to call bls.loadSecretKey(). In fact verifiers should not have access to the secret key at all.

    VerifiedQR includes a small test program similar to the code above that demonstrates the functionality. Simply compile it with


    and run it with

    make run

    This will generate key material, output a qr.png file, and verify the generated data.

    If you don’t have the make command on your system, just take a look at the Makefile to see what commands should be used.

    The program needs some curve parameters for an elliptic curve to use. Some examples are found in the curves/ directory, but depending on your exact needs (performance and security) you might need to generate other curves.

    License and libraries

    This program is distributed under the GNU GPL v3 and makes use of the following libraries:

    If you want to license the code under a different license, want me to help building an application around this, or just want to chat, feel free to contact me.


    Here is the link to download VerifiedQR.

  • English, Kommentar Kommentarer lukket til English posts on this blog

    So far all posts on this blog have been made in Danish for two reasons: 1) I am danish, and 2) most readers of this blog are from Denmark. However, sometimes I have some ideas, tips or comments (usually IT related) that I feel should be available to a broader audience. Up to now I have refrained from writing these posts since most people who might be interested in reading them, would do a search on Google and would never find a danish blog entry about that topic.

    I have considered switching the blog language to english, but it would seem stupid to write posts in english that only a few people in Denmark care about. After considering possible solutions for a while, I came up with the following solution which is now implemented:

    • Technical posts that appeal to a broader audience will from now on be written in english.
    • Other posts (as well as the main language on this blog) will still be in danish. Usually these posts are of a more personal nature.
    • There is now a category called english, that will contain all english posts on this blog.

    I think this is a reasonable solution. Most danish readers might still be interested in the english posts, and they will be mixed with the other posts in danish. All non-danish speakers probably arrive here via Google and will already be on the page they were looking for, but in case they want to see if there are other posts of interest, they can just browse all posts from the english category.


Seneste kommentarer

  • Du har misforstået det hvis du tror det handler om at man b...
  • > En sjælden gang imellem er der dog nogen man skal hold...
  • Currently I'm using Garmin Connect. I need a way to tra...
  • What are you using now? Before the last update I used to lo...
  • This script is obsolete. Use the renew feature of certbot in...