-- |
-- 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
showList :: [Fingerprint] -> ShowS
$cshowList :: [Fingerprint] -> ShowS
show :: Fingerprint -> String
$cshow :: Fingerprint -> String
showsPrec :: Int -> Fingerprint -> ShowS
$cshowsPrec :: Int -> Fingerprint -> ShowS
Show,Fingerprint -> Fingerprint -> Bool
(Fingerprint -> Fingerprint -> Bool)
-> (Fingerprint -> Fingerprint -> Bool) -> Eq Fingerprint
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: Fingerprint -> Fingerprint -> Bool
$c/= :: Fingerprint -> Fingerprint -> Bool
== :: Fingerprint -> Fingerprint -> Bool
$c== :: Fingerprint -> Fingerprint -> Bool
Eq,Fingerprint -> Int
Fingerprint -> Ptr p -> IO ()
Fingerprint -> (Ptr p -> IO a) -> IO a
(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
copyByteArrayToPtr :: Fingerprint -> Ptr p -> IO ()
$ccopyByteArrayToPtr :: forall p. Fingerprint -> Ptr p -> IO ()
withByteArray :: Fingerprint -> (Ptr p -> IO a) -> IO a
$cwithByteArray :: forall p a. Fingerprint -> (Ptr p -> IO a) -> IO a
length :: Fingerprint -> Int
$clength :: Fingerprint -> Int
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 :: 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 ba.
(ByteArray c, ByteArrayAccess ba) =>
HashALG -> ba -> 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 -> ba -> c
mkHash HashALG
HashMD2    = Digest MD2 -> c
forall bin bout.
(ByteArrayAccess bin, ByteArray bout) =>
bin -> bout
convert (Digest MD2 -> c) -> (ba -> Digest MD2) -> ba -> c
forall b c a. (b -> c) -> (a -> b) -> a -> c
. MD2 -> ba -> 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) -> (ba -> Digest MD5) -> ba -> c
forall b c a. (b -> c) -> (a -> b) -> a -> c
. MD5 -> ba -> 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) -> (ba -> Digest SHA1) -> ba -> c
forall b c a. (b -> c) -> (a -> b) -> a -> c
. SHA1 -> ba -> 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) -> (ba -> Digest SHA224) -> ba -> c
forall b c a. (b -> c) -> (a -> b) -> a -> c
. SHA224 -> ba -> 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) -> (ba -> Digest SHA256) -> ba -> c
forall b c a. (b -> c) -> (a -> b) -> a -> c
. SHA256 -> ba -> 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) -> (ba -> Digest SHA384) -> ba -> c
forall b c a. (b -> c) -> (a -> b) -> a -> c
. SHA384 -> ba -> 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) -> (ba -> Digest SHA512) -> ba -> c
forall b c a. (b -> c) -> (a -> b) -> a -> c
. SHA512 -> ba -> Digest SHA512
forall ba alg.
(ByteArrayAccess ba, HashAlgorithm alg) =>
alg -> ba -> Digest alg
hashWith SHA512
SHA512