1{-# LANGUAGE CPP, ForeignFunctionInterface, BangPatterns, ScopedTypeVariables #-}
3 Maintainer: Thomas.DuBuisson@gmail.com
7 Obtain entropy from system sources.
8 Currently, windows and *nix systems with a /dev/urandom are supported.
19import Control.Monad (liftM, when)
20import Data.ByteString as B
21import System.IO (openFile, hClose, IOMode(..), Handle, withBinaryFile)
24{- C example for windows rng - taken from a blog, can't recall which one but thank you!
29 // DISCLAIMER: Don't forget to check your error codes!!
30 // I am not checking as to make the example simple...
32 HCRYPTPROV hCryptCtx = NULL;
33 BYTE randomArray[128];
35 CryptAcquireContext(&hCryptCtx, NULL, MS_DEF_PROV, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT);
36 CryptGenRandom(hCryptCtx, 128, randomArray);
37 CryptReleaseContext(hCryptCtx, 0);
40import Data.ByteString.Internal as BI
41import Data.Int (Int32)
42import Data.Word (Word32, Word8)
43import Foreign.C.String (CString, withCString)
44import Foreign.Ptr (Ptr, nullPtr)
45import Foreign.Marshal.Alloc (alloca)
46import Foreign.Marshal.Utils (toBool)
47import Foreign.Storable (peek)
49newtype CryptHandle = CH Word32
51-- Define the constants we need from WinCrypt.h
53msDefProv = "Microsoft Base Cryptographic Provider v1.0"
55provRSAFull = fromIntegral 1
56cryptVerifyContext :: Word32
57cryptVerifyContext = fromIntegral 0xF0000000
59-- Declare the required CryptoAPI imports
60foreign import stdcall unsafe "CryptAcquireContextA"
61 c_cryptAcquireCtx :: Ptr Word32 -> CString -> CString -> Word32 -> Word32 -> IO Int32
62foreign import stdcall unsafe "CryptGenRandom"
63 c_cryptGenRandom :: Word32 -> Word32 -> Ptr Word8 -> IO Int32
64foreign import stdcall unsafe "CryptReleaseContext"
65 c_cryptReleaseCtx :: Word32 -> Word32 -> IO Int32
67cryptAcquireCtx :: IO Word32
69 alloca $ \handlePtr ->
70 withCString msDefProv $ \provName -> do
71 stat <- c_cryptAcquireCtx handlePtr nullPtr provName (fromIntegral 1) (fromIntegral cryptVerifyContext)
74 else fail "c_cryptAcquireCtx"
76cryptGenRandom :: Word32 -> Int -> IO B.ByteString
78 BI.create i $ \c_buffer -> do
79 stat <- c_cryptGenRandom (fromIntegral h) (fromIntegral i) c_buffer
82 else fail "c_cryptGenRandom"
84cryptReleaseCtx :: Word32 -> IO ()
86 stat <- c_cryptReleaseCtx h 0
89 else fail "c_cryptReleaseCtx"
91-- |Inefficiently get a specific number of bytes of cryptographically
92-- secure random data using the system-specific facilities.
94-- This function will return zero bytes
95-- on platforms without a secure RNG!
96getEntropy :: Int -> IO B.ByteString
99 bs <- cryptGenRandom h n
104-- |Open a handle from which random data can be read
105openHandle :: IO CryptHandle
106openHandle = liftM CH cryptAcquireCtx
108-- |Close the `CryptHandle`
109closeHandle (CH h) = cryptReleaseCtx h
111-- |Read from `CryptHandle`
112hGetEntropy :: CryptHandle -> Int -> IO B.ByteString
113hGetEntropy (CH h) = cryptGenRandom h
116{- Not windows, assuming nix with a /dev/urandom -}
117import Foreign.C.Types
119import Data.ByteString.Internal as B
122source = "/dev/urandom"
124-- |Handle for manual resource mangement
125newtype CryptHandle = CH Handle
127-- |Open a `CryptHandle`
128openHandle :: IO CryptHandle
129openHandle = liftM CH (openFile source ReadMode)
131-- |Close the `CryptHandle`
132closeHandle :: CryptHandle -> IO ()
133closeHandle (CH h) = hClose h
135-- |Read random data from a `CryptHandle`
136hGetEntropy :: CryptHandle -> Int -> IO B.ByteString
137hGetEntropy (CH h) = B.hGet h
140foreign import ccall unsafe "cpu_has_rdrand"
141 c_cpu_has_rdrand :: IO CInt
143foreign import ccall unsafe "get_rand_bytes"
144 c_get_rand_bytes :: Ptr CUChar -> CSize -> IO CInt
146cpuHasRdRand :: IO Bool
147cpuHasRdRand = (/= 0) `fmap` c_cpu_has_rdrand
150-- |Inefficiently get a specific number of bytes of cryptographically
151-- secure random data using the system-specific facilities.
153-- Use '/dev/urandom' on *nix and CryptAPI when on Windows. In short,
154-- this entropy is considered "cryptographically secure" but not true
156getEntropy :: Int -> IO B.ByteString
160 if b then B.create n $ \ptr -> do
161 r <- c_get_rand_bytes (castPtr ptr) (fromIntegral n)
163 (fail "RDRand failed to gather entropy")
167 withBinaryFile source ReadMode (`B.hGet` n)
keysesc to close
- j k
- move down, up
- enter
- open
- esc
- back, or up a level
- 1 2 3 4
- readme, files, commits, refs
- /
- filter
- y
- copy the clone command
- c
- compare the chosen commit with another (or shift-click both)
- ?
- show or hide this list