From 4c6b774a3d8c7059c7f985a2fd94e35129726a31 Mon Sep 17 00:00:00 2001 From: Clint Adams Date: Sun, 10 Jan 2016 17:05:37 -0500 Subject: [PATCH] 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. --- Crypto/PubKey/DSA.hs | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/Crypto/PubKey/DSA.hs b/Crypto/PubKey/DSA.hs index d3493e4..1587c46 100644 --- a/Crypto/PubKey/DSA.hs +++ b/Crypto/PubKey/DSA.hs @@ -29,14 +29,17 @@ module Crypto.PubKey.DSA ) where import Crypto.Random.Types +import Data.Bits (testBit) import Data.Data import Data.Maybe +import Crypto.Number.Basic (numBits) import Crypto.Number.ModArithmetic (expFast, expSafe, inverse) import Crypto.Number.Serialize 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.Hash +import Prelude hiding (length) -- | DSA Public Number, usually embedded in DSA Public Key type PublicNumber = Integer @@ -145,9 +148,11 @@ verify hashAlg pk (Signature r s) m | otherwise = v == r where (Params p g q) = public_params pk y = public_y pk - hm = os2ip $ hashWith hashAlg m + hm = os2ip . truncateHash $ hashWith hashAlg m w = fromJust $ inverse s q u1 = (hm*w) `mod` q u2 = (r*w) `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