Permalink
Browse files

Fix generate(Safe)Prime to guarantee prime size

Add check for size in generatePrime

Add size test in generateSafePrime

Require only that top bit is set, instead of top 2

This is the general standard, see e.g. OpenSSL

Add an error for too few bits being supplied to prime generator, and add documentation

Add some documentation and require highest two bits set

Simplify return syntax in generatePrime and generateSafePrime

Switch exponent to bit-shift for small performance boost
  • Loading branch information...
colatkinson committed Dec 24, 2016
1 parent 16fc2a3 commit 0cec622ddf7d344669797f460806cec737b812ac
Showing with 34 additions and 7 deletions.
  1. +2 −0 .gitignore
  2. +2 −0 Crypto/Error/Types.hs
  3. +29 −6 Crypto/Number/Prime.hs
  4. +1 −1 cryptonite.cabal
View
@@ -10,3 +10,5 @@ QA
benchs/Bench
benchs/Hash
*.sublime-workspace
.cabal-sandbox/
cabal.sandbox.config
View
@@ -43,6 +43,8 @@ data CryptoError =
-- Message authentification error
| CryptoError_MacKeyInvalid
| CryptoError_AuthenticationTagSizeInvalid
-- Prime generation error
| CryptoError_PrimeSizeInvalid
deriving (Show,Eq,Enum,Data,Typeable)
instance E.Exception CryptoError
View
@@ -27,6 +27,7 @@ import Crypto.Number.Basic (sqrti, gcde)
import Crypto.Number.ModArithmetic (expSafe)
import Crypto.Random.Types
import Crypto.Random.Probabilistic
import Crypto.Error
import Data.Bits
@@ -40,22 +41,44 @@ isProbablyPrime !n
| primalityTestFermat 50 (n`div`2) n = primalityTestMillerRabin 30 n
| otherwise = False
-- | generate a prime number of the required bitsize
-- | generate a prime number of the required bitsize (i.e. in the range
-- [2^(b-1)+2^(b-2), 2^b)).
--
-- May throw a CryptoError_PrimeSizeInvalid if the requested size is less
-- than 5 bits, as the smallest prime meeting these conditions is 29.
-- This function requires that the two highest bits are set, so that when
-- multiplied with another prime to create a key, it is guaranteed to be of
-- the proper size.
generatePrime :: MonadRandom m => Int -> m Integer
generatePrime bits = do
sp <- generateParams bits (Just SetTwoHighest) True
return $ findPrimeFrom sp
if bits < 5 then
throwCryptoError $ CryptoFailed $ CryptoError_PrimeSizeInvalid
else do
sp <- generateParams bits (Just SetTwoHighest) True
let prime = findPrimeFrom sp
if prime < 1 `shiftL` bits then
return $ prime
else generatePrime bits
-- | 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.
--
-- The number of safe prime is significantly smaller to the number of prime,
-- as such it shouldn't be used if this number is supposed to be kept safe.
--
-- May throw a CryptoError_PrimeSizeInvalid if the requested size is less than
-- 6 bits, as the smallest safe prime with the two highest bits set is 59.
generateSafePrime :: MonadRandom m => Int -> m Integer
generateSafePrime bits = do
sp <- generateParams bits (Just SetTwoHighest) True
let p = findPrimeFromWith (\i -> isProbablyPrime (2*i+1)) (sp `div` 2)
return (2*p+1)
if bits < 6 then
throwCryptoError $ CryptoFailed $ CryptoError_PrimeSizeInvalid
else do
sp <- generateParams bits (Just SetTwoHighest) True
let p = findPrimeFromWith (\i -> isProbablyPrime (2*i+1)) (sp `div` 2)
let val = 2 * p + 1
if val < 1 `shiftL` bits then
return $ val
else generateSafePrime bits
-- | find a prime from a starting point where the property hold.
findPrimeFromWith :: (Integer -> Bool) -> Integer -> Integer
View
@@ -205,7 +205,7 @@ Library
, bytestring
, memory >= 0.8
, ghc-prim
ghc-options: -Wall -fwarn-tabs -optc-O3 -fno-warn-unused-imports
ghc-options: -Wall -fwarn-tabs -optc-O3 -fno-warn-unused-imports -fobject-code
default-language: Haskell2010
cc-options: -std=gnu99
if flag(old_toolchain_inliner)

0 comments on commit 0cec622

Please sign in to comment.