24
24
module Crypto.Random
25
( -- * Basic Interface
28
-- * Helper functions and expanded interface
25
( -- * Basic Interface
28
-- * Helper functions and expanded interface
34
import System.Crypto.Random
34
import Control.Monad (liftM)
35
35
import Crypto.Types
36
import Control.Monad (liftM)
37
import qualified Data.ByteString as B
38
import qualified Data.ByteString.Lazy as L
40
36
import Data.Bits (xor, setBit, shiftR, shiftL, (.&.))
41
37
import Data.List (foldl')
42
40
import System.IO.Unsafe(unsafeInterleaveIO)
41
import qualified Data.ByteString as B
42
import qualified Data.ByteString.Lazy as L
43
43
import qualified Foreign.ForeignPtr as FP
45
45
#if MIN_VERSION_tagged(0,2,0)
49
-- |Generator failures should always return the appropriate GenError.
50
51
GenErrorOther String -- ^ Misc
51
| RequestedTooManyBytes -- ^ Requested more bytes than a single pass can generate (The maximum request is generator dependent)
52
| RangeInvalid -- ^ When using @genInteger g (l,h)@ and @logBase 2 (h - l) > (maxBound :: Int)@.
53
| NeedReseed -- ^ Some generators cease operation after too high a count without a reseed (ex: NIST SP 800-90)
54
| NotEnoughEntropy -- ^ For instantiating new generators (or reseeding)
55
| NeedsInfiniteSeed -- ^ This generator can not be instantiated or reseeded with a finite seed (ex: 'SystemRandom')
52
| RequestedTooManyBytes -- ^ Requested more bytes than a
53
-- single pass can generate (The
54
-- maximum request is generator
56
| RangeInvalid -- ^ When using @genInteger g (l,h)@
57
-- and @logBase 2 (h - l) > (maxBound
59
| NeedReseed -- ^ Some generators cease operation
60
-- after too high a count without a
61
-- reseed (ex: NIST SP 800-90)
62
| NotEnoughEntropy -- ^ For instantiating new generators
64
| NeedsInfiniteSeed -- ^ This generator can not be
65
-- instantiated or reseeded with a
66
-- finite seed (ex: 'SystemRandom')
56
67
deriving (Eq, Ord, Show)
58
69
-- |A class of random bit generators that allows for the possibility
131
go 1000 = error "The generator instance requested by newGenIO never instantiates (1000 tries). It must be broken."
141
go 1000 = error $ "The generator instance requested by" ++
142
"newGenIO never instantiates (1000 tries). " ++
134
146
getTypedGen :: (CryptoRandomGen g) => Proxy g -> IO (Either GenError g)
164
176
data SystemRandom = SysRandom L.ByteString
166
178
instance CryptoRandomGen SystemRandom where
167
newGen _ = Left NeedsInfiniteSeed
168
genSeedLength = Tagged maxBound
169
genBytes req (SysRandom bs) =
170
let reqI = fromIntegral req
172
rest = L.drop reqI bs
173
in if L.length rnd == reqI
174
then Right (B.concat $ L.toChunks rnd, SysRandom rest)
175
else Left $ GenErrorOther "Error obtaining enough bytes from system random for given request"
176
reseed _ _ = Left NeedsInfiniteSeed
177
newGenIO = getSystemGen
179
newGen _ = Left NeedsInfiniteSeed
180
genSeedLength = Tagged maxBound
181
genBytes req (SysRandom bs) =
182
let reqI = fromIntegral req
184
rest = L.drop reqI bs
185
in if L.length rnd == reqI
186
then Right (B.concat $ L.toChunks rnd, SysRandom rest)
187
else Left $ GenErrorOther "Error obtaining enough bytes \
188
\from system random for given request"
189
reseed _ _ = Left NeedsInfiniteSeed
190
newGenIO = getSystemGen
179
192
-- | While the safety and wisdom of a splitting function depends on the
180
193
-- properties of the generator being split, several arguments from
182
195
-- generators. (see libraries\@haskell.org discussion around Sept, Oct
184
197
splitGen :: CryptoRandomGen g => g -> Either GenError (g,g)
186
let e = genBytes (genSeedLength `for` g) g
199
let e = genBytes (genSeedLength `for` g) g
204
Right new -> Right (g',new)
191
Right new -> Right (g',new)
194
207
-- |Obtain a tagged value for a particular instantiated type.
195
208
for :: Tagged a b -> a -> b