Weave Net Cryptography FAQ
What do you recommend for confidentiality, integrity and authenticity with Weave Net? Weave communicates via TCP and UDP on a well known port, so you may use whatever is appropriate to your requirements – for example an IPsec VPN for...
What do you recommend for confidentiality, integrity and authenticity with Weave Net?
Weave communicates via TCP and UDP on a well known port, so you may use whatever is appropriate to your requirements – for example an IPsec VPN for inter-DC traffic, or VPC/private network inside a datacentre. For cases when this is not convenient, Weave Net includes a secure, performant authenticated encryption mechanism which you can use in conjunction with or as an alternative to other security technologies. The rest of the FAQ pertains to this feature, which is implemented with Daniel J. Bernstein’s NaCl library.
Why did you choose NaCl?
In keeping with our ease-of-use philosophy, the cryptography in Weave is intended to satisfy a particular user requirement: strong, out of the box security without complex set up or the need to wade through configuration of cipher suite negotiation, certificate generation or any of the other things needed to properly secure an IPsec or TLS installation.
In reality Weave’s requirements on a cryptographic protocol are comparatively simple, mainly as a consequence of the fact that we control the software deployed at both ends of the session. Many features common to IPsec and TLS (such as cipher suite negotiation) are not required, and since such complex functionality has historically proven to be a source of protocol design flaws we weren’t keen to include them in Weave.
Finally, there is the matter of robust implementations. Both IPsec and TLS implementations have suffered from a litany of side channel attacks, protocol downgrade vulnerabilities and other bugs. NaCl has been designed and implemented by professional cryptographers to avoid these mistakes, and make state-of-the-art authenticated encryption available to implementers via an API that is highly resistant to misuse. This is why we chose NaCl.
I heard that Weave’s handshake is plaintext!
It is, but so too are those of protocols such as (D)TLS. The following information is transmitted in the clear by each peer when a new connection is established:
- Connection ID
- Protocol Version
- Public Key
This minimal set of non-confidential information is required for Weave’s peer discovery mechanism to work efficiently in the presence of encrypted sessions. By comparison, TLS with client authentication involves sending both server and client certificates containing distinguished names, serial numbers and public keys across the network in plaintext.
I heard that Weave uses an unhashed passphrase (facepalm)
Salting and hashing should be used whenever a service does not require access to the plaintext of a credential – for example when storing user passwords in a database. In other cases, such as the private key of a TLS server, access to the plaintext is essential and as a matter of standard practice (hardware security modules excepted) this material is kept in unencrypted form so that services can restart without operator intervention. You should think of the Weave passphrase in the same way, and protect and distribute it in a similar fashion. Weave never transmits your passphrase over the network.
How is the passphrase used?
Every time a new control plane TCP connection is established between a pair of Weave peers the following steps occur:
- Both peers use NaCl to generate a new Curve25519 keypair, the public half of which is transmitted to the other peer
- Each peer uses NaCl to combine their private key with the received (unauthenticated) public key of the remote peer to derive a shared secret which is unique to that particular session
- Each peer derives an ephemeral session key by computing the SHA256 hash of the shared secret concatenated with the passphrase
If the passphrase is not identical on both peers, the derived session keys will be different, and the connection will be terminated; the same is true if an active attacker attempts to substitute public keys. This scheme has the following properties:
- Offline dictionary attack resistance. The passphrase is never transmitted across the network, so cannot be sniffed and subjected to a brute force attack
- Forward secrecy. Every session between peers uses a pair of freshly generated Curve25519 keypairs, which are then used to derive a shared secret; the passphrase is then mixed into this secret with a 256-bit SHA hash. If the passphrase is disclosed, it is not possible to compromise historic traffic as the ephemeral private halves of the keypairs are not known
- Known-key security. If a session key between peers is compromised, it is not possible to obtain the passphrase nor read traffic between other peers
- Online dictionary attack resistance. An active attacker can make only one guess at the passphrase per protocol interaction; connection acceptance is rate limited to thwart brute force attacks (nevertheless, as with any service it is good practice to monitor your logs for probing behaviour)
How do I choose a passphrase?
You are strongly encouraged to generate a high entropy passphrase from a random source to protect against probing attacks; see here for details.
Is Weave vulnerable to stripping/protocol downgrade attacks?
If a Weave peer is configured to use encryption, it won’t accept or make connections to peers that aren’t. Consequently if you MITM a pair of Weave peers and strip out either of the public keys from the handshake (as you might similarly filter STARTTLS capability from an SMTP connection) the connection will not establish and you will get an error in the logs.
When crypto is enabled Weave automatically uses a sliding receive window of the same type as IPsec and DTLS, implemented efficiently using a bitset. It is sized to permit reordering of recent UDP traffic whilst maintaining perfectly accurate duplicate rejection.
Side channel attacks?
Weave’s crypto is a very thin wrapper around the Go NaCl library contributed by Adam Langley and others, which is in turn a direct port of Bernstein et al’s original C/assembler library of the same name. This code has been systematically constructed to eliminate timing side channels and padding oracles of the kind that have plagued TLS and IPsec for years.
Why does your UDP encryption utilise only eight of the twenty-four NaCl nonce bytes?
NaCl supports 192-bit nonces so that randomly generated nonces have negligible risk of collision under the birthday paradox. Weave Net’s strategy for guaranteeing that a given key/nonce pair is never reused does not rely on chance:
- We use a monotonically increasing message sequence number between each pair of peers (NaCl’s nonces don’t need to be unpredictable, merely distinct) which is reset at the start of each session
- Every session between peers uses a new key
This means we guarantee never to reuse a key/nonce pair until our message sequence number wraps. We chose 64 bits as a reasonable compromise between per packet overhead and wrap protection – gigabit ethernet can transmit approximately 1.5 million minimum sized UDP packets per second, at which rate it would take a 64-bit counter just shy of 390 thousand years to wrap.