
This is excellent news. It's been a while since I was involved with cryptography but here are a few comments.
=============== class (Binary d, Serialize d) => Hash ctx d | d -> ctx, ctx -> d where outputLength :: d -> BitLength -- outputLength must ignore its argument blockLength :: d -> BitLength -- blockLength must ignore its argument hash :: ByteString -> d initialCtx :: ctx updateCtx :: ctx -> ByteString -> ctx finalize :: ctx -> d strength :: d -> Int -- strength must ignore its argument ===============
I'm not clear what strength means. Wouldn't that be something the user should know before using a particular algorithm? And what about when it gets broken e.g. MD5 and SHA1?
Instead I'm thinking of just forcing all cipher text to be a strict ByteString (below). Higher level operations, such as modes, then can use these and produce results :: lazy ByteString. If someone wants to build a Cipher instance for an algorithm that is fundamentally a stream cipher (vs a block cipher + stream mode) then this won't suffice, but I don't see any such algorithm in common use.
RC4? Maybe you should have separate classes for stream and block ciphers.
Crypto Types (type Salt = Nonce, newtype Nonce, BitLength...) Classes (Digest, Cipher, Asymmetric?) -- what would Asymmetric look like?
I think an examples would be very helpful. E.g. what would MD5 look like, what would DES look like, what would RC4 look like and what would RSA look like.
HMAC (hmac) Modes (cbc, ofb, cfb)
Presumably ECB as well.
Test Crypto Hash (KATs, Props) Cipher (KATs, Props) Asymmetric (KATs, Props) -- statistical tests for RNG if someone wants to do the work
There are quite a few tests in the crypto package which ought to be re-used. I might be tempted to do the statistical tests on RNG.
As has became too common, DRBG implements (or should implement) several features that could be done once for all time in a quality Crypto package. Features such as type classes for hashes and ciphers, an hmac definition, and a MonadRandom or something similar for random number generators that can fail. What existing code implements one or more of these features that should be able to use a central Crypto package? Happstack, SHA2, DRBG, SHA, hS3 (actually uses crypto despite [Word8] where ByteString should be used), hoauth, and a few partial-bindings to OpenSSL satisfy several needs.
I couldn't agree more. For information, the crypto package predates ByteString so really didn't have much option.
* Digest result types should be unique to the digest (a la pureMD5, contrary to SHAs use of "Digest" for 4 different hashs and contrary to SHA2s use of ByteString for all digests)
Agree. After all there is really no relation between an MD5 hash and a SHA1 hash.
* For Crypto-Algs pure Haskell code may be preferred but should not be used when costing over ~20% performance degradation when compared to other available implementations.
It's always been a disappointment to me that Haskell crypto performs so badly compared to C given that it should be possible to generate a nice loop from a Haskell fold. It would be great if this could be achieved.
* Keys should receive their own data type declarations (no cryptographic information floating around in a naked ByteString)
How will you handle algorithms that allow different key sizes e.g. AES?
* Data types should have Binary and Serialize instances.
I'm not clear why you would want this. I suspect some specifications will want data serialized in a specific way and then encrypted. It's not clear to me that this would necessarily be the way Binary had serialized it. Or have I missed the point?
* All code should be licensed BSD3 or equivalent
Agreed. I recall with the crypto package one of the authors wanted GPL for their particular alrgorithm implementation which may have put some people off using it.
Minimum quality for inclusion: A suite of KATs and some straight forward QuickCheck tests.
Definitely some published test vectors and at least encrypt . decrypt = id and decrypt . encrypt = id although these may have to be modulo padding. Having mentioned padding, I didn't see anything about it in your proposal.
Anticipating Concerns 1) (Re-) Implementing Crypto is hard / dangerous / a waste of time Most the benefit I aim for is in the common interface, not the algorithms. That said, the -Algs package can largely be a gathering of best-of-hackage with sanitized interface and continually-updated as higher-performance implementations come available. This might have been how the current "Crypto" package started, I don't know, but it is no longer in a sane or useful state.
The current crypto package was my attempt to take the existing (at that time) cryptographic algorithms and put them in one package with some semblance of a common interface. It is now woefully past its sell-by date. I think the benefit of a Haskell only implementation is a) you can see how they work b) no dependencies.
2) OpenSSL is fine For some people, yes - absolutely. Not just fine but insane to replace, seeing as it's (partly) FIPS certified. For other people, such as basically all the packages I listed above, it's obviously lacking something be it portability, footprint, or interface.
As an aside, I would have some concerns about using a Haskell crypto package for applications where failure could have serious consequences. For example, you probably want keys to be flushed from memory after they have been used. It's not clear what guarantees you would have that this had been done in a Haskell implementation. I'm hoping that FIPS certification of openssl would mean concerns like that had been addressed. I think aiming for this for a Haskell implementation would be further that anyone would want to go but there certainly ought to be a warning on the package about it's limitations in this respect. Once again, I'd like to say it's great news that you are taking this on. Dominic.