The Jabberwolk has moved
April 29, 2013
I’ve moved my blog to tommd.github.io which currently includes my exploration of image processing as well as a run-down of commsec-keyexchange.
Clean and reinstall those GHC packages!
November 18, 2011
function ghc-pkg-supercleaner() { b="0" for p in `ghc-pkg check $* 2>&1 | grep problems | awk '{print $6}' | sed -e 's/:$//'` do echo unregistering $p; ghc-pkg $* unregister $p; cabal install $p; b="1" done if [ $b == "1" ]; then ghc-pkg-supercleaner fi }
HacPDX II – More Hacking!
July 7, 2011
HacPDX II is set for July 22-24, 2011 (Friday – Sunday)! Be sure to register or else, exactly like HacPDX 1, you might not get network access.
I hope to spend most of my time working on Hackage (see here and here) with other interested Haskellers both locally and via IRC (#hacpdx on freenode). Still, I might sqeeze in some time for my seemingly never-complete side projects… we’ll see!
Hope to see you there!
Crypto-API, MonadCryptoRandom, DRBG
November 2, 2010
Announcing a new version of crypto-api and the first release of both
DRBG and MonadCryptoRandom. Links can be found at the end of the e-mail
along with acknowledgments.
Crypto-API
Crypto-api, a generic interface for cryptographic algorithms, has hit
version 0.2. Notable additions include:
If you use cryptographic operations then crypto-api is here to give you
an easy implementation and algorithm independent interface.
- The “OS-independent” random source (System.Crypto.Random) now works on
Windows. (thanks Stuart Dootson) - No more MonoLocalBinds or ScopedTypeVariables, GHC < 6.12 should now
work. - No more “instance Monad Either” what-so-ever. It got in the way other
other instances more than being helpful. - The order of arguments are swapped in CryptoRandomGen so it fits
standard convention. - Build deps updated so GHC-7 works (Paulo Tanimoto)
If you maintain block ciphers, hashes, asymmetric ciphers, stream
ciphers, or random number generators then I encourage you to make an
instance for the matching Crypto-API class. Also, make use of the
testing infrastructure provided if possible. AES, SHA*, and Twofish
have lots of known-answer tests and a simple module for parsing NIST
test files is also included.
MonadCryptoRandom
Much like MonadRandom, this has a class for random value generation
(CRandom), a class for monadic operation (MonadCryptoRandom), a
transformer (CRandT), and instances to make all this useful. The main
difference between MonadCryptoRandom from MonadRandom is the use of
CryptoRandomGen instead of RandomGen and the possibility for failure by
way of MonadError.
DRBG
DRBG, a cryptographically secure pseudo random number generator based on
the NIST SP 800-90 standard, is now on hackage. This uses the
crypto-api CryptoMonadRandom class and cryptohash >= 0.6.1.
pureMD5
Incidently, pureMD5’s deps have been bumped to use the new crypto-api.
Future Work
Once we have a cryptocipher like package with BlockCipher instance for
AES, I imagine DRBG will include cipher-based bit generators. Aside
from that, more testing is certainly an order.
Disclaimer
Just so there’s no confusion about my part in all this.
- Crypto-API: I started discussion and hacked up the code for this interface (and that’s all it is, an interface for algorithm producers and algorithm consumers to meet in the middle)
- MonadCryptoRandom: This is just a rip-off of the motivating idea behind MonadRandom but it allows failure. I tried to match even the names as closely as was sensible (CRand instead of Rand, etc).
- DRBG: Its a translation of a NIST spec. I never thought I’d do translator work, but here I am doing English to Haskell transcription.
Links
Crypto-API
Hackage: http://hackage.haskell.org/package/crypto-api
Home: http://trac.haskell.org/crypto-api/wiki
DRBG
Hackage: http://hackage.haskell.org/package/DRBG
Home: None, will share home and bug tracker with crypto-api
MonadCryptoRandom
Hackage: http://hackage.haskell.org/package/monadcryptorandom
Home: None, will share home and bug tracker with crypto-api
Thanks go to Vincent Hanquez for his cryptohash package including
crypto-api instances, Stuart Dootson for getting the Windows code in
System.Crypto.Random working, Paulo Tanimoto for pointing out/patching
an issue with GHC-7
Ben Boeckel – I haven’t forgot about your patch but it seems
cabal/hackage rejects such a .cabal file. I’ll have to investigate or
talk to Duncan.
Convex Hulls with GPS + GPX + HXT
October 22, 2010
GPS, a toy library for basic Latitude/Longitude based calculations, has just received a small face lift. I now leverage the GPX library and its classes/data types of Lat, Lon, and Time so GPS no longer needs to declare Latitude, Longitude, Coordinate, or Location.
In addition to the old addVector, restLocations, heading and divideArea functions GPS now also includes a convexHull function. Here’s how to get a convex hull from a gpx trace produced by a logger:
import Text.XML.HXT.Arrow import Data.GPS import Data.Geo.GPX import System.Environment import Control.Monad main = do fs <- getArgs g >> xpickleDocument xpickle [(a_indent, v_1)] "convexHull.gpx") return ()
Crypto-API Released
September 7, 2010
Crypto-API (hackage, haddock) 0.0.0.1 is now on Hackage.
Crypto-API is a generic interface for cryptographic operations, platform independent quality Entropy, property tests and known-answer tests (KATs) for common algorithms, and a basic benchmark infrastructure. Maintainers of hash and cipher implementations are encouraged to add instances for the classes defined in Crypto.Classes. Crypto users are similarly encouraged to use the interfaces defined in the Classes module.
Previous blogs on crypto-api have discussed its design and the RNG interface. These were to aid design discussion, so note the code there won’t work without minor changes.
Example: Hashes
An example class instance:
instance Hash MD5Context MD5Digest where outputLength = Tagged 128 blockLength = Tagged 512 initialCtx = md5InitialContext updateCtx = md5Update finalize = md5Finalize
The hash user can remain agnostic about which type of hash is used:
authMessage :: Hash ctx dgst => B.ByteString -> MacKey -> dgst -> Bool authMessage msg k = (==) (hmac' k msg) hashFile :: Hash c d => FilePath -> IO d hashFile = liftM hash L.readFile
Example: Block Cipher
Users of block cipher instances probably want to use Crypto.Modes:
import Crypto.Classes import Crypto.Modes (cbc) import Data.Serialize (encode) cipherMsgAppendIV :: (BlockCipher k) => k -> B.ByteString -> IO B.ByteString, cipherMsgAppendIV msg = do iv <- getIVIO return $ B.append (encode iv) (cbc k iv msg)
Example RNG
Its easy to get a DRBG (aka PRNG) that can be used for generating seed material for keys, building asymmetric keys, obtaining initialization vectors, nonces, or many other uses. See Crypto.Random (which users System.Crypto.Random for entropy):
newGenIO :: CryptoRandomGen g => IO g genBytes :: (CryptoRandomGen g) => g -> ByteLength -> Either GenError (ByteString, g) getIV :: (CryptoRandomGen g, BlockCipher k) => g -> Either GenError (IV k, g) buildKeyPair :: CryptoRandomGen g => g -> BitLength -> Maybe ((p, p), g)
Tests
A quick peek in the Test.Crypto module will show you that testing is decent (particularly for AES) and getting better all the time.
Given a BlockCipher instance the entire test code for an AES implementation is:
-- Omitting hack-job instances for SimpleAES in this snippet main = do ts <- makeAESTests (AESKey $ B.replicate 16 0) runTests ts
This automatically reads in hundreds of NIST Known Answer Tests (KATs) and checks the implementation. A lesser infrastructure exists for testing Hashes. Cipher property tests are still needed.
Example: Benchmarking
As with tests, benchmarking is quite simple:
import Data.Digest.Pure.MD5 import Benchmark.Crypto import Criterion.Main main = defaultMain [benchmarkHash (undefined :: MD5Digest) "pureMD5"]
Closing
So please, if you maintain a hash, cipher, or other cryptographic primitive please add instances for the crypto-api classes. If you need these primitives then consider using the crypto-api interfaces, allowing you to remain algorithm and implementation agnostic in all your low level code.
A Better Foundation for Random Values in Haskell
September 2, 2010
RandomGen – The Old Solution
Mathematicians talk about random bits and many programmers talk about streams of random bytes (ex: /dev/urandom, block cipher counter RNGs), so its a bit odd that Haskell adopted the RandomGen class, which only generates random Ints. Several aspects of RandomGen that are non-ideal include:
- Only generates Ints (Ints need to be coerced to obtain other types)
- By virtue of packaging it is often paired with StdGen, a sub-par generator
- Mandates a ‘split’ operation, which is non-sense or unsafe for some generators (as BOS pointed out in a comment on my last post)
- Doesn’t allow for generator failure (too much output without a reseed) – this is important for cryptographically secure RNGs
- Doesn’t allow any method for additional entropy to be included upon request for new data (used at least in NIST SP 800-90 and there are obvious default implementations for all other generators)
Building Something Better
For these reasons I have been convinced that building the new crypto-api package on RandomGen would be a mistake. I’ve thus expanded the scope of crypto-api to include a decent RandomGenerator class. The proposal below is slightly more complex than the old RandomGen, but I consider it more honest (doesn’t hide error conditions / necessitate exceptions).
class RandomGenerator g where -- |Instantiate a new random bit generator newGen :: B.ByteString -> Either GenError g -- |Length of input entropy necessary to instantiate or reseed a generator genSeedLen :: Tagged g Int -- |Obtain random data using a generator genBytes :: g -> Int -> Either GenError (B.ByteString, g) -- |'genBytesAI g i entropy' generates 'i' random bytes and use the -- additional input 'entropy' in the generation of the requested data. genBytesAI :: g -> Int -> B.ByteString -> Either GenError (B.ByteString, g) genBytesAI g len entropy = ... default implementation ... -- |reseed a random number generator reseed :: g -> B.ByteString -> Either GenError g
Compared to the old RandomGen class we have:
- Random data comes in Bytestrings. RandomGen only gave Ints (what is that? 29 bits? 32 bits? 64? argh!), and depended on another class (Random) to build other values. We can still have a ‘Random’ class built for RandomGenerator – should we have that in this module?
- Constructing and reseeding generators is now part of the class.
- Splitting the PRNG is now a separate class (not shown)
- Generators can accept additional input (genBytesAI). Most generators probably won’t use this, so there is a reasonable default implementation (fmap (xor additionalInput) genBytes).
- The possibility to fail – this is not new! Even in the old RandomGen class the underlying PRNGs can fail (the PRNG has hit its period and needs a reseed to avoid repeating the sequence), but RandomGen gave no failure mechanism. I feel justified in forcing all PRNGs to use the same set of error messages because many errors are common to all generators (ex: ReseedRequred) and the action necessary to fix such errors is generalized too.
In Closing
The full Data.Crypto.Random module is online and I welcome comments, complaints and patches. This is the class I intend to force users of the Crypto API block cipher modes and Asymmetric Cipher instances to use, so it’s important to get right!