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 qualified Crypto.Hash.SHA1 as SHA1
import Data.ByteString (ByteString)
import Data.X509
import Data.X509.Validation.Fingerprint
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 $ RSA.verify (toDescr hashALG) key
verifyF (PubKeyDSA key)
| hashALG == HashSHA1 = Just $ \a b -> case dsaToSignature a of
Nothing -> False
Just dsaSig -> DSA.verify SHA1.hash key dsaSig b
| otherwise = Nothing
verifyF _ = Nothing
dsaToSignature :: ByteString -> Maybe DSA.Signature
dsaToSignature b =
case decodeASN1' BER b of
Left _ -> Nothing
Right asn1 -> case fromASN1 asn1 of
Left _ -> Nothing
Right (dsaSig, _) -> Just dsaSig