forked from I2P_Developers/i2p.www
prop 144 updates
This commit is contained in:
@@ -5,7 +5,7 @@ ECIES-X25519-AEAD-Ratchet
|
|||||||
:author: zzz, chisana
|
:author: zzz, chisana
|
||||||
:created: 2018-11-22
|
:created: 2018-11-22
|
||||||
:thread: http://zzz.i2p/topics/2639
|
:thread: http://zzz.i2p/topics/2639
|
||||||
:lastupdated: 2019-09-14
|
:lastupdated: 2019-09-18
|
||||||
:status: Open
|
:status: Open
|
||||||
|
|
||||||
.. contents::
|
.. contents::
|
||||||
@@ -269,23 +269,68 @@ Crypto type 0 is ElGamal.
|
|||||||
Crypto types 1-3 are reserved for ECIES-ECDH-AES-SessionTag, see proposal 145.
|
Crypto types 1-3 are reserved for ECIES-ECDH-AES-SessionTag, see proposal 145.
|
||||||
|
|
||||||
|
|
||||||
|
Noise Protocol Framework
|
||||||
|
------------------------
|
||||||
|
|
||||||
|
This proposal provides the requirements based on the Noise Protocol Framework
|
||||||
|
[NOISE]_ (Revision 34, 2018-07-11).
|
||||||
|
Noise has similar properties to the Station-To-Station protocol
|
||||||
|
[STS]_, which is the basis for the [SSU]_ protocol. In Noise parlance, Alice
|
||||||
|
is the initiator, and Bob is the responder.
|
||||||
|
|
||||||
|
This proposal is based on the Noise protocol Noise_IK_25519_ChaChaPoly_SHA256.
|
||||||
|
(The actual identifier for the initial key derivation function
|
||||||
|
is "Noise_IKelg2_25519_ChaChaPoly_SHA256"
|
||||||
|
to indicate I2P extensions - see KDF 1 section below)
|
||||||
|
This Noise protocol uses the following primitives:
|
||||||
|
|
||||||
|
- Interactive Handshake Pattern: IK
|
||||||
|
Alice immediately transmits her static key to Bob (I)
|
||||||
|
Alice knows Bob's static key already (K)
|
||||||
|
|
||||||
|
- One-Way Handshake Pattern: N
|
||||||
|
Alice does not transmit her static key to Bob (N)
|
||||||
|
|
||||||
|
- DH Function: X25519
|
||||||
|
X25519 DH with a key length of 32 bytes as specified in [RFC-7748]_.
|
||||||
|
|
||||||
|
- Cipher Function: ChaChaPoly
|
||||||
|
AEAD_CHACHA20_POLY1305 as specified in [RFC-7539]_ section 2.8.
|
||||||
|
12 byte nonce, with the first 4 bytes set to zero.
|
||||||
|
Identical to that in [NTCP2]_.
|
||||||
|
|
||||||
|
- Hash Function: SHA256
|
||||||
|
Standard 32-byte hash, already used extensively in I2P.
|
||||||
|
|
||||||
|
|
||||||
|
Additions to the Framework
|
||||||
|
``````````````````````````
|
||||||
|
|
||||||
|
This proposal defines the following enhancements to
|
||||||
|
Noise_XK_25519_ChaChaPoly_SHA256. These generally follow the guidelines in
|
||||||
|
[NOISE]_ section 13.
|
||||||
|
|
||||||
|
1) Cleartext ephemeral keys are encoded with [Elligator2]_.ion using a known
|
||||||
|
|
||||||
|
2) The reply is prefixed with a cleartext tag.
|
||||||
|
|
||||||
|
3) The payload format is defined for messages 1, 2, and the data phase.
|
||||||
|
Of course, this is not defined in Noise.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Handshake Patterns
|
Handshake Patterns
|
||||||
------------------
|
------------------
|
||||||
|
|
||||||
Handshakes similar to Noise handshake patterns: https://noiseprotocol.org/noise.html#handshake-patterns
|
Handshakes are to [Noise]_ handshake patterns.
|
||||||
|
|
||||||
The following letter mapping is used:
|
The following letter mapping is used:
|
||||||
|
|
||||||
- i = one-time ephemeral key
|
|
||||||
- e = one-time ephemeral key
|
- e = one-time ephemeral key
|
||||||
- s = static key
|
- s = static key
|
||||||
- p = message payload
|
- p = message payload
|
||||||
|
|
||||||
One-time and Unbound sessions
|
One-time and Unbound sessions are similar to the Noise N pattern.
|
||||||
`````````````````````````````
|
|
||||||
|
|
||||||
Similar to the Noise N pattern.
|
|
||||||
|
|
||||||
.. raw:: html
|
.. raw:: html
|
||||||
|
|
||||||
@@ -296,19 +341,15 @@ Similar to the Noise N pattern.
|
|||||||
|
|
||||||
{% endhighlight %}
|
{% endhighlight %}
|
||||||
|
|
||||||
Bound sessions
|
Bound sessions are similar to the Noise IK pattern.
|
||||||
``````````````
|
|
||||||
|
|
||||||
Similar to the Noise IK pattern, with an additional ephemeral key in the reply.
|
|
||||||
TODO replace i with a tag?
|
|
||||||
|
|
||||||
.. raw:: html
|
.. raw:: html
|
||||||
|
|
||||||
{% highlight lang='dataspec' %}
|
{% highlight lang='dataspec' %}
|
||||||
<- s
|
<- s
|
||||||
...
|
...
|
||||||
e es s ss p ->
|
e es p s ss p ->
|
||||||
<- i si e ee se p
|
<- tag e ee se p
|
||||||
|
|
||||||
{% endhighlight %}
|
{% endhighlight %}
|
||||||
|
|
||||||
@@ -663,7 +704,7 @@ Encrypted:
|
|||||||
+ +
|
+ +
|
||||||
| New Session Ephemeral Public Key |
|
| New Session Ephemeral Public Key |
|
||||||
+ 32 bytes +
|
+ 32 bytes +
|
||||||
| |
|
| Encoded with Elligator2 |
|
||||||
+ +
|
+ +
|
||||||
| |
|
| |
|
||||||
+----+----+----+----+----+----+----+----+
|
+----+----+----+----+----+----+----+----+
|
||||||
@@ -707,6 +748,9 @@ Encrypted:
|
|||||||
1c) New session format (without binding)
|
1c) New session format (without binding)
|
||||||
----------------------------------------
|
----------------------------------------
|
||||||
|
|
||||||
|
If no reply is required, no static key is sent.
|
||||||
|
|
||||||
|
|
||||||
Encrypted:
|
Encrypted:
|
||||||
|
|
||||||
.. raw:: html
|
.. raw:: html
|
||||||
@@ -716,8 +760,8 @@ Encrypted:
|
|||||||
| |
|
| |
|
||||||
+ +
|
+ +
|
||||||
| New Session Ephemeral Public Key |
|
| New Session Ephemeral Public Key |
|
||||||
+ +
|
+ 32 bytes +
|
||||||
| |
|
| Encoded with Elligator2 |
|
||||||
+ +
|
+ +
|
||||||
| |
|
| |
|
||||||
+----+----+----+----+----+----+----+----+
|
+----+----+----+----+----+----+----+----+
|
||||||
@@ -770,7 +814,7 @@ The payload section must contain an ACK Request block.
|
|||||||
-------------------------------------------
|
-------------------------------------------
|
||||||
|
|
||||||
If only a single message is expected to be sent,
|
If only a single message is expected to be sent,
|
||||||
no session setup or ephemeral key is required.
|
no session setup or static key is required.
|
||||||
|
|
||||||
|
|
||||||
Encrypted:
|
Encrypted:
|
||||||
@@ -782,8 +826,8 @@ Encrypted:
|
|||||||
| |
|
| |
|
||||||
+ +
|
+ +
|
||||||
| Ephemeral Public Key |
|
| Ephemeral Public Key |
|
||||||
+ +
|
+ 32 bytes +
|
||||||
| |
|
| Encoded with Elligator2 |
|
||||||
+ +
|
+ +
|
||||||
| |
|
| |
|
||||||
+----+----+----+----+----+----+----+----+
|
+----+----+----+----+----+----+----+----+
|
||||||
@@ -902,7 +946,7 @@ Typical contents include the following blocks:
|
|||||||
================================== ============= ============
|
================================== ============= ============
|
||||||
Payload Block Type Type Number Block Length
|
Payload Block Type Type Number Block Length
|
||||||
================================== ============= ============
|
================================== ============= ============
|
||||||
I2NP Message 3 varies
|
Garlic Message 3 varies
|
||||||
Options 5 9
|
Options 5 9
|
||||||
Next Key 7 37
|
Next Key 7 37
|
||||||
ACK Request 9 varies
|
ACK Request 9 varies
|
||||||
@@ -910,10 +954,10 @@ Padding 254 varies
|
|||||||
================================== ============= ============
|
================================== ============= ============
|
||||||
|
|
||||||
|
|
||||||
I2NP Message Contents
|
Garlic Message Contents
|
||||||
~~~~~~~~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
The I2NP message sent.
|
The decrypted Garlic Message as specified in [I2NP]_.
|
||||||
|
|
||||||
|
|
||||||
Options Contents
|
Options Contents
|
||||||
@@ -972,8 +1016,6 @@ This is the "e" message pattern:
|
|||||||
Define ck = 32 byte chaining key. Copy the h data to ck.
|
Define ck = 32 byte chaining key. Copy the h data to ck.
|
||||||
Set chainKey = h
|
Set chainKey = h
|
||||||
|
|
||||||
Define rs = Bob's 32-byte static key as published in the RouterInfo
|
|
||||||
|
|
||||||
// MixHash(null prologue)
|
// MixHash(null prologue)
|
||||||
h = SHA256(h);
|
h = SHA256(h);
|
||||||
|
|
||||||
@@ -1039,11 +1081,20 @@ This is the "e" message pattern:
|
|||||||
n = 0
|
n = 0
|
||||||
ad = h
|
ad = h
|
||||||
|
|
||||||
|
End of "es" message pattern.
|
||||||
|
|
||||||
|
This is the "s" message pattern:
|
||||||
|
|
||||||
// MixHash(ciphertext)
|
// MixHash(ciphertext)
|
||||||
// Save for Payload section KDF
|
// Save for Payload section KDF
|
||||||
h = SHA256(h || 64 byte encrypted flags/static key section)
|
h = SHA256(h || 64 byte encrypted flags/static key section)
|
||||||
|
|
||||||
End of "es" message pattern.
|
// Alice's X25519 static keys
|
||||||
|
ask = GENERATE_PRIVATE()
|
||||||
|
apk = DERIVE_PUBLIC(ask)
|
||||||
|
|
||||||
|
End of "s" message pattern.
|
||||||
|
|
||||||
|
|
||||||
{% endhighlight %}
|
{% endhighlight %}
|
||||||
|
|
||||||
@@ -1073,11 +1124,13 @@ This is the "ss" message pattern:
|
|||||||
n = 0
|
n = 0
|
||||||
ad = h
|
ad = h
|
||||||
|
|
||||||
|
End of "ss" message pattern.
|
||||||
|
|
||||||
// MixHash(ciphertext)
|
// MixHash(ciphertext)
|
||||||
// Save for New Session Reply KDF
|
// Save for New Session Reply KDF
|
||||||
h = SHA256(h || encrypted payload section)
|
h = SHA256(h || encrypted payload section)
|
||||||
|
|
||||||
End of "ss" message pattern.
|
TODO tag = HKDF(...)
|
||||||
|
|
||||||
{% endhighlight %}
|
{% endhighlight %}
|
||||||
|
|
||||||
@@ -1085,6 +1138,10 @@ This is the "ss" message pattern:
|
|||||||
KDF for Payload Section (without Alice static key)
|
KDF for Payload Section (without Alice static key)
|
||||||
``````````````````````````````````````````````````
|
``````````````````````````````````````````````````
|
||||||
|
|
||||||
|
Note that this is a Noise "N" pattern, but we use the same "IK" initializer
|
||||||
|
as for bound sessions.
|
||||||
|
|
||||||
|
|
||||||
.. raw:: html
|
.. raw:: html
|
||||||
|
|
||||||
{% highlight lang='text' %}
|
{% highlight lang='text' %}
|
||||||
@@ -1100,35 +1157,21 @@ chainKey = from Flags/Static key section
|
|||||||
1g) New Session Reply format
|
1g) New Session Reply format
|
||||||
----------------------------
|
----------------------------
|
||||||
|
|
||||||
TODO replace i with a tag?
|
|
||||||
|
|
||||||
Encrypted:
|
Encrypted:
|
||||||
|
|
||||||
.. raw:: html
|
.. raw:: html
|
||||||
|
|
||||||
{% highlight lang='dataspec' %}
|
{% highlight lang='dataspec' %}
|
||||||
+----+----+----+----+----+----+----+----+
|
+----+----+----+----+----+----+----+----+
|
||||||
| |
|
| Session Tag 8 bytes |
|
||||||
+ +
|
|
||||||
| New Session Ephemeral Public Key |
|
|
||||||
+ +
|
|
||||||
| |
|
|
||||||
+ +
|
|
||||||
| |
|
|
||||||
+----+----+----+----+----+----+----+----+
|
+----+----+----+----+----+----+----+----+
|
||||||
| |
|
| |
|
||||||
+ Ephemeral Key Section +
|
+ Ephemeral Public Key +
|
||||||
| ChaCha20 encrypted data |
|
|
||||||
+ 48 bytes +
|
|
||||||
| |
|
| |
|
||||||
|
+ 32 bytes +
|
||||||
|
| Encoded with Elligator2 |
|
||||||
+ +
|
+ +
|
||||||
| |
|
| |
|
||||||
+ +
|
|
||||||
| |
|
|
||||||
+----+----+----+----+----+----+----+----+
|
|
||||||
| Poly1305 Message Authentication Code |
|
|
||||||
+ (MAC) for above section +
|
|
||||||
| 16 bytes |
|
|
||||||
+----+----+----+----+----+----+----+----+
|
+----+----+----+----+----+----+----+----+
|
||||||
| |
|
| |
|
||||||
+ Payload Section +
|
+ Payload Section +
|
||||||
@@ -1143,9 +1186,11 @@ Encrypted:
|
|||||||
| 16 bytes |
|
| 16 bytes |
|
||||||
+----+----+----+----+----+----+----+----+
|
+----+----+----+----+----+----+----+----+
|
||||||
|
|
||||||
|
Tag :: 8 bytes, cleartext
|
||||||
|
|
||||||
Public Key :: 32 bytes, little endian, Elligator2, cleartext
|
Public Key :: 32 bytes, little endian, Elligator2, cleartext
|
||||||
|
|
||||||
Ephemeral Key Section encrypted data :: 48 bytes
|
Ephemeral Key Section encrypted data :: 32 bytes
|
||||||
|
|
||||||
Payload Section encrypted data :: remaining data minus 16 bytes
|
Payload Section encrypted data :: remaining data minus 16 bytes
|
||||||
|
|
||||||
@@ -1153,50 +1198,10 @@ Encrypted:
|
|||||||
|
|
||||||
{% endhighlight %}
|
{% endhighlight %}
|
||||||
|
|
||||||
Decrypted:
|
Notes
|
||||||
|
`````
|
||||||
Ephemeral Key Section Decrypted data
|
The tag is generated in the New Session payload KDF.
|
||||||
````````````````````````````````````
|
This correlates the reply to the session.
|
||||||
|
|
||||||
The Ephemeral Key section contains flags and a key.
|
|
||||||
It is always 48 bytes.
|
|
||||||
|
|
||||||
TODO don't need session ID?
|
|
||||||
|
|
||||||
.. raw:: html
|
|
||||||
|
|
||||||
{% highlight lang='dataspec' %}
|
|
||||||
+----+----+----+----+----+----+----+----+
|
|
||||||
| flags | unused | tsB |
|
|
||||||
+----+----+----+----+----+----+----+----+
|
|
||||||
| Session ID |
|
|
||||||
+----+----+----+----+----+----+----+----+
|
|
||||||
| |
|
|
||||||
+ Ephemeral Key +
|
|
||||||
| 32 bytes |
|
|
||||||
+ +
|
|
||||||
| |
|
|
||||||
+ +
|
|
||||||
| |
|
|
||||||
+----+----+----+----+----+----+----+----+
|
|
||||||
|
|
||||||
flags :: 2 bytes
|
|
||||||
bit order: 15 14 .. 3210
|
|
||||||
bit 0: 1 for ephemeral key is to be used
|
|
||||||
bit 1: 1 for the session ID to be used
|
|
||||||
bit 2: 1 for New Session Reply (0 for New Session)
|
|
||||||
bits 15-3: Unused, set to 0 for future compatibility
|
|
||||||
unused :: 2 bytes, set to 0 for future compatibility
|
|
||||||
tsB :: 4 bytes, seconds since epoch, big endian, rolls over in 2106
|
|
||||||
sessionID :: session ID, 8 bytes.
|
|
||||||
Uniquely identifies the session request this is a reply for.
|
|
||||||
key :: the originator's ephemeral key, 32 bytes.
|
|
||||||
|
|
||||||
{% endhighlight %}
|
|
||||||
|
|
||||||
Alice must implement a Bloom filter or other mechanism to prevent replay attacks,
|
|
||||||
using the date in the ephemeral key section. Specification TBD.
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Payload
|
Payload
|
||||||
@@ -1215,83 +1220,52 @@ Optional blocks can have multiple I2NP blocks, but only a single padding block.
|
|||||||
If present, the padding block must be the final block.
|
If present, the padding block must be the final block.
|
||||||
|
|
||||||
|
|
||||||
KDF for Ephemeral Key Section Encrypted Contents
|
KDF for Payload Section Encrypted Contents
|
||||||
````````````````````````````````````````````````
|
````````````````````````````````````````````````
|
||||||
|
|
||||||
Same as Static Key Section in the New Session Message.
|
|
||||||
Needs to be the same, because Alice will not know this is a reply
|
|
||||||
until the Ephemeral Key Section is decrypted.
|
|
||||||
|
|
||||||
.. raw:: html
|
.. raw:: html
|
||||||
|
|
||||||
{% highlight lang='text' %}
|
{% highlight lang='text' %}
|
||||||
// Alice's X25519 static keys
|
// Keys from the New Session message
|
||||||
// apk is sent in original New Session message
|
// Alice's X25519 keys
|
||||||
ask = GENERATE_PRIVATE()
|
// apk and aepk are sent in original New Session message
|
||||||
apk = DERIVE_PUBLIC(ask)
|
// ask = Alice private static key
|
||||||
|
// apk = Alice public static key
|
||||||
|
// aesk = Alice ephemeral private key
|
||||||
|
// aepk = Alice ephemeral public key
|
||||||
|
// Bob's X25519 static keys
|
||||||
|
// bsk = Bob private static key
|
||||||
|
// bpk = Bob public static key
|
||||||
|
|
||||||
// Bob's X25519 one-time-use ephemeral keys
|
// MixHash(tag)
|
||||||
ibsk = GENERATE_PRIVATE_ELG2()
|
h = SHA256(h || tag)
|
||||||
ibpk = DERIVE_PUBLIC(ibsk)
|
|
||||||
// ebpk is sent in cleartext in the
|
This is the "e" message pattern:
|
||||||
|
|
||||||
|
// Bob's X25519 ephemeral keys
|
||||||
|
besk = GENERATE_PRIVATE_ELG2()
|
||||||
|
bepk = DERIVE_PUBLIC(besk)
|
||||||
|
// elg2_bepk is sent in cleartext in the
|
||||||
// beginning of the new session message
|
// beginning of the new session message
|
||||||
ebpk = ENCODE_ELG2(ibpk)
|
elg2_bepk = ENCODE_ELG2(bepk)
|
||||||
// As decoded by Bob
|
// As decoded by Bob
|
||||||
ibpk = DECODE_ELG2(ebpk)
|
ibpk = DECODE_ELG2(elg2_bepk)
|
||||||
|
|
||||||
// Must be the same as the original New Session message
|
End of "e" message pattern.
|
||||||
// Alice doesn't know it's a reply yet
|
|
||||||
INITIAL_ROOT_KEY = SHA256("144-ECIES-X25519-AEAD-Ratchet")
|
|
||||||
|
|
||||||
// Noise-like si
|
This is the "ee" message pattern:
|
||||||
sharedSecret = DH(ask, ibpk) = DH(ibsk, apk)
|
|
||||||
|
|
||||||
// MixKey(DH())
|
|
||||||
// ChaChaPoly parameters to encrypt/decrypt
|
|
||||||
keydata = HKDF(INITIAL_ROOT_KEY, sharedSecret, "NewSessionTmpKey", 64)
|
|
||||||
chainKey = keydata[0:31]
|
|
||||||
k = keydata[32:64]
|
|
||||||
n = 0
|
|
||||||
ad = SHA-256(ebpk)
|
|
||||||
|
|
||||||
// MixHash(ibpk)
|
|
||||||
h = SHA256(h || encrypted payload section)
|
|
||||||
|
|
||||||
|
|
||||||
{% endhighlight %}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
KDF for Payload Section Encrypted Contents
|
|
||||||
``````````````````````````````````````````
|
|
||||||
|
|
||||||
.. raw:: html
|
|
||||||
|
|
||||||
{% highlight lang='text' %}
|
|
||||||
// Bob's X25519 ephemeral keys generated for the Ephemeral Key Section
|
|
||||||
rbsk = GENERATE_PRIVATE()
|
|
||||||
// rbpk decrypted by Alice in Ephemeral Key Section
|
|
||||||
rbpk = DERIVE_PUBLIC(rbsk)
|
|
||||||
|
|
||||||
// Alice's X25519 ephemeral keys from original New Session Message
|
|
||||||
rask = GENERATE_PRIVATE()
|
|
||||||
// rapk was decrypted in original New Session Ephemeral Key Section
|
|
||||||
rapk = DERIVE_PUBLIC(rask)
|
|
||||||
|
|
||||||
// Noise ee
|
|
||||||
// MixKey(sharedSecret)
|
// MixKey(sharedSecret)
|
||||||
// ChaChaPoly parameters to encrypt/decrypt
|
// ChaChaPoly parameters to encrypt/decrypt
|
||||||
// chainKey from original New Session Payload Section
|
// chainKey from original New Session Payload Section
|
||||||
sharedSecret = DH(rask, rbpk) = DH(rbsk, rapk)
|
sharedSecret = DH(aesk, bepk) = DH(besk, bepk)
|
||||||
keydata = HKDF(chainKey, sharedSecret, "", 32)
|
keydata = HKDF(chainKey, sharedSecret, "", 32)
|
||||||
chainKey = keydata[0:31]
|
chainKey = keydata[0:31]
|
||||||
|
|
||||||
// Alice's X25519 static keys from original New Session Message
|
End of "ee" message pattern.
|
||||||
ask = GENERATE_PRIVATE()
|
|
||||||
// apk was decrypted in original New Session Static Key Section
|
This is the "se" message pattern:
|
||||||
apk = DERIVE_PUBLIC(ask)
|
|
||||||
|
|
||||||
// Noise se
|
|
||||||
// MixKey(sharedSecret)
|
// MixKey(sharedSecret)
|
||||||
sharedSecret = DH(ask, rbpk) = DH(rbsk, apk)
|
sharedSecret = DH(ask, rbpk) = DH(rbsk, apk)
|
||||||
keydata = HKDF(chainKey, sharedSecret, "", 64)
|
keydata = HKDF(chainKey, sharedSecret, "", 64)
|
||||||
@@ -1300,9 +1274,13 @@ KDF for Payload Section Encrypted Contents
|
|||||||
n = 0
|
n = 0
|
||||||
ad = SHA-256(rbpk)
|
ad = SHA-256(rbpk)
|
||||||
|
|
||||||
|
End of "se" message pattern.
|
||||||
|
|
||||||
// MixHash()
|
// MixHash()
|
||||||
h = SHA256(h || encrypted payload section)
|
h = SHA256(h || encrypted payload section)
|
||||||
|
|
||||||
|
chainKey is used in the ratchet below.
|
||||||
|
|
||||||
{% endhighlight %}
|
{% endhighlight %}
|
||||||
|
|
||||||
Notes
|
Notes
|
||||||
@@ -1964,7 +1942,7 @@ so the max unencrypted data is 65519 bytes.
|
|||||||
|
|
||||||
blk :: 1 byte
|
blk :: 1 byte
|
||||||
0-2 reserved
|
0-2 reserved
|
||||||
3 I2NP message (Garlic Message only)
|
3 Garlic Message
|
||||||
4 termination
|
4 termination
|
||||||
5 options
|
5 options
|
||||||
6 message number and previous message number (ratchet)
|
6 message number and previous message number (ratchet)
|
||||||
@@ -1997,7 +1975,7 @@ the following blocks are required, in the following order:
|
|||||||
|
|
||||||
Other allowed blocks:
|
Other allowed blocks:
|
||||||
|
|
||||||
- I2NP message (type 3)
|
- Garlic message (type 3)
|
||||||
- Padding (type 254)
|
- Padding (type 254)
|
||||||
|
|
||||||
In the new session reply message,
|
In the new session reply message,
|
||||||
@@ -2007,7 +1985,7 @@ the following blocks are required:
|
|||||||
|
|
||||||
Other allowed blocks:
|
Other allowed blocks:
|
||||||
|
|
||||||
- I2NP message (type 3)
|
- Garlic message (type 3)
|
||||||
- Padding (type 254)
|
- Padding (type 254)
|
||||||
|
|
||||||
No other blocks are allowed.
|
No other blocks are allowed.
|
||||||
@@ -2026,11 +2004,11 @@ a single frame, but it is not prohibited.
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
I2NP Message
|
Garlic Message
|
||||||
````````````
|
````````````
|
||||||
|
|
||||||
An single I2NP message with a modified header.
|
A single decrypted Garlic Message as specified in [I2NP]_.
|
||||||
I2NP messages may not be fragmented across blocks or
|
Garlic messages may not be fragmented across blocks or
|
||||||
across ChaChaPoly frames.
|
across ChaChaPoly frames.
|
||||||
|
|
||||||
This uses the first 9 bytes from the standard NTCP I2NP header,
|
This uses the first 9 bytes from the standard NTCP I2NP header,
|
||||||
@@ -2056,11 +2034,11 @@ and remove the one-byte SHA256 checksum.
|
|||||||
blk :: 3
|
blk :: 3
|
||||||
size :: 2 bytes, big endian, size of type + msg id + exp + message to follow
|
size :: 2 bytes, big endian, size of type + msg id + exp + message to follow
|
||||||
I2NP message body size is (size - 9).
|
I2NP message body size is (size - 9).
|
||||||
type :: 1 byte, I2NP msg type, see I2NP spec
|
type :: 1 byte, I2NP msg type (11 for Garlic Message)
|
||||||
msg id :: 4 bytes, big endian, I2NP message ID
|
msg id :: 4 bytes, big endian, I2NP message ID
|
||||||
short exp :: 4 bytes, big endian, I2NP message expiration, Unix timestamp, unsigned seconds.
|
short exp :: 4 bytes, big endian, I2NP message expiration, Unix timestamp, unsigned seconds.
|
||||||
Wraps around in 2106
|
Wraps around in 2106
|
||||||
message :: I2NP message body
|
message :: Decrypted Garlic Message body
|
||||||
|
|
||||||
{% endhighlight %}
|
{% endhighlight %}
|
||||||
|
|
||||||
@@ -3163,6 +3141,12 @@ References
|
|||||||
https://www.imperialviolet.org/2013/12/25/elligator.html
|
https://www.imperialviolet.org/2013/12/25/elligator.html
|
||||||
See also OBFS4 code
|
See also OBFS4 code
|
||||||
|
|
||||||
|
.. [I2NP]
|
||||||
|
{{ spec_url('i2np') }}
|
||||||
|
|
||||||
|
.. [NTCP2]
|
||||||
|
{{ spec_url('ntcp2') }}
|
||||||
|
|
||||||
.. [NOISE]
|
.. [NOISE]
|
||||||
http://noiseprotocol.org/noise.html
|
http://noiseprotocol.org/noise.html
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user