📜 ⬆️ ⬇️

Do you want to encrypt any TCP connection at all? You now have a NoiseSocket



Hi% username%!

Not everything in this world revolves around browsers and there are situations when TLS is redundant or not applicable at all. Not always there is a need for certificates, very often the usual public keys are enough, to take the same SSH.
')
And there is also IoT, where pushing TLS entirely is generally not a task for the faint of heart. And the backend, which, I am almost sure, all after the balancer communicates with each other via normal HTTP. And P2P and more and more and more ...

Not so long ago, the Noise Protocol Framework specification appeared on the network. This is essentially the constructor of secure data transfer protocols, which in simple language describes the stage of the handshake and what happens after it. The author is Trevor Perrin, the leading developer of the Signal messenger, and Noise itself is used in WhatsApp. So, there was an excellent reason to take a closer look at this protocol framework.

We liked it so much with its simplicity and conciseness that we decided to use it on the basis of a whole new network layer protocol that is not inferior to TLS in security, and even surpasses something in some way. We presented it at DEF CON 25, where it was very warmly received. It's time to talk about him and us.

First, a little about the direct core of NoiseSocket, namely

Noise Protocol Framework


In fact, any of the protocols described by the Noise Framework is a sequence of transmitted public keys and the Diffie-Hellman operations performed on them.

The main idea of ​​the Noise Protocol Framework is that absolutely all actions during the handshake affect the state of the protocol and, therefore, the final session keys. All DH, all additional data that is transmitted or taken into account during the handshake, are mixed into the general state using hashing and form as a result common symmetric keys.

All this happens within a simple system of states, which consists of three parts.



There is, by the way, a video in English, where David Wong tells in a fairly accessible manner how things work there.



HandshakeState is responsible for processing tokens and messages.

SymmetricState generates symmetric keys from DH results and updates them with each new DH. Thus, immediately after the very first DH, the data that follows it (static keys, payload) is already encrypted with some kind of symmetric key.
More SymmetricState hashes additional data, such as the keys themselves, the optional prolog , the names of the protocols, etc. All this allows the protocol to be holistic and protected from outside interference at all stages of data transfer.

CipherState is a symmetric AEAD cipher + nonce (counter) just initialized by some key, which is incremented with each call of the encryption function.

Protocols in Noise are described in a special language that consists of patterns, messages, and tokens.



Consider for example one of the protocols, Noise_XX, which allows you to establish a secure connection by exchanging static server and client keys in the process:

Noise_XX(s, rs):
-> e
<- e, ee, s, es
-> s, se


Noise_XX is a pattern . It describes the sequence of messages and their contents.

(s, rs) indicates that the client and server are initialized with their static ( s ) key pairs. These are the ones that are generated once. r means remote.

As we can see there are three lines with arrows. One line - one message. Arrow means who sends to whom. If right, then the client to the server, otherwise vice versa.

Each line consists of tokens . This is one or two letter expressions separated by commas. Single letter tokens are only e and s and mean ephemeral and static public keys, respectively. Ephemeral generated once per connection, static reusable.
In general, in Noise, all protocols begin with the transfer of an ephemeral key. Thus, Perfect Forward Secrecy is achieved. Approximately the same thing came up in TLS 1.3 when all non-ephemeral ciphersuites were canceled.

Two-letter tokens mean Diffie-Hellman between one of the client and server keys. They are, as it is easy to guess, of four types:
ee , es , se , ss . Depending on what keys DH is between, it performs different functions. ee , for example, is needed to randomize the resulting key for the transport session, and DH with the participation of static keys are responsible for mutual authentication.

As you can see, in the XX pattern, the client's static key is transmitted to the server, exactly as vice versa. Therefore, three messages are used here. There are patterns that suggest that the client has a static server key (for example, when he first made XX) and reduce the number of messages to two. In addition, it is possible to transmit encrypted data immediately in the first message, which is called 0-RTT and reduces the response time from the server.



For each handshake message, you can add a payload. These can be top-level protocol settings, the same certificates, just digital signatures, in general, anything within 64k bytes. All Noise packets are limited to this size. So parsing is simplified, the length is always placed in 2 bytes, it is easier to work with memory.



As a result, the handshake in our hands remains essentially only two symmetric key, which are the result of all DH, occurred earlier. One to send messages, the second to receive them. Everything, after that we can send encrypted packets, incrementing nonce every time after sending.

In addition to the pattern, the Noise Protocol is characterized by algorithms that it uses in each particular case. The specification lists the algorithms for DH, AEAD and hash. No more noise needed.

DH: Curve25519, Curve448,
AEAD: AES-GCM, ChachaPoly1305,
Hash: Blake2, SHA2

All primitives are very fast, no RSA and other inhibitory junk. Although, of course, if you want, you can do it yourself, no one forbids it.

NoiseSocket


We saw all this beauty and realized that this is an ideal candidate for the role of the next generation transport protocol. After all, right there out of the box there are all the necessary security features, performance, the ability to screw up their authentication mechanisms. And the predicted size of the code should allow you to create normal secure connections from any, even the smallest devices. And they began to think.

I wrote the first PoC on Go somewhere around the new year 2017. Almost nothing added to the original Noise, just the length of the packets. He showed it to the guys, wrote to the Noise Mailing List, and by the end of June we finally arrived at a common denominator that could be implemented on more platforms.

So, what we finally added to the noise? After long conversations and dozens of options, there are essentially only three things left:

  1. Negotiation data
  2. Padding
  3. Processing rules

Negotiation data



This is just a set of bytes in which you can put anything. It is needed in order to align the algorithms and patterns between the client and the server. In our version it looks like this:



Only 6 bytes, but this is enough for the server to understand how to handle any Noise messages that get to it.

Padding


I am very glad that he got into the final spec, otherwise everyone would have had to invent it himself. This is packet alignment, which allows you to hide their true size and prevent content from being guessed even without decryption. It is implemented as an additional 2 bytes at the beginning of the encrypted data, which indicate the actual packet size. All that is after - garbage that needs to be thrown out.



Processing rules


These are a few simple rules on how the server responds to the client if it accepts its message or vice versa, does not understand it and wants to switch to another protocol.

Why?


Virgil has its own PKI and we really lacked the ability to establish secure connections right away using public keys, not using certificates and then validate from above. And now we have made the NGINX module and can serve the entire backend through NoiseSocket, adding digital signatures of static keys to it.

You probably think you need to change everything in order to upgrade to NoiseSocket? But no.
If you are writing to Go and you already have HTTP services, then you only need to change the DialTLS method for clients and Listen for servers, everything else will think what works with TLS. This is all thanks to the Go library , which we also implemented.



Of course, there is still a lot of work on the code and specifications, but, hell, we have an alternative to TLS!

Now you do not need to invent something of your own when you want to build a secure link between two nodes, having only public keys in hand. Tor, i2p, bitcoin, where the node is often identified by the public key, can use NoiseSocket immediately without any additives.

SSH, VPN, all kinds of tunnels can add digital signatures of static keys and get a full-featured secure link with a minimum overhead without having to drag openssl to yourself, you can do Libsodium or even Nacl.

The approximate size of compiled crypto-primitives certainly depends on the architecture, but it gives us hope that we climbed into 30 or even 20 kilobytes with a minimal implementation of NoiseSocket. In devices, where the private key is sewn in hardware, this solution simply will not have any special alternatives.

Conclusion


I had high hopes for TLS 1.3, since there and handshake roundtrips were reduced from 8-9 to three, as in Noise, and added 25519. But

First, we decided not to add the ability to work without certificates, simply by key, although there was such a proposal.
Secondly, the ed25519 certificates are not clear when they appear, and in Noise I can use the signatures of 25519 today.

Moreover, not so long ago, one of the Noise patterns, IK (which is 0-RTT), received a formal proof of correctness from the authors of WireGuard VPN, which only increased our confidence in the correctness of the choice.

I suggest to get acquainted with the specification of NoiseSocket and I am sure that in some projects it will suit you more than TLS. Meanwhile, we are waiting for your comments.

Links


Specification Noise Socket
Github
Noise Protocol Framework specification

Source: https://habr.com/ru/post/334506/


All Articles