[noise] Resumption PSKs

str4d str4d at i2pmail.org
Sun Jun 17 18:47:31 PDT 2018


On 06/17/2018 11:19 AM, Christopher Wood wrote:
> On Thu, Jun 14, 2018 at 8:59 AM Trevor Perrin <trevp at trevp.net> wrote:
>>
>> On Thu, Jun 14, 2018 at 3:13 PM, Christopher Wood <christopherwood07 at gmail.com> wrote:
>>>
>>> On Wed, Jun 13, 2018 at 7:51 PM str4d <str4d at i2pmail.org> wrote:
>>>>
>>>> On 06/14/2018 08:18 AM, Trevor Perrin wrote:
>>>>> On Wed, Jun 13, 2018 at 4:40 PM, Christopher Wood <
>>>>> christopherwood07 at gmail.com> wrote:
>>>>>
>>>>>> On Tue, Jun 12, 2018 at 10:20 AM Trevor Perrin <trevp at trevp.net> wrote:>
>>>>>> So the following sketch derives an Additional Symmetric Key (ASK) "master
>>>>>> key" from HKDF, which can then be used to create chains at a later point.
>>>>>>>
>>>>>>> The idea is that we can use this during the handshake as well as during
>>>>>> Split().  We haven't used HKDF info before, but using it now means that
>>>>>> ask_master derivation just requires a single extra HMAC, since it can share
>>>>>> the HKDF-Extract step with the existing HKDF:
>>>>>>>
>>>>>>> # During handshake
>>>>>>> ck, k = HKDF(ck, ikm)
>>>>>>> ask_master = HKDF(ck, ikm, info="ask")
>>>>>>>
>>>>>>> # During split
>>>>>>> transport1, transport2 = HKDF(ck, zerolen)
>>>>>>> ask_master = HKDF(ck, zerolen, info="ask")
>>>>>>>
>>>>>>> # Either case
>>>>>>> create_chains(labels):
>>>>>>>   ask_chain1 = HMAC(ask_master, h || label1)
>>>>>>>   ask_chain2 = HMAC(ask_master, h || label2)
>>>>>>>   ask_chain3 = HMAC(ask_master, h || label3)
>>>>>>>   ...
>>>>>>>   delete ask_master

While implementing the above, I wondered why ikm was an input to
ask_master's HKDF, given that ck already contains it. Then I re-read the
preceding text :)

In order to be able to merge the two HKDF calls, the specification needs
to ensure that the function calls are ordered such that ck isn't
re-defined in between them.

This is my understanding of the full ASK proposal:

# During handshake (in both MixKey and MixKeyAndHash)
if enable_ask:
    ask_master = HKDF(ck, ikm, info="ask")
ck, k = HKDF(ck, ikm)

# During Split
# Can technically be arranged as before, but may as well be consistent
if enable_ask:
    ask_master = HKDF(ck, zerolen, info="ask")
transport1, transport2 = HKDF(ck, zerolen)

create_chains(labels):
    if not (enable_ask and ask_master):
        return Err()
    ask_chains = {}
    for label in labels:
        ask_chains[label] = HMAC(ask_master, h || label)
    delete ask_master

# Suggestions for better name welcome!
invoke_chain(label):
    if not (enable_ask and ask_chains and ask_chains[label]):
        return Err()
    ask_ck = ask_chains[label]
    temp_k1, temp_k2 = HKDF(ask_ck, zerolen)
    ask_chains[label] = temp_k1
    return temp_k2[..32]

I implemented the above here:

https://github.com/str4d/snow/tree/ask-chains

>>>>> Maybe an API vaguely like this?
>>>>>
>>>>> EnableASK():
>>>>>   - sets a boolean that causes ASK master keys to be derived, both during
>>>>> the handshake and at the end of it.
>>>>>
>>>>> InitializeASK(labels):
>>>>>   - Assuming ASK was enabled, and there is a non-empty ASK master key,
>>>>> derives a set of ASK chain keys from the ASK master key and the input
>>>>> labels, then deletes the ASK master key.  This could be called multiple
>>>>> times, including after the handshake and during it, and replaces any
>>>>> previous ASK chains when called.
>>>>>
>>>>> GetASK(label)
>>>>>  - Assuming ASK is enabled and initialized, returns the next key from the
>>>>> appropriate chain, and advances the appropriate ASK chain key, deleting the
>>>>> previous chain key.
>>>>>
>>>>> So if you don't EnableASK(), you don't pay any costs for deriving ASK
>>>>> master keys.  If you do enable it, they you can call InitializeASK/GetASK
>>>>> either during a handshake or after it, to get ASKs with the same level of
>>>>> security as the current encryption keys.
>>>> This API is very similar to how my current draft implementation (of the
>>>> previous proposal) on snow is organised. I'll massage it to implement
>>>> the above proposal, and see if there are any pain points.

The proposed HandshakeState API works reasonably nicely. Both
InitializeASK(labels) and GetASK(label) end up being trivial wrappers
around the actual logic in SymmetricState (as that is what controls the
Hash, at least in snow). Extending this to TransportState (so that users
can call InitializeASK() and GetASK() after into_transport_mode()) would
be trivial (along the lines of my previous key-chains branch).

>> So I think I'd prefer to have this as a zero-cost, opt-in extension that was written up in a separate doc, and which libraries and applications could explicitly choose to support.
> 
> That sounds good to me. Is there a preferred template for extension
> documents? I can put one together for this proposal, unless you or
> someone else wants to do so.

I'd be happy to help with this, as I have a vested interest in the ASK
part being settled in the very near future (I2P's upcoming Noise-based
protocol is being finalised in the next week or two). I shouldn't be the
only author though, as I don't have much to say about the resumption
PSKs part.

Cheers,
str4d

-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 833 bytes
Desc: OpenPGP digital signature
URL: <http://moderncrypto.org/mail-archive/noise/attachments/20180618/755e8ad5/attachment.sig>


More information about the Noise mailing list