I disagree. I think Cryptol is a much smaller language, so it should be much easier to implement an ergonomic FFI system or even a Haskell “transpiler” that does fully use predictable low level features of GHC (e.g. unboxed primitives).
A big problem with that approach is that Cryptol is only a functional (not in the sense of functional programming, but in the sense of “specifies which outputs come from which inputs”) specification language, and many uses of cryptographic primitives have additional nonfunctional requirements that just can’t be expressed in it. An “FFI” would be easy enough - simply rig up a wrapper around the Cryptol interpreter - but that wouldn’t really meet the needs of most people who need crypto.
That’s why libsodium bindings are an excellent bet
No PQ support, and (AFAIK) none planned.
If we wanted to promote Haskell as the language in which to write cryptography algorithm (and on which other languages would bind), we would need to drastically improve the FFI story, tooling, and get many more cryptographers to learn Haskell
It seems that the problem is not with the FFI per se - but with the Haskell compiler and RTS unable at this time to satisfy the necessary “crypto-professional” requirements. Some cryptographers here (especially those interested in formal proofs and such) do know Haskell, others switched to languages like Agda and Coq…
I personally (probably) wouldn’t consider binding to Haskell crypto implementation from other languages - they already have (or likely to get in the near future) either “native” implementations, or FFI access to C-based. And, more than likely - those implementations already exhibit the required properties that seem unattainable in the current Haskell.
DSL - I was going to discount this idea, until I saw the sponsor of that project. I still don’t like it, but probably/hopefully they know what they’re doing, and why.
Yeah, I didn’t mean to single out Cryptol specifically. I did acknowledge that it was probably not a perfect fit due to its focus on specification and not implementation. But I think a small DSL like Cryptol that does allow you to take into accout the nonfunctional requirements would be ideal. Maybe it would need to be more imperative like C, but it would certainly not have to be as complicated and unsafe.
I think that a cryptography-implementation-focused DSL (esp. EDSL) in Haskell is a great research project that I hope someone undertakes and finds success with. And hooking it up to Cryptol for verification of functional properties would be pretty cool.
There is now a fork of cryptonite called cryptol: using crypton by kazu-yamamoto · Pull Request #931 · yesodweb/wai · GitHub
crypton. Cryptol is a DSL for cryptographic algorithms by Galois, Inc.:
It looks to me that the Z-Botan package at the moment could be the closest candidate to potentially become a “proper” way to do cryptography in Haskell (and be able to replace cryptonite/crypton). Brief look at the hackage documentation suggests it’s mostly feature complete.
The only problem is it currently depends on the Z-Haskell project that tried to do what foundation
also did and it seems it didn’t work out (which makes sense, attempts to start from scratch like this are IME doomed to fail unless you have a significant backing, both financial and marketing wise).
So “someone” would need to fork it, rip out the Z-IO
and Z-Data
bits and replace them with the standard deps like bytestring
etc. I don’t know how much work that would be. I would attempt this, but my time budget for OSS has run out
How does it compare to libsodium bindings/wrappers, given that Botan is a C++ library?
From a brief look I had it looks like Botan can be used to implement everything cryptonite/crypton does, I don’t think libsodium can do that (see Comparison of cryptography libraries - Wikipedia, libsodium is missing a lot).
Also, Botan is BSD2, libsodium is GPL3 (it’s not, I looked at the wrong thing).
The best course of action would probably be to make crypton
use Botan for everything underneath over time.
Last audit is a while ago, but doesn’t sound too bad.
Also, Botan is BSD2, libsodium is GPL3.
Can’t see GPL3 in there.
That would be a showstopper indeed.
I took a brief look, and on the surface it doesn’t look too bad - a lot of the changes would need to occur in Z.Botan.FFI
but aside from a few things like the CBytes
type, most of the Z-stuff used here appears to be a lot of type-aliases and re-exports.
More concerning is the issue that it relies on an out of date fork of botan pulled in via git submodule using a Custom
build-type script - it is 3 years out of date, and would need to be replaced with a maintained dependency.
I may not be the best candidate for the job, but I have written my own bindings to libsodium
before, back before cryptonite
existed (and saltine
didn’t provide the APIs I needed), so if time permits, I may give it a go. No promises though
Right, it’s ISC which is equivalent to BSD. Sorry for the confusion, I must’ve looked at the wrong thing.
Indeed, I’m not sure why the author did this. Botan package (at least on Arch Linux) supplies a .pc
file, so using external dependency should be easy with pkgconfig-depends
.
After diving into this yesterday, this is my reaction to many things regarding this library. I did not accomplish much of anything aside from gathering information, but here is what I have discovered so far:
-
Some things like JSON / Text / Vector aren’t re-exports like I initially thought - they are all custom types (yikes!)
-
Most uses of
Text
are used likeCB.fromText . T.toText
or to derive their customZ.Data.Text.Print
class, so I don’t think pose a large problem per se and I think it could be swapped out forData.Text
. -
All uses of
JSON
are just used for deriving instances of it, so they can probably be ignored entirely. -
All uses of
Vector
are forZ.Data.Vector.Bytes
which is actually a thin wrapper aroundPrimArray Word8
- we could convert this to useByteArrayAccess / ByteArray
constraints possibly, but we’re going to have to deal with it. Ditto for another typeCBytes
, which is a direct newtype aroundPrimArray Word8
. -
The
Z.Data.CEBytes
is intended for constant-time equality checks, but it is also a newtype overPrimArray Word8
- this might be replaceable with anewtype ConstEq ba = ConstEq ba
withinstance (ByteArrayAccess ba) => Eq ba where (==) = constEq
or something. We’re going to have to deal with it same asZ.Data.Vector.Bytes
-
Z.IO.BIO stuff is unnecessary / experimental and can probably be jettisoned / ignored entirely.
-
Some stuff in
Z.Foreign
gets a lot of use egwithPrimVectorUnsafe
so we’ll have to be careful bringing in or replacing it.
There’s also some questions of how far do we want to go, beyond our initial focus on stripping out the Z-*
dependencies. We can conceptually look at this as two libraries - there is the low-level botan
bindings in the Z.Botan.FFI
file, and the higher-level crypto
interfaces in Z.Crypto.*
. We should think about what we want the crypto
interfaces to look like.
- A prime example of this is how this library uses large enumerations like the
HashType
andCipherType
data types to represent all algorithms as one type. However, this is entirely the choice of theZ
library author, and is not required bybotan
itself. It is also awkward and limits type-level programming compared to functional dependencies with a witness / proxy a lacryptonite
, or associated type / data families that I’ve written in the past.
I’m sure there will be more, but these are my major thoughts after getting it to build, and rifling through everything a bit yesterday and this morning.
I’ll keep this thread updated as needed.
Edited to differentiate CBytes
and CEBytes
Yeah, that’s a good question. Considering that crypton
seems to have been well-received and a few packages already switched to it, a good option would be to have a low-level package for botan
bindings and then use this package to switch crypton
to use botan
for everything it does over time.
This approach has significant advantage over coming up with a new library since tons of existing dependencies would directly benefit without having to switch to a new API and improvements could be incremental, i.e. make crypton
use AES from botan
, then use hash functions from botan
etc.
botan
supports a ton of cryptographic primitives, so presumably crypton
could use it for everything it does. This needs double checking though.
And since botan
also implements TLS protocol, presumably the tls
package could also be made to use it in the end, which I think would put the Haskell ecosystem in a comfortable place cryptography-wise.
That’s obviously a significant undertaking, but perhaps Haskell Foundation could help here @david-christiansen?
Perhaps! It would be based on a cost-benefit analysis, of course. This is the kind of thing that our proposals process is really built for - to help explore the actual costs and benefits of this kind of thing, and enumerate just what kind of help is needed.
An update on some brief hackery: On closer inspection, I realized I never had actually gotten it to build properly, but I’m not sure it really matters because I discovered many more issues while fiddling around with the Z-Botan
repo knocking out pieces to get it to work.
-
It uses an older version Botan 2, not Botan 3.
- Botan 2 can’t build on M1 mac because it predates the architecture and doesn’t recognize it
- Building The Library — Botan
- [Mac] Fail to build universal (fat) library for arm64 and x86_64 on M1 Mac · Issue #2896 · randombit/botan · GitHub
-
Z-Botan
is itself woefully out of date, even for its ownZ-
dependencies- It has strict
primitive (>=0.7 && <0.8)
and time(>=1.11 && <1.12)
dependencies - It needs
Z-Data 8.6.1
andZ-IO 8.1.1
, which are themselves outdated - It needs
ghc865
to get versions aligned.
- It has strict
-
Botan
setup / configuration is done viaconfigure.py
script- This script is 3400+ lines of python.
-
Z-Botan
calls this during the customSetup.hs
phase (and is a tad inscrutable because there are no comments). -
args = configureFile:"--amalgamation":"--disable-shared":hostFlag
is where we can inject the arguments to control botan’s build - Building The Library — Botan
These issues are severe enough that, between the need to strip out the Z-IO
and Z-Data
plus the need to update to Botan 3
, it might be better to start over with new bindings in a new project rather than try to cajole Z-Botan
back to life.
My next move is probably to see if I can get Botan 3
building solo, then try and integrate it into a fresh project, and then pick a subset of the bindings (eg, hashing) and try to implement them using Z-Botan
as a reference. This should tell us a lot about the viability of this trajectory, without having to update dozens of modules with hundreds of bindings all at the same time. If it goes well, we can continue pulling bindings over from Z-Botan
until we are done.
I am of course open to suggestions, but will otherwise continue on this course as time permits.