[PubKey] move ElGamal to use HashAlgorithm and ByteArrayAccess.

This commit is contained in:
Vincent Hanquez 2015-05-12 07:01:20 +01:00
parent 5d2b417854
commit fdf735d4e2

View File

@ -33,15 +33,15 @@ module Crypto.PubKey.ElGamal
) where ) where
import Data.Maybe (fromJust) import Data.Maybe (fromJust)
import Data.ByteString (ByteString)
import Crypto.Internal.Imports import Crypto.Internal.Imports
import Crypto.Internal.ByteArray (ByteArrayAccess)
import Crypto.Number.ModArithmetic (expSafe, expFast, inverse) import Crypto.Number.ModArithmetic (expSafe, expFast, inverse)
import Crypto.Number.Generate (generateMax) import Crypto.Number.Generate (generateMax)
import Crypto.Number.Serialize (os2ip) import Crypto.Number.Serialize (os2ip)
import Crypto.Number.Basic (gcde) import Crypto.Number.Basic (gcde)
import Crypto.Random.Types import Crypto.Random.Types
import Crypto.PubKey.HashDescr (HashFunction)
import Crypto.PubKey.DH (PrivateNumber(..), PublicNumber(..), Params(..), SharedKey(..)) import Crypto.PubKey.DH (PrivateNumber(..), PublicNumber(..), Params(..), SharedKey(..))
import Crypto.Hash
-- | ElGamal Signature -- | ElGamal Signature
data Signature = Signature (Integer, Integer) data Signature = Signature (Integer, Integer)
@ -95,18 +95,19 @@ decrypt (Params p _) (PrivateNumber a) (c1,c2) = (c2 * sm1) `mod` p
-- with some appropriate value of k, the signature generation can fail, -- with some appropriate value of k, the signature generation can fail,
-- and no signature is returned. User of this function need to retry -- and no signature is returned. User of this function need to retry
-- with a different k value. -- with a different k value.
signWith :: Integer -- ^ random number k, between 0 and p-1 and gcd(k,p-1)=1 signWith :: (ByteArrayAccess msg, HashAlgorithm hash)
=> Integer -- ^ random number k, between 0 and p-1 and gcd(k,p-1)=1
-> Params -- ^ DH params (p,g) -> Params -- ^ DH params (p,g)
-> PrivateNumber -- ^ DH private key -> PrivateNumber -- ^ DH private key
-> HashFunction -- ^ collision resistant hash function -> hash -- ^ collision resistant hash algorithm
-> ByteString -- ^ message to sign -> msg -- ^ message to sign
-> Maybe Signature -> Maybe Signature
signWith k (Params p g) (PrivateNumber x) hashF msg signWith k (Params p g) (PrivateNumber x) hashAlg msg
| k >= p-1 || d > 1 = Nothing -- gcd(k,p-1) is not 1 | k >= p-1 || d > 1 = Nothing -- gcd(k,p-1) is not 1
| s == 0 = Nothing | s == 0 = Nothing
| otherwise = Just $ Signature (r,s) | otherwise = Just $ Signature (r,s)
where r = expSafe g k p where r = expSafe g k p
h = os2ip $ hashF msg h = os2ip $ hashWith hashAlg msg
s = ((h - x*r) * kInv) `mod` (p-1) s = ((h - x*r) * kInv) `mod` (p-1)
(kInv,_,d) = gcde k (p-1) (kInv,_,d) = gcde k (p-1)
@ -116,28 +117,29 @@ signWith k (Params p g) (PrivateNumber x) hashF msg
-- as the signature might fail, the function will automatically retry -- as the signature might fail, the function will automatically retry
-- until a proper signature has been created. -- until a proper signature has been created.
-- --
sign :: MonadRandom m sign :: (ByteArrayAccess msg, HashAlgorithm hash, MonadRandom m)
=> Params -- ^ DH params (p,g) => Params -- ^ DH params (p,g)
-> PrivateNumber -- ^ DH private key -> PrivateNumber -- ^ DH private key
-> HashFunction -- ^ collision resistant hash function -> hash -- ^ collision resistant hash algorithm
-> ByteString -- ^ message to sign -> msg -- ^ message to sign
-> m Signature -> m Signature
sign params@(Params p _) priv hashF msg = do sign params@(Params p _) priv hashAlg msg = do
k <- generateMax (p-1) k <- generateMax (p-1)
case signWith k params priv hashF msg of case signWith k params priv hashAlg msg of
Nothing -> sign params priv hashF msg Nothing -> sign params priv hashAlg msg
Just sig -> return sig Just sig -> return sig
-- | verify a signature -- | verify a signature
verify :: Params verify :: (ByteArrayAccess msg, HashAlgorithm hash)
=> Params
-> PublicNumber -> PublicNumber
-> HashFunction -> hash
-> ByteString -> msg
-> Signature -> Signature
-> Bool -> Bool
verify (Params p g) (PublicNumber y) hashF msg (Signature (r,s)) verify (Params p g) (PublicNumber y) hashAlg msg (Signature (r,s))
| or [r <= 0,r >= p,s <= 0,s >= (p-1)] = False | or [r <= 0,r >= p,s <= 0,s >= (p-1)] = False
| otherwise = lhs == rhs | otherwise = lhs == rhs
where h = os2ip $ hashF msg where h = os2ip $ hashWith hashAlg msg
lhs = expFast g h p lhs = expFast g h p
rhs = (expFast y r p * expFast r s p) `mod` p rhs = (expFast y r p * expFast r s p) `mod` p