diff --git a/Codec/Encryption/AES.hs b/Codec/Encryption/AES.hs
--- a/Codec/Encryption/AES.hs
+++ b/Codec/Encryption/AES.hs
@@ -1,3 +1,4 @@
+{-# LANGUAGE TypeSynonymInstances #-}
 -----------------------------------------------------------------------------
 -- |
 -- Module      :  Codec.Encryption.AES
@@ -15,7 +16,7 @@
 
 module Codec.Encryption.AES (
    -- * Function Types 
-   encrypt, decrypt) where
+   encrypt, decrypt, AESKey) where
 
 import Codec.Encryption.AESAux
 import Data.LargeWord
@@ -23,7 +24,12 @@
 import Data.Word
 import Data.Bits
 
-class (Bits a, Integral a) => AESKey a
+class (Bits a, Integral a) => AESKeyIndirection a
+class AESKeyIndirection a => AESKey a
+
+instance AESKeyIndirection Word128
+instance AESKeyIndirection Word192
+instance AESKeyIndirection Word256
 
 instance AESKey Word128
 instance AESKey Word192
diff --git a/Codec/Encryption/DESAux.hs b/Codec/Encryption/DESAux.hs
--- a/Codec/Encryption/DESAux.hs
+++ b/Codec/Encryption/DESAux.hs
@@ -1,3 +1,5 @@
+{-# LANGUAGE FlexibleInstances #-}
+
 module Codec.Encryption.DESAux (des_enc, des_dec) where
 
 import Data.Word
diff --git a/Codec/Utils.hs b/Codec/Utils.hs
--- a/Codec/Utils.hs
+++ b/Codec/Utils.hs
@@ -19,6 +19,7 @@
    -- * Octet Conversion Functions
    fromTwosComp, toTwosComp,
    toOctets, fromOctets,
+   listFromOctets, listToOctets,
    i2osp
 	      ) where
 
@@ -39,6 +40,30 @@
 toOctets :: (Integral a, Integral b) => a -> b -> [Octet]
 toOctets n x = (toBase n . fromIntegral) x
 
+-- | This is used to (approximately) get back to a starting word list.
+-- For example, if you have a list of 3 Word8 and try to convert them to
+-- a Word32, the Word32 will get null-padded, and without correction, you
+-- will get 4 Word8s when converting back. This corrects it.
+-- Unfortunately, it also means you will have errors if trying to convert
+-- Word8 lists with nulls on the end.
+trimNulls :: [Word8] -> [Word8]
+trimNulls = reverse . (dropWhile (== 0)) . reverse
+
+-- | Converts a list of numbers into a list of octets.
+-- The resultant list has nulls trimmed from the end to make this the dual
+-- of listFromOctets (except when the original octet list ended with nulls;
+-- see 'trimNulls').
+listToOctets :: (Bits a, Integral a) => [a] -> [Octet]
+listToOctets x = trimNulls $ concat paddedOctets where
+    paddedOctets :: [[Octet]]
+    paddedOctets = map (padTo bytes) rawOctets
+    rawOctets :: [[Octet]]
+    rawOctets = map (reverse . toOctets 256) x
+    padTo :: Int -> [Octet] -> [Octet]
+    padTo x y = take x $ y ++ repeat 0
+    bytes :: Int
+    bytes = bitSize (head x) `div` 8
+
 -- | The basic type for encoding and decoding.
 
 type Octet = Word8
@@ -56,6 +81,16 @@
    fromIntegral $ 
    sum $ 
    zipWith (*) (powersOf n) (reverse (map fromIntegral x))
+
+-- | See 'listToOctets'.
+listFromOctets :: (Integral a, Bits a) => [Octet] -> [a]
+listFromOctets [] = []
+listFromOctets x = result where
+    result = first : rest
+    first = fromOctets 256 first'
+    first' = reverse $ take bytes x
+    rest = listFromOctets $ drop bytes x
+    bytes = bitSize first `div` 8
 
 -- | Take the length of the required number of octets and convert the 
 --   number to base 256 padding it out to the required length. If the
diff --git a/Crypto.cabal b/Crypto.cabal
--- a/Crypto.cabal
+++ b/Crypto.cabal
@@ -1,19 +1,29 @@
 Name:            Crypto
-Version:         4.1.0
+Version:         4.2.0
 License:         OtherLicense
-License-File:	 ReadMe.tex
+License-File:    ReadMe.tex
 Author:          Dominic Steinitz
-Maintainer:	 dominic.steinitz@blueyonder.co.uk
+Maintainer:      Creighton Hogg <wchogg@gmail.com>
 Copyright:       Dominic Steinitz 2003 - 2007
-Stability:	 Alpha
-Synopsis:        DES, Blowfish, AES, TEA, SHA1, MD5, RSA, BubbleBabble,
+
+Stability:       Alpha
+Category:        Cryptography, Codec
+Synopsis:        Collects together existing Haskell cryptographic functions into a package
+Description:     DES, Blowfish, AES, TEA, SHA1, MD5, RSA, BubbleBabble,
                  Hexdump, Support for Word128, Word192 and Word256 and Beyond, PKCS5
-                 Padding, Various Encryption Modes e.g. Cipher Block Chaining all in one package.
+                 Padding, Various Encryption Modes e.g. Cipher Block Chaining all in one package,
+                 with HUnit and QuickCheck tests, and examples.
+Data-Files:      CryptoHomePage.html
+
+Build-Type:      Simple
 Cabal-Version:   >= 1.2
+Tested-With:     GHC==6.8.2 GHC==6.10.1
+
 flag small_base
         description: choose the new smaller, split-up base package.
+
 Library
-        Exposed-Modules: 
+        Exposed-Modules:
                  Codec.Binary.BubbleBabble,
                  Codec.Encryption.RSA,
                  Codec.Encryption.RSA.EMEOAEP,
@@ -41,8 +51,9 @@
             Build-Depends: base >= 3, array, random, pretty
         else
             Build-Depends: base < 3
-        Ghc-options:     -fglasgow-exts
-        Other-modules:   
+        Ghc-options:     -fregs-graph
+        Extensions: FlexibleInstances, TypeSynonymInstances 
+        Other-modules:
                  Codec.Encryption.BlowfishAux,
                  Codec.Encryption.DESAux,
                  Codec.Encryption.AESAux,
@@ -50,7 +61,7 @@
 
 Executable      SymmetricTest
   Main-Is:         SymmetricTest.hs
-  Ghc-options:     -fglasgow-exts
+  Ghc-options:     -fregs-graph
   Other-modules:   Codec.Utils
                    Codec.Encryption.Blowfish
                    Codec.Encryption.Modes
@@ -61,11 +72,13 @@
 
 Executable      SHA1Test
   Main-Is:         SHA1Test.hs
+  Ghc-options:     -fregs-graph
   Other-modules:   Codec.Text.Raw
                    Data.Digest.SHA1
 
 Executable      RSATest
   Main-Is:         RSATest.hs
+  Ghc-options:     -fregs-graph
   Other-modules:   Codec.Utils
                    Data.Digest.SHA1
                    Codec.Encryption.RSA.MGF
@@ -74,7 +87,8 @@
 
 Executable      QuickTest
   Main-Is:         QuickTest.hs
-  Ghc-options:     -fglasgow-exts
+  Ghc-options:     -fregs-graph
+  Extensions: TypeSynonymInstances
   Other-modules:   Codec.Utils
                    Codec.Encryption.Blowfish
                    Codec.Encryption.AES
@@ -86,3 +100,7 @@
   Main-Is:         HMACTest.hs
   Other-modules:   Codec.Utils
                    Data.HMAC
+
+Executable      WordListTest
+  Main-Is:         WordListTest.hs
+  Other-modules:   Data.LargeWord
diff --git a/CryptoHomePage.html b/CryptoHomePage.html
new file mode 100644
--- /dev/null
+++ b/CryptoHomePage.html
@@ -0,0 +1,51 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
+             "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en">
+<head>
+<meta http-equiv="Content-Type" content="text/html;charset=us-ascii" />
+<title>The Haskell Cryptographic Library</title>
+</head>
+<body>
+  <h2>The Haskell Cryptographic Library</h2>
+
+  <p>The Haskell Cryptographic Library collects together existing Haskell
+    cryptographic functions into one cabalized package, with
+    <a href="http://hunit.sourceforge.net/">HUnit</a> tests,
+    <a href="http://haskell.org/haskellwiki/Quickcheck">QuickCheck</a>
+    properties, examples showing how to interwork with
+    other cryptographic implementations and examples showing how to
+    handle other
+    <a href="http://en.wikipedia.org/wiki/Abstract_syntax_notation_one">ASN.1</a>
+    definitions.</p>
+
+  <h2>Downloading</h2>
+  <p>Stable releases of Crypto can be found in the Hackage package database:</p>
+
+  <ul><li><a href="http://hackage.haskell.org/cgi-bin/hackage-scripts/package/Crypto">Hackage download</a></li></ul>
+
+  <p>For the latest version, you can use the development repository. You can download it:<br/></p>
+
+  <ul><li>darcs get
+      <a href="http://darcs.haskell.org/crypto">http://darcs.haskell.org/crypto</a></li></ul>
+
+  <h2>Resources</h2>
+  <ul>
+    <li><a href="http://www.haskell.org/crypto/ReadMe.pdf">User guide</a></li>
+    <li><a href="http://www.haskell.org/crypto/doc/html">Haddock documentation</a></li>
+  </ul>
+
+  <h2>Contact</h2>
+
+  <p>All questions, comments, bug reports, flames,
+    requests for updates / changes
+    and suggestions should be directed to 
+    <script language="JavaScript">
+    <!--
+    var name = "dominic.steinitz"
+    var domain = "blueyonder.co.uk"
+    document.write("<a href='mailto:" + name + "@" + domain + "'>")
+    document.write(name + "@" + domain)
+    document.write("</a>")
+    //-->
+    </script>.</p>
+</body> </html>
diff --git a/Data/HMAC.hs b/Data/HMAC.hs
--- a/Data/HMAC.hs
+++ b/Data/HMAC.hs
@@ -48,7 +48,7 @@
 
 hmac_md5 :: [Octet] -- ^ Secret key
          -> [Octet] -- ^ Message text
-         -> [Octet] -- ^ Resulting HMAC-SHA1 value
+         -> [Octet] -- ^ Resulting HMAC-MD5 value
 hmac_md5 = hmac md5_hm
 
 w160_to_w8s :: Word160 -> [Octet]
diff --git a/QuickTest.hs b/QuickTest.hs
--- a/QuickTest.hs
+++ b/QuickTest.hs
@@ -1,3 +1,5 @@
+{-# LANGUAGE TypeSynonymInstances #-}
+
 module Main where
 
 import Codec.Utils
diff --git a/ReadMe.tex b/ReadMe.tex
--- a/ReadMe.tex
+++ b/ReadMe.tex
@@ -20,7 +20,7 @@
 \setlength{\parskip}{\medskipamount}
 \setlength{\parindent}{0pt}
 
-\title{Haskell Cryptographic Library 4.1.0}
+\title{Haskell Cryptographic Library 4.2.0}
 \author{Dominic Steinitz}
 
 \begin{document}
@@ -29,7 +29,7 @@
 
 The 
 \htmladdnormallinkfoot
-{Haskell Cryptographic Library 4.1.0}
+{Haskell Cryptographic Library 4.2.0}
 {http://www.haskell.org/crypto}
 collects together existing Haskell cryptographic
 functions into one cabalized package, together with HUnit tests,
@@ -76,7 +76,7 @@
 
 \lstset{language=shell,basicstyle=\ttfamily\small}
 \begin{lstlisting}[frame=single]
-darcs get --tag "4.1.0" http://www.haskell.org/crypto/src
+darcs get --tag "4.2.0" http://code.haskell.org/crypto
 \end{lstlisting}
 
 Build and install ready for testing:
@@ -368,7 +368,7 @@
 Spencer Janssen
 \end{itemize}
 
-This document was last updated on 1st April 2007.
-\copyright\ 2006--2007 Dominic Steinitz. 
+This document was last updated on 7th December 2008.
+\copyright\ 2006--2008 Dominic Steinitz. 
 
 \end{document}
diff --git a/WordListTest.hs b/WordListTest.hs
new file mode 100644
--- /dev/null
+++ b/WordListTest.hs
@@ -0,0 +1,73 @@
+{-# LANGUAGE ScopedTypeVariables, PatternSignatures,
+             FlexibleInstances, UndecidableInstances,
+             TypeSynonymInstances #-}
+
+import Data.LargeWord (Word128, Word192, Word256, LargeKey)
+import Codec.Utils (listFromOctets, listToOctets)
+import Data.Word (Word8, Word32, Word64)
+import Test.QuickCheck
+
+main :: IO ()
+main = sequence_ $ map test checks where
+    test :: (String, IO ()) -> IO ()
+    test (s, t) = do putStrLn $ "Checking " ++ s
+                     putStr "        "
+                     t
+
+checks :: [(String, IO ())]
+checks = [
+    ("Word32",
+     quickCheck (\(w :: [Word32]) -> (listFromOctets . listToOctets) w == w)),
+    ("Word64",
+     quickCheck (\(w :: [Word64]) -> (listFromOctets . listToOctets) w == w)),
+    ("Word128",
+     quickCheck (\(w :: [Word128]) -> (listFromOctets . listToOctets) w == w)),
+    ("Word192",
+     quickCheck (\(w :: [Word192]) -> (listFromOctets . listToOctets) w == w)),
+    ("Word256",
+     quickCheck (\(w :: [Word256]) -> (listFromOctets . listToOctets) w == w))]
+
+instance Arbitrary Word8 where
+    arbitrary = do
+        let mx,mn :: Integer
+            mx = fromIntegral (maxBound :: Word8)
+            mn = fromIntegral (minBound :: Word8)
+        c <- choose (mx, mn)
+        return $ fromIntegral c
+    coarbitrary a = error "Not implemented"
+
+instance Arbitrary Word32 where
+    arbitrary = do
+        let mx,mn :: Integer
+            mx = fromIntegral (maxBound :: Word32)
+            mn = fromIntegral (minBound :: Word32)
+        c <- choose (mx, mn)
+        return $ fromIntegral c
+    coarbitrary a = error "Not implemented"
+
+instance Arbitrary Word64 where
+    arbitrary = do
+        let mx,mn :: Integer
+            mx = fromIntegral (maxBound :: Word64)
+            mn = fromIntegral (minBound :: Word64)
+        c <- choose (mx, mn)
+        return $ fromIntegral c
+    coarbitrary a = error "Not implemented"
+
+instance Arbitrary Word128 where
+        arbitrary = do
+                x <- vector (128 `div` 8) :: Gen [Word8]
+                return $ head $ listFromOctets x
+        coarbitrary x = error "Not implemented"
+
+instance Arbitrary Word192 where
+        arbitrary = do
+                x <- vector (192 `div` 8) :: Gen [Word8]
+                return $ head $ listFromOctets x
+        coarbitrary x = error "Not implemented"
+
+instance Arbitrary Word256 where
+        arbitrary = do
+                x <- vector (256 `div` 8) :: Gen [Word8]
+                return $ head $ listFromOctets x
+        coarbitrary x = error "Not implemented"
