[Cryptography] Non-deterministic PRF as a MAC-and-Nonce for AEAD?

Jason Cooper cryptography at lakedaemon.net
Mon Jul 2 12:09:42 EDT 2018

Hi Alfie,

On Sat, Jun 30, 2018 at 01:50:47PM +1000, Alfie John wrote:
> On Mon, Jun 04, 2018 at 01:43:04PM +0000, Jason Cooper wrote:
> > > 
> > > Non-deterministic-deterministic functions is an oxymoron... i know :)
> > > 
> > > What I was trying to do was think of a way to get rid of the IV/nonce as
> > > a parameter to an encrypt function call. I've seen code from many
> > > organisation where the coder didn't know what to use for the IV
> > > parameter, so they used the static values from examples copied from the
> > > docs or even forum examples. Give a coder a footgun, and they'll use
> > > it...
> > 
> > Honestly, if the coder doesn't know to ask a cryptographer, or security
> > engineer when they encounter nonce generation for an API, that's an
> > education / experience problem.  A good manager should ensure the junior
> > coder is either a) not going near crypto, or b) is closely supervised by
> > an experienced crypto/security engineer when touching crypto.
> > 
> > The best / easiest solution to your problem isn't technical,
> > unfortunately.  It's human.  There's no substitute for experienced
> > developers mentoring junior developers while working in crypto and
> > security.
> I've been thinking about this for a while now...

Good.  ;-)

> My entire motivation for reducing parameters to calls was because the majority
> of dev shops, let alone at-home hobby projects, do not have an in-house
> security team. Even less likely an in-house cryptographer.

Very true.

> So this *really does* put cryptography out of reach for not only junior
> developers, but also experienced developers who haven't done the required
> reading to stay out of danger. This would probably be the main reason why there
> is so much roll-your-own out in the wild and broken code.

mmm.  That's a bit of a leap.  I'd say there's a lot of "roll-your-own"
for two primary reasons: 1) hobbyists are tinkering and learning,
hanging the result on github or whatever.  And 2) small shops have a
need to secure product(s) and do it in a less-than-advisable manner.

Nothing can be done about (1), other than avoid projects that don't have
an active community, established security bug handling procedures, and
multiple developers contributing / maintaining code.

(2) seems to occur for two main reasons.  The first is cost / speed.  An
established product suddenly needs to "add security", the cheapest /
fastest way to do so is to have the existing dev team do it.  And that
wasn't what they were hired for or experienced in.  The second reason
unfortunately seems to be arrogance.

There's also a third, which is just flat-out mistakes.  The PS3 DSA
nonce is a good example of that (I've never met the engineers who made
the mistake, so I'll presume mistake over arrogance ;-) ).

> libsodium does an awesome job to reduce mistakes and encourage best practices,
> but I think we can reduce the mental load even just a little bit more e.g by
> generating the nonce inside of crypto_aead_chacha20poly1305_encrypt() and then
> appending it to the ciphertext (just like it already does to the authentication
> tag). The first thing crypto_aead_chacha20poly1305_decrypt() would do is strip
> the nonce off the end and use it as it does now.

Well, sure.  But that's a protocol design decision.  Do you really want
the developer who needs to have their hand held regarding nonce
generation to be designing cryptographic protocols?

Regarding your example, it's much better if the nonce is pre-pended.
This way, you can do an early check for duplicated messages (use the
nonce as a unique message ID) and drop it before even trying to
decrypt/auth it if you already received it.  This is especially helpful
when an encrypted message spans multiple MTUs.

> (another cleanup would be to remove alltogether the nsec parameter...)
> Once you did this, look at the clean interface you have, especially in a
> language that understands string lengths:
>     my $ciphertext                  = crypto_aead_chacha20poly1305_encrypt($message, $additional_data, $key);
>     my ($message, $additional_data) = crypto_aead_chacha20poly1305_decrypt($ciphertext, $key);
> Going to be hard for a non-expert to use the above code incorrectly.

Yeah, that's the problem with interface abstraction.  Just because it
looks nice doesn't mean it's genuinely useful or helpful.  This
interface sucks because you've made a decision for me regarding
placement of the nonce in the message.  It also sucks for your target
audience because they still have to design a good protocol *with* the
bad placement of the nonce.

The unfortunate side effect of an api like the above is that a junior
developer is then never exposed to nonce handling, but now thinks they
know how to design cryptographic protocols.  That's dangerous.

A better solution (not applicable here, but same class of problem) is
Apple's recently announced Network.framework [1].  We can debate the
efficacy of the userspace network stack, but it puts the abstraction
right where it should be, at a very high level.  The developer is under
*no* pretense that they are "designing" or "implementing" TLS, bonjour,
DTLS, etc.  They are merely *using* those protocols.

And that helps us see where libsodium and friends (openssl, mbedTLS,
etc) fit in.  They are convenience libraries for _protocol
implementers_, not junior developers.



[1] Video: https://developer.apple.com/wwdc18/715
    Slides: https://devstreaming-cdn.apple.com/videos/wwdc/2018/715o2fzpdzzzf5f0/715/715_introducing_networkframework_a_modern_alternative_to_sockets.pdf
    Example (C): https://developer.apple.com/documentation/network/implementing_netcat_with_network_framework

More information about the cryptography mailing list