From d9b16a529e275a0dee7d03b2680a1e46537bd370 Mon Sep 17 00:00:00 2001 From: Vincent Hanquez Date: Sun, 29 Mar 2015 10:43:45 +0100 Subject: [PATCH] re-enable number generation --- Crypto/Number/Generate.hs | 46 +++++++++++++++++++++------------------ 1 file changed, 25 insertions(+), 21 deletions(-) diff --git a/Crypto/Number/Generate.hs b/Crypto/Number/Generate.hs index 5d6fea3..b650563 100644 --- a/Crypto/Number/Generate.hs +++ b/Crypto/Number/Generate.hs @@ -6,51 +6,55 @@ -- Portability : Good module Crypto.Number.Generate - ( {-generateMax + ( generateMax , generateBetween , generateOfSize - , generateBits-} + , generateBits ) where +import Control.Applicative import Crypto.Number.Basic import Crypto.Number.Serialize +import Crypto.Random.Types import qualified Data.ByteString as B import Data.Bits ((.|.), (.&.), shiftR) -{- + -- | generate a positive integer x, s.t. 0 <= x < m -generateMax :: CPRG g => g -> Integer -> (Integer, g) -generateMax rng 1 = (0, rng) -generateMax rng m - | (result' >= m) = generateMax rng' m - | otherwise = (result', rng') +generateMax :: MonadRandom m => Integer -> m Integer +generateMax 1 = return 0 +generateMax m + | m <= 0 = error "negative value for generateMax" + | otherwise = do + result <- randomInt bytesLength + let result' = result `shiftR` bitsPoppedOff + if result' >= m + then generateMax m + else return result' where bytesLength = lengthBytes m - bitsLength = (log2 (m-1) + 1) + bitsLength = log2 (m-1) + 1 bitsPoppedOff = 8 - (bitsLength `mod` 8) - randomInt bytes = withRandomBytes rng bytes $ \bs -> os2ip bs - (result, rng') = randomInt bytesLength - result' = result `shiftR` bitsPoppedOff + randomInt nbBytes = os2ip <$> getRandomBytes nbBytes -- | generate a number between the inclusive bound [low,high]. -generateBetween :: CPRG g => g -> Integer -> Integer -> (Integer, g) -generateBetween rng low high = (low + v, rng') - where (v, rng') = generateMax rng (high - low + 1) +generateBetween :: MonadRandom m => Integer -> Integer -> m Integer +generateBetween low high = (low +) <$> generateMax (high - low + 1) -- | generate a positive integer of a specific size in bits. -- the number of bits need to be multiple of 8. It will always returns -- an integer that is close to 2^(1+bits/8) by setting the 2 highest bits to 1. -generateOfSize :: CPRG g => g -> Int -> (Integer, g) -generateOfSize rng bits = withRandomBytes rng (bits `div` 8) $ \bs -> - os2ip $ snd $ B.mapAccumL (\acc w -> (0, w .|. acc)) 0xc0 bs +generateOfSize :: MonadRandom m => Int -> m Integer +generateOfSize bits = toInteger <$> getRandomBytes (bits `div` 8) + where + toInteger bs = os2ip $ snd $ B.mapAccumL (\acc w -> (0, w .|. acc)) 0xc0 bs -- | Generate a number with the specified number of bits -generateBits :: CPRG g => g -> Int -> (Integer, g) -generateBits rng nbBits = withRandomBytes rng nbBytes' $ \bs -> modF (os2ip bs) +generateBits :: MonadRandom m => Int -> m Integer +generateBits nbBits = modF . os2ip <$> getRandomBytes nbBytes' where (nbBytes, strayBits) = nbBits `divMod` 8 nbBytes' | strayBits == 0 = nbBytes | otherwise = nbBytes + 1 modF | strayBits == 0 = id | otherwise = (.&.) (2^nbBits - 1) --}