module Network.DomainAuth.DKIM.Verify (
verifyDKIM, prepareDKIM
) where
import Blaze.ByteString.Builder
import Codec.Crypto.RSA
import Data.ByteString (ByteString)
import qualified Data.ByteString as BS
import qualified Data.ByteString.Lazy as BL
import Data.Digest.Pure.SHA
import Network.DomainAuth.DKIM.Btag
import Network.DomainAuth.DKIM.Types
import Network.DomainAuth.Mail
import qualified Network.DomainAuth.Pubkey.Base64 as B
import Network.DomainAuth.Utils
prepareDKIM :: DKIM -> Mail -> Builder
prepareDKIM dkim mail = header
where
dkimField:fields = fieldsFrom dkimFieldKey (mailHeader mail)
hCanon = canonDkimField (dkimHeaderCanon dkim)
canon = fromByteString . removeBtagValue . hCanon
targets = fieldsWith (dkimFields dkim) fields
header = concatCRLFWith hCanon targets +++ canon dkimField
canonDkimField :: DkimCanonAlgo -> Field -> ByteString
canonDkimField DKIM_SIMPLE fld = fieldKey fld +++ ": " +++ fieldValueFolded fld
canonDkimField DKIM_RELAXED fld = fieldSearchKey fld +++ ":" +++ canon fld
where
canon = BS.dropWhile isSpace . removeTrailingWSP . reduceWSP . BS.concat . fieldValue
canonDkimBody :: DkimCanonAlgo -> Body -> Builder
canonDkimBody DKIM_SIMPLE = fromBody . removeTrailingEmptyLine
canonDkimBody DKIM_RELAXED = fromBodyWith relax . removeTrailingEmptyLine
where
relax = removeTrailingWSP . reduceWSP
verifyDKIM :: Mail -> DKIM -> PublicKey -> Bool
verifyDKIM mail dkim pub = bodyHash1 mail == bodyHash2 dkim &&
rsassa_pkcs1_v1_5_verify hashfunc pub cmail sig
where
hashfunc = hashAlgo1 (dkimSigAlgo dkim)
hashfunc2 = hashAlgo2 (dkimSigAlgo dkim)
sig = B.decode . dkimSignature $ dkim
cmail = toLazyByteString (prepareDKIM dkim mail)
bodyHash1 = hashfunc2 . toLazyByteString . canonDkimBody (dkimBodyCanon dkim) . mailBody
bodyHash2 = B.decode . dkimBodyHash
hashAlgo1 :: DkimSigAlgo -> HashInfo
hashAlgo1 RSA_SHA1 = hashSHA1
hashAlgo1 RSA_SHA256 = hashSHA256
hashAlgo2 :: DkimSigAlgo -> BL.ByteString -> BL.ByteString
hashAlgo2 RSA_SHA1 = bytestringDigest . sha1
hashAlgo2 RSA_SHA256 = bytestringDigest . sha256