cprng-aes 0.5.2 → 0.6.1
raw patch · 3 files changed
Files
- Crypto/Random/AESCtr.hs +9/−14
- Crypto/Random/AESCtr/Internal.hs +16/−54
- cprng-aes.cabal +3/−4
Crypto/Random/AESCtr.hs view
@@ -21,7 +21,6 @@ ) where import Crypto.Random-import System.Random (RandomGen(..)) import Crypto.Random.AESCtr.Internal import Control.Arrow (second) @@ -42,10 +41,10 @@ -- -- By default, this generator will automatically reseed after generating -- 1 megabyte of data.-data AESRNG = AESRNG { aesrngState :: RNG+data AESRNG = AESRNG { aesrngState :: !RNG , aesrngEntropy :: EntropyPool- , aesrngThreshold :: Int -- ^ in number of generated block- , aesrngCache :: ByteString }+ , aesrngThreshold :: !Int -- ^ in number of generated block+ , aesrngCache :: !ByteString } instance Show AESRNG where show _ = "aesrng[..]"@@ -56,8 +55,7 @@ , aesrngEntropy = entPool , aesrngThreshold = 1024 -- in blocks generated, so 1mb , aesrngCache = B.empty }- where rng = RNG (get128 iv) (get128 cnt) 0 key- (key, cnt, iv) = makeParams b+ where rng = makeRNG b -- | make an AES RNG from an EntropyPool. --@@ -100,15 +98,10 @@ reseedThreshold :: AESRNG -> AESRNG reseedThreshold rng | getNbChunksGenerated (aesrngState rng) >= lvl =- let ent = toBytes $ grabEntropy 64 (aesrngEntropy rng)- in rng { aesrngState = reseedState ent (aesrngState rng) }+ let newRngState = makeRNG $ toBytes $ grabEntropy 64 (aesrngEntropy rng)+ in rng { aesrngState = newRngState } | otherwise = rng- where- lvl = aesrngThreshold rng- reseedState :: ByteString -> RNG -> RNG- reseedState b g@(RNG _ cnt1 _ _) = RNG (get128 r16 `xor128` get128 iv2) (cnt1 `xor128` get128 cnt2) 0 key2- where (r16, _) = genNextChunk g- (key2, cnt2, iv2) = makeParams b+ where lvl = aesrngThreshold rng instance CPRG AESRNG where cprgCreate = make@@ -122,6 +115,7 @@ cprgFork rng = let (b,rng') = genRanBytes rng 64 in (rng', makeFrom (aesrngEntropy rng) b) +{- instance RandomGen AESRNG where next rng = let (bs, rng') = genRanBytes rng 16 in@@ -132,3 +126,4 @@ let rng' = make (aesrngEntropy rng) in (rng, rng') genRange _ = (0, 0x7fffffff)+-}
Crypto/Random/AESCtr/Internal.hs view
@@ -6,6 +6,7 @@ -- Portability : unknown -- {-# LANGUAGE CPP #-}+{-# LANGUAGE BangPatterns #-} module Crypto.Random.AESCtr.Internal where import qualified Crypto.Cipher.AES as AES@@ -13,68 +14,29 @@ import Data.ByteString (ByteString) import qualified Data.ByteString as B -import Data.Word-import Data.Bits (xor)--import Foreign.Ptr-#if __GLASGOW_HASKELL__ > 704-import Foreign.ForeignPtr.Unsafe (unsafeForeignPtrToPtr)-#else-import Foreign.ForeignPtr (unsafeForeignPtrToPtr)-#endif--import Foreign.Storable-import qualified Data.ByteString.Internal as B--data Word128 = Word128 {-# UNPACK #-} !Word64 {-# UNPACK #-} !Word64- {-| An opaque object containing an AES CPRNG -}-data RNG = RNG- {-# UNPACK #-} !Word128 -- iv- {-# UNPACK #-} !Word128 -- cnt- {-# UNPACK #-} !Int -- number of chunks generated since reseed- {-# UNPACK #-} !AES.AES -- AES context+data RNG = RNG !AES.AESIV !Int !AES.AES getNbChunksGenerated :: RNG -> Int-getNbChunksGenerated (RNG _ _ c _) = c--put128 :: Word128 -> ByteString-put128 (Word128 a b) = B.unsafeCreate 16 (write64 . castPtr)- where write64 :: Ptr Word64 -> IO ()- write64 ptr = poke ptr a >> poke (ptr `plusPtr` 8) b--get128 :: ByteString -> Word128-get128 (B.PS ps s _) = B.inlinePerformIO $ do- let ptr = castPtr (unsafeForeignPtrToPtr ps `plusPtr` s) :: Ptr Word64- a <- peek ptr- b <- peek (ptr `plusPtr` 8)- return $ Word128 a b--xor128 :: Word128 -> Word128 -> Word128-xor128 (Word128 a1 b1) (Word128 a2 b2) = Word128 (a1 `xor` a2) (b1 `xor` b2)--add64 :: Word128 -> Word128-add64 (Word128 a b) = if nb < 64 then Word128 (a+1) nb else Word128 a nb- where nb = b + 64+getNbChunksGenerated (RNG _ c _) = c -{--withBsPtr :: ByteString -> (Ptr Word8 -> IO a) -> IO a-withBsPtr (B.PS ps s _) f = withForeignPtr ps $ \ptr -> f (ptr `plusPtr` s)--}+makeParams :: ByteString -> (AES.AES, AES.AESIV)+makeParams b = key `seq` iv `seq` (key, iv)+ where (keyBS, r1) = B.splitAt 32 b+ (cnt, _) = B.splitAt 16 r1+ !key = AES.initAES keyBS+ !iv = AES.aesIV_ $ B.copy cnt -makeParams :: ByteString -> (AES.AES, ByteString, ByteString)-makeParams b = (key, cnt, iv)- where- key = AES.initAES $ B.take 32 left2- (cnt, left2) = B.splitAt 16 left1- (iv, left1) = B.splitAt 16 b+makeRNG :: ByteString -> RNG+makeRNG b = RNG iv 0 key+ where (key,iv) = makeParams b chunkSize :: Int chunkSize = 1024 genNextChunk :: RNG -> (ByteString, RNG)-genNextChunk (RNG iv counter nbChunks key) = (chunk, newrng)+genNextChunk (RNG counter nbChunks key) =+ chunk `seq` newrng `seq` (chunk, newrng) where- newrng = RNG (get128 chunk) (add64 counter) (nbChunks+1) key- chunk = AES.genCTR key bytes chunkSize- bytes = put128 (iv `xor128` counter)+ newrng = RNG newCounter (nbChunks+1) key+ (chunk,newCounter) = AES.genCounter key counter chunkSize
cprng-aes.cabal view
@@ -1,5 +1,5 @@ Name: cprng-aes-Version: 0.5.2+Version: 0.6.1 Description: Simple crypto pseudo-random-number-generator with really good randomness property. .@@ -34,13 +34,12 @@ Build-Depends: base >= 3 && < 5 , bytestring , byteable- , random , crypto-random >= 0.0.7 && < 0.1+ , cipher-aes >= 0.2.9 && < 0.3+ Exposed-modules: Crypto.Random.AESCtr Other-modules: Crypto.Random.AESCtr.Internal ghc-options: -Wall-- Build-Depends: cipher-aes >= 0.2 && < 0.3 Benchmark bench-cprng-aes hs-source-dirs: Benchmarks