I did not make my point well enough. I don't mind that crypto is inscrutable, that's fine (and unavoidable). Plenty other tech that I use every day is inscrutable (eg TCP, or HyperLogLog, or database query planners, or unicode text rendering, etc). I mind that resources about how to use crypto in software applications are often inscrutable, all the way down to library design, for no good reason. I mean stuff like:
- I learned the other day here on HN that SHA256 is vulnerable to a length extension attack, so if you want 256 bits of SHA goodness, you should use SHA512 and truncate it to 256 bits. This is terrible naming! Name the bad one "SHA-DoNotUse" if it's broken and this is known from the start. Why does it even exist?
- For the first decade or so of JWT library support, many verifiers happily accepted "alg: 'none'" payloads, letting attackers trivially bypass any actual verification. If you wanted JWT safely, you were supposed to know to tell the verifier to only accept the algorithms you were going to use when creating tokens.
- Hash algorithms have names such as "MD5", "SHA1", "bcrypt" and "argon2", ie meaningless character soup. I can't blame novice programmers for just using whatever hash algorithm is the default of their language's hash function, resulting in MD5-hashed passwords being super common until about a decade ago.
Security resources and libraries for programmers should be focused on how a thing should be used, not on how it works. That's what this book gets right (and what its page on elliptic curves gets so wrong).
Or, for another example, my favourite bit of crypto library design is PHP's `password_hash()` function[0]. They added it to the language after the aforementioned decade of MD5-hashed passwords, and that fixed it in one fell swoop. `password_hash()` is great, because it's designed for a purpose, not for some arbitrary set of crypto properties. The purpose is hashing a password. To verify a hashed password, use its brother `password_verify()`. Easy peasy! It's expertly designed, it supports rehashing passwords when necessary, and you don't need to understand any crypto to use it! I don't understand why all other high level programming languages didn't immediately steal this design.
I mean why can't all security libraries be like this? Why do most encryption libs have functions named "crypto_aead_chacha20poly1305" instead of "encrypt_message_symmetrically"? Why do they have defaults that encourage you to use them wrong? Why do they have 5 nearly identically named functions/algorithms for a particular purpose but actually you shouldn't use 4 of them and we won't tell you which ones? Do you want GCM or CCM? Or do you prefer that with AEAD? Do you want that with a MAC, and HMAC, or vanilla? Gaah I just want to send a secret! Tell me how to get it right!
I learnt all I know about crypto from online resources. It’s perhaps a question of taste, so let’s just skip that one.
It’s all good that you can easily hash a password in PHP without knowing what happens[0]. If you need to interface with another language/program however, it’s not as convenient anymore.
I am a fan of understanding what you are doing. Also in crypto.
[0]: But not really though. You need to trust that the PHP-team is competent and understand security. They don’t have the best track record there IMHO.
FWIW sha256 isn't broken, it's just you need to be careful when you're using it to generate HMAC. This follows what other comments are saying where you shouldn't use crypto primitives directly and use abstractions that take care of the rough edges.
Who do you think writes these standards? NSA loves footguns, the more footguns the better. Also these things are contextual, length extension is a problem for MAC, but not a problem for a password hash or a secret token.
Counterpoint: these crypto APIs are inscrutable for the same reason poisonous mushrooms are brightly coloured; they’re warning you away. It is extremely easy to mishandle crypto primatives, so if you’re reaching for crypto_aead_chacha20poly1305 and are confused it’s probably because you should be using a library that provides encrypt_message_symmetrically.
It just so happens that for PHP that library is the STL.
No you are still misreading the point. The complaint isn't that something like crypto_aead_chacha20poly1305 exists. It's that encrypt_message_symmetrically doesn't exist in most places.
It's perfectly imaginable for a library to exist that is designed for a specific use case (eg securely send a message to a recipient that already knows the key), is implemented across many languages and platforms, and defaults to the same algorithms and settings on all those platforms.
It's also perfectly imaginable for such a library to evolve over time, as insights in the security community improve. Eg it could add support for more algorithms, change defaults, etc. And it could provide helpful tools for long-time users to migrate from one algorithm/setting to another with backward compatibility.
It's hard to do, sure. But it rubs me the wrong way that the same people who keep repeating "don't roll your own crypto!" make it so needlessly hard for non-crypto people to use their work.
I think libsodium comes close to this ideal, but I still feel like it's pretty hard to navigate, and it mixes "intended for noobs" with "know what you're doing" functions in a single big bag. In a way, JWT is another thing that comes close, if only it was more opinionated about algorithms and defaults. Paseto (a JWT contender that, afaik, never made the splash I'd hoped it would) seems great, and I guess my entire rant boils down to "why doesn't something like Paseto exist for every common security use case?"
> I mind that resources about how to use crypto in software applications are often inscrutable, all the way down to library design, for no good reason.
I haven't read it, but I plan to, eventually. There's a book titled "Cryptography Engineering: Design Principles and Practical Applications" that could help you.
The character soup is fine. The problem is that people stop after that. Want security? Here, a bucket of character soup! Good luck!
There's nothing stopping library authors from choosing good defaults for well defined use cases. My beef is that mostly this isn't done, and often neither does documentation about security. That's what I like about this "Copenhagen Book": it gets this right. It starts with the use case, and then goes down to clear recommendations on how to combine which crypto primitives. Most resources take it the other way around, they start with explaining the crypto primitives in hard to understand terms and then if you're very lucky, tell you what pitfalls to avoid, and mostly never even make it to the use case at all.
- I learned the other day here on HN that SHA256 is vulnerable to a length extension attack, so if you want 256 bits of SHA goodness, you should use SHA512 and truncate it to 256 bits. This is terrible naming! Name the bad one "SHA-DoNotUse" if it's broken and this is known from the start. Why does it even exist?
- For the first decade or so of JWT library support, many verifiers happily accepted "alg: 'none'" payloads, letting attackers trivially bypass any actual verification. If you wanted JWT safely, you were supposed to know to tell the verifier to only accept the algorithms you were going to use when creating tokens.
- Hash algorithms have names such as "MD5", "SHA1", "bcrypt" and "argon2", ie meaningless character soup. I can't blame novice programmers for just using whatever hash algorithm is the default of their language's hash function, resulting in MD5-hashed passwords being super common until about a decade ago.
Security resources and libraries for programmers should be focused on how a thing should be used, not on how it works. That's what this book gets right (and what its page on elliptic curves gets so wrong).
Or, for another example, my favourite bit of crypto library design is PHP's `password_hash()` function[0]. They added it to the language after the aforementioned decade of MD5-hashed passwords, and that fixed it in one fell swoop. `password_hash()` is great, because it's designed for a purpose, not for some arbitrary set of crypto properties. The purpose is hashing a password. To verify a hashed password, use its brother `password_verify()`. Easy peasy! It's expertly designed, it supports rehashing passwords when necessary, and you don't need to understand any crypto to use it! I don't understand why all other high level programming languages didn't immediately steal this design.
I mean why can't all security libraries be like this? Why do most encryption libs have functions named "crypto_aead_chacha20poly1305" instead of "encrypt_message_symmetrically"? Why do they have defaults that encourage you to use them wrong? Why do they have 5 nearly identically named functions/algorithms for a particular purpose but actually you shouldn't use 4 of them and we won't tell you which ones? Do you want GCM or CCM? Or do you prefer that with AEAD? Do you want that with a MAC, and HMAC, or vanilla? Gaah I just want to send a secret! Tell me how to get it right!
[0] https://www.php.net/manual/en/function.password-hash.php