Crypto relies on number theory and a complexity theoretical assumption that N!=NP (i.e. that there exists one-way/trapdoor functions).
I think it is opaque by the very nature of how it works (math).
Understanding finite fields or elliptic curves (integer groups really) made me able to grok a lot of crypto. It is often a form of the discrete-logarithm problem somehow.
- 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
I don’t agree with you for various reasons.
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.
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.
It just so happens that for PHP that library is the STL.
How should e.g. a C++ program know how PHP encrypts something through “encrypt_message_symmetrically”?
Embedded machinery has other needs and resources than e.g. online banking. So we can’t just have one algorithm for symmetrical/asymmetrical crypto.
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?"
(Note that I disagree that "HMAC-SHA256" qualifies as an abstraction. It's just more character soup)
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.
Yes
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.