[noise] verifying received static remote key

David Wong davidwong.crypto at gmail.com
Fri Nov 3 05:54:42 PDT 2017

>> 1. have a `remoteKeyValid` boolean in the handshake state
>> 2. have split() make sure this boolean is set to true before returning correctly
>> 3. have initialization() set the boolean to true when the rs is set
>> 4. in any other cases, the implementers will have to find a way to set
>> this to true
> You mean initialization() sets it to false, I think?  And split()
> checks that rs is either empty or the boolean is true?

If rs is set, then you trust the other side so isRemoteKeyValid should
be set to true : o
And yes good idea, if rs is empty then no need to check if the boolean
is true so that other unauthenticated patterns can work!

> You're still assuming that verification always completes before
> split().  I could imagine other implementations (in particular if
> verification is a separate thread doing online lookups).

If split completes and verification still hasn't been done, then
aren't you dangerously handling usable (un)secure channels back to the

> Let's think about this more, and revisit once we're editing another
> spec revision.  I like keeping the pseudocode simple and focused on
> crypto logic, so I'm not super-excited about a "placeholder" boolean
> that doesn't do anything except serve as a reminder.
> Adding a bullet in "Application responsibilities" might be a
> lighter-touch way of adding more emphasis to authentication.

Pushing important things to later sections can be dangerous, and I
like the idea of having placeholders that the developers have to fill
in order to make the protocol work. But I'm realizing that validation
of transmitted keys can be made in many different ways and that
definitely complicates having a specific place in the spec/algorithm
where you would enforce that. For the moment I'll leave you with my
suggestion of having this boolean that needs to be set to true in
order to use the post-handshake secure channels.

As an additional feedback, here is how I'm planning to make it work in
my implementation:

1. I am requiring that a PublicKeyVerifier() callback is passed when
using patterns like Noise_X* and Noise_*X.
2. If such a callback is not passed as an argument (for such patterns)
then the application refuses to work.

(For testing, you could just use a PublicKeyVerifier that always
returns `true`, but the documentation will strongly warn against that)

3. in ReadMessage() after DecryptAndHash(): if `isRemoteKeyValid` is
set to false AND `rs` is set, call PublicKeyVerifier()
4. PublicKeyVerifier() is called on `rs` and the received payload
which could be a proof (maybe a signature (inside a certificate))

(This is assuming the "proof" might come from the payload that came
along the remote static key, not from payloads that might have come
before that.)

5. If the synchronous callback returns false, the handshake is aborted
6. Otherwise Split() is called and the handshakes completes.
`isRemoteKeyValid` is set to true.

Additional thoughts:

* If you need something asynchronous, you can run your handshake
asynchronously and make sure that a `handshakeCompleted` is set to
true before Writing or Reading on the post-handshake secure channels.
* For other patterns, a peer can check if the other side has been
authenticated by checking the `isRemoteKeyValid`.

Hope that helps!

More information about the Noise mailing list