CP.hs 1.6 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253
  1. {- |
  2. Crypto algorithms used on capabilities
  3. -}
  4. module Data.SMTP.Crypto.Algos.CP (
  5. Algo,
  6. initCp,
  7. update,
  8. update',
  9. checkSeal,
  10. toSeal
  11. ) where
  12. import Data.ByteString (ByteString)
  13. import qualified Data.ByteString.Lazy as LBS
  14. import qualified Data.SMTP.Seal as Seal
  15. import qualified Crypto.Hash as Hash
  16. import qualified Crypto.Hash.Algorithms as Hashs
  17. import qualified Crypto.PubKey.Ed25519 as Ed25519
  18. import qualified Data.ByteArray as BA
  19. import qualified Data.ByteString as BS
  20. import Crypto.Error
  21. import Data.SMTP.Crypto.Types.CP
  22. data Algo = Sha512Ed25519 deriving (Eq, Ord, Bounded, Enum)
  23. instance Show Algo where
  24. show Sha512Ed25519 = "SHA512-ED25519"
  25. data State = Sha512Ed25519s (Hash.Context Hashs.SHA512)
  26. initCp :: Algo -> State
  27. initCp Sha512Ed25519 = Sha512Ed25519s Hash.hashInit
  28. update :: State -> ByteString -> State
  29. update (Sha512Ed25519s s) dt = Sha512Ed25519s $ Hash.hashUpdate s dt
  30. update' :: State -> LBS.ByteString -> State
  31. update' (Sha512Ed25519s s) dt = Sha512Ed25519s $ Hash.hashUpdates s $ LBS.toChunks dt
  32. checkSeal :: State -> Seal.Seal -> CP -> Bool
  33. checkSeal (Sha512Ed25519s s) (Seal.Seal _ seal _) (Sha512Ed25519Cp _ pk _) = let
  34. dg = Hash.hashFinalize s
  35. sig' = Ed25519.signature seal
  36. in case sig' of
  37. CryptoFailed _ -> False
  38. CryptoPassed sig -> Ed25519.verify pk dg sig
  39. toSeal :: State -> CP -> Maybe Seal.Seal
  40. toSeal (Sha512Ed25519s s) (Sha512Ed25519Cp cpid pk (Just sk)) = let
  41. dg = Hash.hashFinalize s
  42. sig = ba2bs $ Ed25519.sign sk pk dg
  43. in Just $ Seal.Seal cpid sig Nothing
  44. toSeal (Sha512Ed25519s _) _ = Nothing
  45. ba2bs :: BA.ByteArrayAccess a => a -> ByteString
  46. ba2bs = BS.pack . BA.unpack