adhoc-network-1.0.2: Network/AdHoc/Signature.hs
{-# LANGUAGE TypeSynonymInstances #-}
-- |
-- Maintainer: Henning Guenther
--
-- This module is a helper for signature checking. It gives the text
-- that needs to be hashed in order to create or verify a signature.
module Network.AdHoc.Signature
(Signature(..)
,SignType(..)
,SignatureStatus(..)
,NoSignature
,InternalSignature
,ExternalSignature
,ToInternalSignature(..)
,getHashString
,verifySignature
) where
import Data.ByteString hiding (foldl,concatMap)
import Text.XML.HaXml.Types
import Codec.Binary.UTF8.String (encodeString)
import qualified Network.GnuTLS.X509 as X509
-- | A raw signature.
data Signature = Signature
{sign_type :: SignType -- ^ The type of the signature
,signature :: ByteString -- ^ The actual signature
}
deriving (Show,Eq)
-- | Specifies the signature algorithm used to sign a message.
data SignType
= MD5 -- ^ MD5 has been used to sign the message
| SignUnknown String -- ^ An unknown signature algorithm was used
deriving (Show,Eq)
-- | This type represents the possible results of verifying a signature.
data SignatureStatus
= SignatureOK -- ^ The signature was valid
| SignatureWrong -- ^ The signature was invalid
| CertificateMissing (X509.Certificate -> SignatureStatus) -- ^ The signature could not be
-- checked, becuase a 'X509.Certificate' was missing. The function
-- is a callback to be called when the missing certificate has been
-- acquired.
instance Show SignatureStatus where
show SignatureOK = "SignatureOK"
show SignatureWrong = "SignatureWrong"
show (CertificateMissing _) = "CertificateMissing"
instance Eq SignatureStatus where
SignatureOK == SignatureOK = True
SignatureWrong == SignatureWrong = True
_ == _ = False
-- | No signature has been given.
type NoSignature = ()
-- | The message has been locally created, so we know the private key.
type InternalSignature = Either X509.PrivateKey ExternalSignature
-- | The signature has been received via network. The signature might be
-- knwon or not.
type ExternalSignature = Maybe (Signature,SignatureStatus)
-- | A class of types that have an internal signature status.
class ToInternalSignature s where
toInternal :: s -> InternalSignature
instance ToInternalSignature NoSignature where
toInternal _ = Right Nothing
instance ToInternalSignature ExternalSignature where
toInternal = Right
instance ToInternalSignature InternalSignature where
toInternal = id
-- | Given a certificate, this function verifies the Signature of a 'String'.
verifySignature :: String -> Signature -> X509.Certificate -> SignatureStatus
verifySignature str sig cert = case X509.verifySignature cert (encodeString str) (signature sig) of
Left _ -> CertificateMissing (verifySignature (encodeString str) sig)
Right False -> SignatureWrong
Right True -> SignatureOK
-- | Calculates the concatenation of all text nodes in the list of contents, except for receiver elements
getHashString :: [Content i] -> String
getHashString = concatMap getHashStringContent
getHashStringContent :: Content i -> String
getHashStringContent (CElem (Elem "receiver" _ _) _) = "" -- As given by standard
getHashStringContent (CElem (Elem _ _ conts) _) = getHashString conts
getHashStringContent (CString _ str _) = str
getHashStringContent _ = ""
-- getHashStringDocument :: Document i -> String
-- getHashStringDocument (Document _ _ (Elem _ _ conts) _) = getHashString conts