-
Notifications
You must be signed in to change notification settings - Fork 5
/
noise.html
1973 lines (1938 loc) · 139 KB
/
noise.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta http-equiv="Content-Style-Type" content="text/css" />
<meta name="generator" content="pandoc" />
<meta name="author" content="Trevor Perrin (noise@trevp.net)" />
<meta name="date" content="2018-07-11" />
<title>The Noise Protocol Framework</title>
<style type="text/css">code{white-space: pre;}</style>
<link rel="stylesheet" href="spec_markdown.css" type="text/css" />
</head>
<body>
<div id="header">
<h1 class="title">The Noise Protocol Framework</h1>
<b>Author:</b> Trevor Perrin (noise@trevp.net)<br/>
<b>Revision:</b> 34<br/>
<b>Date:</b> 2018-07-11<br/>
<b>Status:</b> official/unstable<br/>
<b>PDF:</b> <a href="noise.pdf">noise.pdf</a><br/>
</div>
<div id="TOC">
<h2 class="toc">Table of Contents</h2>
<ul>
<li><a href="#introduction">1. Introduction</a></li>
<li><a href="#overview">2. Overview</a><ul>
<li><a href="#terminology">2.1. Terminology</a></li>
<li><a href="#overview-of-handshake-state-machine">2.2. Overview of handshake state machine</a></li>
</ul></li>
<li><a href="#message-format">3. Message format</a></li>
<li><a href="#crypto-functions">4. Crypto functions</a><ul>
<li><a href="#dh-functions">4.1. DH functions</a></li>
<li><a href="#cipher-functions">4.2. Cipher functions</a></li>
<li><a href="#hash-functions">4.3. Hash functions</a></li>
</ul></li>
<li><a href="#processing-rules">5. Processing rules</a><ul>
<li><a href="#the-cipherstate-object">5.1. The <code>CipherState</code> object</a></li>
<li><a href="#the-symmetricstate-object">5.2. The <code>SymmetricState</code> object</a></li>
<li><a href="#the-handshakestate-object">5.3. The <code>HandshakeState</code> object</a></li>
</ul></li>
<li><a href="#prologue">6. Prologue</a></li>
<li><a href="#handshake-patterns">7. Handshake patterns</a><ul>
<li><a href="#handshake-pattern-basics">7.1. Handshake pattern basics</a></li>
<li><a href="#alice-and-bob">7.2. Alice and Bob</a></li>
<li><a href="#handshake-pattern-validity">7.3. Handshake pattern validity</a></li>
<li><a href="#one-way-handshake-patterns">7.4. One-way handshake patterns</a></li>
<li><a href="#interactive-handshake-patterns-fundamental">7.5. Interactive handshake patterns (fundamental)</a></li>
<li><a href="#interactive-handshake-patterns-deferred">7.6. Interactive handshake patterns (deferred)</a></li>
<li><a href="#payload-security-properties">7.7. Payload security properties</a></li>
<li><a href="#identity-hiding">7.8. Identity hiding</a></li>
</ul></li>
<li><a href="#protocol-names-and-modifiers">8. Protocol names and modifiers</a><ul>
<li><a href="#handshake-pattern-name-section">8.1. Handshake pattern name section</a></li>
<li><a href="#cryptographic-algorithm-name-sections">8.2. Cryptographic algorithm name sections</a></li>
</ul></li>
<li><a href="#pre-shared-symmetric-keys">9. Pre-shared symmetric keys</a><ul>
<li><a href="#cryptographic-functions">9.1. Cryptographic functions</a></li>
<li><a href="#handshake-tokens">9.2. Handshake tokens</a></li>
<li><a href="#validity-rule">9.3. Validity rule</a></li>
<li><a href="#pattern-modifiers">9.4. Pattern modifiers</a></li>
</ul></li>
<li><a href="#compound-protocols">10. Compound protocols</a><ul>
<li><a href="#rationale-for-compound-protocols">10.1. Rationale for compound protocols</a></li>
<li><a href="#the-fallback-modifier">10.2. The <code>fallback</code> modifier</a></li>
<li><a href="#zero-rtt-and-noise-protocols">10.3. Zero-RTT and Noise protocols</a></li>
<li><a href="#noise-pipes">10.4. Noise Pipes</a></li>
<li><a href="#handshake-indistinguishability">10.5. Handshake indistinguishability</a></li>
</ul></li>
<li><a href="#advanced-features">11. Advanced features</a><ul>
<li><a href="#dummy-keys">11.1. Dummy keys</a></li>
<li><a href="#channel-binding">11.2. Channel binding</a></li>
<li><a href="#rekey">11.3. Rekey</a></li>
<li><a href="#out-of-order-transport-messages">11.4. Out-of-order transport messages</a></li>
<li><a href="#half-duplex-protocols">11.5. Half-duplex protocols</a></li>
</ul></li>
<li><a href="#dh-functions-cipher-functions-and-hash-functions">12. DH functions, cipher functions, and hash functions</a><ul>
<li><a href="#the-25519-dh-functions">12.1. The <code>25519</code> DH functions</a></li>
<li><a href="#the-448-dh-functions">12.2. The <code>448</code> DH functions</a></li>
<li><a href="#the-chachapoly-cipher-functions">12.3. The <code>ChaChaPoly</code> cipher functions</a></li>
<li><a href="#the-aesgcm-cipher-functions">12.4. The <code>AESGCM</code> cipher functions</a></li>
<li><a href="#the-sha256-hash-function">12.5. The <code>SHA256</code> hash function</a></li>
<li><a href="#the-sha512-hash-function">12.6. The <code>SHA512</code> hash function</a></li>
<li><a href="#the-blake2s-hash-function">12.7. The <code>BLAKE2s</code> hash function</a></li>
<li><a href="#the-blake2b-hash-function">12.8. The <code>BLAKE2b</code> hash function</a></li>
</ul></li>
<li><a href="#application-responsibilities">13. Application responsibilities</a></li>
<li><a href="#security-considerations">14. Security considerations</a></li>
<li><a href="#rationales">15. Rationales</a><ul>
<li><a href="#ciphers-and-encryption">15.1. Ciphers and encryption</a></li>
<li><a href="#hash-functions-and-hashing">15.2. Hash functions and hashing</a></li>
<li><a href="#other">15.3. Other</a></li>
</ul></li>
<li><a href="#ipr">16. IPR</a></li>
<li><a href="#acknowledgements">17. Acknowledgements</a></li>
<li><a href="#appendices">18. Appendices</a><ul>
<li><a href="#deferred-patterns">18.1. Deferred patterns</a></li>
<li><a href="#security-properties-for-deferred-patterns">18.2. Security properties for deferred patterns</a></li>
<li><a href="#pattern-derivation-rules">18.3. Pattern derivation rules</a></li>
<li><a href="#change-log">18.4. Change log</a></li>
</ul></li>
<li><a href="#references">19. References</a></li>
</ul>
</div>
<h1 id="introduction">1. Introduction</h1>
<p>Noise is a framework for crypto protocols based on Diffie-Hellman key agreement. Noise can describe protocols that consist of a single message as well as interactive protocols.</p>
<h1 id="overview">2. Overview</h1>
<h2 id="terminology">2.1. Terminology</h2>
<p>A Noise protocol begins with two parties exchanging <strong>handshake messages</strong>. During this <strong>handshake phase</strong> the parties exchange DH public keys and perform a sequence of DH operations, hashing the DH results into a shared secret key. After the handshake phase each party can use this shared key to send encrypted <strong>transport messages</strong>.</p>
<p>The Noise framework supports handshakes where each party has a long-term <strong>static key pair</strong> and/or an <strong>ephemeral key pair</strong>. A Noise handshake is described by a simple language. This language consists of <strong>tokens</strong> which are arranged into <strong>message patterns</strong>. Message patterns are arranged into <strong>handshake patterns</strong>.</p>
<p>A <strong>message pattern</strong> is a sequence of tokens that specifies the DH public keys that comprise a handshake message, and the DH operations that are performed when sending or receiving that message. A <strong>handshake pattern</strong> specifies the sequential exchange of messages that comprise a handshake.</p>
<p>A handshake pattern can be instantiated by <strong>DH functions</strong>, <strong>cipher functions</strong>, and <strong>hash functions</strong> to give a concrete <strong>Noise protocol</strong>.</p>
<h2 id="overview-of-handshake-state-machine">2.2. Overview of handshake state machine</h2>
<p>The core of Noise is a set of variables maintained by each party during a handshake, and rules for sending and receiving handshake messages by sequentially processing the tokens from a message pattern.</p>
<p>Each party maintains the following variables:</p>
<ul>
<li><p><strong><code>s, e</code></strong>: The local party's static and ephemeral key pairs (which may be empty).</p></li>
<li><p><strong><code>rs, re</code></strong>: The remote party's static and ephemeral public keys (which may be empty).</p></li>
<li><p><strong><code>h</code></strong>: A <strong>handshake hash</strong> value that hashes all the handshake data that's been sent and received.</p></li>
<li><p><strong><code>ck</code></strong>: A <strong>chaining key</strong> that hashes all previous DH outputs. Once the handshake completes, the chaining key will be used to derive the encryption keys for transport messages.</p></li>
<li><p><strong><code>k, n</code></strong>: An encryption key <code>k</code> (which may be empty) and a counter-based nonce <code>n</code>. Whenever a new DH output causes a new <code>ck</code> to be calculated, a new <code>k</code> is also calculated. The key <code>k</code> and nonce <code>n</code> are used to encrypt static public keys and handshake payloads. Encryption with <code>k</code> uses some <strong>AEAD</strong> cipher mode (in the sense of Rogaway <span class="citation">[<a href="#ref-Rogaway:2002">1</a>]</span>) and uses the current <code>h</code> value as <strong>associated data</strong> which is covered by the AEAD authentication. Encryption of static public keys and payloads provides some confidentiality and key confirmation during the handshake phase.</p></li>
</ul>
<p>A handshake message consists of some DH public keys followed by a <strong>payload</strong>. The payload may contain certificates or other data chosen by the application. To send a handshake message, the sender specifies the payload and sequentially processes each token from a message pattern. The possible tokens are:</p>
<ul>
<li><p><strong><code>"e"</code></strong>: The sender generates a new ephemeral key pair and stores it in the <code>e</code> variable, writes the ephemeral public key as cleartext into the message buffer, and hashes the public key along with the old <code>h</code> to derive a new <code>h</code>.</p></li>
<li><p><strong><code>"s"</code></strong>: The sender writes its static public key from the <code>s</code> variable into the message buffer, encrypting it if <code>k</code> is non-empty, and hashes the output along with the old <code>h</code> to derive a new <code>h</code>.</p></li>
<li><p><strong><code>"ee", "se", "es", "ss"</code></strong>: A DH is performed between the initiator's key pair (whether static or ephemeral is determined by the first letter) and the responder's key pair (whether static or ephemeral is determined by the second letter). The result is hashed along with the old <code>ck</code> to derive a new <code>ck</code> and <code>k</code>, and <code>n</code> is set to zero.</p></li>
</ul>
<p>After processing the final token in a handshake message, the sender then writes the payload into the message buffer, encrypting it if <code>k</code> is non-empty, and hashes the output along with the old <code>h</code> to derive a new <code>h</code>.</p>
<p>As a simple example, an unauthenticated DH handshake is described by the handshake pattern:</p>
<pre><code> -> e
<- e, ee</code></pre>
<p>The <strong>initiator</strong> sends the first message, which is simply an ephemeral public key. The <strong>responder</strong> sends back its own ephemeral public key. Then a DH is performed and the output is hashed into a shared secret key.</p>
<p>Note that a cleartext payload is sent in the first message, after the cleartext ephemeral public key, and an encrypted payload is sent in the response message, after the cleartext ephemeral public key. The application may send whatever payloads it wants.</p>
<p>The responder can send its static public key (under encryption) and authenticate itself via a slightly different pattern:</p>
<pre><code> -> e
<- e, ee, s, es</code></pre>
<p>In this case, the final <code>ck</code> and <code>k</code> values are a hash of both DH results. Since the <code>es</code> token indicates a DH between the initiator's ephemeral key and the responder's static key, successful decryption by the initiator of the second message's payload serves to authenticate the responder to the initiator.</p>
<p>Note that the second message's payload may contain a zero-length plaintext, but the payload ciphertext will still contain authentication data (such as an authentication tag or "synthetic IV"), since encryption is with an AEAD mode. The second message's payload can also be used to deliver certificates for the responder's static public key.</p>
<p>The initiator can send <em>its</em> static public key (under encryption), and authenticate itself, using a handshake pattern with one additional message:</p>
<pre><code> -> e
<- e, ee, s, es
-> s, se</code></pre>
<p>The following sections flesh out the details, and add some complications. However, the core of Noise is this simple system of variables, tokens, and processing rules, which allow concise expression of a range of protocols.</p>
<h1 id="message-format">3. Message format</h1>
<p>All Noise messages are less than or equal to 65535 bytes in length. Restricting message size has several advantages:</p>
<ul>
<li><p>Simpler testing, since it's easy to test the maximum sizes.</p></li>
<li><p>Reduces the likelihood of errors in memory handling, or integer overflow.</p></li>
<li><p>Enables support for streaming decryption and random-access decryption of large data streams.</p></li>
<li><p>Enables higher-level protocols that encapsulate Noise messages to use an efficient standard length field of 16 bits.</p></li>
</ul>
<p>All Noise messages can be processed without parsing, since there are no type or length fields. Of course, Noise messages might be encapsulated within a higher-level protocol that contains type and length information. Noise messages might encapsulate payloads that require parsing of some sort, but payloads are handled by the application, not by Noise.</p>
<p>A Noise <strong>transport message</strong> is simply an AEAD ciphertext that is less than or equal to 65535 bytes in length, and that consists of an encrypted payload plus 16 bytes of authentication data. The details depend on the AEAD cipher function, e.g. AES256-GCM, or ChaCha20-Poly1305, but typically the authentication data is either a 16-byte authentication tag appended to the ciphertext, or a 16-byte synthetic IV prepended to the ciphertext.</p>
<p>A Noise <strong>handshake message</strong> is also less than or equal to 65535 bytes. It begins with a sequence of one or more DH public keys, as determined by its message pattern. Following the public keys will be a single payload which can be used to convey certificates or other handshake data, but can also contain a zero-length plaintext.</p>
<p>Static public keys and payloads will be in cleartext if they are sent in a handshake prior to a DH operation, and will be AEAD ciphertexts if they occur after a DH operation. (If Noise is being used with pre-shared symmetric keys, this rule is different; see <a href="#pre-shared-symmetric-keys">Section 9</a>). Like transport messages, AEAD ciphertexts will expand each encrypted field (whether static public key or payload) by 16 bytes.</p>
<p>For an example, consider the handshake pattern:</p>
<pre><code> -> e
<- e, ee, s, es
-> s, se</code></pre>
<p>The first message consists of a cleartext public key (<code>"e"</code>) followed by a cleartext payload (remember that a payload is implicit at the end of each message pattern). The second message consists of a cleartext public key (<code>"e"</code>) followed by an encrypted public key (<code>"s"</code>) followed by an encrypted payload. The third message consists of an encrypted public key (<code>"s"</code>) followed by an encrypted payload.</p>
<p>Assuming each payload contains a zero-length plaintext, and DH public keys are 56 bytes, the message sizes will be:</p>
<ol style="list-style-type: decimal">
<li>56 bytes (one cleartext public key and a cleartext payload)</li>
<li>144 bytes (two public keys, the second encrypted, and encrypted payload)</li>
<li>88 bytes (one encrypted public key and encrypted payload)</li>
</ol>
<p> </p>
<h1 id="crypto-functions">4. Crypto functions</h1>
<p>A Noise protocol is instantiated with a concrete set of <strong>DH functions</strong>, <strong>cipher functions</strong>, and <strong>hash functions</strong>. The signature for these functions is defined below. Some concrete functions are defined in <a href="#dh-functions-cipher-functions-and-hash-functions">Section 12</a>.</p>
<p>The following notation will be used in algorithm pseudocode:</p>
<ul>
<li>The <code>||</code> operator concatenates byte sequences.</li>
<li>The <code>byte()</code> function constructs a single byte.</li>
</ul>
<h2 id="dh-functions">4.1. DH functions</h2>
<p>Noise depends on the following <strong>DH functions</strong> (and an associated constant):</p>
<ul>
<li><p><strong><code>GENERATE_KEYPAIR()</code></strong>: Generates a new Diffie-Hellman key pair. A DH key pair consists of <code>public_key</code> and <code>private_key</code> elements. A <code>public_key</code> represents an encoding of a DH public key into a byte sequence of length <code>DHLEN</code>. The <code>public_key</code> encoding details are specific to each set of DH functions.</p></li>
<li><p><strong><code>DH(key_pair, public_key)</code></strong>: Performs a Diffie-Hellman calculation between the private key in <code>key_pair</code> and the <code>public_key</code> and returns an output sequence of bytes of length <code>DHLEN</code>. For security, the Gap-DH problem based on this function must be unsolvable by any practical cryptanalytic adversary <span class="citation">[<a href="#ref-gapdh">2</a>]</span>.</p>
<p>The <code>public_key</code> either encodes some value which is a generator in a large prime-order group (which value may have multiple equivalent encodings), or is an invalid value. Implementations must handle invalid public keys either by returning some output which is purely a function of the public key and does not depend on the private key, or by signaling an error to the caller. The DH function may define more specific rules for handling invalid values.</p></li>
<li><p><strong><code>DHLEN</code></strong> = A constant specifying the size in bytes of public keys and DH outputs. For security reasons, <code>DHLEN</code> must be 32 or greater.</p></li>
</ul>
<h2 id="cipher-functions">4.2. Cipher functions</h2>
<p>Noise depends on the following <strong>cipher functions</strong>:</p>
<ul>
<li><p><strong><code>ENCRYPT(k, n, ad, plaintext)</code></strong>: Encrypts <code>plaintext</code> using the cipher key <code>k</code> of 32 bytes and an 8-byte unsigned integer nonce <code>n</code> which must be unique for the key <code>k</code>. Returns the ciphertext. Encryption must be done with an "AEAD" encryption mode with the associated data <code>ad</code> (using the terminology from <span class="citation">[<a href="#ref-Rogaway:2002">1</a>]</span>) and returns a ciphertext that is the same size as the plaintext plus 16 bytes for authentication data. The entire ciphertext must be indistinguishable from random if the key is secret (note that this is an additional requirement that isn't necessarily met by all AEAD schemes).</p></li>
<li><p><strong><code>DECRYPT(k, n, ad, ciphertext)</code></strong>: Decrypts <code>ciphertext</code> using a cipher key <code>k</code> of 32 bytes, an 8-byte unsigned integer nonce <code>n</code>, and associated data <code>ad</code>. Returns the plaintext, unless authentication fails, in which case an error is signaled to the caller.</p></li>
<li><p><strong><code>REKEY(k)</code></strong>: Returns a new 32-byte cipher key as a pseudorandom function of <code>k</code>. If this function is not specifically defined for some set of cipher functions, then it defaults to returning the first 32 bytes from <code>ENCRYPT(k, maxnonce, zerolen, zeros)</code>, where <code>maxnonce</code> equals 2<sup>64</sup>-1, <code>zerolen</code> is a zero-length byte sequence, and <code>zeros</code> is a sequence of 32 bytes filled with zeros.</p></li>
</ul>
<h2 id="hash-functions">4.3. Hash functions</h2>
<p>Noise depends on the following <strong>hash function</strong> (and associated constants):</p>
<ul>
<li><p><strong><code>HASH(data)</code></strong>: Hashes some arbitrary-length data with a collision-resistant cryptographic hash function and returns an output of <code>HASHLEN</code> bytes.</p></li>
<li><p><strong><code>HASHLEN</code></strong> = A constant specifying the size in bytes of the hash output. Must be 32 or 64.</p></li>
<li><p><strong><code>BLOCKLEN</code></strong> = A constant specifying the size in bytes that the hash function uses internally to divide its input for iterative processing. This is needed to use the hash function with HMAC (<code>BLOCKLEN</code> is <code>B</code> in <span class="citation">[<a href="#ref-rfc2104">3</a>]</span>).</p></li>
</ul>
<p>Noise defines additional functions based on the above <code>HASH()</code> function:</p>
<ul>
<li><p><strong><code>HMAC-HASH(key, data)</code></strong>: Applies <code>HMAC</code> from <span class="citation">[<a href="#ref-rfc2104">3</a>]</span> using the <code>HASH()</code> function. This function is only called as part of <code>HKDF()</code>, below.</p></li>
<li><strong><code>HKDF(chaining_key, input_key_material, num_outputs)</code></strong>: Takes a <code>chaining_key</code> byte sequence of length <code>HASHLEN</code>, and an <code>input_key_material</code> byte sequence with length either zero bytes, 32 bytes, or <code>DHLEN</code> bytes. Returns a pair or triple of byte sequences each of length <code>HASHLEN</code>, depending on whether <code>num_outputs</code> is two or three:
<ul>
<li>Sets <code>temp_key = HMAC-HASH(chaining_key, input_key_material)</code>.</li>
<li>Sets <code>output1 = HMAC-HASH(temp_key, byte(0x01))</code>.</li>
<li>Sets <code>output2 = HMAC-HASH(temp_key, output1 || byte(0x02))</code>.</li>
<li>If <code>num_outputs == 2</code> then returns the pair <code>(output1, output2)</code>.</li>
<li>Sets <code>output3 = HMAC-HASH(temp_key, output2 || byte(0x03))</code>.</li>
<li>Returns the triple <code>(output1, output2, output3)</code>.</li>
</ul></li>
</ul>
<p>Note that <code>temp_key</code>, <code>output1</code>, <code>output2</code>, and <code>output3</code> are all <code>HASHLEN</code> bytes in length. Also note that the <code>HKDF()</code> function is simply <code>HKDF</code> from <span class="citation">[<a href="#ref-rfc5869">4</a>]</span> with the <code>chaining_key</code> as HKDF <code>salt</code>, and zero-length HKDF <code>info</code>.</p>
<h1 id="processing-rules">5. Processing rules</h1>
<p>To precisely define the processing rules we adopt an object-oriented terminology, and present three "objects" which encapsulate state variables and contain functions which implement processing logic. These three objects are presented as a hierarchy: each higher-layer object includes one instance of the object beneath it. From lowest-layer to highest, the objects are:</p>
<ul>
<li><p>A <strong><code>CipherState</code></strong> object contains <code>k</code> and <code>n</code> variables, which it uses to encrypt and decrypt ciphertexts. During the handshake phase each party has a single <code>CipherState</code>, but during the transport phase each party has two <code>CipherState</code> objects: one for sending, and one for receiving.</p></li>
<li><p>A <strong><code>SymmetricState</code></strong> object contains a <code>CipherState</code> plus <code>ck</code> and <code>h</code> variables. It is so-named because it encapsulates all the "symmetric crypto" used by Noise. During the handshake phase each party has a single <code>SymmetricState</code>, which can be deleted once the handshake is finished.</p></li>
<li><p>A <strong><code>HandshakeState</code></strong> object contains a <code>SymmetricState</code> plus DH variables <code>(s, e, rs, re)</code> and a variable representing the handshake pattern. During the handshake phase each party has a single <code>HandshakeState</code>, which can be deleted once the handshake is finished.</p></li>
</ul>
<p>To execute a Noise protocol you <code>Initialize()</code> a <code>HandshakeState</code>. During initialization you specify the handshake pattern, any local key pairs, and any public keys for the remote party you have knowledge of. After <code>Initialize()</code> you call <code>WriteMessage()</code> and <code>ReadMessage()</code> on the <code>HandshakeState</code> to process each handshake message. If any error is signaled by the <code>DECRYPT()</code> or <code>DH()</code> functions then the handshake has failed and the <code>HandshakeState</code> is deleted.</p>
<p>Processing the final handshake message returns two <code>CipherState</code> objects, the first for encrypting transport messages from initiator to responder, and the second for messages in the other direction. At that point the <code>HandshakeState</code> should be deleted except for the hash value <code>h</code>, which may be used for post-handshake channel binding (see <a href="#channel-binding">Section 11.2</a>).</p>
<p>Transport messages are then encrypted and decrypted by calling <code>EncryptWithAd()</code> and <code>DecryptWithAd()</code> on the relevant <code>CipherState</code> with zero-length associated data. If <code>DecryptWithAd()</code> signals an error due to <code>DECRYPT()</code> failure, then the input message is discarded. The application may choose to delete the <code>CipherState</code> and terminate the session on such an error, or may continue to attempt communications. If <code>EncryptWithAd()</code> or <code>DecryptWithAd()</code> signal an error due to nonce exhaustion, then the application must delete the <code>CipherState</code> and terminate the session.</p>
<p>The below sections describe these objects in detail.</p>
<h2 id="the-cipherstate-object">5.1. The <code>CipherState</code> object</h2>
<p>A <code>CipherState</code> can encrypt and decrypt data based on its <code>k</code> and <code>n</code> variables:</p>
<ul>
<li><p><strong><code>k</code></strong>: A cipher key of 32 bytes (which may be <code>empty</code>). <code>Empty</code> is a special value which indicates <code>k</code> has not yet been initialized.</p></li>
<li><p><strong><code>n</code></strong>: An 8-byte (64-bit) unsigned integer nonce.</p></li>
</ul>
<p>A <code>CipherState</code> responds to the following functions. The <code>++</code> post-increment operator applied to <code>n</code> means "use the current <code>n</code> value, then increment it". The maximum <code>n</code> value (2<sup>64</sup>-1) is reserved for other use. If incrementing <code>n</code> results in 2<sup>64</sup>-1, then any further <code>EncryptWithAd()</code> or <code>DecryptWithAd()</code> calls will signal an error to the caller.</p>
<ul>
<li><p><strong><code>InitializeKey(key)</code></strong>: Sets <code>k = key</code>. Sets <code>n = 0</code>.</p></li>
<li><p><strong><code>HasKey()</code></strong>: Returns true if <code>k</code> is non-empty, false otherwise.</p></li>
<li><p><strong><code>SetNonce(nonce)</code></strong>: Sets <code>n = nonce</code>. This function is used for handling out-of-order transport messages, as described in <a href="#out-of-order-transport-messages">Section 11.4</a>.</p></li>
<li><p><strong><code>EncryptWithAd(ad, plaintext)</code></strong>: If <code>k</code> is non-empty returns <code>ENCRYPT(k, n++, ad, plaintext)</code>. Otherwise returns <code>plaintext</code>.</p></li>
<li><p><strong><code>DecryptWithAd(ad, ciphertext)</code></strong>: If <code>k</code> is non-empty returns <code>DECRYPT(k, n++, ad, ciphertext)</code>. Otherwise returns <code>ciphertext</code>. If an authentication failure occurs in <code>DECRYPT()</code> then <code>n</code> is not incremented and an error is signaled to the caller.</p></li>
<li><p><strong><code>Rekey()</code></strong>: Sets <code>k = REKEY(k)</code>.</p></li>
</ul>
<h2 id="the-symmetricstate-object">5.2. The <code>SymmetricState</code> object</h2>
<p>A <code>SymmetricState</code> object contains a <code>CipherState</code> plus the following variables:</p>
<ul>
<li><strong><code>ck</code></strong>: A chaining key of <code>HASHLEN</code> bytes.</li>
<li><strong><code>h</code></strong>: A hash output of <code>HASHLEN</code> bytes.</li>
</ul>
<p>A <code>SymmetricState</code> responds to the following functions:</p>
<ul>
<li><p><strong><code>InitializeSymmetric(protocol_name)</code></strong>: Takes an arbitrary-length <code>protocol_name</code> byte sequence (see <a href="#protocol-names-and-modifiers">Section 8</a>). Executes the following steps:</p>
<ul>
<li><p>If <code>protocol_name</code> is less than or equal to <code>HASHLEN</code> bytes in length, sets <code>h</code> equal to <code>protocol_name</code> with zero bytes appended to make <code>HASHLEN</code> bytes. Otherwise sets <code>h = HASH(protocol_name)</code>.</p></li>
<li><p>Sets <code>ck = h</code>.</p></li>
<li><p>Calls <code>InitializeKey(empty)</code>.</p></li>
</ul></li>
<li><p><strong><code>MixKey(input_key_material)</code></strong>: Executes the following steps:</p>
<ul>
<li>Sets <code>ck, temp_k = HKDF(ck, input_key_material, 2)</code>.</li>
<li>If <code>HASHLEN</code> is 64, then truncates <code>temp_k</code> to 32 bytes.</li>
<li>Calls <code>InitializeKey(temp_k)</code>.</li>
</ul></li>
<li><p><strong><code>MixHash(data)</code></strong>: Sets <code>h = HASH(h || data)</code>.</p></li>
<li><p><strong><code>MixKeyAndHash(input_key_material)</code></strong>: This function is used for handling pre-shared symmetric keys, as described in <a href="#pre-shared-symmetric-keys">Section 9</a>. It executes the following steps:</p>
<ul>
<li>Sets <code>ck, temp_h, temp_k = HKDF(ck, input_key_material, 3)</code>.</li>
<li>Calls <code>MixHash(temp_h)</code>.</li>
<li>If <code>HASHLEN</code> is 64, then truncates <code>temp_k</code> to 32 bytes.</li>
<li>Calls <code>InitializeKey(temp_k)</code>.</li>
</ul></li>
<li><p><strong><code>GetHandshakeHash()</code></strong>: Returns <code>h</code>. This function should only be called at the end of a handshake, i.e. after the <code>Split()</code> function has been called. This function is used for channel binding, as described in <a href="#channel-binding">Section 11.2</a></p></li>
<li><p><strong><code>EncryptAndHash(plaintext)</code></strong>: Sets <code>ciphertext = EncryptWithAd(h, plaintext)</code>, calls <code>MixHash(ciphertext)</code>, and returns <code>ciphertext</code>. Note that if <code>k</code> is <code>empty</code>, the <code>EncryptWithAd()</code> call will set <code>ciphertext</code> equal to <code>plaintext</code>.</p></li>
<li><p><strong><code>DecryptAndHash(ciphertext)</code></strong>: Sets <code>plaintext = DecryptWithAd(h, ciphertext)</code>, calls <code>MixHash(ciphertext)</code>, and returns <code>plaintext</code>. Note that if <code>k</code> is <code>empty</code>, the <code>DecryptWithAd()</code> call will set <code>plaintext</code> equal to <code>ciphertext</code>.</p></li>
<li><strong><code>Split()</code></strong>: Returns a pair of <code>CipherState</code> objects for encrypting transport messages. Executes the following steps, where <code>zerolen</code> is a zero-length byte sequence:
<ul>
<li>Sets <code>temp_k1, temp_k2 = HKDF(ck, zerolen, 2)</code>.</li>
<li>If <code>HASHLEN</code> is 64, then truncates <code>temp_k1</code> and <code>temp_k2</code> to 32 bytes.</li>
<li>Creates two new <code>CipherState</code> objects <code>c1</code> and <code>c2</code>.</li>
<li>Calls <code>c1.InitializeKey(temp_k1)</code> and <code>c2.InitializeKey(temp_k2)</code>.</li>
<li>Returns the pair <code>(c1, c2)</code>.</li>
</ul></li>
</ul>
<h2 id="the-handshakestate-object">5.3. The <code>HandshakeState</code> object</h2>
<p>A <code>HandshakeState</code> object contains a <code>SymmetricState</code> plus the following variables, any of which may be <code>empty</code>. <code>Empty</code> is a special value which indicates the variable has not yet been initialized.</p>
<ul>
<li><strong><code>s</code></strong>: The local static key pair</li>
<li><strong><code>e</code></strong>: The local ephemeral key pair</li>
<li><strong><code>rs</code></strong>: The remote party's static public key</li>
<li><strong><code>re</code></strong>: The remote party's ephemeral public key</li>
</ul>
<p>A <code>HandshakeState</code> also has variables to track its role, and the remaining portion of the handshake pattern:</p>
<ul>
<li><p><strong><code>initiator</code></strong>: A boolean indicating the initiator or responder role.</p></li>
<li><p><strong><code>message_patterns</code></strong>: A sequence of message patterns. Each message pattern is a sequence of tokens from the set <code>("e", "s", "ee", "es", "se", "ss")</code>. (An additional <code>"psk"</code> token is introduced in <a href="#pre-shared-symmetric-keys">Section 9</a>, but we defer its explanation until then.)</p></li>
</ul>
<p>A <code>HandshakeState</code> responds to the following functions:</p>
<ul>
<li><p><strong><code>Initialize(handshake_pattern, initiator, prologue, s, e, rs, re)</code></strong>: Takes a valid <code>handshake_pattern</code> (see <a href="#handshake-patterns">Section 7</a>) and an <code>initiator</code> boolean specifying this party's role as either initiator or responder.</p>
<p>Takes a <code>prologue</code> byte sequence which may be zero-length, or which may contain context information that both parties want to confirm is identical (see <a href="#prologue">Section 6</a>).</p>
<p>Takes a set of DH key pairs <code>(s, e)</code> and public keys <code>(rs, re)</code> for initializing local variables, any of which may be empty. Public keys are only passed in if the <code>handshake_pattern</code> uses pre-messages (see <a href="#handshake-patterns">Section 7</a>). The ephemeral values <code>(e, re)</code> are typically left empty, since they are created and exchanged during the handshake; but there are exceptions (see <a href="#compound-patterns">Section 10</a>).</p>
<p>Performs the following steps:</p>
<ul>
<li><p>Derives a <code>protocol_name</code> byte sequence by combining the names for the handshake pattern and crypto functions, as specified in <a href="#protocol-names-and-modifiers">Section 8</a>. Calls <code>InitializeSymmetric(protocol_name)</code>.</p></li>
<li><p>Calls <code>MixHash(prologue)</code>.</p></li>
<li><p>Sets the <code>initiator</code>, <code>s</code>, <code>e</code>, <code>rs</code>, and <code>re</code> variables to the corresponding arguments.</p></li>
<li><p>Calls <code>MixHash()</code> once for each public key listed in the pre-messages from <code>handshake_pattern</code>, with the specified public key as input (see <a href="#handshake-patterns">Section 7</a> for an explanation of pre-messages). If both initiator and responder have pre-messages, the initiator's public keys are hashed first. If multiple public keys are listed in either party's pre-message, the public keys are hashed in the order that they are listed.</p></li>
<li><p>Sets <code>message_patterns</code> to the message patterns from <code>handshake_pattern</code>.</p></li>
</ul></li>
<li><p><strong><code>WriteMessage(payload, message_buffer)</code></strong>: Takes a <code>payload</code> byte sequence which may be zero-length, and a <code>message_buffer</code> to write the output into. Performs the following steps, aborting if any <code>EncryptAndHash()</code> call returns an error:</p>
<ul>
<li><p>Fetches and deletes the next message pattern from <code>message_patterns</code>, then sequentially processes each token from the message pattern:</p>
<ul>
<li><p>For <code>"e"</code>: Sets <code>e</code> (which must be empty) to <code>GENERATE_KEYPAIR()</code>. Appends <code>e.public_key</code> to the buffer. Calls <code>MixHash(e.public_key)</code>.</p></li>
<li><p>For <code>"s"</code>: Appends <code>EncryptAndHash(s.public_key)</code> to the buffer.</p></li>
<li><p>For <code>"ee"</code>: Calls <code>MixKey(DH(e, re))</code>.</p></li>
<li><p>For <code>"es"</code>: Calls <code>MixKey(DH(e, rs))</code> if initiator, <code>MixKey(DH(s, re))</code> if responder.</p></li>
<li><p>For <code>"se"</code>: Calls <code>MixKey(DH(s, re))</code> if initiator, <code>MixKey(DH(e, rs))</code> if responder.</p></li>
<li><p>For <code>"ss"</code>: Calls <code>MixKey(DH(s, rs))</code>.</p></li>
</ul></li>
<li><p>Appends <code>EncryptAndHash(payload)</code> to the buffer.</p></li>
<li><p>If there are no more message patterns returns two new <code>CipherState</code> objects by calling <code>Split()</code>.</p></li>
</ul></li>
</ul>
<ul>
<li><p><strong><code>ReadMessage(message, payload_buffer)</code></strong>: Takes a byte sequence containing a Noise handshake message, and a <code>payload_buffer</code> to write the message's plaintext payload into. Performs the following steps, aborting if any <code>DecryptAndHash()</code> call returns an error:</p>
<ul>
<li><p>Fetches and deletes the next message pattern from <code>message_patterns</code>, then sequentially processes each token from the message pattern:</p>
<ul>
<li><p>For <code>"e"</code>: Sets <code>re</code> (which must be empty) to the next <code>DHLEN</code> bytes from the message. Calls <code>MixHash(re.public_key)</code>.</p></li>
<li><p>For <code>"s"</code>: Sets <code>temp</code> to the next <code>DHLEN + 16</code> bytes of the message if <code>HasKey() == True</code>, or to the next <code>DHLEN</code> bytes otherwise. Sets <code>rs</code> (which must be empty) to <code>DecryptAndHash(temp)</code>.</p></li>
<li><p>For <code>"ee"</code>: Calls <code>MixKey(DH(e, re))</code>.</p></li>
<li><p>For <code>"es"</code>: Calls <code>MixKey(DH(e, rs))</code> if initiator, <code>MixKey(DH(s, re))</code> if responder.</p></li>
<li><p>For <code>"se"</code>: Calls <code>MixKey(DH(s, re))</code> if initiator, <code>MixKey(DH(e, rs))</code> if responder.</p></li>
<li><p>For <code>"ss"</code>: Calls <code>MixKey(DH(s, rs))</code>.</p></li>
</ul></li>
<li><p>Calls <code>DecryptAndHash()</code> on the remaining bytes of the message and stores the output into <code>payload_buffer</code>.</p></li>
<li><p>If there are no more message patterns returns two new <code>CipherState</code> objects by calling <code>Split()</code>.</p></li>
</ul></li>
</ul>
<h1 id="prologue">6. Prologue</h1>
<p>Noise protocols have a <strong>prologue</strong> input which allows arbitrary data to be hashed into the <code>h</code> variable. If both parties do not provide identical prologue data, the handshake will fail due to a decryption error. This is useful when the parties engaged in negotiation prior to the handshake and want to ensure they share identical views of that negotiation.</p>
<p>For example, suppose Bob communicates to Alice a list of Noise protocols that he is willing to support. Alice will then choose and execute a single protocol. To ensure that a "man-in-the-middle" did not edit Bob's list to remove options, Alice and Bob could include the list as prologue data.</p>
<p>Note that while the parties confirm their prologues are identical, they don't mix prologue data into encryption keys. If an input contains secret data that’s intended to strengthen the encryption, a PSK handshake should be used instead (see <a href="pre-shared-symmetric-keys">Section 9</a>).</p>
<h1 id="handshake-patterns">7. Handshake patterns</h1>
<h2 id="handshake-pattern-basics">7.1. Handshake pattern basics</h2>
<p>A <strong>message pattern</strong> is some sequence of tokens from the set <code>("e", "s", "ee", "es", "se", "ss", "psk")</code>. The handling of these tokens within <code>WriteMessage()</code> and <code>ReadMessage()</code> has been described previously, except for the <code>"psk"</code> token, which will be described in <a href="pre-shared-symmetric-keys">Section 9</a>. Future specifications might introduce other tokens.</p>
<p>A <strong>pre-message pattern</strong> is one of the following sequences of tokens:</p>
<ul>
<li><code>"e"</code></li>
<li><code>"s"</code></li>
<li><code>"e, s"</code></li>
<li>empty</li>
</ul>
<p>A <strong>handshake pattern</strong> consists of:</p>
<ul>
<li><p>A pre-message pattern for the initiator, representing information about the initiator's public keys that is known to the responder.</p></li>
<li><p>A pre-message pattern for the responder, representing information about the responder's public keys that is known to the initiator.</p></li>
<li><p>A sequence of message patterns for the actual handshake messages.</p></li>
</ul>
<p>The pre-messages represent an exchange of public keys that was somehow performed prior to the handshake, so these public keys must be inputs to <code>Initialize()</code> for the "recipient" of the pre-message.</p>
<p>The first actual handshake message is sent from the initiator to the responder. The next message is sent from the responder, the next from the initiator, and so on in alternating fashion.</p>
<p>The following handshake pattern describes an unauthenticated DH handshake consisting of two message patterns:</p>
<pre><code>NN:
-> e
<- e, ee</code></pre>
<p>In the following handshake pattern both the initiator and responder possess static key pairs, and the handshake pattern comprises three message patterns:</p>
<pre><code>XX:
-> e
<- e, ee, s, es
-> s, se</code></pre>
<p>The handshake pattern names are <code>NN</code> and <code>XX</code>. This naming convention will be explained in <a href="#interactive-handshake-patterns-fundamental">Section 7.5</a>.</p>
<p>Non-empty pre-messages are shown as pre-message patterns prior to the delimiter <code>"..."</code>. If both parties have a pre-message, the initiator's is listed first, and hashed first. During <code>Initialize()</code>, <code>MixHash()</code> is called on any pre-message public keys, as described in <a href="#the-handshakestate-object">Section 5.3</a>.</p>
<p>The following handshake pattern describes a handshake where the initiator has pre-knowledge of the responder's static public key and uses it for "zero-RTT" encryption:</p>
<pre><code>NK:
<- s
...
-> e, es
<- e, ee</code></pre>
<p>In the following handshake pattern both parties have pre-knowledge of the other's static public key. The initiator's pre-message is listed first:</p>
<pre><code>KK:
-> s
<- s
...
-> e, es, ss
<- e, ee, se</code></pre>
<h2 id="alice-and-bob">7.2. Alice and Bob</h2>
<p>In all handshake patterns shown previously, the initiator is the party on the left (sending with right-pointing arrows) and the responder is the party on the right.</p>
<p>However, multiple Noise protocols might be used within a <strong>compound protocol</strong> where the responder in one Noise protocol becomes the initiator for a later Noise protocol. As a convenience for terminology and notation in this case, we introduce the notion of <strong>Alice</strong> and <strong>Bob</strong> roles which are different from initiator and responder roles. Alice will be viewed as the party on the left (sending messages with right arrows), and Bob will be the party on the right.</p>
<p>Handshake patterns written in <strong>canonical form</strong> (i.e. <strong>Alice-initiated form</strong>) assume the initiator is Alice (the left-most party). All processing rules and discussion so far have assumed canonical-form handshake patterns.</p>
<p>However, handshake patterns can be written in <strong>Bob-initiated form</strong> by reversing the arrows and the DH tokens (e.g. replacing <code>"es"</code> with <code>"se"</code>, and vice versa). This doesn't change the handshake pattern, it simply makes it easier to view Alice-initiated and Bob-initiated handshakes side-by-side.</p>
<p>Below are the handshake patterns from the previous section in Bob-initiated form:</p>
<pre><code>NN:
<- e
-> e, ee
XX:
<- e
-> e, ee, s, se
<- s, es
NK:
-> s
...
<- e, se
-> e, ee
KK:
<- s
-> s
...
<- e, se, ss
-> e, ee, es</code></pre>
<p>For an example of Bob-initiated notation, see <a href="#the-fallback-modifier">Section 10.2</a>.</p>
<h2 id="handshake-pattern-validity">7.3. Handshake pattern validity</h2>
<p>Handshake patterns must be <strong>valid</strong> in the following senses:</p>
<ol style="list-style-type: decimal">
<li><p>Parties can only perform DH between private keys and public keys they possess.</p></li>
<li><p>Parties must not send their static public key or ephemeral public key more than once per handshake (i.e. including the pre-messages, there must be no more than one occurrence of <code>"e"</code>, and one occurrence of <code>"s"</code>, in the messages sent by any party).</p></li>
<li><p>Parties must not perform a DH calculation more than once per handshake (i.e. there must be no more than one occurrence of <code>"ee"</code>, <code>"es"</code>, <code>"se"</code>, or <code>"ss"</code> per handshake).</p></li>
<li><p>After performing a DH between a remote public key (either static or ephemeral) and the local static key, the local party must not call <code>ENCRYPT()</code> unless it has also performed a DH between its local ephemeral key and the remote public key. In particular, this means that (using canonical notation):</p>
<p>After an <code>"se"</code> token, the initiator must not send a handshake payload or transport payload unless there has also been an <code>"ee"</code> token.</p>
<p>After an <code>"ss"</code> token, the initiator must not send a handshake payload or transport payload unless there has also been an <code>"es"</code> token.</p>
<p>After an <code>"es"</code> token, the responder must not send a handshake payload or transport payload unless there has also been an <code>"ee"</code> token.</p>
<p>After an <code>"ss"</code> token, the responder must not send a handshake payload or transport payload unless there has also been an <code>"se"</code> token.</p></li>
</ol>
<p>Patterns failing the first check are obviously nonsense.</p>
<p>The second and third checks outlaw redundant transmission of values, and redundant computation, to simplify implementation and testing.</p>
<p>The fourth check accomplishes two purposes:</p>
<ul>
<li><p>First, it is necessary because Noise relies on DH outputs involving ephemeral keys to randomize the shared secret keys. Patterns failing this check could result in catastrophic key reuse, because the victim might send a message encrypted with a key that doesn't include a contribution from their local ephemeral key (or where the contribution from their local ephemeral was nullified by an invalid ephemeral from the other party).</p></li>
<li><p>Second, this check guarantees that ephemeral keys are used to provide important security properties such as forward-secrecy and key-compromise impersonation resistance.</p></li>
</ul>
<p>Users are recommended to only use the handshake patterns listed below, or other patterns that have been vetted by experts to satisfy the above checks.</p>
<h2 id="one-way-handshake-patterns">7.4. One-way handshake patterns</h2>
<p>The following handshake patterns represent "one-way" handshakes supporting a one-way stream of data from a sender to a recipient. These patterns could be used to encrypt files, database records, or other non-interactive data streams.</p>
<p>Following a one-way handshake the sender can send a stream of transport messages, encrypting them using the first <code>CipherState</code> returned by <code>Split()</code>. The second <code>CipherState</code> from <code>Split()</code> is discarded - the recipient must not send any messages using it (as this would violate the rules in <a href="#handshake-pattern-validity">Section 7.3</a>).</p>
<p>One-way patterns are named with a single character, which indicates the status of the sender's static key:</p>
<ul>
<li><strong><code>N</code></strong> = <strong><code>N</code></strong>o static key for sender</li>
<li><strong><code>K</code></strong> = Static key for sender <strong><code>K</code></strong>nown to recipient</li>
<li><strong><code>X</code></strong> = Static key for sender <strong><code>X</code></strong>mitted ("transmitted") to recipient</li>
</ul>
<table style="width:36%;">
<colgroup>
<col width="36%" />
</colgroup>
<tbody>
<tr class="odd">
<td><pre><code>N:
<- s
...
-> e, es</code></pre></td>
</tr>
<tr class="even">
<td><pre><code>K:
-> s
<- s
...
-> e, es, ss</code></pre></td>
</tr>
<tr class="odd">
<td><pre><code>X:
<- s
...
-> e, es, s, ss</code></pre></td>
</tr>
</tbody>
</table>
<p><code>N</code> is a conventional DH-based public-key encryption. The other patterns add sender authentication, where the sender's public key is either known to the recipient beforehand (<code>K</code>) or transmitted under encryption (<code>X</code>).</p>
<h2 id="interactive-handshake-patterns-fundamental">7.5. Interactive handshake patterns (fundamental)</h2>
<p>The following handshake patterns represent interactive protocols. These 12 patterns are called the <strong>fundamental</strong> interactive handshake patterns.</p>
<p>The fundamental interactive patterns are named with two characters, which indicate the status of the initiator and responder's static keys:</p>
<p>The first character refers to the initiator's static key:</p>
<ul>
<li><strong><code>N</code></strong> = <strong><code>N</code></strong>o static key for initiator</li>
<li><strong><code>K</code></strong> = Static key for initiator <strong><code>K</code></strong>nown to responder</li>
<li><strong><code>X</code></strong> = Static key for initiator <strong><code>X</code></strong>mitted ("transmitted") to responder</li>
<li><strong><code>I</code></strong> = Static key for initiator <strong><code>I</code></strong>mmediately transmitted to responder, despite reduced or absent identity hiding</li>
</ul>
<p>The second character refers to the responder's static key:</p>
<ul>
<li><strong><code>N</code></strong> = <strong><code>N</code></strong>o static key for responder</li>
<li><strong><code>K</code></strong> = Static key for responder <strong><code>K</code></strong>nown to initiator</li>
<li><strong><code>X</code></strong> = Static key for responder <strong><code>X</code></strong>mitted ("transmitted") to initiator</li>
</ul>
<table style="width:85%;">
<colgroup>
<col width="38%" />
<col width="45%" />
</colgroup>
<tbody>
<tr class="odd">
<td><pre><code>NN:
-> e
<- e, ee</code></pre></td>
<td><pre><code> KN:
-> s
...
-> e
<- e, ee, se</code></pre></td>
</tr>
<tr class="even">
<td><pre><code>NK:
<- s
...
-> e, es
<- e, ee</code></pre></td>
<td><pre><code> KK:
-> s
<- s
...
-> e, es, ss
<- e, ee, se</code></pre></td>
</tr>
<tr class="odd">
<td><pre><code>NX:
-> e
<- e, ee, s, es</code></pre></td>
<td><pre><code> KX:
-> s
...
-> e
<- e, ee, se, s, es</code></pre></td>
</tr>
<tr class="even">
<td><pre><code>XN:
-> e
<- e, ee
-> s, se</code></pre></td>
<td><pre><code> IN:
-> e, s
<- e, ee, se</code></pre></td>
</tr>
<tr class="odd">
<td><pre><code>XK:
<- s
...
-> e, es
<- e, ee
-> s, se</code></pre></td>
<td><pre><code> IK:
<- s
...
-> e, es, s, ss
<- e, ee, se</code></pre></td>
</tr>
<tr class="even">
<td><pre><code>XX:
-> e
<- e, ee, s, es
-> s, se</code></pre></td>
<td><pre><code> IX:
-> e, s
<- e, ee, se, s, es</code></pre></td>
</tr>
</tbody>
</table>
<p>The <code>XX</code> pattern is the most generically useful, since it supports mutual authentication and transmission of static public keys.</p>
<p>All fundamental patterns allow some encryption of handshake payloads:</p>
<ul>
<li><p>Patterns where the initiator has pre-knowledge of the responder's static public key (i.e. patterns ending in <code>K</code>) allow <strong>zero-RTT</strong> encryption, meaning the initiator can encrypt the first handshake payload.</p></li>
<li><p>All fundamental patterns allow <strong>half-RTT</strong> encryption of the first response payload, but the encryption only targets an initiator static public key in patterns starting with <code>K</code> or <code>I</code>.</p></li>
</ul>
<p>The security properties for handshake payloads are usually weaker than the final security properties achieved by transport payloads, so these early encryptions must be used with caution.</p>
<p>In some patterns the security properties of transport payloads can also vary. In particular: patterns starting with <code>K</code> or <code>I</code> have the caveat that the responder is only guaranteed "weak" forward secrecy for the transport messages it sends until it receives a transport message from the initiator. After receiving a transport message from the initiator, the responder becomes assured of "strong" forward secrecy.</p>
<p>More analysis of these payload security properties is in <a href="#payload-security-properties">Section 7.7</a>.</p>
<h2 id="interactive-handshake-patterns-deferred">7.6. Interactive handshake patterns (deferred)</h2>
<p>The fundamental handshake patterns in the previous section perform DH operations for authentication (<code>"es"</code> and <code>"se"</code>) as early as possible.</p>
<p>An additional set of handshake patterns can be described which defer these authentication DHs to the next message. To name these <strong>deferred handshake patterns</strong>, the numeral "1" is used after the first and/or second character in a fundamental pattern name to indicate that the initiator and/or responder's authentication DH is deferred to the next message.</p>
<p>Deferred patterns might be useful for several reasons:</p>
<ul>
<li><p>The initiator might have prior knowledge of the responder's static public key, but not wish to send any 0-RTT encrypted data.</p></li>
<li><p>In some cases, deferring authentication can improve the identity-hiding properties of the handshake (see <a href="#identity-hiding">Section 7.8</a>).</p></li>
<li><p>Future extensions to Noise might be capable of replacing DH operations with signatures or KEM ciphertexts, but would only be able to do so if the sender is authenticating themselves (signatures) or the sender is authenticating the recipient (KEM ciphertexts). Thus every fundamental handshake pattern is only capable of having each authentication DH replaced with a signature <em>or</em> KEM ciphertext, but the deferred variants make both replacements possible.</p></li>
</ul>
<p>Below are two examples showing a fundamental handshake pattern on the left, and deferred variant(s) on the right. The full set of 23 deferred handshake patterns are in the <a href="#deferred-patterns">Appendix</a>.</p>
<table style="width:85%;">
<colgroup>
<col width="38%" />
<col width="45%" />
</colgroup>
<tbody>
<tr class="odd">
<td><pre><code>NK:
<- s
...
-> e, es
<- e, ee</code></pre></td>
<td><pre><code> NK1:
<- s
...
-> e
<- e, ee, es</code></pre></td>
</tr>
<tr class="even">
<td><pre><code>XX:
-> e
<- e, ee, s, es
-> s, se</code></pre></td>
<td><pre><code> X1X:
-> e
<- e, ee, s, es
-> s
<- se
XX1:
-> e
<- e, ee, s
-> es, s, se
X1X1:
-> e
<- e, ee, s
-> es, s
<- se</code></pre></td>
</tr>
</tbody>
</table>
<h2 id="payload-security-properties">7.7. Payload security properties</h2>
<p>The following table lists the security properties for Noise handshake and transport payloads for all the one-way patterns in <a href="#one-way-handshake-patterns">Section 7.4</a> and the fundamental patterns in <a href="#interactive-handshake-patterns-fundamental">Section 7.5</a>. Each payload is assigned a "source" property regarding the degree of authentication of the sender provided to the recipient, and a "destination" property regarding the degree of confidentiality provided to the sender.</p>
<p>The source properties are:</p>
<ol start="0" style="list-style-type: decimal">
<li><p><strong>No authentication.</strong> This payload may have been sent by any party, including an active attacker.</p></li>
<li><p><strong>Sender authentication <em>vulnerable</em> to key-compromise impersonation (KCI)</strong>. The sender authentication is based on a static-static DH (<code>"ss"</code>) involving both parties' static key pairs. If the recipient's long-term private key has been compromised, this authentication can be forged. Note that a future version of Noise might include signatures, which could improve this security property, but brings other trade-offs.</p></li>
<li><p><strong>Sender authentication <em>resistant</em> to key-compromise impersonation (KCI)</strong>. The sender authentication is based on an ephemeral-static DH (<code>"es"</code> or <code>"se"</code>) 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.</p></li>
</ol>
<p>The destination properties are:</p>
<ol start="0" style="list-style-type: decimal">
<li><p><strong>No confidentiality.</strong> This payload is sent in cleartext.</p></li>
<li><p><strong>Encryption to an ephemeral recipient.</strong> This payload has forward secrecy, since encryption involves an ephemeral-ephemeral DH (<code>"ee"</code>). However, the sender has not authenticated the recipient, so this payload might be sent to any party, including an active attacker.</p></li>
<li><p><strong>Encryption to a known recipient, forward secrecy for sender compromise only, vulnerable to replay.</strong> 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.</p></li>
<li><p><strong>Encryption to a known recipient, weak forward secrecy.</strong> This payload is encrypted based on an ephemeral-ephemeral DH and also an ephemeral-static DH involving the recipient's static key pair. However, the binding between the recipient's alleged ephemeral public key and the recipient's static public key hasn't been verified by the sender, so the recipient's alleged ephemeral public key may have been forged by an active attacker. In this case, the attacker could later compromise the recipient's static private key to decrypt the payload. Note that a future version of Noise might include signatures, which could improve this security property, but brings other trade-offs.</p></li>
<li><p><strong>Encryption to a known recipient, weak forward secrecy if the sender's private key has been compromised.</strong> This payload is encrypted based on an ephemeral-ephemeral DH, and also based on an ephemeral-static DH involving the recipient's static key pair. However, the binding between the recipient's alleged ephemeral public and the recipient's static public key has only been verified based on DHs involving both those public keys and the sender's static private key. Thus, if the sender's static private key was previously compromised, the recipient's alleged ephemeral public key may have been forged by an active attacker. In this case, the attacker could later compromise the intended recipient's static private key to decrypt the payload (this is a variant of a "KCI" attack enabling a "weak forward secrecy" attack). Note that a future version of Noise might include signatures, which could improve this security property, but brings other trade-offs.</p></li>
<li><p><strong>Encryption to a known recipient, strong forward secrecy.</strong> 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.</p></li>
</ol>
<p>For one-way handshakes, the below-listed security properties apply to the handshake payload as well as transport payloads.</p>
<p>For interactive handshakes, security properties are listed for each handshake payload. Transport payloads are listed as arrows without a pattern. Transport payloads are only listed if they have different security properties than the previous handshake payload sent from the same party. If two transport payloads are listed, the security properties for the second only apply if the first was received.</p>
<table style="width:88%;">
<colgroup>
<col width="87%" />
</colgroup>
<tbody>
<tr class="odd">
<td><pre><code> Source Destination</code></pre></td>
</tr>
<tr class="even">
<td><pre><code>N 0 2</code></pre></td>
</tr>
<tr class="odd">
<td><pre><code>K 1 2</code></pre></td>
</tr>
<tr class="even">
<td><pre><code>X 1 2</code></pre></td>
</tr>
<tr class="odd">
<td><pre><code>NN
-> e 0 0
<- e, ee 0 1
-> 0 1</code></pre></td>
</tr>
<tr class="even">
<td><pre><code>NK
<- s
...
-> e, es 0 2
<- e, ee 2 1
-> 0 5</code></pre></td>
</tr>
<tr class="odd">
<td><pre><code>NX
-> e 0 0
<- e, ee, s, es 2 1
-> 0 5</code></pre></td>
</tr>
<tr class="even">
<td><pre><code>XN
-> e 0 0
<- e, ee 0 1
-> s, se 2 1
<- 0 5</code></pre></td>
</tr>
<tr class="odd">
<td><pre><code>XK
<- s
...
-> e, es 0 2
<- e, ee 2 1
-> s, se 2 5
<- 2 5</code></pre></td>
</tr>
<tr class="even">
<td><pre><code>XX
-> e 0 0
<- e, ee, s, es 2 1
-> s, se 2 5
<- 2 5</code></pre></td>
</tr>
<tr class="odd">
<td><pre><code>KN
-> s
...
-> e 0 0
<- e, ee, se 0 3
-> 2 1
<- 0 5</code></pre></td>
</tr>
<tr class="even">
<td><pre><code>KK
-> s
<- s
...
-> e, es, ss 1 2
<- e, ee, se 2 4
-> 2 5
<- 2 5</code></pre></td>
</tr>
<tr class="odd">
<td><pre><code>KX
-> s
...
-> e 0 0
<- e, ee, se, s, es 2 3
-> 2 5
<- 2 5</code></pre></td>
</tr>
<tr class="even">
<td><pre><code>IN
-> e, s 0 0
<- e, ee, se 0 3
-> 2 1
<- 0 5</code></pre></td>
</tr>
<tr class="odd">
<td><pre><code>IK
<- s
...
-> e, es, s, ss 1 2
<- e, ee, se 2 4
-> 2 5
<- 2 5</code></pre></td>
</tr>
<tr class="even">
<td><pre><code>IX
-> e, s 0 0
<- e, ee, se, s, es 2 3
-> 2 5
<- 2 5</code></pre></td>
</tr>
</tbody>
</table>
<h2 id="identity-hiding">7.8. Identity hiding</h2>
<p>The following table lists the identity-hiding properties for all the one-way handshake patterns in <a href="#one-way-handshake-patterns">Section 7.4</a> and the fundamental handshake patterns in <a href="#interactive-handshake-patterns-fundamental">Section 7.5</a>. In addition, we list a few deferred handshake patterns which have different identity-hiding properties than the corresponding fundamental pattern.</p>
<p>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.</p>
<p>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.</p>
<p>The properties for the relevant public key are:</p>
<ol start="0" style="list-style-type: decimal">
<li><p>Transmitted in clear.</p></li>
<li><p>Encrypted with forward secrecy, but can be probed by an anonymous initiator.</p></li>
<li><p>Encrypted with forward secrecy, but sent to an anonymous responder.</p></li>
<li><p>Not transmitted, but a passive attacker can check candidates for the responder's private key and determine whether the candidate is correct. An attacker could also replay a previously-recorded message to a new responder and determine whether the two responders are the "same" (i.e. are using the same static key pair) by whether the recipient accepts the message.</p></li>
<li><p>Encrypted to responder's static public key, without forward secrecy. If an attacker learns the responder's private key they can decrypt the initiator's public key.</p></li>
<li><p>Not transmitted, but a passive attacker can check candidates for the pair of (responder's private key, initiator's public key) and learn whether the candidate pair is correct.</p></li>
<li><p>Encrypted but with weak forward secrecy. An active attacker who pretends to be the initiator without the initiator's static private key, then later learns the initiator private key, can then decrypt the responder's public key.</p></li>
<li><p>Not transmitted, but an active attacker who pretends to be the initator without the initiator's static private key, then later learns a candidate for the initiator private key, can then check whether the candidate is correct.</p></li>
<li><p>Encrypted with forward secrecy to an authenticated party.</p></li>
<li><p>An active attacker who pretends to be the initiator and records a single protocol run can then check candidates for the responder's public key.</p></li>
</ol>
<!-- end of list - necesary to trick Markdown into seeing the following -->
<table style="width:60%;">
<colgroup>
<col width="59%" />
</colgroup>
<tbody>
<tr class="odd">
<td><pre><code> Initiator Responder</code></pre></td>
</tr>
<tr class="even">
<td><pre><code>N - 3</code></pre></td>
</tr>
<tr class="odd">
<td><pre><code>K 5 5</code></pre></td>
</tr>
<tr class="even">
<td><pre><code>X 4 3</code></pre></td>
</tr>
<tr class="odd">
<td><pre><code>NN - -</code></pre></td>
</tr>
<tr class="even">
<td><pre><code>NK - 3</code></pre></td>
</tr>
<tr class="odd">
<td><pre><code>NK1 - 9</code></pre></td>
</tr>
<tr class="even">
<td><pre><code>NX - 1</code></pre></td>
</tr>
<tr class="odd">
<td><pre><code>XN 2 -</code></pre></td>
</tr>
<tr class="even">
<td><pre><code>XK 8 3</code></pre></td>
</tr>
<tr class="odd">
<td><pre><code>XK1 8 9</code></pre></td>
</tr>
<tr class="even">
<td><pre><code>XX 8 1</code></pre></td>
</tr>
<tr class="odd">
<td><pre><code>KN 7 -</code></pre></td>
</tr>
<tr class="even">
<td><pre><code>KK 5 5</code></pre></td>
</tr>
<tr class="odd">
<td><pre><code>KX 7 6</code></pre></td>
</tr>
<tr class="even">
<td><pre><code>IN 0 -</code></pre></td>
</tr>
<tr class="odd">
<td><pre><code>IK 4 3</code></pre></td>
</tr>
<tr class="even">
<td><pre><code>IK1 0 9</code></pre></td>
</tr>
<tr class="odd">
<td><pre><code>IX 0 6</code></pre></td>
</tr>
</tbody>
</table>
<h1 id="protocol-names-and-modifiers">8. Protocol names and modifiers</h1>
<p>To produce a <strong>Noise protocol name</strong> for <code>Initialize()</code> you concatenate the ASCII string <code>"Noise_"</code> with four underscore-separated name sections which sequentially name the handshake pattern, the DH functions, the cipher functions, and then the hash functions. The resulting name must be 255 bytes or less. Examples:</p>
<ul>
<li><code>Noise_XX_25519_AESGCM_SHA256</code></li>
<li><code>Noise_N_25519_ChaChaPoly_BLAKE2s</code></li>
<li><code>Noise_IK_448_ChaChaPoly_BLAKE2b</code></li>
</ul>
<p>Each name section must consist only of alphanumeric characters (i.e. characters in one of the ranges <code>"A"</code>...<code>"Z"</code>, <code>"a"</code>...<code>"z"</code>, and <code>"0"</code>...<code>"9"</code>), and the two special characters <code>"+"</code> and <code>"/"</code>.</p>
<p>Additional rules apply to each name section, as specified below.</p>
<h2 id="handshake-pattern-name-section">8.1. Handshake pattern name section</h2>
<p>A handshake pattern name section contains a handshake pattern name plus a sequence of zero or more <strong>pattern modifiers</strong>.</p>
<p>The handshake pattern name must be an uppercase ASCII string containing only alphabetic characters or numerals (e.g. <code>"XX1"</code> or <code>"IK"</code>).</p>
<p>Pattern modifiers specify arbitrary extensions or modifications to the behavior specified by the handshake pattern. For example, a modifier could be applied to a handshake pattern which transforms it into a different pattern according to some rule. The <code>"psk0"</code> and <code>"fallback"</code> modifiers are examples of this, and will be defined later in this document.</p>
<p>A pattern modifier is named with a lowercase alphanumeric ASCII string which must begin with an alphabetic character (not a numeral). The pattern modifier is appended to the base pattern as described below:</p>
<p>The first modifier added onto a base pattern is simply appended. Thus the <code>"fallback"</code> modifier, when added to the <code>"XX"</code> pattern, produces <code>"XXfallback"</code>. Additional modifiers are separated with a plus sign. Thus, adding the <code>"psk0"</code> modifier would result in the name section <code>"XXfallback+psk0"</code>, or a full protocol name such as <code>"Noise_XXfallback+psk0_25519_AESGCM_SHA256"</code>.</p>
<p>In some cases the sequential ordering of modifiers will specify different protocols. However, if the order of some modifiers does not matter, then they are required to be sorted alphabetically (this is an arbitrary convention to ensure interoperability).</p>
<h2 id="cryptographic-algorithm-name-sections">8.2. Cryptographic algorithm name sections</h2>
<p>The rules for the DH, cipher, and hash name sections are identical. Each name section must contain one or more algorithm names separated by plus signs.</p>
<p>Each algorithm name must consist solely of alphanumeric characters and the forward-slash character (<code>"/"</code>). Algorithm names are recommended to be short, and to use the <code>"/"</code> character only when necessary to avoid ambiguity (e.g. <code>"SHA3/256"</code> is preferable to <code>"SHA3256"</code>).</p>
<p>In most cases there will be a single algorithm name in each name section (i.e. no plus signs). Multiple algorithm names are only used when called for by the pattern or a modifier.</p>
<p>None of the patterns or modifiers in this document require multiple algorithm names in any name section. However, this functionality might be useful in future extensions. For example, multiple algorithm names might be used in the DH section to specify "hybrid" post-quantum forward secrecy; or multiple hash algorithms might be specified for different purposes.</p>
<h1 id="pre-shared-symmetric-keys">9. Pre-shared symmetric keys</h1>
<p>Noise provides a <strong>pre-shared symmetric key</strong> or <strong>PSK</strong> mode to support protocols where both parties have a 32-byte shared secret key.</p>
<h2 id="cryptographic-functions">9.1. Cryptographic functions</h2>
<p>PSK mode uses the <code>SymmetricState.MixKeyAndHash()</code> function to mix the PSK into both the encryption keys and the <code>h</code> value.</p>
<p>Note that <code>MixKeyAndHash()</code> uses <code>HKDF(..., 3)</code>. The third output from <code>HKDF()</code> is used as the <code>k</code> value so that calculation of <code>k</code> may be skipped if <code>k</code> is not used.</p>
<h2 id="handshake-tokens">9.2. Handshake tokens</h2>
<p>In a PSK handshake, a <code>"psk"</code> token is allowed to appear one or more times in a handshake pattern. This token can only appear in message patterns (not pre-message patterns). This token is processed by calling <code>MixKeyAndHash(psk)</code>, where <code>psk</code> is a 32-byte secret value provided by the application.</p>
<p>In non-PSK handshakes, the <code>"e"</code> token in a pre-message pattern or message pattern always results in a call to <code>MixHash(e.public_key)</code>. In a PSK handshake, all of these calls are followed by <code>MixKey(e.public_key)</code>. In conjunction with the validity rule in the next section, this ensures that PSK-based encryption uses encryption keys that are randomized using ephemeral public keys as nonces.</p>
<h2 id="validity-rule">9.3. Validity rule</h2>
<p>To prevent catastrophic key reuse, handshake patterns using the <code>"psk"</code> token must follow an additional validity rule:</p>
<ul>
<li>A party may not send any encrypted data after it processes a <code>"psk"</code> token unless it has previously sent an ephemeral public key (an <code>"e"</code> token), either before or after the <code>"psk"</code> token.</li>
</ul>
<p>This rule guarantees that a <code>k</code> derived from a PSK will never be used for encryption unless it has also been randomized by <code>MixKey(e.public_key)</code> using a self-chosen ephemeral public key.</p>
<h2 id="pattern-modifiers">9.4. Pattern modifiers</h2>
<p>To indicate PSK mode and the placement of the <code>"psk"</code> token, pattern modifiers are used (see <a href="#protocol-names-and-modifiers">Section 8</a>). The modifier <code>psk0</code> places a <code>"psk"</code> token at the beginning of the first handshake message. The modifiers <code>psk1</code>, <code>psk2</code>, etc., place a <code>"psk"</code> token at the end of the first, second, etc., handshake message.</p>
<p>Any pattern using one of these modifiers must process tokens according to the rules in <a href="#handshake-tokens%5D">Section 9.2</a>, and must follow the validity rule in <a href="#validity-rule">Section 9.3</a>.</p>
<p>The table below lists some unmodified one-way patterns on the left, and the recommended PSK pattern on the right:</p>
<table>
<colgroup>
<col width="45%" />
<col width="54%" />
</colgroup>
<tbody>
<tr class="odd">
<td><pre><code>N:
<- s
...
-> e, es</code></pre></td>
<td><pre><code> Npsk0:
<- s
...
-> psk, e, es</code></pre></td>
</tr>
<tr class="even">
<td><pre><code>K:
-> s
<- s
...
-> e, es, ss</code></pre></td>
<td><pre><code> Kpsk0:
-> s
<- s
...
-> psk, e, es, ss</code></pre></td>
</tr>
<tr class="odd">
<td><pre><code>X:
<- s
...
-> e, es, s, ss</code></pre></td>
<td><pre><code> Xpsk1:
<- s
...
-> e, es, s, ss, psk</code></pre></td>
</tr>
</tbody>
</table>
<p>Note that the <code>psk1</code> modifier is recommended for <code>X</code>. This is because <code>X</code> transmits the initiator's static public key. Because PSKs are typically pairwise, the responder likely cannot determine the PSK until it has decrypted the initiator's static public key. Thus, <code>psk1</code> is likely to be more useful here than <code>psk0</code>.</p>
<p>Following similar logic, we can define the most likely interactive PSK patterns:</p>
<table>
<colgroup>
<col width="45%" />
<col width="54%" />
</colgroup>
<tbody>
<tr class="odd">
<td><pre><code>NN:
-> e
<- e, ee</code></pre></td>
<td><pre><code>NNpsk0:
-> psk, e
<- e, ee</code></pre></td>
</tr>
<tr class="even">
<td><pre><code>NN:
-> e
<- e, ee</code></pre></td>
<td><pre><code>NNpsk2:
-> e
<- e, ee, psk</code></pre></td>
</tr>
<tr class="odd">
<td><pre><code>NK:
<- s
...
-> e, es
<- e, ee</code></pre></td>
<td><pre><code>NKpsk0:
<- s
...
-> psk, e, es
<- e, ee</code></pre></td>
</tr>
<tr class="even">
<td><pre><code>NK:
<- s
...
-> e, es
<- e, ee</code></pre></td>
<td><pre><code>NKpsk2:
<- s
...
-> e, es
<- e, ee, psk</code></pre></td>
</tr>
<tr class="odd">
<td><pre><code>NX:
-> e
<- e, ee, s, es</code></pre></td>
<td><pre><code> NXpsk2:
-> e
<- e, ee, s, es, psk</code></pre></td>
</tr>
<tr class="even">
<td><pre><code>XN:
-> e
<- e, ee
-> s, se</code></pre></td>
<td><pre><code> XNpsk3:
-> e
<- e, ee
-> s, se, psk</code></pre></td>
</tr>
<tr class="odd">
<td><pre><code>XK:
<- s
...
-> e, es
<- e, ee
-> s, se</code></pre></td>
<td><pre><code> XKpsk3:
<- s
...
-> e, es
<- e, ee
-> s, se, psk</code></pre></td>
</tr>
<tr class="even">
<td><pre><code>XX:
-> e
<- e, ee, s, es
-> s, se</code></pre></td>
<td><pre><code> XXpsk3:
-> e
<- e, ee, s, es
-> s, se, psk</code></pre></td>