Noise Protocol Framework
noiseprotocol.org
noiseprotocol.org
- The interactions in the protocol are precisely specified
- The exact security properties of the different interactions are precisely specified, including in-depth concepts like the AKE's KCI properties (AKE: authenticated key exchange, KCI: key compromise impersonation, where post-compromise, an attacker can impersonate anyone to the victim, instead of being able to just impersonate the victim to anyone).
- Several mutually compatible reference implementations.
As great as it is, most applications should still rely on TLS for transport security. Noise is primarily for places where TLS' properties aren't suitable.
Another interesting tidbit that might not be obvious: like TLS, Noise is one protocol with many instantiations. Because it builds on a few simple primitives, these can be swapped out, although Noise defines sane defaults. However, an application built on top of Noise is far more likely to have one fixed ciphersuite set (agility, but not negotiation) -- so it wouldn't be unreasonable to think of Noise as a blueprint for a set of protocols.
I'd be happy to answer any detailed questions about the Noise protocol; I am a cryptographer, but I've had nothing to do with its development.
The place where it really starts to make sense to think about Noise is when you're already committed to doing a custom protocol. Jason Donenfeld's Wireguard is a great example: a fresh protocol makes a lot of sense for a new VPN transport.
Ironically, in the context of a secure messenger, the Noise/TLS distinction isn't really important at all. The important cryptography in an E2E-secure messenger happens at a layer higher than the transport itself.
Later
Spitballed this question on crypto dork Slack and there is a use case with a clear answer: if you're doing a datagram transport rather than TCP streams, Noise is probably always a clear win. DTLS is a mess.
I was also told that Wireguard uses Noise on top of UDP, so it would be interesting to see what they did there.
Another good point for Noise: if you're planning to implement a TLS-like protocol from scratch, I would go for Noise instead of TLS. It's just simpler, lighter and easy to customize to your own needs.
But indeed DTLS is a mess for other reasons.
For WireGuard I use Noise with stronger DoS resistance and anti replay measures than DTLS, custom tailored for being a layer 3 tunnel. Details here: https://www.wireguard.io/papers/wireguard.pdf
In what way is MITM easier in UDP than TCP? Assuming you use similar techniques to verify your connection, I can't see a difference.
I've been thinking of trying my hand at something like writing a new implementation of the modern protocol, but I have no need for a truly general one supporting every agreement/primitive set, since I'd rather just implement one, exact Noise protocol. Plus, it'd probably be easier to wait for TLS 1.3 to hit libressl and just use libtls, then. Maybe one day, though...
EDIT: Actually, I remember at one point, I had a early version of the original Noise protocol called "TweetNoise" that I tried to fit into 100 tweets, based on TweetNacl. That was fun. I think I got it finished but never released it. Unfortunately my laptop with the SSD holding that code had its fan die after Christmas, so I can't be sure until next week.
If anyone would like to still do this with the new noise, it'd probably be fun. :)
https://www.wireguard.io/papers/wireguard.pdf
That paper has a bit more in depth elaboration, if you're interested.
I also have an Android client written but still private, which I suppose constitutes a GUI.
So: the future will probably include clicks and swipes!
Kind of a higher-level building block instead of working directly with NaCL and such?
If I'm missing something, can someone explain it to me please?
- Low-level primitives, like AES, ChaCha20.
- Usefully combined primitives, like AES-OCB, NaCl secretbox...
- High-level protocols like TLS and Noise.
- (sometimes) crypto spoken over the encrypted protocols, often for E2E crypto e.g. GPG over SMTPS, or CloudFlare blinded CAPTCHA tokens over HTTPS
This matters because people sometimes think that they're not doing homebrew crypto because they are using e.g. AES. Noise builds on many of the things available in libsodium, including Curve25519 DH, ChaCha20, BLAKE2 et cetera.
What we're waiting for is good Noise-primitive implementations in enough languages. The Noise protocols themselves are probably the best secure channel protocols we're going to get for awhile.
Awesome! thanks for the answers everyone. This looks very interesting.
However... I guess the "don't roll your own cryptography" still applies for this? I mean, I know better than trying to "design" my own algorithms. I even know that I shouldn't try to implement anything below what NaCL provides.
But how about this? Could I use this to deploy my own secure protocol for my own projects?
Obviously I have no formal cryptography training so I'm leaning towards "no, you are not qualified to implement anything", but just out of curiosity, is there some point at which we can build something securely without the need to either outsource this to a security team or getting actual training on security stuff?
Or, put in another way, what amount of security training/knowledge should I have to properly use this while avoiding doing something universally stupid? is it still "you need to be actually trained for this" or is it enough to have some idea and being able to follow some best practices?
I think one of the biggest challenges we have remaining is two-fold: appropriately communicate the tradeoffs between different options (e.g. repudiation vs non-repudiation, post-quantum secure KEX vs regular KEX, fast symmetric nonce-using crypto vs nonce-misuse resistant crypto, et cetera), and making alien technology (SNARKs, MPC...) more approachable.
For most applications, you probably still want TLS instead of Noise. But if you want Noise, you really, really, really want Noise. If for some reason it is necessary to set up a tunnel with a pre-shared key, for example, I'd probably suggest you use one of Noise's PSK modes over TLS.
So, it still depends what you're doing. But noise implementations and "toolkits" bring us closer to a future where applications for which TLS isn't appropriate have a decent chance at a secure protocol too.
If you're using something like AES in GCM mode and ECDHE the only part where you have some leeway in implementation is in how you exchange the ephemeral keys. I largely get around this because both clients and servers are required to have valid X509 certificates and the protocol won't proceed if they can't mutually authenticate. You can use these certificates to sign the preliminary messages (selecting ciphers, digests, and protocol specific parameters) until the key exchange is complete and you're encrypting everything with the ephemeral keys. At that point, even if the static keys are compromised you still get PFS.
You can also mitigate things like KCI MITM attacks by simply forcing strong cipher suites and key derivation protocols. AES-128-GCM and AES-256-GCM when used with ephemeral ECDH (using the right curves) is very well studied and known to provide PFS among other things.
The fact these are interoperable confirms they meet the spec.
Contrast to Argon2, where recent independent implementations found the reference implementation was incorrect.
The math operations for each process would have to be made really fast using C libraries or custom assembly code.
Other concurrent languages/libraries would offer the same benefits I suppose.
I guess the same question can be asked of operations on current generation of GPUs.
In fact, "I'm just starting with Erlang/Haskell/Go and I wanted to play with parallelization so I took the first 100 million integers and spawned a thread to add each individual pair together in a distributed fashion and it's ten thousand times slower than just using a C loop, WTF?" is a very popular post on the relevant language forums. In that situation what happens is because the "payload" of each thread is a single machine-language instruction (give or take loading and saving to memory), all you see is the overhead of starting, stopping, and joining threads. (Or processes or greenlets or whatever.)
Key search is embarrassingly parallel, which is basically a term of art that means "it's so easy anything works".
I think this is where the real challenges lie. We've got plenty of good tools for most of this, and we're now seeing protocols like Noise and STROBE that break new ground past TLS and in many cases help fill gaps TLS left open. You don't need to understand all of the design choices in those protocols in order to be able to write useful applications on top of them.
There are plenty of experimental tools left, like SNARKs and multiparty computation and all sorts of cool stuff -- but that's OK, we can take out this class of problems first.