On the Complexity of Passwords

Passwords protect your accounts
Passwords protect your accounts

Nowadays, many applications and services run remotely somewhere on the Internet. In order to use the tools, you usually need to authenticate yourself with a user name and password. The complexer the password the safe your account. There are several ways to make a password complex. For example, you can choose characters from many different character classes: small letters, capital letters, numbers, special characters. Or you can use an extraordinarily long password, for example a sentence like ‘my pigeon loves to jump with the sunglasses of my neighbour on Sundays’. The password will be even more secure if the sentence contains a spelling mistake, and if it reveals something embarrassing it will be easier to remember the sentence :)

I claim that the password sentence above is much more secure than the password a0%Al;k/m (and various password analysis tools support my claim). Consequently, it is even more vexing when the service providers have annoying requirements for a password: it must, for example, consist of lower case letters, upper case letters, digits and be at least 8 and at most 20 characters long. I absolutely cannot understand why some providers put a ceiling on the length of a password!? My secure password sentence above would be rejected, but the rather insecure password gets accepted.

The password strength measured in terms of entropy

I wrote this article when I needed to implement password authentication for one of my projects. However, instead of demanding different character classes and a minimum length I decided to demand a minimum complexity. Here, I measured the complexity in terms of theoretical entropy of the password: the entropy per character of a password, which contains characters from many character classes, is much higher than the entropy of a password, which only consists of numbers.

I calculate the entropy H\Eta (Greek letter Eta) as H=Llog2N\Eta = L\log_2 N, with LL being the length of the password and NN being the size of the alphabet. Thus, a long password has a higher entropy than a short one; a password, which contains characters of different classes, has a higher entropy than a password, which contains only numbers. According to this method, the following passwords have a similar complexity:

  • a0%Al;k/m (59.2647 bit entropy)
  • 123456789012345678 (59.7947 bit entropy)

This allows service operators to define a minimum entropy for chosen passwords and users can chose passwords more liberally. I have attached my implementations below this article.

General password tips

Finally, I have some general tips on choosing and storing passwords.

Use different passwords!

In my opinion that is the most important rule. Passwords get compromised pretty often: A hacker breaks into a provider’s site or a dissatisfied administrator shares the database in some underground forums. If you are using the same password for all services, an attacker will immediately get access to all your accounts. For example, if Twitter gets hacked, the hackers can also access your Facebook profile with your login data.

Of course, it is difficult to remember a different password for each service, especially if you want to have them very complex. Therefore, two tricks:

  • Choose a password rule. For example a_0%Al;k/m, where you always replace the underscore with the first and last letter of the service you want to use the password for. For Twitter the password would be atr0%Al;k/m. This password will then fail on Facebook, where the password would be afk0%Al;k/m.
  • Use a password manager! They are really good. If you do not trust the password safe, you can also remember a prefix or suffix to the passwords. Thus, the password manager only stores a part of the password (which can be complex and long), but you would have to enter a few more characters to use it. This means, even if the password database gets into the wrong hands, an attacker cannot do anything with it: None of the passwords work without your additional knowledge! :)

Use several factors

Many services offer a two-factor authentication. Usually you have to enter a code in addition to a password,

  • which you will receive via SMS,
  • which is calculated by an app, or
  • which is generated by a hardware token.

This type of authentication is much more secure than a pure password.

Implementation of the entropy check

Maybe my implementation helps someone?

Client side at an Angular frontend:

import { AbstractControl, ValidationErrors, ValidatorFn } from '@angular/forms';

/**
 * A validator that checks if a string contains enough entropy.
 * It accept a validation error object to return if it encounters an error,
 * and the minimum number of bits required
 */
export function entropyValidator(error: ValidationErrors, minBits: number = 80): ValidatorFn {
  return (control: AbstractControl): { [key: string]: any } => {
    if (!control.value) {
      // if control is empty return no error
      return null;
    }

    let alphabetSize = 0;
    if (/\d/.test(control.value)) alphabetSize += 10;
    if (/[a-z]/.test(control.value)) alphabetSize += 26;
    if (/[A-Z]/.test(control.value)) alphabetSize += 26;
    if (/[^0-9a-zA-Z]/.test(control.value)) alphabetSize += 34;

    // if true, return no error (no error), else return error passed in the second parameter
    return control.value.length * Math.log2(alphabetSize) > minBits ? null : error;
  };
}

Server side at an PostgreSQL database:

create or replace function XXX.assert_valid_password
(
  new_password text
) returns void as
$$
declare
  alphabet_size  integer := 0;
  min_bits integer := 80;
begin

    -- contains lower case letter
    if (select new_password ~ '[a-z]') then
        alphabet_size = alphabet_size + 26;
    end if;

    -- contains upper case letter
    if (select new_password ~ '[A-Z]') then
        alphabet_size = alphabet_size + 26;
    end if;

    -- contains digit
    if (select new_password ~ '[0-9]') then
        alphabet_size = alphabet_size + 10;
    end if;

    -- contains special char
    if (select new_password ~ '[^A-Za-z0-9]') then
        alphabet_size = alphabet_size + 34;
    end if;

    -- estimate entropy
    if length(new_password) * log (2, alphabet_size) < min_bits then
        raise exception 'Password is too weak' using errcode = 'WEAKP';
    end if;
    
end;
$$
  language plpgsql volatile;

Share files over the network: smoothly and gracefully

Share files between local devices
Share files between local devices

You probably know the situation: You are sitting at a friend’s and/or client’s place and want to share some pictures or an installer. For small files, an e-mail may be justified, but even a few MB may take ages, if the mail server doesn’t refuse larger files at all. Those, who understand the path that an e-mail needs to follow, can certainly understand that this is an extremely inelegant solution.

An alternative is to copy the files to a USB stick, but who always has a stick with them? And then the stick may be formatted in a way that it is not readable on the target system…
Those solutions are rather like this… nineties… ;-)

It is much more elegant to start a webserver on your own laptop, which serves the files in the local network!

Installing and configuring a whole web server for such a nonsense? How fast should the operating system age??

Yes, exactly! But install it virtualised in a container, instead of natively on the laptop. Nowadays, every good IT professional has Docker or something similar on his laptop anyway, and an image from a web server is usually already downloaded (otherwise Docker loads it relatively quickly on first use).
This way, you can share any file very quickly and elegantly. For example, I prefer to use the Nginx web server (but of course you can also use the httpd of Apache, lighttpd and others). If I want to share the file /path/to/file.zip I just call:

docker run --rm -v /path/to/file.zip:/usr/share/nginx/html/file.zip -p 80:80 nginx

Thada…! Now file.zip can be downloaded from the laptop as http://IP.OF.THE.LAPTOP/file.zip. If the laptop received a DNS name in the network it is even more comfortable.

Anyway, this is really amazingly fast and reliable in almost every network. Much faster than sending it to your mail server, which then forwards it to the next mail server, etc…
The only requirement is that the computers must be able to communicate with each other in the local network (a few networks prohibit client-to-client communications). Only files mounted into the container are shared. The webserver will not be able to see any other files on your laptop and, thus, will not accidentally share something else!
However, don’t forget to stop the container at the end of the session to avoid accidentally “sharing” files in the next network and/or accumulating sharing web servers ;-)
Thanks to the --rm flag everything is tidy again afterwards. The system stays young!

More alternatives

  • If both people use the same chat system, you can also quickly transfer files via Matrix or Threema or something like that.
  • If you have a cloud (Nextcloud, Dropbox, Onedrive, Google Drive, Mega, etc), you can of course also share files conveniently via it. There are also a number of providers on the net where you can upload and share files without registration.

However, these approaches mean that the files have to leave the local infrastructure. This is not very nice in terms of security and privacy and tends to take longer.
The solution with the local web server in a docker container would certainly be preferable.

Translated with www.DeepL.com/Translator (free version)

Add Icons to embedded OpenStreetMaps

The local art gallery was searching for a method to present open-air-art on a website. A word and a blow… Using OpenStreetMap it’s possible and beautiful!

Here is an example of the logo of CODE AHOI projected into Rostock’s city harbour:

This is a Placeholder

To display the map you need to download tiles from OpenStreetMap. Their privacy policy is available here: wiki.osmfoundation.org/wiki/Privacy_Policy

That’s cool, isn’t it? :)

Do it Yourself!

Using the OpenLayers project it is comparatively easy. First we need some HTML skeleton:

  • we need to include OpenLayers as a dependency,
  • we need an HTML container to display the map,
  • we need a bit extra HTML to realise a pop-up.

Here is an example template:

<body>

  <div id="map" style="width:100%; height: 50vh">
    <!-- hier wird die Karte angezeigt -->
  </div>
  
  <div id="popup" class="ol-popup">
    <a href="#" id="popup-closer" class="ol-popup-closer">
      <!-- kleines x um das Pop-Up zu schließen -->
    </a>
    <div id="popup-content">
      <!-- Inhalte im Pop-Up -->
    </div>
  </div>

  <!-- Bibliotheken des OpenLayers' Projekt herunterladen -->
  <link rel="stylesheet" href="/path/to/openlayers/ol.css">
  <script src="/path/to/openlayers/ol.js"></script>
  
</body>

One Icon-Feature per Icon

Now the magic begins. For every icon, that we want to display in our embedded map, we need to create an Icon Feature. For the CODE AHOI map above it looks like the following:

// create a feature, that will be displayed as icon
const iconFeature = new ol.Feature({
  geometry: new ol.geom.Point(ol.proj.fromLonLat([12.1110,54.0966])),
  info: {
    headline: "OpenStreetMap AHOI",
    body: "CODE AHOI's paper boat is swimming in Rostock's city habour. [...]"
  },
});

// style the feature: here we're setting an image as icon
iconFeature.setStyle(new ol.style.Style({
  image: new ol.style.Icon({
    src: "https://codeahoi.de/s/articles/2020/openlayers-showcase.png"
  })
}));

// combine everything into a new layer
var vectorLayer = new ol.layer.Vector({
  source: new ol.source.Vector ({
    features: [iconFeature]
  })
});

The first block sets some properties for the icon: Where should it be located on the map? Which headline and what content should be displayed in the pop-up? The second block defines what the icon should look like. Here we load an image from CODE AHOI’s webserver, which will then be shown on the map.. The third block creates a new vector layer, which will be shown on top of the map tiles – that’s the actual speciality of OpenLayers :-)
In this case it may seem very difficult for a single icon, but for many icons it can easily be automatised.

Load the Map

Now we can load the map. The bottom layer should contain the tiles of OpenStreetMap. On top we want to draw our icon. We want to zoom to level 15 and centre the map in Rostock’s city harbour. Coordinates and zoom level can be obtained from openstreetmap.org. If you choose the same coordinates for the icon and the map, the icon will be centred in the map ;-)

var map = new ol.Map({
  // display the map in the container with the id 'map'
  target: 'map',
  
  // the "open" layers ;-)
  layers: [
    new ol.layer.Tile({
      // use tiles from OpenStreetMap for the bottom layer
      source: new ol.source.OSM()
    }),
    // add out vector layer on top
    vectorLayer
  ],
  
  view: new ol.View({
    // initially center the map at [12.1110,54.0966] (Rostock's city harbour)
    center: ol.proj.fromLonLat([12.1110,54.0966]),
    // zoome to level 15
    zoom: 15
  })
});

Now the map get properly loaded and the icon is displayed at the correct location.

Implement a Pop-Up

Almost done, but we want to display a pop-up if the user clicks the CODE AHOI icon. That requires a bit more code:

var container = document.getElementById('popup');
var content = document.getElementById('popup-content');
var closer = document.getElementById('popup-closer');


// the pop-up will become an extra layer
var popup = new ol.Overlay({
  element: container,
  autoPan: true,
  autoPanAnimation: {
    duration: 250
  },
  positioning: 'bottom-center',
  stopEvent: false,
  offset: [0, -25]
});
map.addOverlay(popup);


// event-listener for clicking the x
closer.onclick = function() {
  popup.setPosition(undefined);
  return false;
};


// event-listener for clicking the map: did the user click our icon -> display the pop-up
map.on('click', function(evt) {
  // was our icon clicked?
  var feature = map.forEachFeatureAtPixel(evt.pixel, function(feature) { return feature; });
  // if so, put the information that we stored along the icon into our pup-up
  if (feature) {
    // where should we display the pop-up?
    var coordinates = feature.getGeometry().getCoordinates();
    // what's the textual content in the pop-up?
    content.innerHTML = '<h2>' + feature["values_"]["info"]["headline"] + '</h2><p>' + feature["values_"]["info"]["body"] + "</p>";
    
    // display the pop-up at the proper location
    popup.setPosition(coordinates);
  } else {
    // the user clicked something else in the map -> close the popupo
    popup.setPosition(undefined);
  }
});

We can realise the pop-up as an extra layer (see second code block) in the map – this way the pop-up is less intrusive and comes with better look and feel. The necessary information for the pop-up are already stored along the icon feature. Here we can read and use the properties, if the user clicks the icon (see last code block).

Styling

The logic is done. However, for the make-up we need some proper finishing ;-)
The style depends a lot on the layout of the whole page and some subjective criteria, but in general you would need to add a closing-symbol to the popup-closer container and style the pop-up-bubble a bit. Here is an example:

/* closing-x */
.ol-popup-closer {
  text-decoration: none;
  position: absolute;
  top: 2px;
  right: 8px;
}
.ol-popup-closer:after {
  content: "✖";
}

/* pop-up-bubble with a little triangle pointing to the icon */
.ol-popup {
  position: absolute;
  background-color: white;
  box-shadow: 0 1px 4px rgba(0,0,0,0.2);
  padding: 15px;
  border-radius: 10px;
  border: 1px solid #cccccc;
  bottom: 12px;
  left: -50px;
  min-width: 280px;
  display: none;
}
.ol-popup:after, .ol-popup:before {
  top: 100%;
  border: solid transparent;
  content: " ";
  height: 0;
  width: 0;
  position: absolute;
  pointer-events: none;
}
.ol-popup:after {
  border-top-color: white;
  border-width: 10px;
  left: 48px;
  margin-left: -10px;
}
.ol-popup:before {
  border-top-color: #cccccc;
  border-width: 11px;
  left: 48px;
  margin-left: -11px;
}

Full Solution

My code for the example above is un-obfuscated available for download

The HTML skeleton of the whole article is of course a bit more complex, but that you can find out on your own!

Let's Go!

Lights off & spot on: CODE AHOI goes live! After some preparations I set sail and give it a try :)

I have been learning and working for years at universities. The urge to advance increased, but I am not sure where to go…
I am professionally trained, I love working interdisciplinary, and I quickly become acquainted with new domains. Furthermore, I am an expert in gathering and integrating data from heterogeneous sources, exploring complex materials to find patterns, and communicating results. I would like to apply earned skills and help organisations and the local economy.
Thus, CODE AHOI is my freelancing-attempt to obtain broad experience in many domains, to eventually learn where to continue my journey.

A first walking advertisement is this website. I decided for a static page with Jekyll: the web server does nothing but serving pre-compiled pages. Such a website is much more performant and eco-friendly, it typically tracks less personal information, and, as no scripts are executed, it can be considered much more secure. In addition, my whole infrastructure is powered by green energy!

The initial setup of such a site may be a bit more complicated, but with a little technical sense you can even make it multilingual (note the flag top right)! :)

I also decided against any kind of tracking: read or skip and click whatever you want — I do not care. If you want my attention just leave a message through the contact form at the bottom of that page.

I am highly motivated and very excited!