Files
i2p.www/i2p2www/spec/proposals/111-ntcp-2.rst

2361 lines
79 KiB
ReStructuredText
Raw Normal View History

2016-04-04 12:51:03 +00:00
======
NTCP 2
======
.. meta::
2018-04-02 13:12:03 +00:00
:author: EinMByte, psi, str4d, zzz
:editor: manas, str4d
2016-04-04 12:51:03 +00:00
:created: 2014-02-13
:thread: http://zzz.i2p/topics/1577
2018-04-17 16:11:51 +00:00
:lastupdated: 2018-04-17
:status: Open
:supercedes: 106
2016-04-04 12:51:03 +00:00
.. contents::
2018-04-02 13:12:03 +00:00
Note
====
2018-04-04 13:54:03 +00:00
Major revisions in progress. For now, not necessarily complete or even
consistent. Not ready for implementation.
2018-04-02 13:12:03 +00:00
Overview
========
This proposal describes an authenticated key agreement protocol to improve the
resistance of [NTCP]_ to various forms of automated identification and attacks.
The proposal is organized as follows: the security goals are presented,
followed by a discussion of the basic protocol. Next, a complete specification
of all protocol messages is given. Finally, router addresses and version
identification are discussed. An appendix discussing a generic attack on common
padding schemes is also included, as well as an appendix containing a number of
candidates for the authenticated cipher.
Motivation
==========
2016-04-04 12:51:03 +00:00
2018-04-04 13:54:03 +00:00
[NTCP]_ data is encrypted after the first message (and the first message
appears to be random data), thus preventing protocol identification through
"payload analysis". It is still vulnerable to protocol identification through
"flow analysis". That's because the first 4 messages (i.e. the handshake) are
fixed length (288, 304, 448, and 48 bytes).
2016-04-04 12:51:03 +00:00
By adding random amounts of random data to each of the messages, we can make it
a lot harder.
2018-04-04 13:54:03 +00:00
The authors acknowledge that standard security practices would suggest to use
an existing protocol such as TLS, but this is [Prop104]_ and it has problems of
its own. Wherever appropriate, "future work" paragraphs have been added to
indicate missing features or subjects of discussion.
2016-04-04 12:51:03 +00:00
Design Goals
============
2016-04-04 12:51:03 +00:00
- Support NTCP 1 and 2 on a single port, auto-detect, and published as a single
"transport" (i.e. [RouterAddress]_) in the [NetDB]_.
- Publish support for version 1 only, 2 only, or 1+2 in the NetDB in a separate
field, and default to version 1 only (don't bind version support to a
particular router version)
2018-04-02 13:12:03 +00:00
- Ensure that all implementations (Java/i2pd/kovri/go) can add version 2
support (or not) on their own schedules
2016-04-04 12:51:03 +00:00
- Add random padding to all NTCP messages including handshake and data messages
(i.e. length obfuscation so all messages aren't a multiple of 16 bytes)
Provide options mechanism for both sides to request min and max padding
and/or padding distribution. Specifics of the padding distribution are
implementation-dependent and may or may not be specified in the protocol
itself.
- Obfuscate the contents of messages that aren't encrypted (1 and 2),
sufficiently so that DPI boxes and AV signatures can't easily classify them.
Also ensure that the messages going to a single peer or set of peers do not
have a similar pattern of bits.
2018-04-04 13:54:03 +00:00
- Fix loss of bits in DH due to Java format [Ticket1112]_, possibly (probably?)
by switching to X25519.
- Switch to a real key derivation function (KDF) rather than using the DH
result as-is?
- Add "probing resistance" (as Tor calls it); this includes replay resistance.
- Maintain 2-way authenticated key exchange (2W-AKE). 1W-AKE is not sufficient
for our application.
- Continue to use the variable-type, variable-length signatures (from the
2018-04-04 13:54:03 +00:00
published [RouterIdentity]_ signing key) as a part of authentication. Rely
on a static public key published in the RouterInfo as another part of
authentication.
- Add options/version in handshake for future extensibility.
- Add resistance to malicious MitM TCP segmentation if possible.
- Don't add significantly to CPU required for connection setup; if possible,
reduce it significantly.
2018-04-04 13:54:03 +00:00
- Add message authentication (MAC), possibly HMAC-SHA256 and Poly1305, and
remove Adler checksum.
2018-04-02 13:12:03 +00:00
- Shorten and simplify I2NP header:
Shorten expiration to 4 bytes, as in SSU.
Remove one-byte truncated SHA256 checksum.
- If possible, reduce the 4-message, two-round-trip handshake to a 3-message,
one-round-trip handshake, as in [SSU]_. This would require moving Bob's
signature in message 4 to message 2. Research the reason for 4 messages in
the ten-year-old email/status/meeting archives.
- Maintain timestamps for replay and skew detection.
- Avoid any year 2038 issues in timestamps, must work until at least 2106.
- Increase max message size from 16K to 32K or 64K.
- Any new crypto should be readily available in libraries for use in Java
(1.7), C++, and Go router implementations.
- Include representatives of Java, C++, and Go router developers in the design.
2016-09-17 16:09:19 +00:00
- Minimize changes (but there will still be a lot).
2016-07-03 18:42:21 +00:00
- Support both versions in a common set of code (this may not be possible and
is implementation-dependent in any case).
2016-07-03 18:42:21 +00:00
2018-04-02 13:12:03 +00:00
2016-07-03 18:42:21 +00:00
Non-Goals
---------
2018-04-04 13:54:03 +00:00
- Bullet-proof DPI resistance... that would be pluggable transports,
[Prop109]_.
- A TLS-based (or HTTPS-lookalike) transport... that would be [Prop104]_.
2018-04-02 13:12:03 +00:00
- It's ok to change the symmetric stream crypto.
- Timing-based DPI resistance (inter-message timing/delays can be
implementation-dependent; intra-message delays can be introduced at any
point, including before sending the random padding, for example). Artificial
delays (what obfs4 calls IAT or inter-arrival time) are independent of the
protocol itself.
- Deniability of participating in a session (there's signatures in there).
2016-04-04 12:51:03 +00:00
Non-goals that may be partially reconsidered or discussed:
- The degree of protection against Deep Packet Inspection (DPI)
- Post-Quantum (PQ) security
- Deniability
2016-04-04 12:51:03 +00:00
2018-04-02 13:12:03 +00:00
2016-07-03 19:17:09 +00:00
Related Goals
-------------
2016-07-03 19:17:09 +00:00
- Implement a NTCP 1/2 test setup
Security Goals
==============
We consider three parties:
- Alice, who wishes to establish a new session.
- Bob, with whom Alice wishes to establish a session.
- Mallory, the "man in the middle" between Alice and Bob.
At most two participants can engage in active attacks.
Alice and Bob are both in possession of a static key pair, which is contained
in their [RouterIdentity]_.
2016-07-03 19:17:09 +00:00
The proposed protocol attempts to allow Alice and Bob to agree on a shared
2018-04-02 13:12:03 +00:00
secret key (K) under the following requirements:
2016-04-04 12:51:03 +00:00
1) Private key security: neither Bob nor Mallory learns anything about Alice's
static private key. Symmetrically, Alice does not learn anything about Bob's
static private key.
2016-12-02 15:47:46 +00:00
2) The session key K is only known by Alice and Bob.
2016-12-02 15:47:46 +00:00
3) Perfect forward secrecy: the agreed upon session key remains secret in the
future, even when the static private keys of Alice and/or Bob are revealed
after the key has been agreed upon.
2016-12-02 15:47:46 +00:00
4) Two-way authentication: Alice is certain that she has established a session
with Bob, and vice versa.
2016-12-02 15:47:46 +00:00
2018-04-02 13:12:03 +00:00
5) Protection against online DPI: Ensure that it is not trivial to detect that
Alice and Bob are engaged in the protocol using only straightforward deep
2018-04-02 13:12:03 +00:00
packet inspection (DPI) techniques. See below.
6) Limited deniability: neither Alice nor Bob can deny participation in the
protocol, but if either leaks the shared key the other party can deny the
authenticity of the contents of the transmitted data.
The present proposal attempts to provide all five requirements based on the
Station-To-Station (STS) protocol [STS]_. Note that this protocol is also the
basis for the [SSU]_ protocol.
2018-04-02 13:12:03 +00:00
Additional DPI Discussion
-------------------------
We assume two DPI components:
1) Online DPI
`````````````
2018-04-04 13:54:03 +00:00
Online DPI inspecting all flows in real-time. Connections may be blocked or
otherwise tampered with. Connection data or metadata may be identified and
stored for offline analysis. The online DPI does not have access to the I2P
network database. The online DPI has only limited real-time computational
capability, including length calculation, field inspection, and simple
calculations such as XOR. The online DPI does have the capability of fast
real-time cryptographic functions such as AES, AEAD, and hashing, but these
would be too expensive to apply to most or all flows. Any application of these
cryptographic operations would apply only to flows on IP/Port combinations
previously identified by offline analysis. The online DPI does not have the
capability of high-overhead cryptographic functions such as DH or elligator2.
The online DPI is not designed specifically to detect I2P, although it may have
limited classification rules for that purpose.
2018-04-02 13:12:03 +00:00
It is a goal to prevent protocol identification by an online DPI.
2018-04-04 13:54:03 +00:00
The notion of online or "straightforward" DPI is here taken to include the
following adversary capabilities:
1) The ability to inspect all data sent or received by the target.
2) The ability to perform operations on the observed data, such as
applying block ciphers or hash functions.
3) The ability to store and compare with previously sent messages.
4) The ability to modify, delay or fragment packets.
2018-04-02 13:12:03 +00:00
However, the online DPI is assumed to have the following restrictions:
2018-04-02 13:12:03 +00:00
5) The inability to map IP addresses to router hashes. While this is trivial
with real-time access to the network database,
it would require a DPI system specifically designed to target I2P.
6) The inability to use timing information to detect the protocol.
2018-04-04 13:54:03 +00:00
7) Generally speaking, the online DPI toolbox does not contain any built-in
tools that are specifically designed for I2P detection. This includes
creating "honeypots", which would for example include nonrandom padding in
their messages. Note that this does not exclude machine learning systems or
highly configurable DPI tools as long as they meet the other requirements.
To counter payload analysis, it is ensured that all messages are
indistinguishable from random. This also requires their length to be random,
which is more complicated than just adding random padding. In fact, in Appendix
A, the authors argue that a naive (i.e. uniform) padding scheme does not
resolve the problem. Appendix A therefore proposes to include either random
delays or to develop an alternate padding scheme that can provide reasonable
protection for the proposed attack.
To protect against the sixth entry above, implementations should include random
delays in the protocol. Such techniques are not covered by this proposal, but
they could also resolve the padding length issues. In summary, the proposal
provides good protection against payload analysis (when the considerations in
Appendix A are taken into account), but only limited protection against flow
analysis.
2018-04-02 13:12:03 +00:00
2) Offline DPI
``````````````
Offline DPI inspecting data stored by the online DPI for later analysis.
The offline DPI may be designed specifically to detect I2P.
The offline DPI does have real-time access to the I2P network database.
The offline DPI does have access to this and other I2P specifications.
The offline DPI has unlimited computational capability, including
all cryptographic functions defined in this specification.
2018-04-04 13:54:03 +00:00
The offline DPI does not have the ability to block existing connections. The
offline DPI does have the capability to do near-realtime (within minutes of
setup) sending to host/port of parties, for example TCP RST. The offline DPI
does have the capability to do near-realtime (within minutes of setup) replay
of previous messages (modified or not) for "probing" or other reasons.
2018-04-02 13:12:03 +00:00
It is not a goal to prevent protocol identification by an offline DPI.
All decoding of obfuscated data in the first two messages, which
is implemented by I2P routers, may also be implemented by the offline DPI.
It is a goal to reject attempted connections using replay of previous messages.
Future work
```````````
- Consider the behavior of the protocol when packets are dropped or reordered
by an attacker. Recent interesting work in this area can be found in
[IACR-1150]_.
- Provide a more accurate classification of DPI systems, taking into account
the existing literature related to the subject.
- Discuss the formal security of the proposed protocol, ideally taking into
account the DPI attacker model.
2018-04-02 13:12:03 +00:00
Noise Protocol Framework
========================
2016-04-04 12:51:03 +00:00
2018-04-04 13:54:03 +00:00
This proposal provides the requirements based on the Noise Protocol Framework
2018-04-17 16:11:51 +00:00
[NOISE]_ (Revision 33, 2017-10-04).
Noise has similar properties to the Station-To-Station protocol
2018-04-04 13:54:03 +00:00
[STS]_, which is the basis for the [SSU]_ protocol. In Noise parlance, Alice
is the initiator, and Bob is the responder.
2016-04-04 12:51:03 +00:00
2018-04-02 13:12:03 +00:00
The Noise Protocol Identifier for NTCP2 is Noise_XK_25519_ChaChaPoly_SHA256.
This uses the following primitives:
2016-04-04 12:51:03 +00:00
2018-04-02 13:12:03 +00:00
- Handshake Pattern: XK
Alice transmits her key to Bob (X)
Alice knows Bob's static key already (K)
2016-04-04 12:51:03 +00:00
2018-04-02 13:12:03 +00:00
- DH Function: X25519
X25519 DH with a key length of 32 bytes as specified in [RFC-7748]_.
2018-04-02 13:12:03 +00:00
- Cipher Function: ChaChaPoly
AEAD_CHACHA20_POLY1305 as specified in [RFC-7539]_.
12 byte nonce, with the first 4 bytes set to zero.
2018-04-02 13:12:03 +00:00
- Hash Function: SHA256
Standard 32-byte hash, already used extensively in I2P.
2018-04-02 13:12:03 +00:00
Additions to the Framework
==========================
2018-04-04 13:54:03 +00:00
This proposal defines the following enhancements to
Noise_XK_25519_ChaChaPoly_SHA256. These generally follow the guidelines in
[NOISE]_ section 13.
2018-04-04 13:54:03 +00:00
1) Cleartext ephemeral keys are obfuscated with AES encryption using a known
key and IV. This is quicker than elligator2.
2018-04-02 13:12:03 +00:00
2) Random cleartext padding is added to messages 1 and 2.
The cleartext padding is included in the handshake hash calculation.
Random AEAD padding is added to message 3 and data phase messages.
3) A two-byte frame length field is added, as is required for Noise over TCP,
and as in obfs4. This is used in message 3 and data phase messages.
Message 1 and 2 AEAD frames are fixed length.
4) The two-byte frame length field is obfuscated with SipHash,
as in obfs4.
2016-04-04 12:51:03 +00:00
2018-04-02 13:12:03 +00:00
5) The payload format is defined for messages 1,2,3, and the data phase.
It of course is not defined in Noise.
2018-04-02 13:12:03 +00:00
Processing overhead estimate
============================
2018-04-02 14:21:24 +00:00
Message sizes for the 3 messages:
2018-04-04 13:54:03 +00:00
1) 64 bytes + padding (NTCP was 288 bytes)
2) 56 bytes + padding (NTCP was 304 bytes)
3) 66 bytes + Alice router info + padding Average router info is about 750
bytes Total average 816 bytes (NTCP was 448 bytes)
4) not required in NTCP2 (NTCP was 48 bytes)
2018-04-02 13:12:03 +00:00
Total before padding:
NTCP2: 936 bytes
NTCP: 1088 bytes
Note that if Alice connected to Bob for the purpose of sending
a DatabaseStore Message of her RouterInfo, that message is not required,
saving approximately 800 bytes.
The following crypto operations are required by each party to complete
the handshake and start the data phase:
- AES: 2
2018-04-04 13:54:03 +00:00
- SHA256: 8 (Alice), 6 (Bob) (not including 4 Alice, 6 Bob precalculated for
all connections) (not including HMAC-SHA256)
2018-04-02 13:12:03 +00:00
- HMAC-SHA256: 15
- ChaCha/Poly: 4
- X25519 DH: 3
- SipHash: 1
2018-04-04 13:54:03 +00:00
- Signature verification: 1 (Bob) (Alice previously signed when generating her
RI) Presumably Ed25519 (dependent on RI sigtype)
2018-04-02 13:12:03 +00:00
The following crypto operations are required by each party for each data phase message:
- SipHash: 1
- ChaCha/Poly: 1
2016-04-04 12:51:03 +00:00
Messages
========
2018-04-02 13:12:03 +00:00
All NTCP2 messages are less than or equal to 65537 bytes in length. The message
format is based on Noise messages, with modifications for framing and indistinguishability.
Implementations using standard Noise libraries may need to pre-process received
messages to/from the Noise message format. All encrypted fields are AEAD
ciphertexts.
The establishment sequence is as follows:
2016-07-03 19:17:09 +00:00
.. raw:: html
2016-07-03 19:17:09 +00:00
{% highlight %}
Alice Bob
2016-07-03 19:17:09 +00:00
SessionRequest ------------------->
<------------------- SessionCreated
SessionConfirmed ----------------->
{% endhighlight %}
2016-07-03 19:17:09 +00:00
2018-04-02 13:12:03 +00:00
Using Noise terminology, the establishment and data sequence is as follows:
2018-04-16 15:49:00 +00:00
(Payload Security Properties)
2018-04-02 13:12:03 +00:00
.. raw:: html
2018-04-02 14:45:40 +00:00
{% highlight lang='text' %}
2018-04-02 13:12:03 +00:00
XK(s, rs): Authentication Confidentiality
<- s
...
-> e, es 0 2
<- e, ee 2 1
-> s, se 2 5
<- 2 5
{% endhighlight %}
Once a session has been established, Alice and Bob can exchange Data messages.
2016-07-03 19:17:09 +00:00
All message types (SessionRequest, SessionCreated, SessionConfirmed, Data and
TimeSync) are specified in this section.
2016-07-03 19:17:09 +00:00
Some notations::
2016-07-03 19:17:09 +00:00
2018-04-02 13:12:03 +00:00
- RH_A = Router Hash for Alice (32 bytes)
- RH_B = Router Hash for Bob (32 bytes)
Authenticated Encryption
------------------------
There are three separate authenticated encryption instances (CipherStates).
One during the handshake phase, and two (transmit and receive) for the data phase.
Each has its own key from a KDF.
Encrypted/authenticated data will be represented as
.. raw:: html
{% highlight lang='dataspec' %}
+----+----+----+----+----+----+----+----+
| |
+ +
| Encrypted and authenticated data |
~ . . . ~
| |
+----+----+----+----+----+----+----+----+
{% endhighlight %}
ChaCha20/Poly1305
`````````````````
2018-04-02 14:21:24 +00:00
Encrypted and authenticated data format.
Inputs to the encryption/decryption functions:
2018-04-02 13:12:03 +00:00
.. raw:: html
{% highlight lang='dataspec' %}
2018-04-04 13:54:03 +00:00
k :: 32 byte cipher key, as generated from KDF
2018-04-02 13:12:03 +00:00
nonce :: Counter-based nonce, 12 bytes.
Starts at 0 and incremented for each message.
First four bytes are always zero.
Maximum value is 2**64 - 2.
Connection must be dropped and restarted after
it reaches that value.
The value 2**64 - 1 must never be sent.
ad :: In handshake phase:
Associated data, 32 bytes.
The SHA-256 hash of all preceding data.
In data phase:
Zero bytes
data :: Plaintext data, 0 or more bytes
2018-04-02 14:21:24 +00:00
{% endhighlight %}
Output of the encryption function, input to the decryption function:
.. raw:: html
2018-04-02 13:12:03 +00:00
2018-04-02 14:21:24 +00:00
{% highlight lang='dataspec' %}
2018-04-02 13:12:03 +00:00
+----+----+----+----+----+----+----+----+
2018-04-02 13:53:31 +00:00
|Obfs Len | MAC |
2018-04-02 13:12:03 +00:00
+----+----+ +
| Poly1305 Message Authetication Code |
+ +----+----+----+----+----+----+
|16 bytes | |
+----+----+ +
| ChaCha20 encrypted data |
~ . . . ~
| |
+----+----+----+----+----+----+----+----+
2018-04-02 13:53:31 +00:00
Obfs Len :: Length of MAC + encryptd data to follow
2018-04-12 12:56:50 +00:00
Obfuscation using SipHash (see below)
Not used in message 1 or 2, where the length is fixed
2018-04-02 13:12:03 +00:00
MAC :: Poly1305 message authentication code
encrypted data :: Same size as plaintext data
{% endhighlight %}
For ChaCha20, what is described here corresponds to [RFC-7539]_, which is also
used similarly in TLS [RFC-7905]_.
Notes
`````
- Since ChaCha20 is a stream cipher, plaintexts need not be padded.
Additional keystream bytes are discarded.
- The key for the cipher (256 bits) is agreed upon by means of the SHA256 KDF.
2018-04-12 12:56:50 +00:00
The details of the KDF for each message are in separate sections below.
2018-04-02 13:12:03 +00:00
2018-04-12 12:56:50 +00:00
- ChaCha/Poly blocks for messages 1, 2, and the first part of message 3,
are of known size. Starting with the second part of message 3,
blocks are of variable size, and are prepended with a two-byte length
obfuscated with SipHash as in obfs4.
2018-04-02 13:12:03 +00:00
2018-04-12 12:56:50 +00:00
- Padding is outside the authenticated data block for messages 1 and 2.
The padding is used in the KDF for the next message so tampering will
be detected. Starting in message 3, padding is inside the authenticated
data block.
2018-04-02 13:12:03 +00:00
Key Derivation Function (KDF) (for handshake message 1 and message 3 part 1)
----------------------------------------------------------------------------
The KDF generates a handshake phase ciper key k from the DH result,
using HMAC-SHA256(key, data) as defined in [RFC-2104]_.
These are the InitializeSymmetric(), MixHash(), and MixKey() functions,
exactly as defined in the Noise spec.
.. raw:: html
2018-04-02 14:45:40 +00:00
{% highlight lang='text' %}
2018-04-02 13:12:03 +00:00
This is the "e" message pattern:
2018-04-04 13:54:03 +00:00
Define protocol_name.
Set protocol_name = "Noise_XK_25519_ChaChaPoly_SHA256" which is 32 bytes
(US-ASCII encoded, no NULL termination).
2018-04-02 13:12:03 +00:00
2018-04-04 13:54:03 +00:00
Define Hash h = 32 bytes
h = SHA256(protocol_name);
2018-04-02 13:12:03 +00:00
2018-04-04 13:54:03 +00:00
Define ck = 32 byte chaining key.
Set ck = h
2018-04-02 13:12:03 +00:00
2018-04-04 13:54:03 +00:00
Define rs = Bob's 32-byte static key as published in the RouterInfo
2018-04-02 13:12:03 +00:00
2018-04-04 13:54:03 +00:00
// MixHash(null prologue)
h = SHA256(h);
// No Alice static key
// MixHash(null s)
h = SHA256(h);
// No Alice ephemeral key
// MixHash(null e)
h = SHA256(h);
2018-04-02 13:12:03 +00:00
2018-04-04 13:54:03 +00:00
// up until here, can all be precalculated by Alice for all outgoing connnections
2018-04-02 13:12:03 +00:00
2018-04-04 13:54:03 +00:00
// Alice must validate that Bob's static key is a valid point on the curve here.
2018-04-02 13:12:03 +00:00
2018-04-04 13:54:03 +00:00
// Bob static key
// MixHash(rs)
// || below means append
h = SHA256(h || rs);
// No Bob ephemeral key
// MixHash(null re)
h = SHA256(h);
2018-04-02 13:12:03 +00:00
2018-04-04 13:54:03 +00:00
// up until here, can all be precalculated by Bob for all incoming connnections
2018-04-02 13:12:03 +00:00
2018-04-04 13:54:03 +00:00
This is the "e" message pattern:
2018-04-02 13:12:03 +00:00
2018-04-04 13:54:03 +00:00
Alice generates her ephemeral DH keypair e.
2018-04-02 13:12:03 +00:00
2018-04-04 13:54:03 +00:00
// Alice ephemeral key X
// MixHash(e.pubkey)
// || below means append
h = SHA256(h || e.pubkey);
2018-04-02 13:12:03 +00:00
2018-04-04 13:54:03 +00:00
// h is used as the associated data for the AEAD in message 1
// Retain the Hash h for the message 2 KDF
2018-04-02 13:12:03 +00:00
2018-04-04 13:54:03 +00:00
End of "e" message pattern.
2018-04-02 13:12:03 +00:00
2018-04-04 13:54:03 +00:00
This is the "es" message pattern:
2018-04-02 13:12:03 +00:00
2018-04-04 13:54:03 +00:00
// DH(e, rs) == DH(s, re)
Define input_key_material = 32 byte DH result of Alice's ephemeral key and Bob's static key
Set input_key_material = X25519 DH result
2018-04-02 13:12:03 +00:00
2018-04-04 13:54:03 +00:00
// MixKey(DH())
2018-04-02 13:12:03 +00:00
2018-04-04 13:54:03 +00:00
Define temp_key = 32 bytes
Define HMAC-SHA256(key, data) as in [RFC-2104]_
// Generate a temp key from the chaining key and DH result
// ck is the chaining key, which is the hash of the noise name, defined above
temp_key = HMAC-SHA256(ck, input_key_material)
// overwrite the DH result in memory, no longer needed
input_key_material = (all zeros)
2018-04-02 13:12:03 +00:00
2018-04-04 13:54:03 +00:00
// Output 1
// Set a new chaining key from the temp key
// byte() below means a single byte
ck = HMAC-SHA256(temp_key, byte(0x01)).
2018-04-02 13:12:03 +00:00
2018-04-04 13:54:03 +00:00
// Output 2
// Generate the cipher key k
Define k = 32 bytes
// || below means append
// byte() below means a single byte
k = HMAC-SHA256(temp_key, ck || byte(0x02)).
// overwrite the temp_key in memory, no longer needed
temp_key = (all zeros)
2018-04-02 13:12:03 +00:00
2018-04-04 13:54:03 +00:00
// retain the chaining key ck for message 2 KDF
2018-04-02 13:12:03 +00:00
2018-04-04 13:54:03 +00:00
End of "es" message pattern.
2018-04-02 13:12:03 +00:00
{% endhighlight %}
2016-07-03 19:17:09 +00:00
1) SessionRequest
2016-04-04 12:51:03 +00:00
------------------
2018-04-02 13:12:03 +00:00
Alice sends to Bob.
Noise content: Alice's ephemeral key X
Noise payload: 16 byte option block
Non-noise payload: Random padding
2018-04-16 15:49:00 +00:00
(Payload Security Properties)
2018-04-02 13:12:03 +00:00
.. raw:: html
2018-04-02 14:45:40 +00:00
{% highlight lang='text' %}
2018-04-02 13:12:03 +00:00
XK(s, rs): Authentication Confidentiality
-> e, es 0 2
Authentication: None (0).
This payload may have been sent by any party, including an active attacker.
Confidentiality: 2.
2018-04-04 13:54:03 +00:00
Encryption to a known recipient, forward secrecy for sender compromise
only, vulnerable to replay. This payload is encrypted based only on DHs
involving the recipient's static key pair. If the recipient's static
private key is compromised, even at a later date, this payload can be
decrypted. This message can also be replayed, since there's no ephemeral
contribution from the recipient.
2018-04-02 13:12:03 +00:00
2018-04-04 13:54:03 +00:00
"e": Alice generates a new ephemeral key pair and stores it in the e
variable, writes the ephemeral public key as cleartext into the
message buffer, and hashes the public key along with the old h to
derive a new h.
2018-04-02 13:12:03 +00:00
2018-04-04 13:54:03 +00:00
"es": A DH is performed between the Alice's ephemeral key pair and the
Bob's static key pair. The result is hashed along with the old ck to
derive a new ck and k, and n is set to zero.
2018-04-02 13:12:03 +00:00
{% endhighlight %}
2018-04-12 12:56:50 +00:00
The X value is encrypted to ensure payload indistinguishably
2018-04-02 13:12:03 +00:00
and uniqueness, which are necessary DPI countermeasures.
We use AES encryption to achieve this,
rather than more complex and slower alternatives such as elligator2.
Asymmetric encryption to Bob's router public key would be far too slow.
AES encryption uses Bob's router hash as the key and Bob's IV as published
in the network database.
AES encryption is for DPI resistance only.
Any party knowing Bob's router hash, and IV, which are published in the network database,
may decrypt the X value in this message.
2018-04-12 12:56:50 +00:00
The padding is not encrypted by Alice.
2018-04-02 13:12:03 +00:00
It may be necessary for Bob to decrypt the padding,
to inhibit timing attacks.
Raw contents:
.. raw:: html
{% highlight lang='dataspec' %}
+----+----+----+----+----+----+----+----+
| |
2018-04-02 13:12:03 +00:00
+ obfuscated with RH_B +
| AES-CBC-256 encrypted X |
+ (32 bytes) +
| |
+ +
| |
+----+----+----+----+----+----+----+----+
| |
+ +
| ChaCha/Poly frame |
+ (32 bytes) +
| k = KDF from KDF for msg 1 |
+ n = 0 +
| |
+----+----+----+----+----+----+----+----+
2018-04-12 12:56:50 +00:00
| unencrypted, authenticated |
2018-04-02 13:12:03 +00:00
~ padding (optional) ~
| length defined in options block |
+----+----+----+----+----+----+----+----+
2018-04-02 13:12:03 +00:00
X :: AES-256-CBC encrypted X, little endian
key: RH_B
2018-04-12 12:56:50 +00:00
iv: As published in Bobs netdb
2018-04-02 13:12:03 +00:00
padding :: Random data, 0 or more bytes.
Total message length must be 65535 bytes or less.
Total message length must be 287 bytes or less if
Bob is publishing his address as "NTCP"
(see Version Detection section below)
2018-04-12 12:56:50 +00:00
Alice and Bob will use the padding data in the KDF for message 2.
It is authenticated in that any tampering will cause the
next message to fail.
2018-04-02 13:12:03 +00:00
{% endhighlight %}
2018-04-12 12:56:50 +00:00
Unencrypted data (Poly1305 auth tag not shown):
.. raw:: html
{% highlight lang='dataspec' %}
+----+----+----+----+----+----+----+----+
| |
2018-04-02 13:12:03 +00:00
+ +
| X |
+ (32 bytes) +
| |
2018-04-02 13:12:03 +00:00
+ +
| |
+----+----+----+----+----+----+----+----+
2018-04-02 13:12:03 +00:00
| options |
+ (16 bytes) +
| |
2018-04-02 13:12:03 +00:00
+----+----+----+----+----+----+----+----+
2018-04-12 12:56:50 +00:00
| unencrypted, authenticated |
2018-04-02 13:12:03 +00:00
+ padding (optional) +
| length defined in options block |
~ . . . ~
| |
+----+----+----+----+----+----+----+----+
2018-04-02 13:12:03 +00:00
X :: 32 bytes, little endian
options :: options block, 16 bytes
2018-04-02 13:12:03 +00:00
ext_options :: Optional. Additional options blocks, format currently undefined.
If present, length is multiple of 16 bytes
padding :: Random data, 0 or more bytes.
Total message length must be 65535 bytes or less.
Total message length must be 287 bytes or less if
Bob is publishing his address as "NTCP"
(see Version Detection section below)
2018-04-12 12:56:50 +00:00
Alice and Bob will use the padding data in the KDF for message 2.
It is authenticated in that any tampering will cause the
next message to fail.
{% endhighlight %}
Options block:
2018-04-02 13:12:03 +00:00
Note: All fields are big-endian.
.. raw:: html
{% highlight lang='dataspec' %}
+----+----+----+----+----+----+----+----+
| ver | KE | auth | padLen |
+----+----+----+----+----+----+----+----+
2018-04-02 13:12:03 +00:00
| tsA | Reserved (0) |
+----+----+----+----+----+----+----+----+
ver :: Protocol version (currently 2)
2018-04-02 13:12:03 +00:00
KE :: Key exchange mechanism used
0: Unsupported, reserved for old NTCP
Diffie-Hellman in Z/pZ [RFC-3526], 2048 bit p
KDF = SHA256
1: X25519
KDF = HMAC-SHA256 as defined below
auth :: Authenticated encryption mode
Key = K, to be agreed upon using KE
2018-04-02 13:12:03 +00:00
0: Unsupported, reserved for old NTCP
AES-CBC-256/HMAC-MD5 [RFC-2104]
1: ChaCha20/Poly1305, 12 byte nonce with first 4 bytes set to zero.
padLen :: Length of the padding, 0 or more
Min/max guidelines TBD. Random size from 0 to 31 bytes minimum?
(Distribution to be determined, see Appendix A.)
2018-04-02 13:12:03 +00:00
tsA :: Unix timestamp, unsigned seconds.
Wraps around in 2106
2018-04-02 13:12:03 +00:00
Reserved :: 4 bytes, set to 0 for compatiblity with future options
{% endhighlight %}
2016-04-04 12:51:03 +00:00
Notes
`````
2018-04-04 13:54:03 +00:00
- When the published address is "NTCP", Bob supports both NTCP and NTCP2 on the
same port. For compatibility, when initiating a connection to an address
published as "NTCP", Alice must limit the maximum size of this message,
including padding, to 287 bytes or less. This facilitates automatic protocol
identification by Bob. When published as "NTCP2", there is no size
restriction. See the Published Addresses and Version Detection sections
below.
- The unique X value in the initial AES block ensure that the ciphertext is
different for every session.
- Bob must reject connections where the timestamp value is too far off from the
current time. Call the maximum delta time "D". Bob must maintain a local
cache of previously-used handshake values and reject duplicates, to prevent
replay attacks. Values in the cache must have a lifetime of at least 2*D.
2018-04-02 13:12:03 +00:00
The cache values are implementation-dependent, however the 32-byte X value
(or its encrypted equivalent) may be used.
- Reserved options must be set to zero if ver = 2. This increases the accuracy
of version detection.
- Diffie-Hellman parameters may never be sent twice to avoid DPI attacks.
- The "KE" and "auth" options must be compatible, i.e. the shared secret K must
be of the appropriate size. If more "auth" options are added, this could
implicitly change the meaning of the "KE" flag to use a different KDF or a
different truncation size.
2018-04-04 13:54:03 +00:00
- Bob must validate that Alice's ephemeral key is a valid point on the curve
here.
2018-04-04 13:54:03 +00:00
- Padding should be limited to a reasonable amount. Bob may reject connections
with excessive padding. Bob will specify his padding options in message 2.
2018-04-02 13:12:03 +00:00
Min/max guidelines TBD. Random size from 0 to 31 bytes minimum?
(Distribution to be determined, see Appendix A.)
2018-04-04 13:54:03 +00:00
- On any error, including AEAD, DH, timestamp, apparent replay, or key
validation failure, Bob must halt further message processing and close the
connection without responding. This should be an abnormal close (TCP RST).
2018-04-04 13:54:03 +00:00
- To facilitate rapid version detection and handshaking, implementations must
ensure that Alice buffers and then flushes the entire contents of the first
message at once, including the padding. This increases the likelihood that
the data will be contained in a single TCP packet (unless segmented by the OS
or middleboxes), and received all at once by Bob. Additionally,
implementations must ensure that Bob buffers and then flushes the entire
contents of the second message at once, including the padding. and that Bob
buffers and then flushes the entire contents of the third message at once.
This is also for efficiency and to ensure the effectiveness of the random
padding.
2018-04-02 13:12:03 +00:00
Issues
``````
2018-04-12 12:56:50 +00:00
- Is the fixed-size option block big enough?
- KE and auth bytes may not be needed, or may be redefined
2018-04-02 13:12:03 +00:00
Key Derivation Function (KDF) (for handshake message 2)
-------------------------------------------------------
.. raw:: html
2018-04-02 14:45:40 +00:00
{% highlight lang='text' %}
2018-04-02 13:12:03 +00:00
// probably do this also:
2018-04-04 13:54:03 +00:00
h = SHA256(h || random padding from message 1)
2018-04-02 13:12:03 +00:00
2018-04-04 13:54:03 +00:00
This is the "e" message pattern:
2018-04-02 13:12:03 +00:00
2018-04-04 13:54:03 +00:00
Bob generates his ephemeral DH keypair e.
2018-04-02 13:12:03 +00:00
2018-04-04 13:54:03 +00:00
// h is from KDF for handshake message 1
// Bob ephemeral key Y
// MixHash(e.pubkey)
// || below means append
h = SHA256(h || e.pubkey);
2018-04-02 13:12:03 +00:00
2018-04-04 13:54:03 +00:00
// h is used as the associated data for the AEAD in message 2
// Retain the Hash h for the message 3 KDF
2018-04-02 13:12:03 +00:00
2018-04-04 13:54:03 +00:00
End of "e" message pattern.
2018-04-02 13:12:03 +00:00
2018-04-04 13:54:03 +00:00
This is the "ee" message pattern:
2018-04-02 13:12:03 +00:00
2018-04-04 13:54:03 +00:00
// DH(e, re)
Define input_key_material = 32 byte DH result of Alice's ephemeral key and Bob's ephemeral key
Set input_key_material = X25519 DH result
// overwrite Alice's ephemeral key in memory, no longer needed
// Alice:
e(public and private) = (all zeros)
// Bob:
re = (all zeros)
2018-04-02 13:12:03 +00:00
2018-04-04 13:54:03 +00:00
// MixKey(DH())
2018-04-02 13:12:03 +00:00
2018-04-04 13:54:03 +00:00
Define temp_key = 32 bytes
Define HMAC-SHA256(key, data) as in [RFC-2104]_
// Generate a temp key from the chaining key and DH result
// ck is the chaining key, from the KDF for handshake message 1
temp_key = HMAC-SHA256(ck, input_key_material)
// overwrite the DH result in memory, no longer needed
input_key_material = (all zeros)
2018-04-02 13:12:03 +00:00
2018-04-04 13:54:03 +00:00
// Output 1
// Set a new chaining key from the temp key
// byte() below means a single byte
ck = HMAC-SHA256(temp_key, byte(0x01)).
2018-04-02 13:12:03 +00:00
2018-04-04 13:54:03 +00:00
// Output 2
// Generate the cipher key k
Define k = 32 bytes
// || below means append
// byte() below means a single byte
k = HMAC-SHA256(temp_key, ck || byte(0x02)).
// overwrite the temp_key in memory, no longer needed
temp_key = (all zeros)
2018-04-02 13:12:03 +00:00
2018-04-04 13:54:03 +00:00
// retain the chaining key ck for message 3 KDF
2018-04-02 13:12:03 +00:00
2018-04-04 13:54:03 +00:00
End of "es" message pattern.
2018-04-02 13:12:03 +00:00
{% endhighlight %}
2) SessionCreated
------------------
Bob sends to Alice.
Noise content: Bob's ephemeral key Y
Noise payload: 8 byte option block
Non-noise payload: Random padding
2018-04-16 15:49:00 +00:00
(Payload Security Properties)
2018-04-02 13:12:03 +00:00
.. raw:: html
2018-04-02 14:45:40 +00:00
{% highlight lang='text' %}
2018-04-02 13:12:03 +00:00
XK(s, rs): Authentication Confidentiality
<- e, ee 2 1
Authentication: 2.
Sender authentication resistant to key-compromise impersonation (KCI).
The sender authentication is based on an ephemeral-static DH ("es" or "se")
between the sender's static key pair and the recipient's ephemeral key pair.
Assuming the corresponding private keys are secure, this authentication cannot be forged.
Confidentiality: 1.
Encryption to an ephemeral recipient.
This payload has forward secrecy, since encryption involves an ephemeral-ephemeral DH ("ee").
However, the sender has not authenticated the recipient,
so this payload might be sent to any party, including an active attacker.
"e": Bob generates a new ephemeral key pair and stores it in the e variable,
writes the ephemeral public key as cleartext into the message buffer,
and hashes the public key along with the old h to derive a new h.
"ee": A DH is performed between the Bob's ephemeral key pair and the Alice's ephemeral key pair.
The result is hashed along with the old ck to derive a new ck and k, and n is set to zero.
{% endhighlight %}
2018-04-04 13:54:03 +00:00
The Y value is encrypted to ensure payload indistinguishably and uniqueness,
which are necessary DPI countermeasures. We use AES encryption to achieve
this, rather than more complex and slower alternatives such as elligator2.
Asymmetric encryption to Alice's router public key would be far too slow. AES
encryption uses Bob's router hash as the key and the AES state from message 1
(which was initialized with Bob's IV as published in the network database).
2018-04-02 13:12:03 +00:00
2018-04-04 13:54:03 +00:00
AES encryption is for DPI resistance only. Any party knowing Bob's router hash
and IV, which are published in the network database, and captured the first 32
bytes of message 1, may decrypt the Y value in this message.
2018-04-02 13:12:03 +00:00
Raw contents:
.. raw:: html
{% highlight lang='dataspec' %}
+----+----+----+----+----+----+----+----+
| |
2018-04-02 13:12:03 +00:00
+ obfuscated with RH_B +
| AES-CBC-256 encrypted Y |
+ (32 bytes) +
| |
+ +
| |
2018-04-02 13:12:03 +00:00
+----+----+----+----+----+----+----+----+
| ChaCha/Poly frame |
+ Encrypted and authenticated data +
| 24 bytes |
+ k from KDF for msg 2 +
| n = 0 |
+----+----+----+----+----+----+----+----+
2018-04-12 12:56:50 +00:00
| unencrypted, authenticated |
2018-04-02 13:12:03 +00:00
+ padding (optional) +
| length defined in options block |
~ . . . ~
| |
+----+----+----+----+----+----+----+----+
2018-04-02 13:12:03 +00:00
Y :: AES-256-CBC encrypted Y, little endian
key: RH_B
2018-04-12 12:56:50 +00:00
iv: As published in Bobs netdb
2018-04-02 13:12:03 +00:00
{% endhighlight %}
2018-04-12 12:56:50 +00:00
Unencrypted data (Poly1305 auth tag not shown):
.. raw:: html
{% highlight lang='dataspec' %}
+----+----+----+----+----+----+----+----+
| |
2018-04-02 13:12:03 +00:00
+ +
| Y |
+ (32 bytes) +
| |
2018-04-02 13:12:03 +00:00
+ +
| |
+----+----+----+----+----+----+----+----+
2018-04-02 13:12:03 +00:00
| padLen | tsB | Rsrvd(0)|
+----+----+----+----+----+----+----+----+
2018-04-12 12:56:50 +00:00
| unencrypted, authenticated |
2018-04-02 13:12:03 +00:00
+ padding (optional) +
| length defined in options block |
~ . . . ~
| |
+----+----+----+----+----+----+----+----+
2018-04-02 13:12:03 +00:00
Y :: 32 bytes, little endian
2018-04-02 13:12:03 +00:00
padLen :: Length of the padding, 0 or more
Min/max guidelines TBD. Random size from 0 to 31 bytes minimum?
(Distribution to be determined, see Appendix A.)
2018-04-02 13:12:03 +00:00
tsB :: Unix timestamp, unsigned seconds.
Wraps around in 2106
2018-04-02 13:12:03 +00:00
Reserved :: 2 bytes, set to 0 for compatiblity with future options
2018-04-12 12:56:50 +00:00
padding :: Random data, 0 or more bytes.
Total message length must be 65535 bytes or less.
Alice and Bob will use the padding data in the KDF for message 3 part 1.
It is authenticated in that any tampering will cause the
next message to fail.
2018-04-02 13:12:03 +00:00
{% endhighlight %}
Notes
`````
2018-04-04 13:54:03 +00:00
- Alice must reject connections where the timestamp value is too far off from
the current time. Call the maximum delta time "D". Alice must maintain a
local cache of previously-used handshake values and reject duplicates, to
prevent replay attacks. Values in the cache must have a lifetime of at least
2*D. The cache values are implementation-dependent, however the 32-byte Y
value (or its encrypted equivalent) may be used.
2018-04-02 13:12:03 +00:00
2018-04-04 13:54:03 +00:00
- Alice must validate that Bob's ephemeral key is a valid point on the curve
here.
2018-04-02 13:12:03 +00:00
- Padding should be limited to a reasonable amount.
Alice may reject connections with excessive padding.
Alice will specify her padding options in message 3.
Min/max guidelines TBD. Random size from 0 to 31 bytes minimum?
(Distribution to be determined, see Appendix A.)
2018-04-04 13:54:03 +00:00
- On any error, including AEAD, DH, timestamp, apparent replay, or key
validation failure, Alice must halt further message processing and close the
connection without responding. This should be an abnormal close (TCP RST).
2018-04-02 13:12:03 +00:00
2018-04-04 13:54:03 +00:00
- To facilitate rapid handshaking, implementations must ensure that Bob buffers
and then flushes the entire contents of the first message at once, including
the padding. This increases the likelihood that the data will be contained
in a single TCP packet (unless segmented by the OS or middleboxes), and
received all at once by Alice. This is also for efficiency and to ensure the
effectiveness of the random padding.
2018-04-02 13:12:03 +00:00
Issues
``````
- Is it good practice to include the IP and port of both parties in the
signature to avoid replay attacks within the bounds of what is undetectable
with timestamps? This is what SSU does, but it doesn't seem to be necessary
as X and Y also have to match.
- Should the padding be inside the authenticated data, not outside?
It's inside for obfs4. Noise implies it should be inside.
2018-04-12 12:56:50 +00:00
The arbitrary padding is not encrypted but it is used in the KDF
for message 3 part 1, so any tampering will cause the handshake to fail.
2018-04-02 13:12:03 +00:00
- Include min/max padding options here?
- ChaCha/Poly block must be of known size. Otherwise, we must prepend an
obfuscated length field. If we must do that, we may as well prepend
a 16-byte options block, and AES encrypt it, same as message 1.
2018-04-12 12:56:50 +00:00
- Is the fixed-size option block big enough?
2018-04-02 13:12:03 +00:00
Encryption for for handshake message 3 part 1, using message 1 KDF)
-------------------------------------------------------------------
.. raw:: html
2018-04-02 14:45:40 +00:00
{% highlight lang='text' %}
2018-04-02 13:12:03 +00:00
// probably do this also:
2018-04-04 13:54:03 +00:00
h = SHA256(h || random padding from message 2)
// h is used as the associated data for the AEAD in message 3 part 1, below
2018-04-02 13:12:03 +00:00
2018-04-04 13:54:03 +00:00
This is the "s" message pattern:
2018-04-02 13:12:03 +00:00
2018-04-04 13:54:03 +00:00
Define s = Alice's static public key, 32 bytes
2018-04-02 13:12:03 +00:00
2018-04-04 13:54:03 +00:00
// EncryptAndHash(s.publickey)
// EncryptWithAd(h, s.publickey)
// k is from handshake message 1
// n is 1
ciphertext = ENCRYPT(k, n++, h, s.publickey)
// MixHash(ciphertext)
// || below means append
h = SHA256(h || ciphertext);
2018-04-02 13:12:03 +00:00
2018-04-04 13:54:03 +00:00
// h is used as the associated data for the AEAD in message 3 part 2
2018-04-02 13:12:03 +00:00
2018-04-04 13:54:03 +00:00
End of "s" message pattern.
2018-04-02 13:12:03 +00:00
{% endhighlight %}
Key Derivation Function (KDF) (for handshake message 3 part 2)
--------------------------------------------------------------
.. raw:: html
2018-04-02 14:45:40 +00:00
{% highlight lang='text' %}
2018-04-02 13:12:03 +00:00
This is the "se" message pattern:
2018-04-04 13:54:03 +00:00
// DH(s, re) == DH(e, rs)
Define input_key_material = 32 byte DH result of Alice's static key and Bob's ephemeral key
Set input_key_material = X25519 DH result
// overwrite Bob's ephemeral key in memory, no longer needed
// Alice:
re = (all zeros)
// Bob:
e(public and private) = (all zeros)
2018-04-02 13:12:03 +00:00
2018-04-04 13:54:03 +00:00
// MixKey(DH())
2018-04-02 13:12:03 +00:00
2018-04-04 13:54:03 +00:00
Define temp_key = 32 bytes
Define HMAC-SHA256(key, data) as in [RFC-2104]_
// Generate a temp key from the chaining key and DH result
// ck is the chaining key, from the KDF for handshake message 1
temp_key = HMAC-SHA256(ck, input_key_material)
// overwrite the DH result in memory, no longer needed
input_key_material = (all zeros)
2018-04-02 13:12:03 +00:00
2018-04-04 13:54:03 +00:00
// Output 1
// Set a new chaining key from the temp key
// byte() below means a single byte
ck = HMAC-SHA256(temp_key, byte(0x01)).
2018-04-02 13:12:03 +00:00
2018-04-04 13:54:03 +00:00
// Output 2
// Generate the cipher key k
Define k = 32 bytes
// || below means append
// byte() below means a single byte
k = HMAC-SHA256(temp_key, ck || byte(0x02)).
2018-04-02 13:12:03 +00:00
2018-04-04 13:54:03 +00:00
// retain the chaining key ck for the data phase KDF
2018-04-02 13:12:03 +00:00
2018-04-04 13:54:03 +00:00
End of "se" message pattern.
2018-04-02 13:12:03 +00:00
2018-04-04 13:54:03 +00:00
KDF for SipHash for length field:
SipHash uses two 8-byte keys (big endian) and 8 byte IV for first data.
2018-04-02 13:12:03 +00:00
2018-04-04 13:54:03 +00:00
Alice to Bob SipHash k1, k2, IV:
2018-04-02 13:12:03 +00:00
2018-04-04 13:54:03 +00:00
sipkeys_ab = HMAC-SHA256(temp_key, k_ba || byte(0x03)).
sipk1_ab = sipkeys[0:7]
sipk2_ab = sipkeys[8:15]
sipiv_ab = sipkeys[16:23]
2018-04-02 13:12:03 +00:00
2018-04-04 13:54:03 +00:00
// overwrite the temp_key in memory, no longer needed
temp_key = (all zeros)
2018-04-02 13:12:03 +00:00
{% endhighlight %}
3) SessionConfirmed
--------------------
Alice sends to Bob.
Noise content: Alice's static key
Noise payload: Alice's RouterInfo and random padding
Non-noise payload: none
2018-04-16 15:49:00 +00:00
(Payload Security Properties)
2018-04-02 13:12:03 +00:00
.. raw:: html
2018-04-02 14:45:40 +00:00
{% highlight lang='text' %}
2018-04-02 13:12:03 +00:00
XK(s, rs): Authentication Confidentiality
-> s, se 2 5
Authentication: 2.
2018-04-04 13:54:03 +00:00
Sender authentication resistant to key-compromise impersonation (KCI). The
sender authentication is based on an ephemeral-static DH ("es" or "se")
between the sender's static key pair and the recipient's ephemeral key
pair. Assuming the corresponding private keys are secure, this
authentication cannot be forged.
2018-04-02 13:12:03 +00:00
Confidentiality: 5.
2018-04-04 13:54:03 +00:00
Encryption to a known recipient, strong forward secrecy. This payload is
encrypted based on an ephemeral-ephemeral DH as well as an ephemeral-static
DH with the recipient's static key pair. Assuming the ephemeral private
keys are secure, and the recipient is not being actively impersonated by an
attacker that has stolen its static private key, this payload cannot be
decrypted.
2018-04-02 13:12:03 +00:00
2018-04-04 13:54:03 +00:00
"s": Alice writes her static public key from the s variable into the
message buffer, encrypting it, and hashes the output along with the old h
to derive a new h.
2018-04-02 13:12:03 +00:00
2018-04-04 13:54:03 +00:00
"se": A DH is performed between the Alice's static key pair and the Bob's
ephemeral key pair. The result is hashed along with the old ck to derive a
new ck and k, and n is set to zero.
2018-04-02 13:12:03 +00:00
{% endhighlight %}
This contains two ChaCha/Poly frames.
The first is Alice's encrypted static public key.
2018-04-04 13:54:03 +00:00
The second is the Noise payload: Alice's encrypted RouterInfo, optional
options, and optional padding. They use different keys, because the MixKey()
function is called in between.
2016-04-04 12:51:03 +00:00
Raw contents:
.. raw:: html
{% highlight lang='dataspec' %}
+----+----+----+----+----+----+----+----+
| |
2018-04-12 12:56:50 +00:00
+ ChaCha/Poly frame (48 bytes) +
2018-04-02 13:12:03 +00:00
| Encrypted and authenticated |
+ Alice's static key +
2018-04-12 12:56:50 +00:00
| (32 bytes) |
2018-04-02 13:12:03 +00:00
+ +
| k from KDF for msg 1 |
+ n = 1 +
| |
+ +
| |
+----+----+----+----+----+----+----+----+
2018-04-02 13:12:03 +00:00
|obf. size| |
+----+----+ +
| |
2018-04-02 13:12:03 +00:00
+ ChaCha/Poly frame +
| Encrypted and authenticated |
+ +
| Alice's RouterInfo |
+ using block format 2 +
| Arbitrary padding |
+ using block format 255 +
| |
+ +
2018-04-02 13:12:03 +00:00
| k from KDF for msg 3 part 2 |
+ n = 0 +
| |
~ . . . ~
| |
+----+----+----+----+----+----+----+----+
2018-04-02 13:12:03 +00:00
obf. size :: Size of frame to follow, obfuscated with SipHash
KDF for SipHash TBD
{% endhighlight %}
2018-04-12 12:56:50 +00:00
Unencrypted data (Poly1305 auth tag not shown):
.. raw:: html
{% highlight lang='dataspec' %}
+----+----+----+----+----+----+----+----+
| |
2018-04-02 13:12:03 +00:00
+ +
| |
2018-04-02 13:12:03 +00:00
+ Alice's static key +
| (32 bytes) |
+ +
| |
2018-04-02 13:12:03 +00:00
+ +
+----+----+----+----+----+----+----+----+
| size | |
+----+----+ +
| |
+ +
| Alice's RouterInfo block |
~ . . . ~
| |
+----+----+----+----+----+----+----+----+
2018-04-02 13:12:03 +00:00
| |
+ Optional Options block +
| |
~ . . . ~
| |
+----+----+----+----+----+----+----+----+
| |
2018-04-02 13:12:03 +00:00
+ Optional Padding block +
| |
~ . . . ~
| |
+----+----+----+----+----+----+----+----+
2018-04-02 13:12:03 +00:00
2018-04-12 12:56:50 +00:00
size :: Size of frame to follow, plus 16 for the
Poly1305 auth tag (not shown)
{% endhighlight %}
2016-04-04 12:51:03 +00:00
2018-04-02 13:12:03 +00:00
Notes
`````
2018-04-02 13:12:03 +00:00
- Bob must perform the usual Router Info validation.
Ensure the sig type is supported, verify the signature,
verify the timestamp is within bounds, and any other checks necessary.
2016-04-04 12:51:03 +00:00
2018-04-02 13:12:03 +00:00
- Bob must verify that Alice's static key received in the first frame matches
the static key in the Router Info. Bob must first search the Router Info for
a Router Address with a matching Noise Name (nn) and version (v) option.
If none is present, get the key from the Router Info options.
See Published Router Info section below.
2016-04-04 12:51:03 +00:00
2018-04-02 13:12:03 +00:00
- If Bob has an older version of Alice's RouterInfo in his netdb, verify
that the static key in the router info is the same in both, if present,
and if the older version is less than XXX old (see key rotate time below)
2016-04-04 12:51:03 +00:00
2018-04-02 13:12:03 +00:00
- Bob must validate that Alice's static key is a valid point on the curve here.
2016-04-04 12:51:03 +00:00
2018-04-02 13:12:03 +00:00
- Options should be included, to specify padding parameters.
2016-04-04 12:51:03 +00:00
2018-04-02 13:12:03 +00:00
- On any error, including AEAD, RI, DH, timestamp, or key validation failure,
2018-04-04 13:54:03 +00:00
Bob must halt further message processing and close the connection without
responding. This should be an abnormal close (TCP RST).
2016-04-04 12:51:03 +00:00
2018-04-04 13:54:03 +00:00
- To facilitate rapid handshaking, implementations must ensure that Alice
buffers and then flushes the entire contents of the third message at once,
2018-04-02 13:12:03 +00:00
including both AEAD blocks.
2018-04-04 13:54:03 +00:00
This increases the likelihood that the data will be contained in a single TCP
packet (unless segmented by the OS or middleboxes), and received all at once
by Bob. This is also for efficiency and to ensure the effectiveness of the
random padding.
2018-04-02 13:12:03 +00:00
Key Derivation Function (KDF) (for data phase)
----------------------------------------------
The data phase uses a zero-length associated data input.
The KDF generates two cipher keys k_ab and k_ba from the chaining key ck,
using HMAC-SHA256(key, data) as defined in [RFC-2104]_.
This is the Split() function, exactly as defined in the Noise spec.
.. raw:: html
2018-04-02 15:07:59 +00:00
{% highlight lang='text' %}
2018-04-02 13:12:03 +00:00
ck = from handshake phase
2018-04-04 13:54:03 +00:00
// zerolen is a zero-length byte array
temp_key = HMAC-SHA256(ck, zerolen)
// overwrite the chaining key in memory, no longer needed
ck = (all zeros)
2018-04-02 13:12:03 +00:00
2018-04-04 13:54:03 +00:00
// Output 1
// cipher key, for Alice transmits to Bob (Noise doesn't make clear which is which, but Java code does)
k_ab = HMAC-SHA256(temp_key, byte(0x01)).
2018-04-02 13:12:03 +00:00
2018-04-04 13:54:03 +00:00
// Output 2
// cipher key, for Bob transmits to Alice (Noise doesn't make clear which is which, but Java code does)
k_ba = HMAC-SHA256(temp_key, k_ab || byte(0x02)).
2018-04-02 13:12:03 +00:00
2018-04-04 13:54:03 +00:00
KDF for SipHash for length field:
SipHash uses two 8-byte keys (big endian) and 8 byte IV for first data.
2018-04-02 13:12:03 +00:00
2018-04-04 13:54:03 +00:00
Alice to Bob SipHash k1, k2, IV:
2018-04-02 13:12:03 +00:00
2018-04-04 13:54:03 +00:00
sipkeys_ab = HMAC-SHA256(temp_key, k_ba || byte(0x03)).
sipk1_ab = sipkeys[0:7]
sipk2_ab = sipkeys[8:15]
sipiv_ab = sipkeys[16:23]
2018-04-02 13:12:03 +00:00
2018-04-04 13:54:03 +00:00
Bob to Alice SipHash k1, k2, IV:
2018-04-02 13:12:03 +00:00
2018-04-04 13:54:03 +00:00
sipkeys_ba = HMAC-SHA256(temp_key, sipkeys_ab || byte(0x04)).
sipk1_ba = sipkeys[0:7]
sipk2_ba = sipkeys[8:15]
sipiv_ba = sipkeys[16:23]
2018-04-02 13:12:03 +00:00
2018-04-04 13:54:03 +00:00
// overwrite the temp_key in memory, no longer needed
temp_key = (all zeros)
2018-04-02 13:12:03 +00:00
{% endhighlight %}
4) Data and TimeSync
--------------------
2016-04-04 12:51:03 +00:00
2018-04-02 13:12:03 +00:00
Noise payload: As defined below, including random padding
Non-noise payload: none
Starting with the 2nd part of message 3, all messages are inside
an authenticated and encrypted ChaCha/Poly "frame"
with a prepended two-byte obfuscated length.
All padding is inside the frame.
Inside the frame is a standard format with zero or more "blocks".
Each block has a one-byte type and a two-byte length.
Types include date/time, I2NP message, options, termination, and padding.
Note: Bob may, but is not required, to send his RouterInfo to Alice as
his first message to Alice in the data phase.
2018-04-16 15:49:00 +00:00
(Payload Security Properties)
2018-04-02 13:12:03 +00:00
.. raw:: html
2018-04-02 14:45:40 +00:00
{% highlight lang='text' %}
2018-04-02 13:12:03 +00:00
XK(s, rs): Authentication Confidentiality
<- 2 5
-> 2 5
Authentication: 2.
Sender authentication resistant to key-compromise impersonation (KCI).
The sender authentication is based on an ephemeral-static DH ("es" or "se")
between the sender's static key pair and the recipient's ephemeral key pair.
Assuming the corresponding private keys are secure, this authentication cannot be forged.
Confidentiality: 5.
Encryption to a known recipient, strong forward secrecy.
This payload is encrypted based on an ephemeral-ephemeral DH as well as
an ephemeral-static DH with the recipient's static key pair.
Assuming the ephemeral private keys are secure, and the recipient is not being actively impersonated
by an attacker that has stolen its static private key, this payload cannot be decrypted.
{% endhighlight %}
Notes
`````
- For efficiency and to minimize identification of the length field,
implementations must ensure that the sender buffers and then flushes the entire contents
of data messages at once, including the length field and the AEAD block.
This increases the likelihood that the data will be contained in a single TCP packet
(unless segmented by the OS or middleboxes), and received all at once the other party.
This is also for efficiency and to ensure the effectiveness of the random padding.
- The router may choose to terminate the session on AEAD error, or may continue to attempt communications.
If continuing, the router should terminate after repeated errors.
SipHash obfuscated length?
``````````````````````````
Reference: [SipHash]_
Following is from obfs4:
.. raw:: html
2018-04-02 15:07:59 +00:00
{% highlight lang='text' %}
2018-04-02 13:12:03 +00:00
2018-04-04 13:54:03 +00:00
Once both sides have completed the handshake, they transfer application
2018-04-02 13:12:03 +00:00
data broken up into "packets", that are then encrypted and authenticated in
NaCl crypto_secretbox_xsalsa20poly1305 [5] "frames".
+------------+----------+--------+--------------+------------+------------+
| 2 bytes | 16 bytes | 1 byte | 2 bytes | (optional) | (optional) |
| Frame len. | Tag | Type | Payload len. | Payload | Padding |
+------------+----------+--------+--------------+------------+------------+
\_ Obfs. _/ \___________ NaCl secretbox (Poly1305/XSalsa20) ___________/
The frame length refers to the length of the succeeding secretbox. To
avoid transmitting identifiable length fields in stream, the frame length
is obfuscated by XORing a mask derived from SipHash-2-4 in OFB mode.
K = The SipHash-2-4 key from the KDF. (two 8-byte long integers)
IV[0] = The SipHash-2-4 OFB from the KDF. (8 bytes)
For each packet:
IV[n] = SipHash-2-4(K, IV[n-1])
Mask[n] = First 2 bytes of IV[n]
obfuscatedLength = length ^ Mask[n]
As the receiver has the SipHash-2-4 key and IV, decoding the length is done
via deriving the mask used to obfsucate the length and XORing the truncated
digest to obtain the length of the secretbox.
The payload length refers to the length of the payload portion of the frame
and does not include the padding. It is possible for the payload length to
be 0 in which case all the remaining data is authenticated and decrypted,
but ignored.
The maximum allowed frame length is 1448 bytes, which allows up to 1427
bytes of useful payload to be transmitted per "frame".
{% endhighlight %}
Maximum size
````````````
Raw contents
````````````
.. raw:: html
{% highlight lang='dataspec' %}
+----+----+----+----+----+----+----+----+
2018-04-02 15:07:59 +00:00
|obf size | |
2018-04-02 13:12:03 +00:00
+----+----+ +
| |
2018-04-02 13:12:03 +00:00
+ ChaCha/Poly frame +
| Encrypted and authenticated |
+ k = KDF for data phase +
| n starts at 0 and increments |
+ for each frame +
| 16 bytes minimum |
+ +
| |
~ . . . ~
| |
+----+----+----+----+----+----+----+----+
2018-04-02 13:12:03 +00:00
2018-04-02 15:07:59 +00:00
obf size :: 2 bytes length obfuscated with SipHash
Maximum size is 65537 bytes.
Obfuscated length is 2 bytes.
Maximum ChaCha/poly frame is 65535 bytes.
2018-04-02 13:12:03 +00:00
{% endhighlight %}
2018-04-02 13:12:03 +00:00
Unencrypted data
````````````````
There are zero or more blocks in the encrypted frame.
Each block contains a one-byte identifier, a two-byte length,
and zero or more bytes of data.
For extensibility, receivers must ignore blocks with unknown identifiers,
and treat them as padding.
Encrypted data is 65535 bytes max, including a 16-byte authentication header,
so the max unencrypted data is 65519 bytes.
2018-04-17 16:11:51 +00:00
(Poly1305 auth tag not shown):
.. raw:: html
{% highlight lang='dataspec' %}
+----+----+----+----+----+----+----+----+
2018-04-02 13:12:03 +00:00
|blk | size | data |
+----+----+----+ +
| |
~ . . . ~
| |
+----+----+----+----+----+----+----+----+
2018-04-02 13:12:03 +00:00
|blk | size | data |
+----+----+----+ +
| |
~ . . . ~
| |
+----+----+----+----+----+----+----+----+
2018-04-02 13:12:03 +00:00
~ . . . ~
2018-04-02 13:12:03 +00:00
blk :: 0 for datetime,
1 for options,
2 for RouterInfo,
3 for I2NP msg,
4 for termination,
254 for padding
255 reserved for future extension
size :: size of data to follow, 0 - 65516
2018-04-02 15:07:59 +00:00
data :: the data
2018-04-02 13:12:03 +00:00
2018-04-02 15:07:59 +00:00
Maximum ChaCha/Poly frame is 65535 bytes.
Poly1305 tag is 16 bytes
Maximum total block size is 65519 bytes
Maximum single block size is 65519 bytes
Block type is 1 byte
Block length is 2 bytes
Maximum single block data size is 65516 bytes.
{% endhighlight %}
2018-04-02 13:12:03 +00:00
DateTime
````````
Special case for time synchronization:
.. raw:: html
{% highlight lang='dataspec' %}
+----+----+----+----+----+----+----+
| 0 | 4 | timestamp |
+----+----+----+----+----+----+----+
blk :: 0
size :: 4
timestamp :: Unix timestamp, unsigned seconds.
Wraps around in 2106
{% endhighlight %}
Options
```````
Pass updated options.
Options include: Min and max padding.
2018-04-17 16:11:51 +00:00
Options block will be variable length.
.. raw:: html
{% highlight lang='dataspec' %}
+----+----+----+----+----+----+----+----+
2018-04-02 13:12:03 +00:00
| 1 | size | options |
+----+----+----+ +
| |
~ . . . ~
| |
+----+----+----+----+----+----+----+----+
2018-04-02 13:12:03 +00:00
blk :: 1
size :: size of options to follow TBD
options :: Format TBD
2018-04-02 15:07:59 +00:00
Requested padding parameters.
Min is for desired DPI resistance
Max is for bandwidth limits.
4 bytes tx_pad_min, tx_pad_max, rx_pad_min, rx_pad_max
Each is a 4.4 fixed-point float representing 0 to 15.9375
2018-04-17 16:11:51 +00:00
(or think of it as an unsigned 8-bit integer divided by 16.0).
2018-04-02 15:07:59 +00:00
This is the ratio of padding to data. Examples:
Value of 0x00 means no padding
Value of 0x01 means add 6% padding
Value of 0x10 means add 100% padding
Value of 0x80 means add 800% (8x) padding
Alice and Bob will negotiate the minimum and maximum in each direction.
These are guidelines, there is no enforcement.
Sender should honor receiver's maximum.
Sender may or may not honor receiver's minimum, within bandwidth constraints.
Padding distribution specified as additional parameters?
Random delay specified as additional parameters?
2018-04-02 13:12:03 +00:00
{% endhighlight %}
2018-04-17 16:11:51 +00:00
Options Issues
``````````````
- Options format is TBD.
- Options negotiation is TBD.
2018-04-02 13:12:03 +00:00
RouterInfo
``````````
Pass Alice's RouterInfo to Bob.
Used in handshake message 3 part 2.
Pass Alice's RouterInfo to Bob, or Bob's to Alice.
Used optionally in the data phase.
.. raw:: html
{% highlight lang='dataspec' %}
+----+----+----+----+----+----+----+----+
| 2 | size |flg | RouterInfo |
+----+----+----+----+ +
| (Alice's in handshake msg 3 part 2) |
~ (Alice's or Bob's in data phase) ~
| |
~ . . . ~
| |
+----+----+----+----+----+----+----+----+
2018-04-02 13:12:03 +00:00
blk :: 2
size :: size of router info to follow
flg :: 1 byte flag
bit order: 76543210
bit 0: 0 for local store, 1 for flood request
bits 7-1: Unused, set to 0 for future compatibility
routerinfo :: Alice's or Bob's RouterInfo
{% endhighlight %}
2016-04-04 12:51:03 +00:00
Notes
`````
2018-04-02 13:12:03 +00:00
- When used in the data phase, receiver (Alice or Bob) shall validate that
it's the same Router Hash as originally sent (for Alice) or sent to (for Bob).
Then, treat it as a local I2NP DatabaseStore Message. Validate signature,
validate more recent timestamp, and store in the local netdb.
If the flag bit 0 is 1, and the receiving party is floodfill,
treat it as a DatabaseStore Message with a nonzero reply token,
and flood it to the nearest floodfills.
2018-04-02 13:12:03 +00:00
- The Router Info is NOT gzipped compressed
(unlike in a DatabaseStore Message, where it is)
2018-04-02 13:12:03 +00:00
- Flooding must not be requested unless there are published
RouterAddresses in the RouterInfo. The receiving router
must not flood the RouterInfo unless there are published
RouterAddresses in it.
2018-04-02 13:12:03 +00:00
Issues
``````
- Could also be used in data phase, instead of a I2NP DatabaseStoreMessage.
For example, Bob could use it to start off the data phase.
2018-04-02 13:12:03 +00:00
I2NP Message
````````````
An single I2NP message with a modified header.
I2NP messages may not be fragmented across blocks or
across chacha/poly segments.
This removes 7 bytes from the NTCP I2NP header:
The one-byte SHA-256 checksum,
go from 8 to 4 bytes for expiration,
and remove the 2 byte length (use the block size - 9).
.. raw:: html
{% highlight lang='dataspec' %}
+----+----+----+----+----+----+----+----+
2018-04-02 13:12:03 +00:00
| 3 | size |type| msg id |
+----+----+----+----+----+----+----+----+
2018-04-02 13:12:03 +00:00
| short exp | message |
+----+----+----+----+ +
| |
~ . . . ~
| |
+----+----+----+----+----+----+----+----+
2018-04-02 13:12:03 +00:00
blk :: 3
size :: size of type + msg id + exp + data to follow
I2NP message body size is (size - 9).
type :: I2NP msg type, see I2NP spec
msg id :: I2NP msg id, 4 bytes
short exp :: I2NP message expiration, Unix timestamp, unsigned seconds.
Wraps around in 2106
message :: I2NP message body
{% endhighlight %}
2018-04-02 13:12:03 +00:00
Termination
```````````
Noise recommends an explicit termination message.
Original NTCP doesn't have one.
Drop the connection.
This should be the last non-padding block.
.. raw:: html
{% highlight lang='dataspec' %}
+----+----+----+----+----+----+----+----+
2018-04-02 13:12:03 +00:00
| 4 | 1 |rsn | last valid
+----+----+----+----+----+----+----+----+
2018-04-02 13:12:03 +00:00
nonce received |
+----+----+----+----+
blk :: 4
size :: 0
rsn :: reason, 1 byte:
0: unspecified
1: termination received
2: idle timeout
3: router shutdown
4: AEAD failure
5: incompatible options
6: incompatible sig type
7: clock skew
2018-04-17 16:11:51 +00:00
8: padding violation
9: AEAD framing error
10: payload framing error
2018-04-02 13:12:03 +00:00
...
2018-04-17 16:11:51 +00:00
last valid nonce received: The nonce (counter) for the last valid AEAD block received
2018-04-02 13:12:03 +00:00
8 bytes
Note: Not all reasons may actually be used; handshake failures will
generally result in immediate close with TCP RST instead.
{% endhighlight %}
2018-04-02 13:12:03 +00:00
Padding
```````
This is for padding inside AEAD.
Padding for messages 1 and 2 are outside AEAD.
All padding for message 3 and the data phase is inside AEAD.
Padding inside AEAD should roughly adhere to the negotiated parameters.
Bob sent his requested tx/rx min/max parameters in message 2.
Alice sent her requested tx/rx min/max parameters in message 3.
Updated options may be sent during the data phase.
See options block information above.
2018-04-17 16:11:51 +00:00
.. raw:: html
{% highlight lang='dataspec' %}
+----+----+----+----+----+----+----+----+
2018-04-02 13:12:03 +00:00
|254 | size | padding |
+----+----+----+ +
| |
~ . . . ~
| |
+----+----+----+----+----+----+----+----+
2018-04-02 13:12:03 +00:00
blk :: 254
size :: size of padding to follow
padding :: random data
{% endhighlight %}
2018-04-17 16:11:51 +00:00
Padding Issues
``````````````
- Padding strategies TBD.
- Minimum padding TBD.
- Need for padding-only messages TBD.
- Padding defaults TBD.
- Padding parameter negotiation TBD.
- Is padding important for data phase or only handshake?
- How to ensure low-bandwidth routers aren't "swamped"
- How to ensure high-bandwidth routers send/receive enough padding
- Noise limits messages to 64KB, any other padding (except in handshake msg 1/2)
would have to be outside Noise.
- Disconnect if negotiated padding is violated or can't negotiate?
2018-04-02 13:12:03 +00:00
Other block types
`````````````````
Implementations should ignore unknown block types for
forward compatibility.
Future work
```````````
- The padding length is either to be decided on a per-message basis and
estimates of the length distribution, or random delays should be added.
These countermeasures are to be included to resist DPI, as message sizes
would otherwise reveal that I2P traffic is being carried by the transport
protocol. The exact padding scheme is an area of future work, Appendix A
provides more information on the topic.
2018-04-02 13:12:03 +00:00
5) Termination
--------------
Connections may be terminated via normal or abnormal TCP socket close,
or, as Noise recommends, an explicit termination message.
The explicit termination message is defined in the data phase above.
Upon any normal or abnormal termination, routers should
zero-out any in-memory ephemeral data, including handshake ephemeral keys,
symmetric crypto keys, and related information.
Published Router Info
=====================
Published Addresses
-------------------
The published RouterAddress (part of the RouterInfo) will have a
protocol identifier of either "NTCP" or "NTCP2".
The RouterAddress must contain "host" and "port" options, as in
the current NTCP protocol.
The RouterAddress must contain four options
to indicate NTCP2 support:
- n=NXK2CS
The Noise Protocol Name.
Value shortened from Noise_XK_25519_ChaChaPoly_SHA256.
Future values will be named similarly, with 6 chars to represent
the 5 Noise name fields.
2018-04-12 12:56:50 +00:00
TODO: There may be value in using the "official" noise name,
at a cost of 26 bytes per address.
2018-04-02 13:12:03 +00:00
- s=(Base64 key)
The current Noise static public key (s) for this RouterAddress.
Base 64 encoded using the standard I2P Base 64 alphabet.
32 bytes in binary, 44 bytes as Base 64 encoded,
little-endian X25519 public key.
- i=(Base64 IV)
The current IV for encrypting the X value in message 1 for this RouterAddress.
Base 64 encoded using the standard I2P Base 64 alphabet.
16 bytes in binary, 24 bytes as Base 64 encoded,
big-endian.
- v=2
The current version (2).
When published as "NTCP", additional support for version 1 is implied.
Support for future versions will be with comma-separated values,
e.g. v=2,3
Implementation should verify compatibility, including multiple
versions if a comma is present. Comma-separated versions must
be in numerical order.
Alice must verify that all three options are present and valid
before connecting using the NTCP2 protocol.
When published as "NTCP" with "n", "s", "i", and "v" options,
the router must accept incoming connections on that host and port
2018-04-04 13:54:03 +00:00
for both NTCP and NTCP2 protocols, and automatically detect the protocol
version.
2018-04-02 13:12:03 +00:00
When published as "NTCP2" with "n", "s", "i", and "v" options,
the router accepts incoming connections on that host and port
for the NTCP2 protocol only.
2018-04-17 16:11:51 +00:00
If a router supports both NTCP1 and NTCP2 connections but
does not implement automatic version detection for incoming connections,
it must advertise both "NTCP" and "NTCP2" addresses, and include
the ntcp2 options in the "NTCP2" address only.
2018-04-02 13:12:03 +00:00
If multiple NTCP2 RouterAddresses (either as "NTCP" or "NTCP2") are published
in the same RouterInfo (for additional IP addresses or ports),
2018-04-17 16:11:51 +00:00
all addressses specifying the same port must contain the identical ntcp2 options and values.
In particular, all must contain the same static key and iv.
2018-04-02 13:12:03 +00:00
Unpublished NTCP Address
------------------------
If Alice does not publish her NTCP2 address (as "NTCP" or "NTCP2),
she must include her Noise static public key in her RouterInfo options.
The option name is N(shortened Noise name)(NTCP2 Version)s.
- NNXK2CS2s=(Base64 key)
2018-04-04 13:54:03 +00:00
Name shortened from (N)TCP2 (N)oise_(XK)_(2)5519_(C)haChaPoly_(S)HA256
version (2) (s)tatic key.
2018-04-02 13:12:03 +00:00
Future options will be named similarly, with 6 chars to represent
the 5 Noise name fields.
The current Noise static public key (s) for this Router.
Base 64 encoded using the standard I2P Base 64 alphabet.
32 bytes in binary, 44 bytes as Base 64 encoded,
little-endian X25519 public key.
2018-04-17 16:11:51 +00:00
TODO: There may be value in using the "official" noise name,
at a cost of 26 bytes per address.
2018-04-02 13:12:03 +00:00
Public Key and IV Rotation
--------------------------
2018-04-12 12:56:50 +00:00
Due to caching of RouterInfos, routers must not rotate the static public key or IV
2018-04-04 13:54:03 +00:00
while the router is up, whether in a published address or not. Routers must
2018-04-12 12:56:50 +00:00
persistently store this key and IV for reuse after an immediate restart, so incoming
2018-04-04 13:54:03 +00:00
connections will continue to work, and restart times are not exposed. Routers
must persistently store, or otherwise determine, last-shutdown time, so that
the previous downtime may be calculated at startup.
2018-04-12 12:56:50 +00:00
Subject to concerns about exposing restart times, routers may rotate this key or IV
2018-04-04 13:54:03 +00:00
at startup if the router was previously down for some time (a couple hours at
least).
If the router has any published NTCP2 RouterAddresses (as NTCP or NTCP2), the
minimum downtime before rotation should be much longer, for example one month,
2018-04-02 13:12:03 +00:00
unless the local IP address has changed or the router "rekeys".
2018-04-04 13:54:03 +00:00
If the router has any published SSU RouterAddresses, but not NTCP2 (as NTCP or
NTCP2) the minimum downtime before rotation should be longer, for example one
day, unless the local IP address has changed or the router "rekeys". This
applies even if the published SSU address has introducers.
2018-04-02 13:12:03 +00:00
2018-04-04 13:54:03 +00:00
If the router does not have any published RouterAddresses (NTCP, NTCP2, or
SSU), the minimum downtime before rotation may be as short as two hours, even
if the IP address changes, unless the router "rekeys".
2018-04-02 13:12:03 +00:00
2018-04-04 13:54:03 +00:00
If the router "rekeys" to a different Router Hash, it should generate a new
2018-04-12 12:56:50 +00:00
noise key and IV as well.
2018-04-02 13:12:03 +00:00
2018-04-12 12:56:50 +00:00
Implementations must be aware that changing the static public key or IV will prohibit
2018-04-02 13:12:03 +00:00
incoming NTCP2 connections from routers that have cached an older RouterInfo.
2018-04-04 13:54:03 +00:00
RouterInfo publishing, tunnel peer selection (including both OBGW and IB
closest hop), zero-hop tunnel selection, transport selection, and other
implementation strategies must take this into account.
2018-04-02 13:12:03 +00:00
2018-04-12 12:56:50 +00:00
IV rotation is subject to identical rules as key rotation, except that IVs are not present
2018-04-04 13:54:03 +00:00
except in published RouterAddresses, so there is no IV for hidden or firewalled
2018-04-12 12:56:50 +00:00
routers. If anything changes (version, key, options?) it is recommended that
the IV change as well.
2018-04-02 13:12:03 +00:00
2018-04-04 13:54:03 +00:00
Note: The minimum downtime before rekeying may be modified to ensure network
health, and to prevent reseeding by a router down for a moderate amount of
time.
2018-04-02 13:12:03 +00:00
2016-04-04 12:51:03 +00:00
2018-04-02 13:12:03 +00:00
Identity Hiding
```````````````
Deniability is not a goal. See overview above.
2016-04-04 12:51:03 +00:00
2018-04-04 13:54:03 +00:00
Each pattern is assigned properties describing the confidentiality supplied to
the initiator's static public key, and to the responder's static public key.
The underlying assumptions are that ephemeral private keys are secure, and that
parties abort the handshake if they receive a static public key from the other
party which they don't trust.
2018-04-02 13:12:03 +00:00
2018-04-04 13:54:03 +00:00
This section only considers identity leakage through static public key fields
in handshakes. Of course, the identities of Noise participants might be
exposed through other means, including payload fields, traffic analysis, or
metadata such as IP addresses.
2018-04-02 13:12:03 +00:00
Alice: (8) Encrypted with forward secrecy to an authenticated party.
2018-04-04 13:54:03 +00:00
Bob: (3) Not transmitted, but a passive attacker can check candidates for the
responder's private key and determine whether the candidate is correct.
2018-04-02 13:12:03 +00:00
Bob publishes his static public key in the netdb. Alice may or may not?
Issues
``````
- If Bob changes his static key, could fallback to a "XX" pattern?
Version Detection
=================
2018-04-04 13:54:03 +00:00
When published as "NTCP", the router must automatically detect the protocol
version for incoming connections.
2018-04-02 13:12:03 +00:00
This detection is implementation-dependent, but here is some general guidance.
2016-04-04 12:51:03 +00:00
To detect the version of an incoming NTCP connection, Bob proceeds as follows:
2016-04-04 12:51:03 +00:00
2018-04-02 13:12:03 +00:00
- Wait for at least 64 bytes (minimum NTCP2 message 1 size)
- If the initial received data is 288 or more bytes, the incoming connection
is version 1.
2018-04-02 14:45:40 +00:00
- If less than 288 bytes, either
2018-04-02 15:07:59 +00:00
2018-04-04 13:54:03 +00:00
- Wait for a short time for more data (good strategy before widespread NTCP2
adoption) if at least 288 total received, it's NTCP 1.
2018-04-02 15:07:59 +00:00
2018-04-04 13:54:03 +00:00
- Try the first stages of decoding as version 2, if it fails, wait a short
time for more data (good strategy after widespread NTCP2 adoption)
2018-04-02 15:07:59 +00:00
2018-04-02 13:12:03 +00:00
- Decrypt the first 32 bytes (the X key)
of the SessionRequest packet using AES-256 with key RH_B.
2018-04-02 15:07:59 +00:00
2018-04-02 13:12:03 +00:00
- Verify a valid point on the curve.
If it fails, wait a short time for more data for NTCP 1
2018-04-02 15:07:59 +00:00
2018-04-02 13:12:03 +00:00
- Verify the AEAD block.
If it fails, wait a short time for more data for NTCP 1
Note that changes or additional strategies may be recommended if we detect
active TCP segmentation attacks on NTCP 1.
2018-04-04 13:54:03 +00:00
To facilitate rapid version detection and handshaking, implementations must
ensure that Alice buffers and then flushes the entire contents of the first
message at once, including the padding.
This increases the likelihood that the data will be contained in a single TCP
packet (unless segmented by the OS or middleboxes), and received all at once by
Bob. This is also for efficiency and to ensure the effectiveness of the random
padding.
2018-04-02 13:12:03 +00:00
This applies to both NTCP and NTCP2 handshakes.
Variants, Fallbacks, and General Issues
=======================================
- If Alice and Bob both support NTCP2, Alice should connect with NTCP2.
2018-04-04 13:54:03 +00:00
- If Alice fails to connect to Bob using NTCP2 for any reason, the connection
fails.
2018-04-02 13:12:03 +00:00
Alice may not retry using old NTCP 1.
2018-04-04 13:54:03 +00:00
- Fallback to XX pattern if Bob changes his keys? This would require a type
byte prepended?
2018-04-02 13:12:03 +00:00
2018-04-04 13:54:03 +00:00
- "Fall forward" to KK pattern if Alice reconnects, assuming Bob still has her
static key? This doesn't save any round trips and uses 4 DH rounds compared
to 3 for XK. Probably not.
2018-04-02 13:12:03 +00:00
.. raw:: html
{% highlight lang='dataspec' %}
KK(s, rs):
-> s
<- s
...
-> e, es, ss
<- e, ee, se
{% endhighlight %}
2016-04-04 12:51:03 +00:00
Appendix A: Padding Scheme
==========================
2016-04-04 12:51:03 +00:00
2018-04-04 13:54:03 +00:00
This section discusses an attack on typical padding schemes that allows
attackers to discover the probability distribution of the length of the
unpadded messages, by only observing the length of the padded messages. Let N
be a random variable describing the number of unpadded bytes, and P likewise
for the number of padding bytes. The total message size is then N + P.
2016-04-04 12:51:03 +00:00
Assume that for an unpadded size of n, at least ``P_min(n) >= 0`` and at most
``P_max(n) >= P_min(n)`` bytes of padding are added in a padding scheme. The
obvious scheme uses padding of length P uniformly chosen at random:
2016-04-04 12:51:03 +00:00
::
2016-04-04 12:51:03 +00:00
Pr[P = p | N = n] = 1 / (P_max(n) - P_min(n)) if P_min(n) <= p <= P_max(n),
0 otherwise.
2016-04-04 12:51:03 +00:00
A naive padding scheme would simply ensure that the size of the padded message
does not exceed N_max:
2016-04-04 12:51:03 +00:00
::
2016-04-04 12:51:03 +00:00
P_max(n) = N_max - n, n <= N_max
P_min(n) = 0.
2016-04-04 12:51:03 +00:00
However, this leaks information about the unpadded length.
2016-04-04 12:51:03 +00:00
An attacker can easily estimate ``Pr[x <= N + P <= y]``, for example by means
of a histogram.
2016-04-04 12:51:03 +00:00
- From this, he can also try to estimate ``Pr[n_1 <= N <= n_2]``, indeed:
2016-04-04 12:51:03 +00:00
::
2016-04-04 12:51:03 +00:00
Pr[N + P = m] = Σ_n Pr[N = n] Pr[P = m - n | N = n].
2016-04-04 12:51:03 +00:00
In the naive scheme,
2016-04-04 12:51:03 +00:00
::
2016-04-04 12:51:03 +00:00
Pr[N + P = m] = Σ_{n <= m} Pr[N = n] / (N_max - n).
2016-04-04 12:51:03 +00:00
It's pretty obvious, as it was before doing the above calculation, that this
leaks information about ``Pr[N = n]``: if the length of packets is almost
always more than m, then N + P <= m will almost never be observed. This is not
the largest issue though, although being able to observe the minimum message
length can be considered to be a problem by itself.
2016-04-04 12:51:03 +00:00
A bigger issue is that it is possible to determine ``Pr[N = n]`` exactly:
::
Pr[N + P = m] - Pr[N + P = m-1] = Pr[N = m] / (N_max - m),
that is
::
Pr[N = n] = (N_max - n)(Pr[N + P = n] - Pr[N + P = n - 1])
To distinguish NTCP2, then, the attacker can use any of the following:
- Estimate ``Pr[kB <= N <= (k + 1)B - 1]`` for positive integers k. It will
always be zero for NTCP2.
- Estimate ``Pr[N = kB]`` and compare with a standard I2P profile.
This simple attack hence partially destroys the purpose of padding, which
attempts to obfuscate the size distribution of the unpadded messages. The
amount of messages that the attacker has to observe to distinguish the protocol
depends on the desired accuracy and on the minimum and maximum unpadded message
sizes that occur in practice. Note that it is easy to gather many messages for
the attacker, since he can use all traffic sent from and to the particular port
that the target is using.
In some forms (e.g. estimation of ``Pr[kB <= N <= (k + 1)B - 1]``) the attack
requires only a few bytes of memory (one integer is enough) and it could be
argued that such an attack might be included in many slightly more advanced but
nevertheless standard DPI frameworks.
This proposal suggests using one of the following countermeasures:
- Develop an alternate padding scheme that takes into account the (estimated)
distribution of N by using a non-uniform padding length distribution. A good
padding scheme would probably require maintaining a histogram of the number
of blocks per message.
- Add random delays between (randomly sized) fragments of messages.
The second option is more generally preferred, because it can be simultaneously
used as a countermeasure against flow analysis. However, such delays may be out
of scope for the NTCP2 protocol, such that the first option, which is also
easier to implement, may be preferred instead.
2018-04-02 13:12:03 +00:00
Appendix B: Random Delays
=========================
2018-04-02 13:12:03 +00:00
Timing-based DPI resistance (inter-message timing/delays can be
implementation-dependent; intra-message delays can be introduced at any
point, including before sending the random padding, for example). Artificial
delays (what obfs4 calls IAT or inter-arrival time) are independent of the
protocol itself.
References
==========
.. [IACR-1150]
https://eprint.iacr.org/2015/1150
.. [NetDB]
{{ site_url('docs/how/network-database', True) }}
2018-04-02 13:12:03 +00:00
.. [NOISE]
http://noiseprotocol.org/noise.html
.. [NTCP]
{{ site_url('docs/transport/ntcp', True) }}
.. [Prop104]
{{ proposal_url('104') }}
.. [Prop109]
{{ proposal_url('109') }}
.. [RFC-2104]
https://tools.ietf.org/html/rfc2104
.. [RFC-3526]
https://tools.ietf.org/html/rfc3526
.. [RFC-6151]
https://tools.ietf.org/html/rfc6151
.. [RFC-7539]
https://tools.ietf.org/html/rfc7539
2018-04-02 13:12:03 +00:00
.. [RFC-7748]
https://tools.ietf.org/html/rfc7748
.. [RFC-7905]
https://tools.ietf.org/html/rfc7905
.. [RouterAddress]
{{ ctags_url('RouterAddress') }}
.. [RouterIdentity]
{{ ctags_url('RouterIdentity') }}
.. [SIDH]
De Feo, Luca; Jao, Plut., Towards quantum-resistant cryptosystems from
supersingular elliptic curve isogenies
.. [SigningPublicKey]
{{ ctags_url('SigningPublicKey') }}
2018-04-02 13:12:03 +00:00
.. [SipHash]
https://www.131002.net/siphash/
.. [SSU]
{{ site_url('docs/transport/ssu', True) }}
.. [STS]
Diffie, W.; van Oorschot P. C.; Wiener M. J., Authentication and
Authenticated Key Exchanges
.. [Ticket1112]
https://{{ i2pconv('trac.i2p2.i2p') }}/ticket/1112
.. [Ticket1849]
https://{{ i2pconv('trac.i2p2.i2p') }}/ticket/1849
.. [1] http://www.chesworkshop.org/ches2009/presentations/01_Session_1/CHES2009_ekasper.pdf
.. [2] https://www.blackhat.com/docs/us-16/materials/us-16-Devlin-Nonce-Disrespecting-Adversaries-Practical-Forgery-Attacks-On-GCM-In-TLS.pdf
.. [3] https://eprint.iacr.org/2014/613.pdf
2016-04-04 12:51:03 +00:00
.. [4] https://www.imperialviolet.org/2013/10/07/chacha20.html
2016-04-04 12:51:03 +00:00
.. [5] https://tools.ietf.org/html/rfc7539