[number] remove the need for a random generator for testing primality
a DRG is implicitely created when calling the non gmp primality test
This commit is contained in:
parent
ed48246740
commit
c0e50547ad
@ -26,6 +26,7 @@ import Crypto.Number.Generate
|
|||||||
import Crypto.Number.Basic (sqrti, gcde)
|
import Crypto.Number.Basic (sqrti, gcde)
|
||||||
import Crypto.Number.ModArithmetic (expSafe)
|
import Crypto.Number.ModArithmetic (expSafe)
|
||||||
import Crypto.Random.Types
|
import Crypto.Random.Types
|
||||||
|
import Crypto.Random.Probabilistic
|
||||||
|
|
||||||
import Data.Bits
|
import Data.Bits
|
||||||
|
|
||||||
@ -33,17 +34,17 @@ import Data.Bits
|
|||||||
-- first a list of small primes are implicitely tested for divisibility,
|
-- first a list of small primes are implicitely tested for divisibility,
|
||||||
-- then a fermat primality test is used with arbitrary numbers and
|
-- then a fermat primality test is used with arbitrary numbers and
|
||||||
-- then the Miller Rabin algorithm is used with an accuracy of 30 recursions
|
-- then the Miller Rabin algorithm is used with an accuracy of 30 recursions
|
||||||
isProbablyPrime :: MonadRandom m => Integer -> m Bool
|
isProbablyPrime :: Integer -> Bool
|
||||||
isProbablyPrime !n
|
isProbablyPrime !n
|
||||||
| any (\p -> p `divides` n) (filter (< n) firstPrimes) = return False
|
| any (\p -> p `divides` n) (filter (< n) firstPrimes) = False
|
||||||
| primalityTestFermat 50 (n`div`2) n = primalityTestMillerRabin 30 n
|
| primalityTestFermat 50 (n`div`2) n = primalityTestMillerRabin 30 n
|
||||||
| otherwise = return False
|
| otherwise = False
|
||||||
|
|
||||||
-- | generate a prime number of the required bitsize
|
-- | generate a prime number of the required bitsize
|
||||||
generatePrime :: MonadRandom m => Int -> m Integer
|
generatePrime :: MonadRandom m => Int -> m Integer
|
||||||
generatePrime bits = do
|
generatePrime bits = do
|
||||||
sp <- generateOfSize bits
|
sp <- generateParams bits (Just SetTwoHighest) True
|
||||||
findPrimeFrom sp
|
return $ findPrimeFrom sp
|
||||||
|
|
||||||
-- | generate a prime number of the form 2p+1 where p is also prime.
|
-- | generate a prime number of the form 2p+1 where p is also prime.
|
||||||
-- it is also knowed as a Sophie Germaine prime or safe prime.
|
-- it is also knowed as a Sophie Germaine prime or safe prime.
|
||||||
@ -53,37 +54,35 @@ generatePrime bits = do
|
|||||||
generateSafePrime :: MonadRandom m => Int -> m Integer
|
generateSafePrime :: MonadRandom m => Int -> m Integer
|
||||||
generateSafePrime bits = do
|
generateSafePrime bits = do
|
||||||
sp <- generateOfSize bits
|
sp <- generateOfSize bits
|
||||||
p <- findPrimeFromWith (\i -> isProbablyPrime (2*i+1)) (sp `div` 2)
|
let p = findPrimeFromWith (\i -> isProbablyPrime (2*i+1)) (sp `div` 2)
|
||||||
return (2*p+1)
|
return (2*p+1)
|
||||||
|
|
||||||
-- | find a prime from a starting point where the property hold.
|
-- | find a prime from a starting point where the property hold.
|
||||||
findPrimeFromWith :: MonadRandom m => (Integer -> m Bool) -> Integer -> m Integer
|
findPrimeFromWith :: (Integer -> Bool) -> Integer -> Integer
|
||||||
findPrimeFromWith prop !n
|
findPrimeFromWith prop !n
|
||||||
| even n = findPrimeFromWith prop (n+1)
|
| even n = findPrimeFromWith prop (n+1)
|
||||||
| otherwise = do
|
| otherwise =
|
||||||
primed <- isProbablyPrime n
|
if not (isProbablyPrime n)
|
||||||
if not primed
|
|
||||||
then findPrimeFromWith prop (n+2)
|
then findPrimeFromWith prop (n+2)
|
||||||
else do
|
else
|
||||||
validate <- prop n
|
if prop n
|
||||||
if validate
|
then n
|
||||||
then return n
|
|
||||||
else findPrimeFromWith prop (n+2)
|
else findPrimeFromWith prop (n+2)
|
||||||
|
|
||||||
-- | find a prime from a starting point with no specific property.
|
-- | find a prime from a starting point with no specific property.
|
||||||
findPrimeFrom :: MonadRandom m => Integer -> m Integer
|
findPrimeFrom :: Integer -> Integer
|
||||||
findPrimeFrom n =
|
findPrimeFrom n =
|
||||||
case gmpNextPrime n of
|
case gmpNextPrime n of
|
||||||
GmpSupported p -> return p
|
GmpSupported p -> p
|
||||||
GmpUnsupported -> findPrimeFromWith (\_ -> return True) n
|
GmpUnsupported -> findPrimeFromWith (\_ -> True) n
|
||||||
|
|
||||||
-- | Miller Rabin algorithm return if the number is probably prime or composite.
|
-- | Miller Rabin algorithm return if the number is probably prime or composite.
|
||||||
-- the tries parameter is the number of recursion, that determines the accuracy of the test.
|
-- the tries parameter is the number of recursion, that determines the accuracy of the test.
|
||||||
primalityTestMillerRabin :: MonadRandom m => Int -> Integer -> m Bool
|
primalityTestMillerRabin :: Int -> Integer -> Bool
|
||||||
primalityTestMillerRabin tries !n =
|
primalityTestMillerRabin tries !n =
|
||||||
case gmpTestPrimeMillerRabin tries n of
|
case gmpTestPrimeMillerRabin tries n of
|
||||||
GmpSupported b -> return b
|
GmpSupported b -> b
|
||||||
GmpUnsupported -> run
|
GmpUnsupported -> probabilistic run
|
||||||
where
|
where
|
||||||
run
|
run
|
||||||
| n <= 3 = error "Miller-Rabin requires tested value to be > 3"
|
| n <= 3 = error "Miller-Rabin requires tested value to be > 3"
|
||||||
|
|||||||
28
Crypto/Random/Probabilistic.hs
Normal file
28
Crypto/Random/Probabilistic.hs
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
-- |
|
||||||
|
-- Module : Crypto.Random.Probabilistic
|
||||||
|
-- License : BSD-style
|
||||||
|
-- Maintainer : Vincent Hanquez <vincent@snarc.org>
|
||||||
|
-- Stability : experimental
|
||||||
|
-- Portability : Good
|
||||||
|
--
|
||||||
|
module Crypto.Random.Probabilistic
|
||||||
|
( probabilistic
|
||||||
|
) where
|
||||||
|
|
||||||
|
import Crypto.Internal.Compat
|
||||||
|
import Crypto.Random.Types
|
||||||
|
import Crypto.Random
|
||||||
|
|
||||||
|
-- | This create a random number generator out of thin air with
|
||||||
|
-- the system entropy; don't generally use as the IO is not exposed
|
||||||
|
-- this can have unexpected random for.
|
||||||
|
--
|
||||||
|
-- This is useful for probabilistic algorithm like Miller Rabin
|
||||||
|
-- probably prime algorithm, given appropriate choice of the heuristic
|
||||||
|
--
|
||||||
|
-- Generally, it's advise not to use this function.
|
||||||
|
probabilistic :: MonadPseudoRandom ChaChaDRG a -> a
|
||||||
|
probabilistic f = fst $ withDRG drg f
|
||||||
|
where {-# NOINLINE drg #-}
|
||||||
|
drg = unsafeDoIO drgNew
|
||||||
|
{-# NOINLINE probabilistic #-}
|
||||||
@ -147,6 +147,7 @@ Library
|
|||||||
Crypto.Random.Entropy.Source
|
Crypto.Random.Entropy.Source
|
||||||
Crypto.Random.Entropy.Backend
|
Crypto.Random.Entropy.Backend
|
||||||
Crypto.Random.ChaChaDRG
|
Crypto.Random.ChaChaDRG
|
||||||
|
Crypto.Random.Probabilistic
|
||||||
Crypto.PubKey.Internal
|
Crypto.PubKey.Internal
|
||||||
Crypto.PubKey.ElGamal
|
Crypto.PubKey.ElGamal
|
||||||
Crypto.Internal.ByteArray
|
Crypto.Internal.ByteArray
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user