Botan: Crypto and TLS for Modern C++
github.com
github.com
Or
which battle tested applications exist today using crypto+, that illustrate it's a better choice than what sofar held up under libsodium (which is a lot)?
Especially if you are directly comparing against libsodium and Daniel Bernstein who is a widely respected engineer whose work is widely used and heavily reviewed.
libsodium doesn't put any metadata (including library and/or construction "version") in any its results, like boxes, keys, etc. So, there is no mechanism for versioning and backward compatibility.
So, it is so-so Ok for real time communication between two installations of software product (and even then two ends could have different versions of software and/or library used!), but it is not suitable for long-time storage or communication between different systems.
You store your "boxed" backup [keys] on disk. You want to read it 15 years later. How could you be sure, that libsodium didn't change algorithms in these 15 years? You need exactly same version of library that created this "box".
And even application which is aware of this problem could not properly solve this: it could record & check libsodium version and refuse to work with "old" data, but how could it enforce future libsodium to read product of old one, as there is no any provision for this in API?
libsodium is too simple for many tasks.
New API like secretstream includes algo into API names, so, I hope, it is "stable forever", but it is rather new feature.
Basic APIs like "crypto_secretbox" are "black boxes" and there are no any guarantees spelled out. Algorithms are mentioned in documentation, though.
What will do libsodium if used algorithm will be broken? I don't know.
Means you'd have to find a compiled lib with the exact same settings to decrypt them though.
In 12 years, libsodium never had any breaking API changes, even though I don't like the NaCl API much (especially usage of `unsigned long long` instead of `size_t` for sizes).
API stability is something I'm very committed to, in all my software. APIs can always be improved. But from a developer perspective, a suboptimal but stable API is far better than something that requires changes to all your applications every time the dependencies are updated.
I found its modern "style" pleasant to write code for, and easy to integrate with good docs. That said, I did notice the large number of algorithms as others have pointed out, and I'm not sure I'd use it for more serious purposes when libsodium is well-established. It certainly wouldn't be an obvious choice.
But to quickly add support for common hash algorithms in a small project, I thought it was a good option and enjoyed its API design and simplicity.
sic transit gloria mundi or something. :)
The essential question is whether he would be able to use OpenSSL implementation without changing internals of Botan or his own zero knowledge crypto system implementation. In modular libraries this is less of an issue as itself generally implies working with abstract groups and writing wrappers or implementations outside.
If you assemble your own system out of random components found on the web, there is a good chance that one of those components will either disappear or stop being supported. A single monolithic library is much likely to survive once it gets a critical mass of developers.
Regarding supply chain attacks one of the important points is to establish consensus on dependency versions and their hashes via distributed replication or transparency logs (like in go). The big monolith then does not offer any advantages in this aspect.
(2) How come "simply check the specs for inputs and outputs to remain unchanged" helps with trustworthiness or gives _any_ assurance of the incorrect implementations? (unless it's agda/coq, but we are not talking about them). The specs can say whatever, and yet the program might full of bugs.
(3) How do you select a library in an area you are not familiar with? It seems you know cryptography well, so let's choose a different topic - what would you examine to find, say, good audio capture library, or a good OpenGL wrapper? For me, I'd look at popularity (by number of reverse dependencies in my repo, mentions on the web, or github stats); liveness (activity in repo and mailing list, open/closed bugs); general quality (commit history, CI logs if they are public, etc..). All of those would be _vastly_ easier with a single large repo vs tons of smaller one.
(4) Think of few supply chain compromises that come to your mind. How many of those would be prevented by "distributed replication or transparency logs"? I've thought of xz compromise, left-pad pull and Marak's colors.js. _None_ of them would be fixed by "consensus on dependency versions and their hashes". All of them would be fixed if people just kept packages bigger, so that every one has actual CI, release team, and so on.
On the other hand libraries for hashes, encryptions, cryptographic groups, pseudorandom number generators are much more testable on their own. One can take specs and other engineered tests and check that inputs corespond to outputs. The rest is solved via memory safe languages and common sense of not having tests commented out or made special cases for them.
> How do you select a library in an area you are not familiar with?
By either having popularity or by being able to read the code and seeing that there are clear expectations communicated to the user via API or documentation. I wouldn’t consider security much when chosing user facing libraries much, but for network facing libraries popularity would be essential to me.
> All of them would be fixed if people just kept packages bigger, so that every one has actual CI, release team, and so on.
A bunch of small libraries can still be maintained by a large organization. It does not make difference if the are installed seperatelly. However modularity does add the benefit of being able to break into complexity to contributue and also gives more transparency for new users who can see what parts of the library are actually widely tested in the production and which are not and need more care.
Regarding xz, the lesson here is that one should not use programming languages where it’s limitations are deferred to preprocessors and complex build systems that only few can read. Similarly lesson from Log4j is that readability and language base features like string interpolation is much more preferable to having simply popularity.
I know the layered network protocol design is flawed, but I really like the elegance of the old design where TLS/IPSec/DTLS/WireGuard is just an option you pass to connect() rather than a library you need to pull in and maintain. Windows has something like that and it feels like somewhat of a missed opportunity for the internet.
I think an opaque layer that lets you poke at internals when you decide you know what you're doing is the way to go. Eg. About 10 years ago I implemented certificate pinning atop a 1990s Microsoft API... you can use the api the "dumb" way and not touch it, and then optionally you can easily switch to implementing features the API vendor never envisioned.
And it is only way to performant TLS.
Bulk ciphering is pretty inexpensive since Intel Haswell (2014) where there was a big improvement in AES-NI, but the load and store around ciphering static content that could otherwise avoid a trip through the CPU can be a significant bottleneck at 100gbps+. I'm sure there are measurable gains from TLS offload in other situations, but it's only critical for static content at high bit rates.
- ECDSA with P-256 for signature - ECDH with P-256 for key establishment - AES_128_GCM for data encryption with SHA-256 for hashing and KDF
But its not obvious that the same is true for a library.
The RustCrypto project breaks each algorithm into its own crate, while botan implrments everything.
Its not obvious to me that one approach is clearly superior to the other.
Yes, if you want a cryptography library for a greenfield project, then you want something tiny and simple and secure (e.g., libsodium). For other things you'll want a more complete library.
I assume the parent is actually a Rust programmer, or at least, intend to use this from Rust, so, yeah, plain Rustls is an obvious choice. https://crates.io/crates/rustls
As Thomas Ptacek emphasised above, despite Botan saying it's "Crypto and TLS" if you think you might need some sort of "Crypto" rather than you just want to speak TLS, such libraries have way too many knobs and switches you don't understand, as does OpenSSL. The whole point of libsodium and similar libraries is to not have switches you don't need. Spell out a use case and deliver exactly what's needed for that use case, nothing else, no switches, no "optional" features.
Rust has a libsodium wrapper, which is especially useful if you either trust libsodium particularly or you have experience with those APIs, and also some similar but Rust flavor approaches where they don't give you all the knobs and switches just an API that makes sense for the specific use case you chose from their list - either the library is correct or it's not, no "What kind of idiot pushes the red button?" problems.
It nicely wraps BoringSSL, and is actively maintained. The API is the most pleaseant of all crypto APIs I've seen in Rust.