preroll music
Herald: So, the next talk would be from Trevor Perrin. He has been called -- wait
for it -- "Living Evangelist in cryptographic protocol modernization"; he
helped out design some of the protocols that your phone right now is executing and
sending to that AP over there. Like signal, which gave him the award of the
Levchin Prize and the Noise Protocol Framework, which is used by WhatsApp for
client-to-server communication and WireGuard, the VPN from Jason Donenfeld,
which I don't see around here... Anyways, the talk will focus on the Noise Protocol
Framework. What is the rationale behind it and how to use it. Please hand of
applause. applause
Trevor: All right, thank you everyone for being here. My name is Trevor Perrin; I do
cryptography, consulting and secure protocol design. I'm going to be talking
to you this evening about a project I've been working on for the last few years in
the field of protocol design, which is the Noise Protocol Framework. Noise is a
framework that helps you in creating cryptographic secure channel protocols.
The sort of protocols it addresses is things like TLS or SSH or IPSec, where you
have 2 parties -- they're online at the same time, for example an internet client
talking to an internet server -- they're going to want to exchange a few messages
to authenticate each other and then establish some some shared secret keys,
which they can use for further communication. Secure channel protocols
like this are the the workhorses of practical cryptography; most the time when
crypto is used, it's within the context of some sort of secure channel protocol.
There's other sorts of protocols, like secure messaging and cryptocurrency and
all sorts of other things, but Noise is specifically focused on secure channels,
so that's what I'm going to be talking about in this talk. And probably a lot of
people, just kind of off the bat, have a reaction to that of being like "Well, why?
We we have secure channel protocols already: We have TLS; we have SSH; we have
IPSec; and these things have been a huge amount of effort to design over the last
20+ years. We've been bolting features onto them and picking bugs out of them.
Why would we want to start down that road again and build different and newer
protocols?" And I think, that's a very legitimate question and source of
skepticism. And my feelings about this is as follows: It's that, what a secure
channel protocol does is really a very simple thing; it just sends a couple
messages -- 2 or 3, maybe 4 -- sets up a secure channel. So, these protocols really
should be pretty simple; they should be simple to implement; they should be simple
to design; and I think, a lot of the ones that we find ourselves with -- the
mainstream ones -- for what they do, for what they actually accomplish, I think,
they're probably often too complex, too complicated and too difficult to extend.
And I think, we need to extend them; we're going to need to keep adding features and
extending them into new areas and with new types of cryptography. So, it's important
to have good frameworks and good ways of doing this. I think, this is an area where
we need a lot of room for improvement. And so, Noise is a somewhat, I guess,
ambitious effort in that direction. It's ambitious in the sense that I love to get
it to a point where people could use Noise for building all sorts of new and future
protocols. I'll be the first to admit that it's a work in progress; it hasn't
achieved all of its ambitions yet; its achieved some of them. But we're still
working to extend it and if, by the end of this talk, I have then convinced people in
the next 20 minutes to try to use Noise for all your new protocol design...
Challenges, that's going to be okay. What I mainly want to get across is, just
something about how these protocols work, the components that go into them, the
design space they're a part of, because I think, these protocols are so essential to
computer security, it's helpful for everyone to understand, how they work and
what they do, and not just think of them as kind of black magic that only a few
wizards can ever touch. So, to understand these sorts of protocols, secure channel
protocols, I'm going to want to start by giving just some background on the type of
cryptography that's involved in them: And the main cryptographic construct in any
secure channel protocol is going to be what cryptographers call an "Authenticated
Key Exchange" or "AKE protocol" . And an AKE is just a sequence of messages that go
back and forth between 2 parties, between Alice and Bob, so they can authenticate
each other and then, at the end of that, have a shared secret key that they know
they share with their authenticated party. These protocols, these AKE protocols, can
have different properties: All the ones we're going to look at have forward
secrecy; they might have mutual authentication of both parties; they might
have one-way authentication; how they handled identity information might be
different in different AKEs, so maybe in some AKEs, both parties start off knowing
each other's identity and public key and some AKEs will have to transmit this
information. In other AKEs, they might want to transmit this information, but do
it only after the other party has negotiated some encryption, so that their
identity information is encrypted, is protected on the wire. So, there are
different properties of how these things work; there are different types of crypto
we can use to design AKEs that have these properties. And I want to expand on this a
little bit, because most AKEs that people have experience with, the mainstream ones,
all do their AKE in kind of the same way: They do a AKE using signatures for
authenticaton and Diffie-Hellman for a key agreement. But in the last... that's a 10
or so... 10+ years, there has been a growing interest in doing AKEs that are
just purely based on Diffie-Hellman key agreement without signatures, and there
has been a bunch of papers that analyze security models and do proofs for this
sort of AKE. People have put this into practice in things like Tor and Tor key
agreement by Ian Goldberg and a number of designs by Daniel Bernstein and others,
like SALT cryptoboxes, CurveCP, etc. So, there has been a kind of interest in doing
this and Noise is particularly trying to take this idea and run with it. So, I want
to explain a little bit more about how these sorts of Diffie-Hellman-centric AKEs
work. And so, we'll start by looking at just the key exchange part of an AKE and
this is part is going to be sort of generic to all the protocols, all the AKE
protocols, we talked about, which is just going to be an unauthenticated dDffie-
Hellman key exchange. The way you think about Diffie-Hellman is that there's Alice
and Bob: They each have a key pair, a private key and a public key; they're each
going to exchange their public key with the others; then they're going to take
their public key, they're going to take their private key; they're going to
combine these two and get a shared secret, which is the same for both parties. So,
that's just a basic Diffie-Hellman to add... to key agreement, to turn it into
an authenticated key exchange, you exchange, we're going to add
authentication. And so, we can do that by adding signatures in a very conventional
way: Let's say both parties know each other's public keys, so Bob just has to
send an encrypted signature to Alice; Alice responds with an encrypted
signature; now we have an AKE. And this design is called Sigma, it's essentially
Sigma, and it's essentially how something like TLS 1.3 works, where you first get a
secret key, then send signatures as authenticators under the encryption. And
there's nothing wrong with this design, it's a good design. We can look at that
schematically by imagining that what's happening if we don't consider the message
sequences: Alice and Bob are each signing the key agreement, so that once they get a
shared key, they know that the other party agrees with this shared key by verifying
the signature. If we want to do an AKE that's entirely signature-based, we're
going to have to replace these signatures with some sort of Diffie-Hellman, while
still getting that same confidence and that same guarantee, that the other party
agrees on the ultimate, final, shared secret key we get out of this AKE. So, the
way we can do that is, we can say "Well, these these long-lived key pairs that
people have, we'll call them static key pairs; they're going to be Diffie-Hellman
key pairs instead of signature key pairs; and each party is going, to in addition to
doing an ephemeral, do ephemeral DH for forward secrecy, do an ephemeral DH to the
other party's static key for authentication, and then hash all these
DHs together to get a final key. And the reason why this convinces each party that
the other party has agreed to the final key is, because this final key is a hash
that includes the DH of the authentication DH of their ephemeral key, the other
party's static private key -- the only other party who knows the output of that
DH is the other party -- thus, if we do anything with the final shared secret key,
like receive any encrypted message from it, we know that key can only have been
calculated by the correct counterparty. So, we're accomplishing authentication by
using DH instead of signatures here and so this is a... it's a well understood thing,
but I wanted to kind of just touch on that before we talk about... where I dive into
the history of Noise. And the history of Noise is that a few years ago, I was
reading a lot of these papers that talked, Diffie-Hellman-based key exchange, and
looking at a number of these designs where people were doing Diffie-Hellman-based key
exchange and I thought, these were cool designs. I thought, they were elegant; I
thought they were efficient. But every time someone did a new Diffie-Hellman-
based thing, like nTor or salt or CurveCP or OPTLS, they would sort of start from
scratch and they'd say "Okay, how are we going to do key derivation? How are we
going to do transcript hashing? How are we going to do key confirmation?" If they
were doing security analysis, they'd create their own security model; they'd
write their own Gap DH ROM-based security proof that's pretty much the same
as everyone else's security proof, but it's still a lot of work. So, there was a
lot of reused or sort of repeated work being done to build this style of protocol
and so, the the motivating idea for Noise was, whether we could capture that work
into a framework that just provided you some common elements so people could
easily combine those elements together and create a wide range of different protocols
in this style. And so, I started working on ways of kind of connecting protocol
pieces together. Eventually, I talked to Mike Hamburg who's working on something
else -- this Strobe Protocol Framework that was kind of based on sponge-based
cryptography -- and we kind of took some ideas from that. With with all those ideas
we were able to come up with I think a pretty good system for describing a wide
range of protocols just by taking a Diffie-Hellman operation and some simple
other cryptography and combining them in a bunch of different ways. That core design
of noise is what we arrived at by 2015 and it's been stable since then. We know noise
is still a work in progress because we're trying to extend it and add new forms of
cryptography and build more things around this core but we do have a pretty good
core at this point. We've built a small community around it with a mailing list,
website, specifications, test suites, open source libraries in a bunch of common
languages and we also have a couple users: Noise Based Protocol is used by WhatsApp
for client-to-server communication from the app to the server and WireGuard which
is a next generation VPN tunnel project by Jason Donenfeld, it also uses a a noise
based secure channel protocol. We're also getting interest from some some other
directions, from people doing like Internet of Things, embedded systems,
anonymity network type systems, the Lightning Network proposal for Bitcoin
which will incorporate a Noise Based Protocol. So I think we're getting
interest from people who potentially want a customized secure channel protocol for a
new area they're working in but don't want to drag in a lot of extraneous complexity.
They want something simple and efficient that addresses their use case. That's what
I think is the sweet spot for Noise so far. For the rest of this talk, what I
want to do is talk about what the components of a secure channel protocol
are, why I think it's a good idea to have a framework that addresses the design of
these things, and then fill in the details on what the Noise framework actually is.
Secure channel protocols all have kind of the same structure: they start with a
handshake phase where parties send a few messages back and forth to get a shared
secret key, then they use this shared secret key for the transport phase of just
doing bulk encryption. The transport phase is a simple thing, it's pretty easy to
just use shared keys to encrypt data back and forth, so I'm not going to say a lot
more about it. The handshake phase is where all the excitement and the
interesting things are. Of course, the main component of a secure protocol, a
secure channel, is the handshake. It's going to be just an authenticated key
exchange, an AKE of some sort, but a lot of secure channel protocols will also have
some sort of negotiation that happens logically before the rest of this that
determines the type of AKE, and the parameters of the AKE, and the parameters
of the encryption such as which cipher to use. You can think of this negotiation
happening logically before everything else because it determines everything else, but
in practice, for efficiency, the negotiation of the AKE are usually
overlaid or woven together a little bit. So I might send an initial message from
the client that says "I'm speculatively executing this AKE protocol but I'm
willing to execute these other protocols and I'm willing to use these ciphers for
the transport phase", and then the server can respond by saying "I want you to do a
different AKE, I want you to use these ciphers at the end of it". So you have
these negotiation in AKE happening kind of simultaneously, which is one of the
reasons these protocols are a little complicated to think about. But anyways,
if we were building a single secure channel protocol, we would be trying to
fill in these elements. We would be saying, okay, what AKE do we want to use,
how do we want to instantiate the cryptography within them, and then how do
we want to design a negotiation structure that can select one of these different
things, and how do we assemble all that together. We're not trying to build a a
single AKE protocol, we're trying to build a framework for building AKE protocols, so
we're doing something a little bit more confusing and the reason is pretty simple.
If you're trying to build a single protocol, you have a hard decision, and a
difficult trade-off to manage between adding features into this protocol and
keeping it simple. Because the more features you add, the more negotiations
you have, the more different branches your protocol can take, the more complexity
every implementer has to deal with, the more attack service you have, because if
there's any bug in any of these features that an attacker can navigate to, that's
potentially a problem. We want to work on things that have a lot of features that
address a lot of cases, but we also want to keep things simple. So if we think of
ourselves as creating not just a single protocol, but a framework of protocols, we
can kind of manage that tension a little bit better by imagining that we have all
these features and all these capabilities off to the side, and a library or a tool
somewhere. And when we build a concrete protocol, we're just going to select a
bunch of features and hopefully have some simple combination rules for putting them
together and to get a very customized protocol that does exactly what we want
and not anything that we we don't want. That means that working with Noise is
different from working with something like TLS because with most cryptographic
protocols, you probably can just take a TLS library, point it at another TLS
library, and they'll figure out how to connect. They'll do negotiations, fall
backs, retries, ... and they'll find the intersection of cipher suites and
versions, etc. that they support, and will connect to each other. That's a feat of
engineering, but there's a lot of complexity that lies behind that, and
there's a lot of opacity in understanding what you're really getting. To use Noise,
on the other hand, you have to think in advance about what you want to use, what
AKEs you want to use, what cryptography you're gonna get... You're going to choose
all these things. You're going to have to understand why you want the sequence of
messages, you're going to put them together, and you're going to end up with
something that very much addresses your use case, hopefully, but is not going to
have a lot of extraneous complexity. So that's a different way of working with
protocols and thinking about protocols, but I think it's the right answer for a
lot of cases. At least that's our goal. We want to build as a framework where we can
choose a bunch of things, combine them together, and then end up with a wide
range of different protocols. But to get there is a little bit complicated. To get
there, we're gonna have to take our structure of a secure channel protocol and
break it up into some different elements so that we can mix and match these
elements and get different protocols. We're gonna break it up in a couple
different ways. The first way we're going to do that is we're gonna separate out all
the points in the protocol where runtime decisions are made from all the points of
the protocol, we can think of, it's just straight line, linear code. And the reason
why is because, if we have straight line, just linear cryptographic code that just
does one thing after another and sends one message after another, and does nothing
else, except maybe erroring if it detects, say, it detects cryptographic
authentication failure. We have code like that. It's very easy to test, it's easy to
think about, it's easy to design things around because it just does one thing in a
sequence. And so that's… Noise is very much going to be about forcing people to
use straight line code with no branches as much as possible. Our idea of being a
framework hopefully helps with that because we've moved a lot of decisions
that might have been runtime decisions, negotiation decision in a full protocol,
we're moving them to, hopefully, design time decisions within a framework. But we
might still have some negotiation decisions remaining about, like, which
cipher to use or, you know like, if we try to do a zero round-trip encryption, we
might have to fall back to something else. So there might be some decisions that
remain. We're going to try to compress all those decisions into kind of one, and say
there's only one point in this framework where runtime decisions get made, which is
selecting what we're going to call a Noise protocol. And the Noise… And this notion
of the Noise protocol is going to encapsulate everything else that happens.
It's just a linear sequence of code, it's going to be the AKE plus whatever
transport encryption happens after that. So with this framework we've hopefully…
You know, we hate decision-making at runtime but we're going to compress it
down to one if we have to and then call everything else just a straight line
sequence of code. The next thing we're going to do to make this framework sort of
manageable and break it down, is zoom in on this notion of the Noise protocol and
break that into pieces too. And so we're going to view that as a combination of,
what we call a handshake pattern, with some actual crypto algorithms. And a
handshake pattern is going to be like an abstract notion of an AKE, so it's going
to be an AKE protocol that just says: do some sort of Diffie-Hellman, encrypt this
in some way, hash this in some way, but it's not going to tell you what crypto to
use. You're going to plug in crypto, and it's that combination of things is gonna
give you a concrete Noise protocol, which is in kind of an implementable unit of
this framework. So, the whole framework then kind of ends up being like this: the
sort of core central piece is this notion of the Noise protocol which is, what we've
probably spent most of our engineering effort on, where we combine some abstract
notion of an AKE, a handshake pattern, with some crypto to get a Noise protocol.
We're going to imagine a negotiation layer that can really just make one decision
which is: does the server want to switch from the initial noise protocol to a
different one. So we're only going to allow one transition, just to make things
really simple. And then the only other layer we're going to add, is this notion
of an encoding layer which is that, we might want to send our messages over TCP,
in which case we'd have to add length fields. Or we might send them over HTTP,
in which case we'll have to encode them as HTTP requests. So we have this kind of
abstract notion of our protocol, but we might need to add a little bit more
encoding to actually fit it into a particular context. And that's, you know,
that's gonna be kind of just the whole way we build secure channel protocols. So, the
main thing that you're going to interact with, is, or the kind of central piece of
this is the Noise protocol and the main way that you're going to interact with
Noise protocols and design them as a user, is by just giving them names. And so we
have this notion of, you can precisely name a Noise protocol and then that just,
kind of like, defines the entire protocol. So here we have a Noise protocol that's,
you know, this is a concrete implementable thing: it uses the NX pattern which, I
haven't explained what that means, but it also combines that pattern that AKE notion
with Curve25519 for Diffie-Hellman, with AES-GCM for encryption, with SHA-256 for
hashing, we can plug in or out different options of any one of these things. So we
could have different patterns, different ciphers, etc. to get a Noise protocol and
then the specification, and most of our Noise libraries can take this name and
will just automatically know what to do. They'll synthesize a whole protocol around
this, just with some some pretty simple rules. And, so the pattern notion and the
way we're naming patterns… There is a naming convention here but I think more
important than understanding the naming convention, is understanding this simple
language that it's built on top of. And, so we're gonna have a sort of simple
language for describing a range of sort of abstract AKE patterns based on, based on
this set of concepts, based on just saying we have Alice and Bob, they each might
have a static key and they might have an ephemeral key, and the only things we're
gonna allow them to do, as part of their AKE protocol, is send their public keys
back and forth and do Diffie-Hellman operations and the only Diffie-Hellman
operations they can do are, you know, these four involving some combination of
their keys which you can just read from left to right, so they can do this static-
static Diffie-Hellman, they can do the Alice's static to Bob's ephemeral which
sort of authenticates Alice, you can do Alice's ephemeral to Bob's static which
authenticates Bob, or they can do this EE Diffie-Hellman for forward secrecy. So
we're going to allow them just to combine these units in different ways and get a
wide range of different AKEs out of this. So let's start demonstrate... I'm going to
demonstrate a bunch of patterns and kind of go through them quickly, and let's
start with something that's very simple, which is just a public key encryption. So
this AKE pattern doesn't even describe an interactive protocol, it's just Alice
encrypting a message to Bob. And so, our little language here, we're going to add
three dots to indicate when Alice has prior knowledge of something before the
protocol starts. So this is a protocol where Alice knows Bob's public key at the
outset. She's going to send one message which is an ephemeral public key she
chooses. She's going to do an ES, Ephemeral Static Diffie-Hellman, to
authenticate Bob and that's going to give her public key encryption because then
she's going to have keys that she can use for sort of the transport phase encryption
of the message she's sending to Bob. So that's just--you could think of this as in
like an ECIES or an ephemeral static public key encryption. We could make this
more complicated by saying both parties know their public keys and we want Alice
to authenticate to Bob, and now we just throw in the static-static encryption and
now we have Alice authenticating herself to Bob. We could make another step in
complexity and say we want Alice to authenticate herself to Bob and also send
her public key to Bob, and she might also have to send certificates and things like
that to convince Bob her public key is to be trusted. That can go in the transport
payload, but the point is now we've taken Alice's public key and say instead of it
being prior knowledge of Bob's, it's transported in the message itself, and
we're going to have this additional rule which is that any time we send the static
public key we're gonna encrypt it with all the other keys that have come before. So
in this case Alice's static public key is encrypted with the output of the ephemeral
static DH, which provides some identity hiding, so someone looking at the wire
doesn't know who Alice's is, even though Bob knows. We can move on to interactive
protocols and look at unauthenticated Diffie-Hellman, just looks like this: an
exchange of the ephemeral public keys and a Diffie-Hellman. You could add server
authentication to that, where the server just sends its static public key and does
a Diffie-Hellman. You could imagine that the server's public key is known in
advance by the client and in this case we're not transporting it from the server,
but if we're in this case we can use something even better, which is kind of a
nice property of the style of protocol. We can move that ephemeral static DH from the
second message to the first and say Alice can actually do zero round-trip encryption
to Bob or to the server's public key. So she does--the first message there is
essentially what I earlier called the public key encryption. She's just
encrypting straight away to Bob in her first message, and that's something we can
do with a Diffie-Hellman-based AKE that you can't do with say a signature-based
AKE, because if Bob's static key is the signing key you would not be able to
encrypt to it. So, you know, that's kind of an example of some nice features we get
from this style of AKE. We could continue making things more complicated. So we
could add not just zero round-trip encryption, zero round-trip
authentication, in this first flow by having Alice send her identity and doing
an additional Diffie-Hellman. And if we're doing that we should probably also refresh
the authentication in the second message with this ES so that Bob's authentication
of Alice is based on a fresh ephemeral instead of a long-term static key which
could potentially be compromised. And if we do all this, we get actually--this is
very close to WireGuard's pattern. WireGuard adds an additional feature that
is a pre-shared symmetric key, and that's something that, you know, we designed
working with the WireGuard designer Jason Donenfeld that just allows you to add an
extra key that gets mixed into everything. The idea being that in a VPN context the
two parties want to share a secret key, then your security will depend on either
that or all these Diffie-Hellmans, and so even if someone is able to break Diffie-
Hellman through cryptanalysis or a quantum computer, if you've shared a secret key
through some other means they would not be able to go back and break your traffic. So
that's kind of just an example of how we can take this language that is a fairly
simple language, extend it with new features, and we're interested in
continuing that process and adding new features onto this. So, you know things
that are there in the mix is trying to figure out how to add you know post
quantum resistant algorithms to provide hybrid forward secrecy onto these
protocols, even going back and adding the notions of signatures into this. Because
just like all this machinery we have is good for Diffie-Hellman based protocols,
probably we can take all these notions of patterns and of Noise protocols and how
our approach to negotiation and apply them even to more conventional AKEs
into other things as well. So that's sort of our framework, you know it ends up
looking kind of like this, with some, you know, a very simple negotiation layer
switching to this very linear notion of a fixed Noise protocol that you can assemble
together by taking an abstract notion of patterns and combining it with
cryptography of your choice. You know we're still working on a lot of extensions
for this, I'd love to get more people who wanted to experiment with it or use it for
anything. You can find more on our website which has links to our mailing list as
well. I'm happy to talk about it with anyone. There's gonna be a WireGuard meet
up tomorrow at 3 o'clock and I'll probably be milling around there as well, but if
you want to talk to Jason and other WireGuard people and see how all this
works in a concrete context, that would be you know a good way to learn more about
it. Thank you for listening, and do I have time for questions? Maybe a brief amount
of time. applause
Herald-Angel: Microphone one. Question: So in the context of like multi-
party systems, if you have like a person that has either multiple devices or
multiple keys, is there anything that you could use inside Noise to work with that
so that you have like messages being sent to both identities, or would you recommend
some doing something like that over like a central registry and then linking the keys
and having it sent to one and the devices sharing with each other?
Answer: Yeah that's a good question, I mean I think that really gets into the
scope of what like secure messaging protocols try to address, is when you have
notions of groups and want to be consistent with the group and you want to
talk to everyone in the group and maybe everyone in the group isn't online at the
same time, and I would say that's a different and more complex class of
protocols that we're kind of just not trying to handle here. I think with Noise
hopefully we're looking at something that's a very simple and well understood
design space so we can build a lot of machinery around it, because it's so
simple, and these other cases you're talking about I think just add a lot of
complexity about how you would want to do all those things. So we've kind of just
chosen a narrow scope to make this specific problem a lot easier, I would
say. Q: Okay, thanks!
Q: Does Noise include any of the ratcheting or sort of key evolution over
time properties that we've seen in protocols like this in the past?
A: No, so Noise has a pretty simple model of just you have like a handshake phase
and a transport phase and the transport phase just uses a key. Now we have added a
notion of being able to like update this key by just replacing it with, like, you
know, some of its own output, essentially. So we can kind of roll it forward in a
very simple way and we have an efficient way of doing that, so you could do things
like have every one of your messages update the key to the next key, and then
you have within the protocol forward secrecy. We don't try to do like more
complicated things with Diffie-Hellman ratchets or anything like that,
Q: When would be--what's the simple sales pitch for why to use Noise over TLS?
A: You know, probably the simplest sales pitch would be like, if you really really
want your protocol to just do like one thing and you don't want to drag around a
lot of code that does like a lot of things, you know like Noise will let you
produce a very fine-tuned protocol that's a very small amount of code that just does
like one thing pretty easily.
Herald: That's it, thanks a lot
Perrin: Thank you. applause
postroll music