cprng-aes (empty) → 0.1.0
raw patch · 5 files changed
+202/−0 lines, 5 filesdep +basedep +bytestringdep +cerealsetup-changed
Dependencies added: base, bytestring, cereal, crypto-api, cryptocipher
Files
- Crypto/Random/AESCtr.hs +114/−0
- LICENSE +27/−0
- README.md +15/−0
- Setup.hs +2/−0
- cprng-aes.cabal +44/−0
+ Crypto/Random/AESCtr.hs view
@@ -0,0 +1,114 @@+-- |+-- Module : Crypto.Random.AESCtr+-- License : BSD-style+-- Maintainer : Vincent Hanquez <vincent@snarc.org>+-- Stability : stable+-- Portability : unknown+--+-- this CPRNG is an AES cbc based counter system.+--+-- the internal size of fields are: 16 bytes IV, 16 bytes counter, 32 bytes key+--+-- each block are generated the following way:+-- (IV `xor` counter) `aes` key -> 16 bytes output+--++module Crypto.Random.AESCtr+ ( AESRNG+ , make+ , makeSystem+ , getRandomBytes+ ) where++import Control.Applicative ((<$>))++import Crypto.Random+import System.Crypto.Random (getEntropy)+import qualified Crypto.Cipher.AES as AES++import Data.ByteString (ByteString)+import qualified Data.ByteString as B++import Data.Word+import Data.Bits (xor)+import Data.Serialize++data Word128 = Word128 !Word64 !Word64++{-| An opaque object containing an AES CPRNG -}+data AESRNG = RNG !ByteString !Word128 !AES.Key++instance Show AESRNG where+ show _ = "aesrng[..]"++put128 :: Word128 -> ByteString+put128 (Word128 a b) = runPut (putWord64host a >> putWord64host b)++get128 :: ByteString -> Word128+get128 = either (\_ -> Word128 0 0) id . runGet (getWord64host >>= \a -> (getWord64host >>= \b -> return $ Word128 a b))++add1 :: Word128 -> Word128+add1 (Word128 a b) = if b == 0xffffffffffffffff then Word128 (a+1) 0 else Word128 a (b+1)++makeParams :: ByteString -> (AES.Key, ByteString, ByteString)+makeParams b = (key, cnt, iv)+ where+ (Right key) = AES.initKey256 $ B.take 32 left2+ (cnt, left2) = B.splitAt 16 left1+ (iv, left1) = B.splitAt 16 b++-- | make an AESRNG from a bytestring. the bytestring need to be at least 64 bytes.+-- if the bytestring is longer, the extra bytes will be ignored and will not take part in+-- the initialization.+make :: B.ByteString -> Either GenError AESRNG+make b+ | B.length b < 64 = Left NotEnoughEntropy+ | otherwise = Right $ RNG iv (get128 cnt) key+ where+ (key, cnt, iv) = makeParams b++chunkSize :: Int+chunkSize = 16++bxor :: ByteString -> ByteString -> ByteString+bxor a b = B.pack $ B.zipWith xor a b++nextChunk :: AESRNG -> (ByteString, AESRNG)+nextChunk (RNG iv counter key) = (chunk, newrng)+ where+ newrng = RNG chunk (add1 counter) key+ chunk = AES.encryptCBC key iv bytes+ bytes = iv `bxor` (put128 counter)++-- | Initialize a new AESRng using the system entropy.+makeSystem :: IO AESRNG+makeSystem = ofRight . make <$> getEntropy 64+ where+ ofRight (Left _) = error "ofRight on a Left value"+ ofRight (Right x) = x++-- | get a Random number of bytes from the RNG.+-- for efficienty and not wasted any randomness, it's better to generate+-- bytes on multiple of 16, however it will works for any size.+getRandomBytes :: AESRNG -> Int -> (ByteString, AESRNG)+getRandomBytes rng n =+ let list = helper rng n in+ (B.concat $ map fst list, snd $ last list)+ where+ helper _ 0 = []+ helper g i =+ let (b, g') = nextChunk g in+ if chunkSize >= i+ then [ (B.take i b, g') ]+ else (b, g') : helper g' (i-chunkSize)++instance CryptoRandomGen AESRNG where+ newGen = make+ genSeedLength = 64+ genBytes len rng = Right $ getRandomBytes rng len+ reseed b rng@(RNG _ cnt1 _)+ | B.length b < 64 = Left NotEnoughEntropy+ | otherwise = Right $ RNG (r16 `bxor` iv2) (get128 (put128 cnt1 `bxor` cnt2)) key2+ where+ (r16, _) = nextChunk rng+ (key2, cnt2, iv2) = makeParams b
+ LICENSE view
@@ -0,0 +1,27 @@+Copyright (c) 2010-2011 Vincent Hanquez <vincent@snarc.org>++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 REGENTS AND 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.
+ README.md view
@@ -0,0 +1,15 @@+CPRNG-AES+=========++This module provides a crypto pseudo random number generator using AES in counter mode.++to import:++ import Crypto.Random.AESCtr++to use:++ rng <- makeSystem+ let (ran, rng') = getRandomBytes rng 1024++it's also an instance of CryptoRandomGen from the crypto-api package.
+ Setup.hs view
@@ -0,0 +1,2 @@+import Distribution.Simple+main = defaultMain
+ cprng-aes.cabal view
@@ -0,0 +1,44 @@+Name: cprng-aes+Version: 0.1.0+Description: + Simple crypto pseudo-random-number-generator with really good randomness property.+ .+ Using ent, a randomness property maker on one 1Mb sample:+ Entropy = 7.999837 bits per byte.+ Optimum compression would reduce the size of this 1048576 byte file by 0 percent.+ Chi square distribution for 1048576 samples is 237.02+ Arithmetic mean value of data bytes is 127.3422 (127.5 = random)+ Monte Carlo value for Pi is 3.143589568 (error 0.06 percent)+ .+ Compared to urandom with the same sampling:+ Entropy = 7.999831 bits per byte.+ Optimum compression would reduce the size of this 1048576 byte file by 0 percent.+ Chi square distribution for 1048576 samples is 246.63 + Arithmetic mean value of data bytes is 127.6347 (127.5 = random).+ Monte Carlo value for Pi is 3.132465868 (error 0.29 percent).++License: BSD3+License-file: LICENSE+Copyright: Vincent Hanquez <vincent@snarc.org>+Author: Vincent Hanquez <vincent@snarc.org>+Maintainer: Vincent Hanquez <vincent@snarc.org>+Synopsis: Crypto Pseudo Random Number Generator using AES in counter mode.+Build-Type: Simple+Category: Cryptography+stability: experimental+Cabal-Version: >=1.6+Homepage: http://github.com/vincenthz/hs-cprng-aes+data-files: README.md++Library+ Build-Depends: base >= 3 && < 5+ , bytestring+ , crypto-api >= 0.5+ , cryptocipher >= 0.2.5 && < 0.3.0+ , cereal >= 0.3.0 && < 0.4.0+ Exposed-modules: Crypto.Random.AESCtr+ ghc-options: -Wall++source-repository head+ type: git+ location: git://github.com/vincenthz/hs-cprng-aes