Update: Work on botan
recommences!
Now that the lower level libraries are more or less stable, I’ve had the pleasure of being able to focus back on the high-level botan
library, with its idiomatic and pure-as-possible interface. I have made several large strides in the background while writing the latest monthly update, since I am finally getting to work a bunch of fun stuff that had to be put off until now.
First off, Botan.RNG
has been strongly refined, and use of random generators has been ensmoothened with the introduction of the MonadRandomIO
monad and the RandomT
monad transformer (which is an instance of MonadRandomIO
). Getting this right is essential - because of the many functions that rely on it, it affects the ergonomics of the rest of the library.
Now, there are two ways of accessing randomness:
- Directly using an
RNG
context - Implicit access to an
RNG
context usingMonadRandomIO
Direct usage is the old way, and it pretty much looks like this:
main = do
rng <- newRNG Autoseeded
addEntropyRNG "Fee fi fo fum!" rng
reseedRNG 32 rng
x <- getRandomBytesRNG 12 rng
print x
Implicit access to an RNG through MonadRandomIO is the new way. IO
is itself a convenient instance of MonadRandomIO
that
uses the systemRNG
:
main = do
addEntropy "Fee fi fo fum!"
x <- getRandomBytes 12
print x
It is also possible to use the RandomT
transformer or RandomIO
monad (currently a typealias for ReaderT RNG
and ReaderT RNG IO
respectively):
main = do
rng <- newRNG Autoseeded
flip runRandomIO rng $ do
addEntropy "Fee fi fo fum!"
x <- getRandomBytes 12
liftIO $ print x
I’m not exactly sure how MonadRandomIO
will change under the hood (RandomT
is probably going to become a newtype at least) but basically, any functions that need random values, or that take an RNG as an argument, can now be MonadRandomIO
instead - this should make it really easy to generate keys and whatnot, and reduce the number of arguments in general.
For example, with MonadRandomIO
, bcryptGenerate
now only takes 2 parameters!
main = do
dg <- bcryptGenerate "Fee fi fo fum!" Fast
print dg
Secondly, all of the algorithm name constants and functions have been completely vertically integrated, from botan-bindings
to botan-low
to botan
. This makes using a given algorithm much easier and more consistent no matter what level of library you are using.
Thirdly I’ve created a KeySpec class for a better representation of what keys sizes are available for a given primitive. Its similar to the KeySpecifier
from crypton
. I’m probably going to rename it.
Fourthly, in the Botan C FFI, you have to initialize a cipher or hash or mac context in order to query its sizes, but this data is constant and initializing a context is not free, so I’ve been writing pure / static versions of key spec / block size / tag length / other size query functions so that I can just say:
let bsz = hashBlockSize MD5
Instead of:
bsz <- do
ctx <- Low.hashInit (hashName MD5)
Low.hashBlockSize ctx
This is just overall a much better experience, as we can get algorithm parameters by referencing the algorithm itself instead of referencing an initialized context. It is really helpful for generating keys even if you aren’t looking to use them immediately.
Lastly, CI is working - at least for MacOS. I need to test manual Botan C++ installation for Linux, as I’ve determined that botan 3.x
packages haven’t been published yet, but that seems to be the only issue at the moment!
As always, these changes have been pushed to the repo