From f7999cecc2bb0c76d88005444478e8500c624786 Mon Sep 17 00:00:00 2001 From: Joey Hess Date: Wed, 19 Apr 2017 20:07:47 -0400 Subject: fully working signatures This commit was sponsored by Ethan Aubin. --- Crypto.hs | 75 +++++++++++++++++++++++++++++++++++++++++++++++++-------------- 1 file changed, 59 insertions(+), 16 deletions(-) (limited to 'Crypto.hs') diff --git a/Crypto.hs b/Crypto.hs index a99d497..d973034 100644 --- a/Crypto.hs +++ b/Crypto.hs @@ -1,3 +1,5 @@ +{-# LANGUAGE OverloadedStrings, RankNTypes #-} + module Crypto where import Val @@ -13,27 +15,68 @@ import Data.ByteString dummySignature :: Signature dummySignature = OtherSignature (Val mempty) --- | Sign any Hashable value. -sign :: Hashable v => MySessionKey -> v -> Signature +class Signed t where + getSignature :: t -> Signature + hashExceptSignature :: t -> Hash + mkSigned :: MySessionKey -> (Signature -> t) -> t + mkSigned sk mk = + let tmp = mk dummySignature + in mk (sign sk tmp) + +instance Hashable a => Signed (Activity a) where + getSignature = activitySignature + hashExceptSignature (Activity a mp _s) = hash $ + Tagged "Activity" [hash a, hash mp] + +instance Signed Control where + getSignature = controlSignature + hashExceptSignature (Control a _s) = hash $ + Tagged "Control" a + +instance Hashable t => Signed (Message t) where + getSignature (ActivityMessage a) = getSignature a + getSignature (ControlMessage c) = getSignature c + hashExceptSignature (ActivityMessage a) = hashExceptSignature a + hashExceptSignature (ControlMessage c) = hashExceptSignature c + +sign :: Signed 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)) = + Ed25519.sign sk pk (toSign v) + +toSign :: Signed v => v -> ByteString +toSign = val . hashValue . hashExceptSignature + +-- | Verifiy the signature of a Signed value. +verifySigned :: Signed v => SigVerifier -> v -> Bool +verifySigned (SigVerifier verifier) v = + case getSignature v of + Ed25519Signature (Val s) -> + case Ed25519.signature s of + CryptoPassed sig -> verifier (toSign v) sig + CryptoFailed _ -> False + OtherSignature _ -> False + +data SigVerifier = SigVerifier (ByteString -> Ed25519.Signature -> Bool) + +mkSigVerifier :: PublicKey -> SigVerifier +mkSigVerifier (PublicKey (Val pk) _) = 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 + CryptoPassed pk' -> SigVerifier (Ed25519.verify pk') + CryptoFailed _ -> mempty + +instance Monoid SigVerifier where + mempty = SigVerifier $ \_b _s -> False + mappend (SigVerifier a) (SigVerifier b) = + SigVerifier $ \d s -> b d s || a d s data MySessionKey = MySessionKey Ed25519.SecretKey Ed25519.PublicKey +-- TODO add gpg signature when available +myPublicKey :: MySessionKey -> IO PublicKey +myPublicKey (MySessionKey _ pk) = do + let gpgsig = Nothing + return $ PublicKey (Val (convert pk)) gpgsig + genMySessionKey :: IO MySessionKey genMySessionKey = do -- Crypto.Random.Entropy may use rdrand, or /dev/random. -- cgit v1.2.3