<div dir="ltr"><br><div class="gmail_extra"><br><div class="gmail_quote">On Tue, Jan 17, 2017 at 4:19 AM, Trevor Perrin <span dir="ltr"><<a href="mailto:trevp@trevp.net" target="_blank">trevp@trevp.net</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">They basically separate the chaining key (ck) into 2 separate ck, and<br>
do periodic HKDF updates to get a new ck, k. That's a secure design<br>
(assuming HKDF is a PRF), and nicely reuses the HKDF key chain.<br>
<br>
It does mean storing two extra ck values during the transport phase.<br>
The Noise spec reserved the high nonce value, with the alternative<br>
idea that we could generate extra secret values from that, if needed<br>
(key updates, resumption PSKs, or a catch-all like TLS exporters).<br></blockquote><div><br></div><div>I like the Lightning method too. My Rekey() function suffers from roll-forward problems: if the key for a segment of the session data is compromised, then all future segment keys can be easily re-computed. And if the encryption algorithm becomes vulnerable to a known-plaintext attack in the future, the segment keys can theoretically be rolled backwards. Oops.<br></div><div><br></div>Lightning's use of an extra chaining key and HKDF fixes these problems in a fairly elegant way. At the cost of some extra state for a direction: HASHLEN bytes for ck and 32 bytes for k. The main issue I have is the need to store the raw k value between segments. With the current Noise design, the k value can be discarded after the call to InitializeKey() because it has been transformed into a key schedule.<br><br></div><div class="gmail_quote">Before looking at the Lightning spec, I was thinking of ways to fix Rekey(). The best I came up with was to generate a secret value during Split() that was combined with the output of EncryptWithAd() using HMAC or HKDF to generate the new encryption key. Essentially this secret value would play the same role as the rolling ck' values in Lightning.<br><br></div><div class="gmail_quote">The two methods could be combined as follows:<br><br></div><div class="gmail_quote">Split():<br></div><div class="gmail_quote"> - k1, k2 = HKDF(ck, zerolen)<br></div><div class="gmail_quote"> - s1, s2 = HKDF(ck, onelen) // onelen is a 1 byte sequence of zeroes<br><br></div><div class="gmail_quote">Rekey(s): // secret value for this direction, either s1 or s2<br></div><div class="gmail_quote"> - temp is set to the output of encrypting a block of zeroes with EncryptWithAd() and the special 2^64 - 1 nonce.<br></div><div class="gmail_quote"> - s, k = HKDF(s, temp)<br></div><div class="gmail_quote"> - InitializeKey(k)<br></div><br><div class="gmail_quote">Each direction needs an extra HASHLEN-sized "s" value in the permanent state to assist with key rotation.<br></div><div class="gmail_quote"><br></div>Cheers,<br><br></div><div class="gmail_extra">Rhys.<br></div></div>