{-# LANGUAGE OverloadedStrings #-}
module Voting.Protocol.Trustee.Indispensable where
import Control.Monad (Monad(..), foldM, unless)
import Control.Monad.Trans.Except (ExceptT(..), throwE)
import Data.Eq (Eq(..))
import Data.Function (($))
import Data.Maybe (maybe)
import Data.Semigroup (Semigroup(..))
import Text.Show (Show(..))
import qualified Control.Monad.Trans.State.Strict as S
import qualified Data.ByteString as BS
import qualified Data.List as List
import Voting.Protocol.Utils
import Voting.Protocol.Arithmetic
import Voting.Protocol.Credential
import Voting.Protocol.Election
import Voting.Protocol.Tally
data TrusteePublicKey q = TrusteePublicKey
{ trustee_PublicKey :: PublicKey q
, trustee_SecretKeyProof :: Proof q
} deriving (Eq,Show)
data ErrorTrusteePublicKey
= ErrorTrusteePublicKey_Wrong
deriving (Eq,Show)
proveIndispensableTrusteePublicKey ::
Monad m => RandomGen r => SubGroup q =>
SecretKey q -> S.StateT r m (TrusteePublicKey q)
proveIndispensableTrusteePublicKey trustSecKey = do
let trustee_PublicKey = publicKey trustSecKey
trustee_SecretKeyProof <-
prove trustSecKey [groupGen] $
hash (indispensableTrusteePublicKeyStatement trustee_PublicKey)
return TrusteePublicKey{..}
verifyIndispensableTrusteePublicKey ::
Monad m => SubGroup q =>
TrusteePublicKey q ->
ExceptT ErrorTrusteePublicKey m ()
verifyIndispensableTrusteePublicKey TrusteePublicKey{..} =
unless ((proof_challenge trustee_SecretKeyProof ==) $
hash
(indispensableTrusteePublicKeyStatement trustee_PublicKey)
[commit trustee_SecretKeyProof groupGen trustee_PublicKey]) $
throwE ErrorTrusteePublicKey_Wrong
indispensableTrusteePublicKeyStatement :: PublicKey q -> BS.ByteString
indispensableTrusteePublicKeyStatement trustPubKey = "pok|"<>bytesNat trustPubKey<>"|"
combineIndispensableTrusteePublicKeys ::
SubGroup q => [TrusteePublicKey q] -> PublicKey q
combineIndispensableTrusteePublicKeys =
List.foldr (\TrusteePublicKey{..} -> (trustee_PublicKey *)) one
verifyIndispensableDecryptionShareByTrustee ::
SubGroup q => Monad m =>
EncryptedTally q -> [PublicKey q] -> [DecryptionShare q] ->
ExceptT ErrorDecryptionShare m ()
verifyIndispensableDecryptionShareByTrustee encTally =
isoZipWithM_ (throwE $ ErrorDecryptionShare_Invalid "verifyIndispensableDecryptionShareByTrustee")
(verifyDecryptionShare encTally)
combineIndispensableDecryptionShares ::
SubGroup q => [PublicKey q] -> EncryptedTally q -> DecryptionShareCombinator q
combineIndispensableDecryptionShares pubKeyByTrustee encTally decShareByTrustee = do
verifyIndispensableDecryptionShareByTrustee encTally pubKeyByTrustee decShareByTrustee
(d0,ds) <- maybe err return $ List.uncons decShareByTrustee
foldM
(\decFactorByChoiceByQuest DecryptionShare{..} ->
isoZipWithM err
(\acc df -> maybe err return $ isoZipWith (*) acc df)
decFactorByChoiceByQuest decryptionShare_factors)
(decryptionShare_factors d0) ds
where err = throwE $ ErrorDecryptionShare_Invalid "combineIndispensableDecryptionShares"