module Data.X509.Validation.Signature
( verifySignedSignature
, verifySignature
, SignatureVerification(..)
, SignatureFailure(..)
) where
import Crypto.Error (CryptoFailable(..))
import qualified Crypto.PubKey.RSA.PKCS15 as RSA
import qualified Crypto.PubKey.RSA.PSS as PSS
import qualified Crypto.PubKey.DSA as DSA
import qualified Crypto.PubKey.ECC.Types as ECC
import qualified Crypto.PubKey.ECC.ECDSA as ECDSA
import qualified Crypto.PubKey.Ed25519 as Ed25519
import qualified Crypto.PubKey.Ed448 as Ed448
import Crypto.Hash
import Data.ByteString (ByteString)
import Data.X509
import Data.X509.EC
import Data.ASN1.Types
import Data.ASN1.Encoding
import Data.ASN1.BinaryEncoding
data SignatureVerification =
SignaturePass
| SignatureFailed SignatureFailure
deriving (Int -> SignatureVerification -> ShowS
[SignatureVerification] -> ShowS
SignatureVerification -> String
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [SignatureVerification] -> ShowS
$cshowList :: [SignatureVerification] -> ShowS
show :: SignatureVerification -> String
$cshow :: SignatureVerification -> String
showsPrec :: Int -> SignatureVerification -> ShowS
$cshowsPrec :: Int -> SignatureVerification -> ShowS
Show,SignatureVerification -> SignatureVerification -> Bool
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: SignatureVerification -> SignatureVerification -> Bool
$c/= :: SignatureVerification -> SignatureVerification -> Bool
== :: SignatureVerification -> SignatureVerification -> Bool
$c== :: SignatureVerification -> SignatureVerification -> Bool
Eq)
data SignatureFailure =
SignatureInvalid
| SignaturePubkeyMismatch
| SignatureUnimplemented
deriving (Int -> SignatureFailure -> ShowS
[SignatureFailure] -> ShowS
SignatureFailure -> String
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [SignatureFailure] -> ShowS
$cshowList :: [SignatureFailure] -> ShowS
show :: SignatureFailure -> String
$cshow :: SignatureFailure -> String
showsPrec :: Int -> SignatureFailure -> ShowS
$cshowsPrec :: Int -> SignatureFailure -> ShowS
Show,SignatureFailure -> SignatureFailure -> Bool
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: SignatureFailure -> SignatureFailure -> Bool
$c/= :: SignatureFailure -> SignatureFailure -> Bool
== :: SignatureFailure -> SignatureFailure -> Bool
$c== :: SignatureFailure -> SignatureFailure -> Bool
Eq)
verifySignedSignature :: (Show a, Eq a, ASN1Object a)
=> SignedExact a
-> PubKey
-> SignatureVerification
verifySignedSignature :: forall a.
(Show a, Eq a, ASN1Object a) =>
SignedExact a -> PubKey -> SignatureVerification
verifySignedSignature SignedExact a
signedObj PubKey
pubKey =
SignatureALG
-> PubKey -> ByteString -> ByteString -> SignatureVerification
verifySignature (forall a. (Show a, Eq a, ASN1Object a) => Signed a -> SignatureALG
signedAlg Signed a
signed)
PubKey
pubKey
(forall a.
(Show a, Eq a, ASN1Object a) =>
SignedExact a -> ByteString
getSignedData SignedExact a
signedObj)
(forall a. (Show a, Eq a, ASN1Object a) => Signed a -> ByteString
signedSignature Signed a
signed)
where signed :: Signed a
signed = forall a. (Show a, Eq a, ASN1Object a) => SignedExact a -> Signed a
getSigned SignedExact a
signedObj
verifySignature :: SignatureALG
-> PubKey
-> ByteString
-> ByteString
-> SignatureVerification
verifySignature :: SignatureALG
-> PubKey -> ByteString -> ByteString -> SignatureVerification
verifySignature (SignatureALG_Unknown OID
_) PubKey
_ ByteString
_ ByteString
_ = SignatureFailure -> SignatureVerification
SignatureFailed SignatureFailure
SignatureUnimplemented
verifySignature (SignatureALG HashALG
hashALG PubKeyALG
PubKeyALG_RSAPSS) PubKey
pubkey ByteString
cdata ByteString
signature = case PubKey -> Maybe (ByteString -> ByteString -> Bool)
verifyF PubKey
pubkey of
Maybe (ByteString -> ByteString -> Bool)
Nothing -> SignatureFailure -> SignatureVerification
SignatureFailed SignatureFailure
SignatureUnimplemented
Just ByteString -> ByteString -> Bool
f -> if ByteString -> ByteString -> Bool
f ByteString
cdata ByteString
signature
then SignatureVerification
SignaturePass
else SignatureFailure -> SignatureVerification
SignatureFailed SignatureFailure
SignatureInvalid
where
verifyF :: PubKey -> Maybe (ByteString -> ByteString -> Bool)
verifyF (PubKeyRSA PublicKey
key)
| HashALG
hashALG forall a. Eq a => a -> a -> Bool
== HashALG
HashSHA256 = forall a. a -> Maybe a
Just forall a b. (a -> b) -> a -> b
$ forall hash.
HashAlgorithm hash =>
PSSParams hash ByteString ByteString
-> PublicKey -> ByteString -> ByteString -> Bool
PSS.verify (forall seed output hash.
(ByteArrayAccess seed, ByteArray output, HashAlgorithm hash) =>
hash -> PSSParams hash seed output
PSS.defaultPSSParams SHA256
SHA256) PublicKey
key
| HashALG
hashALG forall a. Eq a => a -> a -> Bool
== HashALG
HashSHA384 = forall a. a -> Maybe a
Just forall a b. (a -> b) -> a -> b
$ forall hash.
HashAlgorithm hash =>
PSSParams hash ByteString ByteString
-> PublicKey -> ByteString -> ByteString -> Bool
PSS.verify (forall seed output hash.
(ByteArrayAccess seed, ByteArray output, HashAlgorithm hash) =>
hash -> PSSParams hash seed output
PSS.defaultPSSParams SHA384
SHA384) PublicKey
key
| HashALG
hashALG forall a. Eq a => a -> a -> Bool
== HashALG
HashSHA512 = forall a. a -> Maybe a
Just forall a b. (a -> b) -> a -> b
$ forall hash.
HashAlgorithm hash =>
PSSParams hash ByteString ByteString
-> PublicKey -> ByteString -> ByteString -> Bool
PSS.verify (forall seed output hash.
(ByteArrayAccess seed, ByteArray output, HashAlgorithm hash) =>
hash -> PSSParams hash seed output
PSS.defaultPSSParams SHA512
SHA512) PublicKey
key
| HashALG
hashALG forall a. Eq a => a -> a -> Bool
== HashALG
HashSHA224 = forall a. a -> Maybe a
Just forall a b. (a -> b) -> a -> b
$ forall hash.
HashAlgorithm hash =>
PSSParams hash ByteString ByteString
-> PublicKey -> ByteString -> ByteString -> Bool
PSS.verify (forall seed output hash.
(ByteArrayAccess seed, ByteArray output, HashAlgorithm hash) =>
hash -> PSSParams hash seed output
PSS.defaultPSSParams SHA224
SHA224) PublicKey
key
| Bool
otherwise = forall a. Maybe a
Nothing
verifyF PubKey
_ = forall a. Maybe a
Nothing
verifySignature (SignatureALG HashALG
hashALG PubKeyALG
pubkeyALG) PubKey
pubkey ByteString
cdata ByteString
signature
| PubKey -> PubKeyALG
pubkeyToAlg PubKey
pubkey forall a. Eq a => a -> a -> Bool
== PubKeyALG
pubkeyALG = case PubKey -> Maybe (ByteString -> ByteString -> Bool)
verifyF PubKey
pubkey of
Maybe (ByteString -> ByteString -> Bool)
Nothing -> SignatureFailure -> SignatureVerification
SignatureFailed SignatureFailure
SignatureUnimplemented
Just ByteString -> ByteString -> Bool
f -> if ByteString -> ByteString -> Bool
f ByteString
cdata ByteString
signature
then SignatureVerification
SignaturePass
else SignatureFailure -> SignatureVerification
SignatureFailed SignatureFailure
SignatureInvalid
| Bool
otherwise = SignatureFailure -> SignatureVerification
SignatureFailed SignatureFailure
SignaturePubkeyMismatch
where
verifyF :: PubKey -> Maybe (ByteString -> ByteString -> Bool)
verifyF (PubKeyRSA PublicKey
key) = forall a. a -> Maybe a
Just forall a b. (a -> b) -> a -> b
$ HashALG -> PublicKey -> ByteString -> ByteString -> Bool
rsaVerify HashALG
hashALG PublicKey
key
verifyF (PubKeyDSA PublicKey
key)
| HashALG
hashALG forall a. Eq a => a -> a -> Bool
== HashALG
HashSHA1 = forall a. a -> Maybe a
Just forall a b. (a -> b) -> a -> b
$ forall {msg} {hash}.
(ByteArrayAccess msg, HashAlgorithm hash) =>
hash -> PublicKey -> msg -> ByteString -> Bool
dsaVerify SHA1
SHA1 PublicKey
key
| HashALG
hashALG forall a. Eq a => a -> a -> Bool
== HashALG
HashSHA224 = forall a. a -> Maybe a
Just forall a b. (a -> b) -> a -> b
$ forall {msg} {hash}.
(ByteArrayAccess msg, HashAlgorithm hash) =>
hash -> PublicKey -> msg -> ByteString -> Bool
dsaVerify SHA224
SHA224 PublicKey
key
| HashALG
hashALG forall a. Eq a => a -> a -> Bool
== HashALG
HashSHA256 = forall a. a -> Maybe a
Just forall a b. (a -> b) -> a -> b
$ forall {msg} {hash}.
(ByteArrayAccess msg, HashAlgorithm hash) =>
hash -> PublicKey -> msg -> ByteString -> Bool
dsaVerify SHA256
SHA256 PublicKey
key
| Bool
otherwise = forall a. Maybe a
Nothing
verifyF (PubKeyEC PubKeyEC
key) = HashALG -> PubKeyEC -> Maybe (ByteString -> ByteString -> Bool)
verifyECDSA HashALG
hashALG PubKeyEC
key
verifyF PubKey
_ = forall a. Maybe a
Nothing
dsaToSignature :: ByteString -> Maybe DSA.Signature
dsaToSignature :: ByteString -> Maybe Signature
dsaToSignature ByteString
b =
case forall a.
ASN1Decoding a =>
a -> ByteString -> Either ASN1Error [ASN1]
decodeASN1' BER
BER ByteString
b of
Left ASN1Error
_ -> forall a. Maybe a
Nothing
Right [ASN1]
asn1 ->
case [ASN1]
asn1 of
Start ASN1ConstructionType
Sequence:IntVal Integer
r:IntVal Integer
s:End ASN1ConstructionType
Sequence:[ASN1]
_ ->
forall a. a -> Maybe a
Just forall a b. (a -> b) -> a -> b
$ DSA.Signature { sign_r :: Integer
DSA.sign_r = Integer
r, sign_s :: Integer
DSA.sign_s = Integer
s }
[ASN1]
_ ->
forall a. Maybe a
Nothing
dsaVerify :: hash -> PublicKey -> msg -> ByteString -> Bool
dsaVerify hash
hsh PublicKey
key msg
b ByteString
a =
case ByteString -> Maybe Signature
dsaToSignature ByteString
a of
Maybe Signature
Nothing -> Bool
False
Just Signature
dsaSig -> forall msg hash.
(ByteArrayAccess msg, HashAlgorithm hash) =>
hash -> PublicKey -> Signature -> msg -> Bool
DSA.verify hash
hsh PublicKey
key Signature
dsaSig msg
b
rsaVerify :: HashALG -> PublicKey -> ByteString -> ByteString -> Bool
rsaVerify HashALG
HashMD2 = forall hashAlg.
HashAlgorithmASN1 hashAlg =>
Maybe hashAlg -> PublicKey -> ByteString -> ByteString -> Bool
RSA.verify (forall a. a -> Maybe a
Just MD2
MD2)
rsaVerify HashALG
HashMD5 = forall hashAlg.
HashAlgorithmASN1 hashAlg =>
Maybe hashAlg -> PublicKey -> ByteString -> ByteString -> Bool
RSA.verify (forall a. a -> Maybe a
Just MD5
MD5)
rsaVerify HashALG
HashSHA1 = forall hashAlg.
HashAlgorithmASN1 hashAlg =>
Maybe hashAlg -> PublicKey -> ByteString -> ByteString -> Bool
RSA.verify (forall a. a -> Maybe a
Just SHA1
SHA1)
rsaVerify HashALG
HashSHA224 = forall hashAlg.
HashAlgorithmASN1 hashAlg =>
Maybe hashAlg -> PublicKey -> ByteString -> ByteString -> Bool
RSA.verify (forall a. a -> Maybe a
Just SHA224
SHA224)
rsaVerify HashALG
HashSHA256 = forall hashAlg.
HashAlgorithmASN1 hashAlg =>
Maybe hashAlg -> PublicKey -> ByteString -> ByteString -> Bool
RSA.verify (forall a. a -> Maybe a
Just SHA256
SHA256)
rsaVerify HashALG
HashSHA384 = forall hashAlg.
HashAlgorithmASN1 hashAlg =>
Maybe hashAlg -> PublicKey -> ByteString -> ByteString -> Bool
RSA.verify (forall a. a -> Maybe a
Just SHA384
SHA384)
rsaVerify HashALG
HashSHA512 = forall hashAlg.
HashAlgorithmASN1 hashAlg =>
Maybe hashAlg -> PublicKey -> ByteString -> ByteString -> Bool
RSA.verify (forall a. a -> Maybe a
Just SHA512
SHA512)
verifySignature (SignatureALG_IntrinsicHash PubKeyALG
pubkeyALG) PubKey
pubkey ByteString
cdata ByteString
signature
| PubKey -> PubKeyALG
pubkeyToAlg PubKey
pubkey forall a. Eq a => a -> a -> Bool
== PubKeyALG
pubkeyALG = PubKey -> SignatureVerification
doVerify PubKey
pubkey
| Bool
otherwise = SignatureFailure -> SignatureVerification
SignatureFailed SignatureFailure
SignaturePubkeyMismatch
where
doVerify :: PubKey -> SignatureVerification
doVerify (PubKeyEd25519 PublicKey
key) = forall {t} {t}.
(t -> ByteString -> t -> Bool)
-> (ByteString -> CryptoFailable t) -> t -> SignatureVerification
eddsa forall ba.
ByteArrayAccess ba =>
PublicKey -> ba -> Signature -> Bool
Ed25519.verify forall ba. ByteArrayAccess ba => ba -> CryptoFailable Signature
Ed25519.signature PublicKey
key
doVerify (PubKeyEd448 PublicKey
key) = forall {t} {t}.
(t -> ByteString -> t -> Bool)
-> (ByteString -> CryptoFailable t) -> t -> SignatureVerification
eddsa forall ba.
ByteArrayAccess ba =>
PublicKey -> ba -> Signature -> Bool
Ed448.verify forall ba. ByteArrayAccess ba => ba -> CryptoFailable Signature
Ed448.signature PublicKey
key
doVerify PubKey
_ = SignatureFailure -> SignatureVerification
SignatureFailed SignatureFailure
SignatureUnimplemented
eddsa :: (t -> ByteString -> t -> Bool)
-> (ByteString -> CryptoFailable t) -> t -> SignatureVerification
eddsa t -> ByteString -> t -> Bool
verify ByteString -> CryptoFailable t
toSig t
key =
case ByteString -> CryptoFailable t
toSig ByteString
signature of
CryptoPassed t
sig
| t -> ByteString -> t -> Bool
verify t
key ByteString
cdata t
sig -> SignatureVerification
SignaturePass
| Bool
otherwise -> SignatureFailure -> SignatureVerification
SignatureFailed SignatureFailure
SignatureInvalid
CryptoFailed CryptoError
_ -> SignatureFailure -> SignatureVerification
SignatureFailed SignatureFailure
SignatureInvalid
verifyECDSA :: HashALG -> PubKeyEC -> Maybe (ByteString -> ByteString -> Bool)
verifyECDSA :: HashALG -> PubKeyEC -> Maybe (ByteString -> ByteString -> Bool)
verifyECDSA HashALG
hashALG PubKeyEC
key =
PubKeyEC -> Maybe CurveName
ecPubKeyCurveName PubKeyEC
key forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= forall {msg}.
ByteArrayAccess msg =>
SerializedPoint -> CurveName -> Maybe (msg -> ByteString -> Bool)
verifyCurve (PubKeyEC -> SerializedPoint
pubkeyEC_pub PubKeyEC
key)
where
verifyCurve :: SerializedPoint -> CurveName -> Maybe (msg -> ByteString -> Bool)
verifyCurve SerializedPoint
pub CurveName
curveName = forall a. a -> Maybe a
Just forall a b. (a -> b) -> a -> b
$ \msg
msg ByteString
sigBS ->
case forall a.
ASN1Decoding a =>
a -> ByteString -> Either ASN1Error [ASN1]
decodeASN1' BER
BER ByteString
sigBS of
Left ASN1Error
_ -> Bool
False
Right [Start ASN1ConstructionType
Sequence,IntVal Integer
r,IntVal Integer
s,End ASN1ConstructionType
Sequence] ->
let curve :: Curve
curve = CurveName -> Curve
ECC.getCurveByName CurveName
curveName
in case Curve -> SerializedPoint -> Maybe Point
unserializePoint Curve
curve SerializedPoint
pub of
Maybe Point
Nothing -> Bool
False
Just Point
p -> let pubkey :: PublicKey
pubkey = Curve -> Point -> PublicKey
ECDSA.PublicKey Curve
curve Point
p
in (forall {msg}.
ByteArrayAccess msg =>
HashALG -> PublicKey -> Signature -> msg -> Bool
ecdsaVerify HashALG
hashALG) PublicKey
pubkey (Integer -> Integer -> Signature
ECDSA.Signature Integer
r Integer
s) msg
msg
Right [ASN1]
_ -> Bool
False
ecdsaVerify :: HashALG -> PublicKey -> Signature -> msg -> Bool
ecdsaVerify HashALG
HashMD2 = forall msg hash.
(ByteArrayAccess msg, HashAlgorithm hash) =>
hash -> PublicKey -> Signature -> msg -> Bool
ECDSA.verify MD2
MD2
ecdsaVerify HashALG
HashMD5 = forall msg hash.
(ByteArrayAccess msg, HashAlgorithm hash) =>
hash -> PublicKey -> Signature -> msg -> Bool
ECDSA.verify MD5
MD5
ecdsaVerify HashALG
HashSHA1 = forall msg hash.
(ByteArrayAccess msg, HashAlgorithm hash) =>
hash -> PublicKey -> Signature -> msg -> Bool
ECDSA.verify SHA1
SHA1
ecdsaVerify HashALG
HashSHA224 = forall msg hash.
(ByteArrayAccess msg, HashAlgorithm hash) =>
hash -> PublicKey -> Signature -> msg -> Bool
ECDSA.verify SHA224
SHA224
ecdsaVerify HashALG
HashSHA256 = forall msg hash.
(ByteArrayAccess msg, HashAlgorithm hash) =>
hash -> PublicKey -> Signature -> msg -> Bool
ECDSA.verify SHA256
SHA256
ecdsaVerify HashALG
HashSHA384 = forall msg hash.
(ByteArrayAccess msg, HashAlgorithm hash) =>
hash -> PublicKey -> Signature -> msg -> Bool
ECDSA.verify SHA384
SHA384
ecdsaVerify HashALG
HashSHA512 = forall msg hash.
(ByteArrayAccess msg, HashAlgorithm hash) =>
hash -> PublicKey -> Signature -> msg -> Bool
ECDSA.verify SHA512
SHA512