module Crypto where import Val import Hash import Types import qualified Crypto.PubKey.Ed25519 as Ed25519 import Crypto.Error import Crypto.Random.Entropy import Data.ByteArray (convert) import Data.ByteString dummySignature :: Signature dummySignature = OtherSignature (Val mempty) -- | Sign any Hashable value. sign :: Hashable v => MySessionKey -> v -> Signature sign (MySessionKey sk pk) v = Ed25519Signature $ Val $ convert $ Ed25519.sign sk pk $ val $ hashValue $ hash v -- | Verifiy a signature of any Hashable value. -- -- To avoid overhead of converting the PublicKey to the Ed25519.PublicKey -- each time, partially evaluate this function. verify :: Hashable v => PublicKey -> v -> Signature -> Bool verify (PublicKey (Val pk) _) v (Ed25519Signature (Val s)) = case Ed25519.publicKey pk of CryptoPassed pk' -> case Ed25519.signature s of CryptoPassed sig -> Ed25519.verify pk' (val $ hashValue $ hash v) sig CryptoFailed _ -> False CryptoFailed _ -> False verify _ _ (OtherSignature _) = False data MySessionKey = MySessionKey Ed25519.SecretKey Ed25519.PublicKey genMySessionKey :: IO MySessionKey genMySessionKey = do -- Crypto.Random.Entropy may use rdrand, or /dev/random. -- Even if you don't trust rdrand to be free of backdoors, -- it seems safe enough to use it for a session key that -- is only used for signing, not encryption. rand32 <- getEntropy 32 :: IO ByteString sk <- throwCryptoErrorIO $ Ed25519.secretKey rand32 return $ MySessionKey sk (Ed25519.toPublic sk)