Wrapping Libraries Redux
Created on July 18, 2025
Last updated on July 18, 2025
So it seems that I have a problem with wrapping libraries for usage in .NET Core. It's not so much a problem as it is an addiction. I just love going a step further than other people do- that's not to denigrate the work of others, just to say that I try to expose all the knobs and I don't hide functionality that might be tricky to wrap.
I started with random number libraries, then moved on to crypto libraries (and before you say it- this isn't rolling my own; this is using known-good C/C++ libraries and exposing their functionality in .NET Core- there's a big difference), and now I started with compression and decompression libraries (starting with Meta's Zstandard).
Sometimes there are existing wrappers out there (see above) and sometimes there's not, or sometimes they are packaged in different ways or as parts of larger packages. What I am doing is keeping things small and separate. Whereas someone might wrap libsodium which has chacha20 support along with Argon2 and Scrypt, I do a chacha20, and I do an Argon2 and a separate Scrypt. Why? Because each one deserves attention to make it the best library it can be, not an afterthought in a larger library. It also allows me to learn the intricacies of each library (because I am building them for 4 platforms each).
That's another area that I'm big on- making sure we have full platform coverage (or at least win x64, linux x64, macOS x64 & arm64). This allows me to really understand these libraries and how they are optimized and how to produce optimized builds. An unfortunate example is when I was working on the AEAD library which is an implementation of chacha20+poly1305 (RFC 8439), I discovered that my initial chacha20 and poly1305 might not have been as optimized as they should have been, and internal dispatch from the BoringSSL source might have been using non-SIMD optimized code. So I went back through with a fine-toothed comb and forced the issue to make sure the libraries were optimized. It's things like that that I'm not sure other library providers are doing. Some do, many don't is what I've seen in my informal analysis.
Anyway, I like wrapping well-known libraries for .NET Core because I feel like having those well known libraries makes the ecosystem more convenient to new users and it helps the ecosystem grow. The more people that use .NET Core, especially outside of the corporate ecosystem, the more the ecosystem will accomodate those users. It's a self-reinforcing cycle.
So what have I done so far? Too many rngs to name (lol), ChaCha20, Poly1305, ChaCha20+Poly1305 (RFC 8439), Scrypt, Argon2 and ZStandard. I also implemented my own Blake2b. Why? There wasn't a library other than the original, un-optimized distribution, and since it's a hash algorithm with published known-good vectors, I felt like I could do it correctly. Everything else is a wrapper of a well-known library (mostly boringssl from Google).
Do I feel like this is cheating? No. I work on other projects too, and if there had been Nuget packages that met my needs I wouldn't have done the wrapping. I figure if I need it, someone else does too, so we might as well kill two birds with one stone.
So here's the latest addition to the family, Meta's Zstandard compression (complete with streaming & dictionary support): dotZstd Github
If there's something (reasonably sized) that you'd like to see made available in the .NET Core ecosystem, let me know and I'll see what I can do.
Take care and happy coding,
padawan, 2025