Preshared Keys

You can optionally “enhance” the security of a WireGuard connection between two hosts by configuring it to use a secret, randomly-generated preshared key. This secret should be 256 bits (32 bytes) long, and be supplied as a base64-encoded string (when base64 encoded, it will appear as 44 alphanumeric characters, ending with an equals sign). It should not be reused for a connection between any other two hosts.

On Linux, you can generate a random preshared key with the following WireGuard command:

$ wg genpsk
/UwcSPg38hW/D9Y3tcS1FOV0K1wuURMbS0sesJEP5ak=

Copy and paste the output of this command into any Preshared Key field in Pro Custodibus (or as the “PresharedKey” setting in a wg-quick-style configuration file).

If you configure one side of a WireGuard connection with a preshared key, you must configure the other side of the connection with the exact same key.

Why?

The connection between two WireGuard peers is secured by the Noise protocol, using ChaCha20-Poly1305 encryption with an ephemeral symmetric key derived via ECDH from the X25519 public key pairs of the two peers. While there are no known practical attacks against this, eventually it might become practical for quantum computers to “crack” this encryption, by calculating the private key of one peer from its paired public key.

To hedge against this possibility (or the possibility that one of the private keys may be stolen by conventional means), you may configure the connection between two peers with a secret shared key. WireGuard will mix this secret preshared key into the derivation process for its symmetric encryption keys. This means that for an attacker to be able to decrypt the data exchanged between the two peers, she would not only have to steal or crack the private key used by one of the peers, she would also have to steal the preshared key (a randomly-generated preshared key would not be “crackable” by quantum computers, nor any other means).

Corresponding Endpoints

In order for two hosts to communicate over WireGuard, they must be configured with corresponding endpoints. Each host must have an interface configured with a unique public key pair, representing the interface’s own peer identity, and each interface must have an endpoint configured with the other interface’s peer identity (ie the other interface’s public key).

From the perspective of the first host, its own interface is the local side of the connection, and this interface’s public key pair is its local peer identity. The second host’s public key pair is the remote peer identity, and that peer is connected to the first host’s interface as an endpoint of that interface.

The perspective of the second host is the mirror image. To the second host, its own local interface, using its own local peer identity, is the local side of the connection; and the endpoint of its local interface configured with the first host’s peer identity represents the remote side of the connection.

So the first host is configured with Peer 1 for its local interface, with an endpoint to Peer 2. The second host is configured with Peer 2 for its local interface, with an endpoint to Peer 1. These two endpoints represent the two sides of the same connection — each corresponds to the other. The first endpoint is the remote endpoint from the perspective of the first host; and the second endpoint is the remote endpoint from the perspective of the second host.

Two hosts connected via corresponding endpoints

These two corresponding endpoints must either be configured with the exact same preshared key, or they must be configured with no preshared key at all.

SHA-256 Hash

Because a preshared key is useful only if it remains secret, the Pro Custodibus UI will not display the key directly (except on the page that allows you to change the key, or on the page that allows you to download the configuration settings for an interface). Instead it will display the SHA-256 hash of the preshared key (which reveals nothing about the content of the key, yet identifies it semi-uniquely).

The hash that Pro Custodibus displays is calculated from the raw, unencoded preshared key itself — not the base64-encoded version of the key (although the hash, once calculated, is displayed with base64 encoding). On Linux, you can calculate the SHA-256 hash of a base64-encoded preshared key the same way, with the following command:

$ echo /UwcSPg38hW/D9Y3tcS1FOV0K1wuURMbS0sesJEP5ak= | base64 -d | sha256sum | cut -d' ' -f1 | xxd -r -p | base64
zsi4Ky9Kp0JVWkdDozwfDBQUZoRJUpPRVEj+7cuxxAg=