Do DSS truncation on verify

RFC 4880 and FIPS 186-4 require that DSA signatures truncate the
hash to the size of q.  This changes Crypto.PubKey.DSA.verify
to do so in all cases.
This commit is contained in:
Clint Adams 2016-01-10 17:05:37 -05:00
parent 08edce4ec7
commit 4c6b774a3d

View File

@ -29,14 +29,17 @@ module Crypto.PubKey.DSA
) where ) where
import Crypto.Random.Types import Crypto.Random.Types
import Data.Bits (testBit)
import Data.Data import Data.Data
import Data.Maybe import Data.Maybe
import Crypto.Number.Basic (numBits)
import Crypto.Number.ModArithmetic (expFast, expSafe, inverse) import Crypto.Number.ModArithmetic (expFast, expSafe, inverse)
import Crypto.Number.Serialize import Crypto.Number.Serialize
import Crypto.Number.Generate import Crypto.Number.Generate
import Crypto.Internal.ByteArray (ByteArrayAccess) import Crypto.Internal.ByteArray (ByteArrayAccess(length), convert, index, dropView, takeView)
import Crypto.Internal.Imports import Crypto.Internal.Imports
import Crypto.Hash import Crypto.Hash
import Prelude hiding (length)
-- | DSA Public Number, usually embedded in DSA Public Key -- | DSA Public Number, usually embedded in DSA Public Key
type PublicNumber = Integer type PublicNumber = Integer
@ -145,9 +148,11 @@ verify hashAlg pk (Signature r s) m
| otherwise = v == r | otherwise = v == r
where (Params p g q) = public_params pk where (Params p g q) = public_params pk
y = public_y pk y = public_y pk
hm = os2ip $ hashWith hashAlg m hm = os2ip . truncateHash $ hashWith hashAlg m
w = fromJust $ inverse s q w = fromJust $ inverse s q
u1 = (hm*w) `mod` q u1 = (hm*w) `mod` q
u2 = (r*w) `mod` q u2 = (r*w) `mod` q
v = ((expFast g u1 p) * (expFast y u2 p)) `mod` p `mod` q v = ((expFast g u1 p) * (expFast y u2 p)) `mod` p `mod` q
-- if the hash is larger than the size of q, truncate it; FIXME: deal with the case of a q not evenly divisible by 8
truncateHash h = if numBits (os2ip h) > numBits q then takeView h (numBits q `div` 8) else dropView h 0