Skip to content
Browse files

Unix (and maybe Windows) getRandomBytes

  • Loading branch information...
1 parent 12faae1 commit ea00e87a373dd2f939ca84babe7fc6aafbab4304 @bos committed Oct 1, 2012
Showing with 83 additions and 0 deletions.
  1. +24 −0 Data/Hashable/RandomSource.hs
  2. +57 −0 cbits/getRandomBytes.c
  3. +2 −0 hashable.cabal
View
24 Data/Hashable/RandomSource.hs
@@ -0,0 +1,24 @@
+{-# LANGUAGE CPP, ForeignFunctionInterface #-}
+
+module Data.Hashable.RandomSource
+ (
+ getRandomBytes
+ ) where
+
+import Data.ByteString as B
+import Data.ByteString.Internal (create)
+import Data.Word (Word8)
+import Foreign.C.Error (throwErrnoIfMinus1_)
+import Foreign.C.Types (CInt(..))
+import Foreign.Ptr (Ptr)
+
+getRandomBytes :: Int -> IO ByteString
+getRandomBytes nbytes
+ | nbytes <= 0 = return B.empty
+ | otherwise =
+ create nbytes $
+ throwErrnoIfMinus1_ "getRandomBytes" .
+ c_getRandomBytes (fromIntegral nbytes)
+
+foreign import ccall unsafe "hashable_getRandomBytes" c_getRandomBytes
+ :: CInt -> Ptr Word8 -> IO CInt
View
57 cbits/getRandomBytes.c
@@ -0,0 +1,57 @@
+#include "MachDeps.h"
+
+int hashable_getRandomBytes(int nbytes, unsigned char *dest);
+
+#if defined(mingw32_HOST_OS) || defined(__MINGW32__)
+
+#include "wincrypt.h"
+
+int hashable_getRandomBytes(int nbytes, unsigned char *dest)
+{
+ HCRYPTPROV hCryptProv;
+ int ret;
+
+ if (CryptAcquireContext(&hCryptProv, NULL, NULL, PROV_RSA_FULL,
+ CRYPT_VERIFYCONTEXT))
+ return -1;
+
+ if (!CryptGenRandom(hCryptProv, (DWOORD) nbytes, (BYTE *) dest))
+ ret = -1;
+
+ CryptReleaseContext(hCryptProv, 0);
+
+ bail:
+ return ret;
+}
+
+#else
+
+#include <fcntl.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+int hashable_getRandomBytes(int nbytes, unsigned char *dest)
+{
+ ssize_t off, nread;
+ int fd;
+
+ fd = open("/dev/urandom", O_RDONLY);
+ if (fd == -1)
+ return -1;
+
+ for (off = 0; nbytes > 0; nbytes -= nread) {
+ nread = read(fd, dest + off, nbytes);
+ off += nread;
+ if (nread == -1) {
+ off = -1;
+ break;
+ }
+ }
+
+ bail:
+ close(fd);
+
+ return off;
+}
+
+#endif
View
2 hashable.cabal
@@ -30,6 +30,7 @@ Flag integer-gmp
Library
Exposed-modules: Data.Hashable
Data.Hashable.SipHash
+ Other-modules: Data.Hashable.RandomSource
Build-depends: base >= 4.0 && < 5.0,
bytestring >= 0.9
if impl(ghc)
@@ -39,6 +40,7 @@ Library
Build-depends: integer-gmp >= 0.2
C-sources: cbits/hashByteString.c
+ cbits/getRandomBytes.c
Ghc-options: -Wall
if impl(ghc >= 6.8)
Ghc-options: -fwarn-tabs

0 comments on commit ea00e87

Please sign in to comment.
Something went wrong with that request. Please try again.