I’m generally not a fan of coupling cryptographic libraries to language or stdlib release cycles. If there’s a bug in the crypto library, you wanna be able to push a change as quickly as possible, and bumping a language’s version is not typically ideal.
This bit of sample code jumps out at me (as a total crypto noob, pretty nervous about writing any crypto-related code):
$nonce = random_bytes(24);
$ciphertext = sodium_crypto_box($plaintext, $nonce, $message_keypair);
Would it make sense for a safe-defaults-oriented crypto api to generate $nonce by itself, and return it along with the ciphertext? That way I can’t screw it up by re-using it or using something predictable.
Meta: I can’t stand “first” claims. Title suggest: PHP 7.2 Adds Modern Cryptography to its Standard Library
PHP 7.2 Adds Modern Cryptography to its Standard Library
The nonce does not necessarily have to be randomly generated, and in fact it can have some semantic meaning if you want it to. For example, in “Practical Cryptography,” Schneier and Ferguson suggest using the message number plus some additional information as a nonce, assuming the messaging system has the concept of a message number. The most important aspect of a nonce is that it is used only once (hence, “Number used once”), and does not necessarily have to be high-entropy. If you want it to have some kind of meaning, then having the crypto library choose it for you is not always what you want.
Just to be pedantic and because I’m taking a break at work:
I’m like 90% sure that the etymology isn’t “Number used once”, but rather from the Middle English “nonce”, meaning “current occasion”, via the linguistics term “nonce word”, meaning a word that is expected to only occur once.
Why yes, I am fun at parties.
I won’t argue with you at all, as I had absolutely no idea what the etymology of the word is :). Assuming you are right, I still find my mental link of “nonce” == “number used once” useful because it helps me to remember the actual purpose behind the use of the value.
No, no, your version is immediately more useful. I just like linguistics. :)
Oh, interesting! That makes me feel better, so hopefully the docs will include similar guidance :)
I wonder then, if sodium_crypto_box is stateful, and will refuse to work if $nonce is reused? I didn’t find relevant libsodium docs with a quick search, but I think I just don’t know the right keywords.
Secretbox is an abstraction of the concept: “given a key x nonce pair, push data into a thing and get the encrypted data on the other side”. An application could potentially have thousands of secretboxes at once and they really shouldn’t know anything about each other.
key x nonce
Think of a secretbox being stateful the way an iterator is: if you give it all the same parameters its going to replay exactly the same behavior.
Finally, the nonce space can be very large (depending on the cartographic algorithm being used and what it specifies). In the case of Salsa20, it is 64 bits. It isn’t realistic to track a space that size. (When using libsodium you should really stick to the symbolic constants, like crypto_secretbox_NONCEBYTES, and not, say, 24.)
As long as you never use the same key x nonce pair, you’re fine. As @untothebreach said, using an application invariant that guarantees the nonce will be unique is often sufficient. For many algorithms, the nonce space is large enough to randomly generate the nonce each time and not worry about it (if that sounds fishy to you, recall that the nature of cryptography is to make bad things really unlikely and then accept that it’s fine).
Does “once” in this case mean once, ever. Or once in this application of the algorithm? Is some randomness required?
But to go back to @phil’s point, it sounds like a safe default would be to generate the nonce in the library. But you can always provide your own.
Once with the same key
PHP: The First Programming Language to Make md5('240610708') == md5('QNKCDZO') Return True
md5('240610708') == md5('QNKCDZO')
It’s not as bad as Java’s “let’s override + to do string concatenation but leave == on strings to do object identity comparison…”
It’s not as bad as Java’s …
Well, yeah. I don’t expect PHP to be understandable. :)