module Data.X509.Validation.Signature
( verifySignedSignature
, verifySignature
, SignatureVerification(..)
, SignatureFailure(..)
) where
import qualified Crypto.PubKey.RSA.PKCS15 as RSA
import qualified Crypto.PubKey.DSA as DSA
import Crypto.Hash
import Data.ByteString (ByteString)
import Data.X509
import Data.ASN1.Types
import Data.ASN1.Encoding
import Data.ASN1.BinaryEncoding
data SignatureVerification =
SignaturePass
| SignatureFailed SignatureFailure
deriving (Show,Eq)
data SignatureFailure =
SignatureInvalid
| SignaturePubkeyMismatch
| SignatureUnimplemented
deriving (Show,Eq)
verifySignedSignature :: (Show a, Eq a, ASN1Object a)
=> SignedExact a
-> PubKey
-> SignatureVerification
verifySignedSignature signedObj pubKey =
verifySignature (signedAlg signed)
pubKey
(getSignedData signedObj)
(signedSignature signed)
where signed = getSigned signedObj
verifySignature :: SignatureALG
-> PubKey
-> ByteString
-> ByteString
-> SignatureVerification
verifySignature (SignatureALG_Unknown _) _ _ _ = SignatureFailed SignatureUnimplemented
verifySignature (SignatureALG hashALG pubkeyALG) pubkey cdata signature
| pubkeyToAlg pubkey == pubkeyALG = case verifyF pubkey of
Nothing -> SignatureFailed SignatureUnimplemented
Just f -> if f cdata signature
then SignaturePass
else SignatureFailed SignatureInvalid
| otherwise = SignatureFailed SignaturePubkeyMismatch
where
verifyF (PubKeyRSA key) = Just $ rsaVerify hashALG key
verifyF (PubKeyDSA key)
| hashALG == HashSHA1 = Just $ \a b -> case dsaToSignature a of
Nothing -> False
Just dsaSig -> DSA.verify SHA1 key dsaSig b
| otherwise = Nothing
verifyF _ = Nothing
dsaToSignature :: ByteString -> Maybe DSA.Signature
dsaToSignature b =
case decodeASN1' BER b of
Left _ -> Nothing
Right asn1 ->
case asn1 of
Start Sequence:IntVal r:IntVal s:End Sequence:_ ->
Just $ DSA.Signature { DSA.sign_r = r, DSA.sign_s = s }
_ ->
Nothing
rsaVerify HashMD2 = RSA.verify (Just MD2)
rsaVerify HashMD5 = RSA.verify (Just MD5)
rsaVerify HashSHA1 = RSA.verify (Just SHA1)
rsaVerify HashSHA224 = RSA.verify (Just SHA224)
rsaVerify HashSHA256 = RSA.verify (Just SHA256)
rsaVerify HashSHA384 = RSA.verify (Just SHA384)
rsaVerify HashSHA512 = RSA.verify (Just SHA512)