"nofollow" is a deterrent for spammers: they cannot put links and hope
to increase their SEO when all these links have the nofollow
relationship.
"noopener" is a security for links opening a new window. They ensure
the target cannot control us.
Fix#373
Many of the Docker images on hub.docker.com are outdated. The one
specified in the documentation doesn't exist anymore. We provide a
decent Dockerfile to build our own Docker image.
This uses a multi-stage build to avoid polluting the final image with
the intermediate artifacts. The final image is 155 MB. It should be
possible to squeeze it even more by using Alpine Linux for the last
two parts instead of Stretch.
The service is using gunicorn. The user is expected to complete the
installation with a reverse proxy configuration.
Hex-digits with character count above 17 cannot be safely converted to an Integer, see [MAX_SAFE_INTEGER](https://medium.com/the-node-js-collection/javascripts-number-type-8d59199db1b6#53cd).
Therefore, when long keys (e.g. 32 characters) are passed into `generateIdenticon()`, and the modulus of 2^18 is performed, the result is 0 all the time. This means, the identicon will render as an empty svg image.
Here is a proof-of-concept (run in any modern browser):
```js
const key = '841b625dcf75413ff3ed5137a81ff1c3';
const int = parseInt(key, 16);
const hash = int % Math.pow(2, 18);
// throws, due to floating point conversion / integer overflow
console.assert(258499 === hash, "Modulus for 'hash' should be != 0");
const int2 = parseInt(key.substr(-16), 16);
const hash2 = int2 % Math.pow(2, 18);
// works as expected
console.assert(258048 === hash2, "Modulus 'hash2' should be != 0");
```
Truncating the passed in argument to a maximum of 16 characters solves the issue.
As a sidenote, the same code in Python will work correctly:
```python
key = '841b625dcf75413ff3ed5137a81ff1c3'
int = int(key, 16)
hash = int % pow(2, 18)
assert 258499 == hash
```