-- |
-- Module      : Data.X509.Validation.Fingerprint
-- License     : BSD-style
-- Maintainer  : Vincent Hanquez <vincent@snarc.org>
-- Stability   : experimental
-- Portability : unknown
--
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
module Data.X509.Validation.Fingerprint
    ( Fingerprint(..)
    , getFingerprint
    ) where

import Crypto.Hash
import Data.X509
import Data.ASN1.Types
import Data.ByteArray (convert, ByteArrayAccess)
import Data.ByteString (ByteString)

-- | Fingerprint of a certificate
newtype Fingerprint = Fingerprint ByteString
    deriving (Int -> Fingerprint -> ShowS
[Fingerprint] -> ShowS
Fingerprint -> String
(Int -> Fingerprint -> ShowS)
-> (Fingerprint -> String)
-> ([Fingerprint] -> ShowS)
-> Show Fingerprint
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> Fingerprint -> ShowS
showsPrec :: Int -> Fingerprint -> ShowS
$cshow :: Fingerprint -> String
show :: Fingerprint -> String
$cshowList :: [Fingerprint] -> ShowS
showList :: [Fingerprint] -> ShowS
Show,Fingerprint -> Fingerprint -> Bool
(Fingerprint -> Fingerprint -> Bool)
-> (Fingerprint -> Fingerprint -> Bool) -> Eq Fingerprint
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: Fingerprint -> Fingerprint -> Bool
== :: Fingerprint -> Fingerprint -> Bool
$c/= :: Fingerprint -> Fingerprint -> Bool
/= :: Fingerprint -> Fingerprint -> Bool
Eq,Fingerprint -> Int
(Fingerprint -> Int)
-> (forall p a. Fingerprint -> (Ptr p -> IO a) -> IO a)
-> (forall p. Fingerprint -> Ptr p -> IO ())
-> ByteArrayAccess Fingerprint
forall p. Fingerprint -> Ptr p -> IO ()
forall ba.
(ba -> Int)
-> (forall p a. ba -> (Ptr p -> IO a) -> IO a)
-> (forall p. ba -> Ptr p -> IO ())
-> ByteArrayAccess ba
forall p a. Fingerprint -> (Ptr p -> IO a) -> IO a
$clength :: Fingerprint -> Int
length :: Fingerprint -> Int
$cwithByteArray :: forall p a. Fingerprint -> (Ptr p -> IO a) -> IO a
withByteArray :: forall p a. Fingerprint -> (Ptr p -> IO a) -> IO a
$ccopyByteArrayToPtr :: forall p. Fingerprint -> Ptr p -> IO ()
copyByteArrayToPtr :: forall p. Fingerprint -> Ptr p -> IO ()
ByteArrayAccess)

-- | Get the fingerprint of the whole signed object
-- using the hashing algorithm specified
getFingerprint :: (Show a, Eq a, ASN1Object a)
               => SignedExact a -- ^ object to fingerprint
               -> HashALG       -- ^ algorithm to compute the fingerprint
               -> Fingerprint   -- ^ fingerprint in binary form
getFingerprint :: forall a.
(Show a, Eq a, ASN1Object a) =>
SignedExact a -> HashALG -> Fingerprint
getFingerprint SignedExact a
sobj HashALG
halg = ByteString -> Fingerprint
Fingerprint (ByteString -> Fingerprint) -> ByteString -> Fingerprint
forall a b. (a -> b) -> a -> b
$ HashALG -> ByteString -> ByteString
forall {c} {a}.
(ByteArray c, ByteArrayAccess a) =>
HashALG -> a -> c
mkHash HashALG
halg (ByteString -> ByteString) -> ByteString -> ByteString
forall a b. (a -> b) -> a -> b
$ SignedExact a -> ByteString
forall a.
(Show a, Eq a, ASN1Object a) =>
SignedExact a -> ByteString
encodeSignedObject SignedExact a
sobj
  where
    mkHash :: HashALG -> a -> c
mkHash HashALG
HashMD2    = Digest MD2 -> c
forall bin bout.
(ByteArrayAccess bin, ByteArray bout) =>
bin -> bout
convert (Digest MD2 -> c) -> (a -> Digest MD2) -> a -> c
forall b c a. (b -> c) -> (a -> b) -> a -> c
. MD2 -> a -> Digest MD2
forall ba alg.
(ByteArrayAccess ba, HashAlgorithm alg) =>
alg -> ba -> Digest alg
hashWith MD2
MD2
    mkHash HashALG
HashMD5    = Digest MD5 -> c
forall bin bout.
(ByteArrayAccess bin, ByteArray bout) =>
bin -> bout
convert (Digest MD5 -> c) -> (a -> Digest MD5) -> a -> c
forall b c a. (b -> c) -> (a -> b) -> a -> c
. MD5 -> a -> Digest MD5
forall ba alg.
(ByteArrayAccess ba, HashAlgorithm alg) =>
alg -> ba -> Digest alg
hashWith MD5
MD5
    mkHash HashALG
HashSHA1   = Digest SHA1 -> c
forall bin bout.
(ByteArrayAccess bin, ByteArray bout) =>
bin -> bout
convert (Digest SHA1 -> c) -> (a -> Digest SHA1) -> a -> c
forall b c a. (b -> c) -> (a -> b) -> a -> c
. SHA1 -> a -> Digest SHA1
forall ba alg.
(ByteArrayAccess ba, HashAlgorithm alg) =>
alg -> ba -> Digest alg
hashWith SHA1
SHA1
    mkHash HashALG
HashSHA224 = Digest SHA224 -> c
forall bin bout.
(ByteArrayAccess bin, ByteArray bout) =>
bin -> bout
convert (Digest SHA224 -> c) -> (a -> Digest SHA224) -> a -> c
forall b c a. (b -> c) -> (a -> b) -> a -> c
. SHA224 -> a -> Digest SHA224
forall ba alg.
(ByteArrayAccess ba, HashAlgorithm alg) =>
alg -> ba -> Digest alg
hashWith SHA224
SHA224
    mkHash HashALG
HashSHA256 = Digest SHA256 -> c
forall bin bout.
(ByteArrayAccess bin, ByteArray bout) =>
bin -> bout
convert (Digest SHA256 -> c) -> (a -> Digest SHA256) -> a -> c
forall b c a. (b -> c) -> (a -> b) -> a -> c
. SHA256 -> a -> Digest SHA256
forall ba alg.
(ByteArrayAccess ba, HashAlgorithm alg) =>
alg -> ba -> Digest alg
hashWith SHA256
SHA256
    mkHash HashALG
HashSHA384 = Digest SHA384 -> c
forall bin bout.
(ByteArrayAccess bin, ByteArray bout) =>
bin -> bout
convert (Digest SHA384 -> c) -> (a -> Digest SHA384) -> a -> c
forall b c a. (b -> c) -> (a -> b) -> a -> c
. SHA384 -> a -> Digest SHA384
forall ba alg.
(ByteArrayAccess ba, HashAlgorithm alg) =>
alg -> ba -> Digest alg
hashWith SHA384
SHA384
    mkHash HashALG
HashSHA512 = Digest SHA512 -> c
forall bin bout.
(ByteArrayAccess bin, ByteArray bout) =>
bin -> bout
convert (Digest SHA512 -> c) -> (a -> Digest SHA512) -> a -> c
forall b c a. (b -> c) -> (a -> b) -> a -> c
. SHA512 -> a -> Digest SHA512
forall ba alg.
(ByteArrayAccess ba, HashAlgorithm alg) =>
alg -> ba -> Digest alg
hashWith SHA512
SHA512