diff --git a/LICENSE b/LICENSE
new file mode 100644
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,30 @@
+Copyright (c) Thomas DuBuisson
+
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+1. Redistributions of source code must retain the above copyright
+   notice, this list of conditions and the following disclaimer.
+
+2. Redistributions in binary form must reproduce the above copyright
+   notice, this list of conditions and the following disclaimer in the
+   documentation and/or other materials provided with the distribution.
+
+3. Neither the name of the author nor the names of his contributors
+   may be used to endorse or promote products derived from this software
+   without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE CONTRIBUTORS ``AS IS'' AND ANY EXPRESS
+OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED.  IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
diff --git a/Setup.hs b/Setup.hs
new file mode 100644
--- /dev/null
+++ b/Setup.hs
@@ -0,0 +1,2 @@
+import Distribution.Simple
+main = defaultMain
diff --git a/System/Entropy.hs b/System/Entropy.hs
new file mode 100644
--- /dev/null
+++ b/System/Entropy.hs
@@ -0,0 +1,154 @@
+{-# LANGUAGE CPP, ForeignFunctionInterface, BangPatterns, ScopedTypeVariables #-}
+{-|
+ Maintainer: Thomas.DuBuisson@gmail.com
+ Stability: beta
+ Portability: portable
+
+ Obtain entropy from system sources.
+ Currently, windows and *nix systems with a /dev/urandom are supported.
+-}
+
+module System.Entropy
+	( getEntropy
+	, CryptHandle
+	, openHandle
+	, hGetEntropy
+	, closeHandle
+	) where
+
+import Control.Exception as X
+import Control.Monad (liftM)
+import Data.ByteString as B
+import Data.ByteString.Lazy as L
+import System.IO (openFile, hClose, IOMode(..), Handle)
+import qualified Control.Exception as X
+
+#if defined(isWindows)
+{- C example for windows rng - taken from a blog, can't recall which one but thank you!
+        #include <Windows.h>
+        #include <Wincrypt.h>
+        ...
+        //
+        // DISCLAIMER: Don't forget to check your error codes!!
+        // I am not checking as to make the example simple...
+        //
+        HCRYPTPROV hCryptCtx = NULL;
+        BYTE randomArray[128];
+
+        CryptAcquireContext(&hCryptCtx, NULL, MS_DEF_PROV, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT);
+        CryptGenRandom(hCryptCtx, 128, randomArray);
+        CryptReleaseContext(hCryptCtx, 0);
+-}
+
+import Data.ByteString.Internal as BI
+import Data.Int (Int32)
+import Data.Word (Word32, Word8)
+import Foreign.C.String (CString, withCString)
+import Foreign.Ptr (Ptr, nullPtr)
+import Foreign.Marshal.Alloc (alloca)
+import Foreign.Marshal.Utils (toBool)
+import Foreign.Storable (peek)
+
+newtype CryptHandle = CH Word32
+
+-- Define the constants we need from WinCrypt.h 
+msDefProv :: String
+msDefProv = "Microsoft Base Cryptographic Provider v1.0"
+provRSAFull :: Word32
+provRSAFull = fromIntegral 1
+cryptVerifyContext :: Word32
+cryptVerifyContext = fromIntegral 0xF0000000
+
+-- Declare the required CryptoAPI imports 
+foreign import stdcall unsafe "CryptAcquireContextA"
+   c_cryptAcquireCtx :: Ptr Word32 -> CString -> CString -> Word32 -> Word32 -> IO Int32
+foreign import stdcall unsafe "CryptGenRandom"
+   c_cryptGenRandom :: Word32 -> Word32 -> Ptr Word8 -> IO Int32
+foreign import stdcall unsafe "CryptReleaseContext"
+   c_cryptReleaseCtx :: Word32 -> Word32 -> IO Int32
+
+cryptAcquireCtx :: IO Word32
+cryptAcquireCtx = 
+   alloca $ \handlePtr -> 
+      withCString msDefProv $ \provName -> do
+         stat <- c_cryptAcquireCtx handlePtr nullPtr provName (fromIntegral 1) (fromIntegral cryptVerifyContext)
+         if (toBool stat)
+            then peek handlePtr
+            else fail "c_cryptAcquireCtx"
+
+cryptGenRandom :: Word32 -> Int -> IO B.ByteString
+cryptGenRandom h i = 
+   B.create i $ \c_buffer -> do
+      stat <- c_cryptGenRandom (fromIntegral h) (fromIntegral i) c_buffer
+      if (toBool stat)
+         then return ()
+         else fail "c_cryptGenRandom"
+
+cryptReleaseCtx :: Word32 -> IO ()
+cryptReleaseCtx h = do
+   stat <- c_cryptReleaseCtx h 0
+   if (toBool stat)
+      then return ()
+      else fail "c_cryptReleaseCtx"
+
+-- |Inefficiently get a specific number of bytes of cryptographically
+-- secure random data using the system-specific facilities.
+--
+-- This function will return zero bytes
+-- on platforms without a secure RNG!
+getEntropy :: Int -> IO B.ByteString
+getEntropy n = do
+  X.catch (do
+            h <- cryptAcquireCtx
+            bs <- cryptGenRandom h n
+            let !bs' = bs
+            cryptReleaseCtx h
+            return bs')
+    (\(e :: X.IOException) -> return B.empty)
+
+-- |Open a handle from which random data can be read
+openHandle :: IO CryptHandle
+openHandle = liftM CH cryptAcquireCtx
+
+-- |Close the `CryptHandle`
+closeHandle (CH h) = cryptReleaseCtx h
+
+-- |Read from `CryptHandle`
+hGetEntropy :: CryptHandle -> Int -> IO B.ByteString 
+hGetEntropy (CH h) = cryptGenRandom h
+
+#else
+source = "/dev/urandom"
+
+-- |Handle for manual resource mangement
+newtype CryptHandle = CH Handle
+
+-- |Open a `CryptHandle`
+openHandle :: IO CryptHandle
+openHandle = liftM CH (openFile source ReadMode)
+
+-- |Close the `CryptHandle`
+closeHandle :: CryptHandle -> IO ()
+closeHandle (CH h) = hClose h
+
+-- |Read random data from a `CryptHandle`
+hGetEntropy :: CryptHandle -> Int -> IO B.ByteString 
+hGetEntropy (CH h) = B.hGet h
+
+-- |Inefficiently get a specific number of bytes of cryptographically
+-- secure random data using the system-specific facilities.
+--
+-- Use '/dev/urandom' on *nix and CryptAPI when on Windows.  In short,
+-- this entropy is considered "cryptographically secure" but not true
+-- entropy.
+getEntropy :: Int -> IO B.ByteString
+getEntropy n = 
+  X.catch (do
+            h <- openFile source ReadMode
+            bs <- B.hGet h n
+            let !bs' = bs
+            hClose h
+            return bs')
+  (\(e :: X.IOException) -> return B.empty)
+#endif
+
diff --git a/entropy.cabal b/entropy.cabal
new file mode 100644
--- /dev/null
+++ b/entropy.cabal
@@ -0,0 +1,29 @@
+name:           entropy
+version:        0.1
+license:        BSD3
+license-file:   LICENSE
+copyright:      Thomas DuBuisson <thomas.dubuisson@gmail.com>
+author:         Thomas DuBuisson <thomas.dubuisson@gmail.com>
+maintainer:     Thomas DuBuisson <thomas.dubuisson@gmail.com>
+description:    A platform independent method to obtain cryptographically strong entropy (/dev/urandom on Linux, CryptAPI on Windows, patches welcome)
+                Users looking for cryptographically strong (number-theoretically sound) PRNGs should see the 'DRBG' package too!
+synopsis:       A platform independent entropy source
+category:       Data, Cryptography
+homepage:       http://trac.haskell.org/crypto-api/wiki
+bug-reports:    http://trac.haskell.org/crypto-api/report/1
+stability:      stable
+build-type:     Simple
+cabal-version:  >= 1.6
+tested-with:    GHC == 6.12.1
+data-files:
+extra-source-files:
+
+Library
+  Build-Depends: base == 4.*, bytestring
+  ghc-options:
+  hs-source-dirs:
+  exposed-modules: System.Entropy
+  other-modules:
+  if os(windows)
+    cpp-options: -DisWindows
+    extra-libraries: advapi32
