packages feed

hjugement-protocol 0.0.9.20191031 → 0.0.10.20191104

raw patch · 18 files changed

+1117/−950 lines, 18 filesPVP: major bump suggested

API removals or changes: PVP suggests a major version bump

API changes (from Hackage documentation)

- Voting.Protocol.Arith: (*) :: Multiplicative a => a -> a -> a
- Voting.Protocol.Arith: (+) :: Additive a => a -> a -> a
- Voting.Protocol.Arith: (-) :: Negable a => a -> a -> a
- Voting.Protocol.Arith: (/) :: Invertible a => a -> a -> a
- Voting.Protocol.Arith: (^) :: forall crypto c. Reifies c crypto => Multiplicative (G crypto c) => G crypto c -> E crypto c -> G crypto c
- Voting.Protocol.Arith: Base64SHA256 :: Text -> Base64SHA256
- Voting.Protocol.Arith: E :: Natural -> E crypto c
- Voting.Protocol.Arith: G :: FieldElement crypto -> G crypto c
- Voting.Protocol.Arith: Hash :: E crypto c -> Hash crypto c
- Voting.Protocol.Arith: HexSHA256 :: Text -> HexSHA256
- Voting.Protocol.Arith: [unE] :: E crypto c -> Natural
- Voting.Protocol.Arith: [unG] :: G crypto c -> FieldElement crypto
- Voting.Protocol.Arith: base64SHA256 :: ByteString -> Base64SHA256
- Voting.Protocol.Arith: bytesNat :: ToNatural n => n -> ByteString
- Voting.Protocol.Arith: class Additive a
- Voting.Protocol.Arith: class FromNatural a
- Voting.Protocol.Arith: class (Multiplicative (G crypto c), Invertible (G crypto c), FromNatural (G crypto c), ToNatural (G crypto c), Eq (G crypto c), Ord (G crypto c), Show (G crypto c), NFData (G crypto c), FromJSON (G crypto c), ToJSON (G crypto c), Reifies c crypto) => GroupParams crypto c
- Voting.Protocol.Arith: class Multiplicative a => Invertible a
- Voting.Protocol.Arith: class Multiplicative a
- Voting.Protocol.Arith: class Additive a => Negable a
- Voting.Protocol.Arith: class ReifyCrypto crypto
- Voting.Protocol.Arith: class ToNatural a
- Voting.Protocol.Arith: decodeBigEndian :: ByteString -> Natural
- Voting.Protocol.Arith: fromNatural :: FromNatural a => Natural -> a
- Voting.Protocol.Arith: groupGen :: GroupParams crypto c => G crypto c
- Voting.Protocol.Arith: groupGenInverses :: GroupParams crypto c => [G crypto c]
- Voting.Protocol.Arith: groupGenPowers :: GroupParams crypto c => [G crypto c]
- Voting.Protocol.Arith: groupOrder :: GroupParams crypto c => Proxy c -> Natural
- Voting.Protocol.Arith: hash :: GroupParams crypto c => ByteString -> [G crypto c] -> E crypto c
- Voting.Protocol.Arith: hexSHA256 :: ByteString -> Text
- Voting.Protocol.Arith: infixl 6 -
- Voting.Protocol.Arith: infixl 7 /
- Voting.Protocol.Arith: infixr 8 ^
- Voting.Protocol.Arith: instance Control.DeepSeq.NFData (Voting.Protocol.Arith.E crypto c)
- Voting.Protocol.Arith: instance Control.DeepSeq.NFData (Voting.Protocol.Arith.Hash crypto c)
- Voting.Protocol.Arith: instance Control.DeepSeq.NFData Voting.Protocol.Arith.Base64SHA256
- Voting.Protocol.Arith: instance Control.DeepSeq.NFData Voting.Protocol.Arith.HexSHA256
- Voting.Protocol.Arith: instance Data.Aeson.Types.FromJSON.FromJSON Voting.Protocol.Arith.Base64SHA256
- Voting.Protocol.Arith: instance Data.Aeson.Types.FromJSON.FromJSON Voting.Protocol.Arith.HexSHA256
- Voting.Protocol.Arith: instance Data.Aeson.Types.ToJSON.ToJSON (Voting.Protocol.Arith.E crypto c)
- Voting.Protocol.Arith: instance Data.Aeson.Types.ToJSON.ToJSON Voting.Protocol.Arith.Base64SHA256
- Voting.Protocol.Arith: instance Data.Aeson.Types.ToJSON.ToJSON Voting.Protocol.Arith.HexSHA256
- Voting.Protocol.Arith: instance GHC.Classes.Eq (Voting.Protocol.Arith.E crypto c)
- Voting.Protocol.Arith: instance GHC.Classes.Eq (Voting.Protocol.Arith.Hash crypto c)
- Voting.Protocol.Arith: instance GHC.Classes.Eq Voting.Protocol.Arith.Base64SHA256
- Voting.Protocol.Arith: instance GHC.Classes.Eq Voting.Protocol.Arith.HexSHA256
- Voting.Protocol.Arith: instance GHC.Classes.Ord (Voting.Protocol.Arith.E crypto c)
- Voting.Protocol.Arith: instance GHC.Classes.Ord (Voting.Protocol.Arith.Hash crypto c)
- Voting.Protocol.Arith: instance GHC.Classes.Ord Voting.Protocol.Arith.Base64SHA256
- Voting.Protocol.Arith: instance GHC.Classes.Ord Voting.Protocol.Arith.HexSHA256
- Voting.Protocol.Arith: instance GHC.Generics.Generic Voting.Protocol.Arith.Base64SHA256
- Voting.Protocol.Arith: instance GHC.Generics.Generic Voting.Protocol.Arith.HexSHA256
- Voting.Protocol.Arith: instance GHC.Show.Show (Voting.Protocol.Arith.E crypto c)
- Voting.Protocol.Arith: instance GHC.Show.Show (Voting.Protocol.Arith.Hash crypto c)
- Voting.Protocol.Arith: instance GHC.Show.Show Voting.Protocol.Arith.Base64SHA256
- Voting.Protocol.Arith: instance GHC.Show.Show Voting.Protocol.Arith.HexSHA256
- Voting.Protocol.Arith: instance System.Random.Random GHC.Natural.Natural
- Voting.Protocol.Arith: instance Voting.Protocol.Arith.Additive GHC.Integer.Type.Integer
- Voting.Protocol.Arith: instance Voting.Protocol.Arith.Additive GHC.Natural.Natural
- Voting.Protocol.Arith: instance Voting.Protocol.Arith.Additive GHC.Types.Int
- Voting.Protocol.Arith: instance Voting.Protocol.Arith.GroupParams crypto c => Data.Aeson.Types.FromJSON.FromJSON (Voting.Protocol.Arith.E crypto c)
- Voting.Protocol.Arith: instance Voting.Protocol.Arith.GroupParams crypto c => GHC.Enum.Enum (Voting.Protocol.Arith.E crypto c)
- Voting.Protocol.Arith: instance Voting.Protocol.Arith.GroupParams crypto c => System.Random.Random (Voting.Protocol.Arith.E crypto c)
- Voting.Protocol.Arith: instance Voting.Protocol.Arith.GroupParams crypto c => Voting.Protocol.Arith.Additive (Voting.Protocol.Arith.E crypto c)
- Voting.Protocol.Arith: instance Voting.Protocol.Arith.GroupParams crypto c => Voting.Protocol.Arith.FromNatural (Voting.Protocol.Arith.E crypto c)
- Voting.Protocol.Arith: instance Voting.Protocol.Arith.GroupParams crypto c => Voting.Protocol.Arith.Multiplicative (Voting.Protocol.Arith.E crypto c)
- Voting.Protocol.Arith: instance Voting.Protocol.Arith.GroupParams crypto c => Voting.Protocol.Arith.Negable (Voting.Protocol.Arith.E crypto c)
- Voting.Protocol.Arith: instance Voting.Protocol.Arith.Multiplicative GHC.Integer.Type.Integer
- Voting.Protocol.Arith: instance Voting.Protocol.Arith.Multiplicative GHC.Natural.Natural
- Voting.Protocol.Arith: instance Voting.Protocol.Arith.Multiplicative GHC.Types.Int
- Voting.Protocol.Arith: instance Voting.Protocol.Arith.Negable GHC.Integer.Type.Integer
- Voting.Protocol.Arith: instance Voting.Protocol.Arith.Negable GHC.Types.Int
- Voting.Protocol.Arith: instance Voting.Protocol.Arith.ToNatural (Voting.Protocol.Arith.E crypto c)
- Voting.Protocol.Arith: instance Voting.Protocol.Arith.ToNatural GHC.Natural.Natural
- Voting.Protocol.Arith: inv :: Invertible a => a -> a
- Voting.Protocol.Arith: nat :: ToNatural a => a -> Natural
- Voting.Protocol.Arith: neg :: Negable a => a -> a
- Voting.Protocol.Arith: newtype Base64SHA256
- Voting.Protocol.Arith: newtype E crypto c
- Voting.Protocol.Arith: newtype G crypto c
- Voting.Protocol.Arith: newtype Hash crypto c
- Voting.Protocol.Arith: newtype HexSHA256
- Voting.Protocol.Arith: one :: Multiplicative a => a
- Voting.Protocol.Arith: random :: Monad m => RandomGen r => Random i => Negable i => Multiplicative i => StateT r m i
- Voting.Protocol.Arith: randomR :: Monad m => RandomGen r => Random i => Negable i => Multiplicative i => i -> StateT r m i
- Voting.Protocol.Arith: reifyCrypto :: ReifyCrypto crypto => crypto -> (forall c. Reifies c crypto => GroupParams crypto c => Proxy c -> r) -> r
- Voting.Protocol.Arith: sum :: (Additive a, Foldable f) => f a -> a
- Voting.Protocol.Arith: type family FieldElement crypto :: *
- Voting.Protocol.Arith: zero :: Additive a => a
- Voting.Protocol.Credential: type PublicKey = G
- Voting.Protocol.Credential: type SecretKey = E
- Voting.Protocol.Election: DisjProof :: [Proof crypto v c] -> DisjProof crypto v c
- Voting.Protocol.Election: Encryption :: !G crypto c -> !G crypto c -> Encryption crypto v c
- Voting.Protocol.Election: ErrorVerifyEncryption_InvalidProofLength :: Natural -> Natural -> ErrorVerifyEncryption
- Voting.Protocol.Election: Proof :: !Challenge crypto c -> !E crypto c -> Proof crypto v c
- Voting.Protocol.Election: Signature :: !PublicKey crypto c -> !Proof crypto v c -> Signature crypto v c
- Voting.Protocol.Election: Version :: [Natural] -> [(Text, Natural)] -> Version
- Voting.Protocol.Election: ZKP :: ByteString -> ZKP
- Voting.Protocol.Election: [encryption_nonce] :: Encryption crypto v c -> !G crypto c
- Voting.Protocol.Election: [encryption_vault] :: Encryption crypto v c -> !G crypto c
- Voting.Protocol.Election: [proof_challenge] :: Proof crypto v c -> !Challenge crypto c
- Voting.Protocol.Election: [proof_response] :: Proof crypto v c -> !E crypto c
- Voting.Protocol.Election: [signature_proof] :: Signature crypto v c -> !Proof crypto v c
- Voting.Protocol.Election: [signature_publicKey] :: Signature crypto v c -> !PublicKey crypto c
- Voting.Protocol.Election: [version_branch] :: Version -> [Natural]
- Voting.Protocol.Election: [version_tags] :: Version -> [(Text, Natural)]
- Voting.Protocol.Election: booleanDisjunctions :: forall crypto c. GroupParams crypto c => [Disjunction crypto c]
- Voting.Protocol.Election: commit :: forall crypto v c. Reifies v Version => GroupParams crypto c => Proof crypto v c -> G crypto c -> G crypto c -> Commitment crypto c
- Voting.Protocol.Election: commitQuicker :: GroupParams crypto c => Proof crypto v c -> G crypto c -> G crypto c -> Commitment crypto c
- Voting.Protocol.Election: data Encryption crypto v c
- Voting.Protocol.Election: data ErrorVerifyEncryption
- Voting.Protocol.Election: data Proof crypto v c
- Voting.Protocol.Election: data Signature crypto v c
- Voting.Protocol.Election: data Version
- Voting.Protocol.Election: encrypt :: Reifies v Version => GroupParams crypto c => Monad m => RandomGen r => PublicKey crypto c -> E crypto c -> StateT r m (EncryptionNonce crypto c, Encryption crypto v c)
- Voting.Protocol.Election: encryptionCommitments :: Reifies v Version => GroupParams crypto c => PublicKey crypto c -> Encryption crypto v c -> Disjunction crypto c -> Proof crypto v c -> [G crypto c]
- Voting.Protocol.Election: encryptionStatement :: GroupParams crypto c => ZKP -> Encryption crypto v c -> ByteString
- Voting.Protocol.Election: experimentalVersion :: Version
- Voting.Protocol.Election: fakeProof :: GroupParams crypto c => Monad m => RandomGen r => StateT r m (Proof crypto v c)
- Voting.Protocol.Election: hasVersionTag :: Version -> Text -> Bool
- Voting.Protocol.Election: instance (Control.DeepSeq.NFData (Voting.Protocol.Arith.G crypto c), Control.DeepSeq.NFData crypto) => Control.DeepSeq.NFData (Voting.Protocol.Election.Ballot crypto v c)
- Voting.Protocol.Election: instance (Control.DeepSeq.NFData crypto, Control.DeepSeq.NFData (Voting.Protocol.Arith.G crypto c)) => Control.DeepSeq.NFData (Voting.Protocol.Election.Election crypto v c)
- Voting.Protocol.Election: instance (Control.DeepSeq.NFData crypto, Control.DeepSeq.NFData (Voting.Protocol.Arith.G crypto c)) => Control.DeepSeq.NFData (Voting.Protocol.Election.Signature crypto v c)
- Voting.Protocol.Election: instance (Data.Reflection.Reifies v Voting.Protocol.Election.Version, Voting.Protocol.Arith.GroupParams crypto c) => Data.Aeson.Types.FromJSON.FromJSON (Voting.Protocol.Election.Answer crypto v c)
- Voting.Protocol.Election: instance (Data.Reflection.Reifies v Voting.Protocol.Election.Version, Voting.Protocol.Arith.GroupParams crypto c) => Data.Aeson.Types.FromJSON.FromJSON (Voting.Protocol.Election.Ballot crypto v c)
- Voting.Protocol.Election: instance (Data.Reflection.Reifies v Voting.Protocol.Election.Version, Voting.Protocol.Arith.GroupParams crypto c) => Data.Aeson.Types.FromJSON.FromJSON (Voting.Protocol.Election.Encryption crypto v c)
- Voting.Protocol.Election: instance (Data.Reflection.Reifies v Voting.Protocol.Election.Version, Voting.Protocol.Arith.GroupParams crypto c) => Data.Aeson.Types.FromJSON.FromJSON (Voting.Protocol.Election.Signature crypto v c)
- Voting.Protocol.Election: instance (Data.Reflection.Reifies v Voting.Protocol.Election.Version, Voting.Protocol.Arith.GroupParams crypto c) => Data.Aeson.Types.ToJSON.ToJSON (Voting.Protocol.Election.Answer crypto v c)
- Voting.Protocol.Election: instance (Data.Reflection.Reifies v Voting.Protocol.Election.Version, Voting.Protocol.Arith.GroupParams crypto c) => Data.Aeson.Types.ToJSON.ToJSON (Voting.Protocol.Election.Encryption crypto v c)
- Voting.Protocol.Election: instance (Data.Reflection.Reifies v Voting.Protocol.Election.Version, Voting.Protocol.Arith.GroupParams crypto c) => Data.Aeson.Types.ToJSON.ToJSON (Voting.Protocol.Election.Signature crypto v c)
- Voting.Protocol.Election: instance (Data.Reflection.Reifies v Voting.Protocol.Election.Version, Voting.Protocol.Arith.GroupParams crypto c, Data.Aeson.Types.ToJSON.ToJSON (Voting.Protocol.Arith.G crypto c)) => Data.Aeson.Types.ToJSON.ToJSON (Voting.Protocol.Election.Ballot crypto v c)
- Voting.Protocol.Election: instance (Data.Reflection.Reifies v Voting.Protocol.Election.Version, Voting.Protocol.Arith.GroupParams crypto c, Data.Aeson.Types.ToJSON.ToJSON crypto) => Data.Aeson.Types.ToJSON.ToJSON (Voting.Protocol.Election.Election crypto v c)
- Voting.Protocol.Election: instance (GHC.Classes.Eq crypto, GHC.Classes.Eq (Voting.Protocol.Arith.G crypto c)) => GHC.Classes.Eq (Voting.Protocol.Election.Election crypto v c)
- Voting.Protocol.Election: instance (GHC.Show.Show (Voting.Protocol.Arith.G crypto c), GHC.Show.Show (Voting.Protocol.Arith.G crypto c)) => GHC.Show.Show (Voting.Protocol.Election.Answer crypto v c)
- Voting.Protocol.Election: instance (GHC.Show.Show (Voting.Protocol.Arith.G crypto c), GHC.Show.Show (Voting.Protocol.Arith.G crypto c)) => GHC.Show.Show (Voting.Protocol.Election.Encryption crypto v c)
- Voting.Protocol.Election: instance (GHC.Show.Show crypto, GHC.Show.Show (Voting.Protocol.Arith.G crypto c)) => GHC.Show.Show (Voting.Protocol.Election.Election crypto v c)
- Voting.Protocol.Election: instance Control.DeepSeq.NFData (Voting.Protocol.Arith.G crypto c) => Control.DeepSeq.NFData (Voting.Protocol.Election.Answer crypto v c)
- Voting.Protocol.Election: instance Control.DeepSeq.NFData (Voting.Protocol.Arith.G crypto c) => Control.DeepSeq.NFData (Voting.Protocol.Election.Encryption crypto v c)
- Voting.Protocol.Election: instance Control.DeepSeq.NFData (Voting.Protocol.Election.DisjProof crypto v c)
- Voting.Protocol.Election: instance Control.DeepSeq.NFData (Voting.Protocol.Election.Proof crypto v c)
- Voting.Protocol.Election: instance Control.DeepSeq.NFData Voting.Protocol.Election.Version
- Voting.Protocol.Election: instance Data.Aeson.Types.FromJSON.FromJSON Voting.Protocol.Election.Version
- Voting.Protocol.Election: instance Data.Aeson.Types.ToJSON.ToJSON (Voting.Protocol.Election.DisjProof crypto v c)
- Voting.Protocol.Election: instance Data.Aeson.Types.ToJSON.ToJSON (Voting.Protocol.Election.Proof crypto v c)
- Voting.Protocol.Election: instance Data.Aeson.Types.ToJSON.ToJSON Voting.Protocol.Election.Version
- Voting.Protocol.Election: instance Data.Reflection.Reifies v Voting.Protocol.Election.Version => Data.Aeson.Types.FromJSON.FromJSON (Voting.Protocol.Election.Question v)
- Voting.Protocol.Election: instance Data.Reflection.Reifies v Voting.Protocol.Election.Version => Data.Aeson.Types.ToJSON.ToJSON (Voting.Protocol.Election.Question v)
- Voting.Protocol.Election: instance Data.String.IsString Voting.Protocol.Election.Version
- Voting.Protocol.Election: instance GHC.Classes.Eq (Voting.Protocol.Arith.G crypto c) => GHC.Classes.Eq (Voting.Protocol.Election.Answer crypto v c)
- Voting.Protocol.Election: instance GHC.Classes.Eq (Voting.Protocol.Arith.G crypto c) => GHC.Classes.Eq (Voting.Protocol.Election.Encryption crypto v c)
- Voting.Protocol.Election: instance GHC.Classes.Eq (Voting.Protocol.Election.DisjProof crypto v c)
- Voting.Protocol.Election: instance GHC.Classes.Eq (Voting.Protocol.Election.Proof crypto v c)
- Voting.Protocol.Election: instance GHC.Classes.Eq Voting.Protocol.Election.ErrorVerifyEncryption
- Voting.Protocol.Election: instance GHC.Classes.Eq Voting.Protocol.Election.Version
- Voting.Protocol.Election: instance GHC.Classes.Ord Voting.Protocol.Election.Version
- Voting.Protocol.Election: instance GHC.Generics.Generic (Voting.Protocol.Election.DisjProof crypto v c)
- Voting.Protocol.Election: instance GHC.Generics.Generic (Voting.Protocol.Election.Encryption crypto v c)
- Voting.Protocol.Election: instance GHC.Generics.Generic (Voting.Protocol.Election.Proof crypto v c)
- Voting.Protocol.Election: instance GHC.Generics.Generic (Voting.Protocol.Election.Signature crypto v c)
- Voting.Protocol.Election: instance GHC.Generics.Generic Voting.Protocol.Election.Version
- Voting.Protocol.Election: instance GHC.Show.Show (Voting.Protocol.Election.DisjProof crypto v c)
- Voting.Protocol.Election: instance GHC.Show.Show (Voting.Protocol.Election.Proof crypto v c)
- Voting.Protocol.Election: instance GHC.Show.Show Voting.Protocol.Election.ErrorVerifyEncryption
- Voting.Protocol.Election: instance GHC.Show.Show Voting.Protocol.Election.Version
- Voting.Protocol.Election: instance Voting.Protocol.Arith.GroupParams crypto c => Data.Aeson.Types.FromJSON.FromJSON (Voting.Protocol.Election.DisjProof crypto v c)
- Voting.Protocol.Election: instance Voting.Protocol.Arith.GroupParams crypto c => Data.Aeson.Types.FromJSON.FromJSON (Voting.Protocol.Election.Proof crypto v c)
- Voting.Protocol.Election: instance Voting.Protocol.Arith.GroupParams crypto c => Voting.Protocol.Arith.Additive (Voting.Protocol.Election.Encryption crypto v c)
- Voting.Protocol.Election: intervalDisjunctions :: forall crypto c. GroupParams crypto c => Natural -> Natural -> [Disjunction crypto c]
- Voting.Protocol.Election: newtype DisjProof crypto v c
- Voting.Protocol.Election: newtype ZKP
- Voting.Protocol.Election: parseReadP :: ReadP a -> String -> Maybe a
- Voting.Protocol.Election: prove :: forall crypto v c list m r. Reifies v Version => GroupParams crypto c => Monad m => RandomGen r => Functor list => E crypto c -> list (G crypto c) -> Oracle list crypto c -> StateT r m (Proof crypto v c)
- Voting.Protocol.Election: proveEncryption :: Reifies v Version => GroupParams crypto c => Monad m => RandomGen r => PublicKey crypto c -> ZKP -> ([Disjunction crypto c], [Disjunction crypto c]) -> (EncryptionNonce crypto c, Encryption crypto v c) -> StateT r m (DisjProof crypto v c)
- Voting.Protocol.Election: proveQuicker :: Reifies v Version => GroupParams crypto c => Monad m => RandomGen r => Functor list => E crypto c -> list (G crypto c) -> Oracle list crypto c -> StateT r m (Proof crypto v c)
- Voting.Protocol.Election: readVersion :: String -> Maybe Version
- Voting.Protocol.Election: signatureCommitments :: GroupParams crypto c => ToNatural (G crypto c) => ZKP -> Commitment crypto c -> ByteString
- Voting.Protocol.Election: signatureStatement :: GroupParams crypto c => Foldable f => f (Answer crypto v c) -> [G crypto c]
- Voting.Protocol.Election: stableVersion :: Version
- Voting.Protocol.Election: type Challenge = E
- Voting.Protocol.Election: type Commitment = G
- Voting.Protocol.Election: type Disjunction = G
- Voting.Protocol.Election: type EncryptionNonce = E
- Voting.Protocol.Election: type Oracle list crypto c = list (Commitment crypto c) -> Challenge crypto c
- Voting.Protocol.Election: verifyEncryption :: Reifies v Version => GroupParams crypto c => Monad m => PublicKey crypto c -> ZKP -> [Disjunction crypto c] -> (Encryption crypto v c, DisjProof crypto v c) -> ExceptT ErrorVerifyEncryption m Bool
- Voting.Protocol.Election: versionTagQuicker :: Text
- Voting.Protocol.FFC: instance Control.DeepSeq.NFData (Voting.Protocol.Arith.G Voting.Protocol.FFC.FFC c)
- Voting.Protocol.FFC: instance Data.Aeson.Types.ToJSON.ToJSON (Voting.Protocol.Arith.G Voting.Protocol.FFC.FFC c)
- Voting.Protocol.FFC: instance Data.Reflection.Reifies c Voting.Protocol.FFC.FFC => Data.Aeson.Types.FromJSON.FromJSON (Voting.Protocol.Arith.G Voting.Protocol.FFC.FFC c)
- Voting.Protocol.FFC: instance Data.Reflection.Reifies c Voting.Protocol.FFC.FFC => System.Random.Random (Voting.Protocol.Arith.G Voting.Protocol.FFC.FFC c)
- Voting.Protocol.FFC: instance Data.Reflection.Reifies c Voting.Protocol.FFC.FFC => Voting.Protocol.Arith.Additive (Voting.Protocol.Arith.G Voting.Protocol.FFC.FFC c)
- Voting.Protocol.FFC: instance Data.Reflection.Reifies c Voting.Protocol.FFC.FFC => Voting.Protocol.Arith.FromNatural (Voting.Protocol.Arith.G Voting.Protocol.FFC.FFC c)
- Voting.Protocol.FFC: instance Data.Reflection.Reifies c Voting.Protocol.FFC.FFC => Voting.Protocol.Arith.GroupParams Voting.Protocol.FFC.FFC c
- Voting.Protocol.FFC: instance Data.Reflection.Reifies c Voting.Protocol.FFC.FFC => Voting.Protocol.Arith.Invertible (Voting.Protocol.Arith.G Voting.Protocol.FFC.FFC c)
- Voting.Protocol.FFC: instance Data.Reflection.Reifies c Voting.Protocol.FFC.FFC => Voting.Protocol.Arith.Multiplicative (Voting.Protocol.Arith.G Voting.Protocol.FFC.FFC c)
- Voting.Protocol.FFC: instance Data.Reflection.Reifies c Voting.Protocol.FFC.FFC => Voting.Protocol.Arith.Negable (Voting.Protocol.Arith.G Voting.Protocol.FFC.FFC c)
- Voting.Protocol.FFC: instance GHC.Classes.Eq (Voting.Protocol.Arith.G Voting.Protocol.FFC.FFC c)
- Voting.Protocol.FFC: instance GHC.Classes.Ord (Voting.Protocol.Arith.G Voting.Protocol.FFC.FFC c)
- Voting.Protocol.FFC: instance GHC.Show.Show (Voting.Protocol.Arith.G Voting.Protocol.FFC.FFC c)
- Voting.Protocol.FFC: instance Voting.Protocol.Arith.ReifyCrypto Voting.Protocol.FFC.FFC
- Voting.Protocol.FFC: instance Voting.Protocol.Arith.ToNatural (Voting.Protocol.Arith.G Voting.Protocol.FFC.FFC c)
- Voting.Protocol.Tally: instance (Data.Reflection.Reifies v Voting.Protocol.Election.Version, Voting.Protocol.Arith.GroupParams crypto c) => Data.Aeson.Types.FromJSON.FromJSON (Voting.Protocol.Tally.Tally crypto v c)
- Voting.Protocol.Tally: instance (Data.Reflection.Reifies v Voting.Protocol.Election.Version, Voting.Protocol.Arith.GroupParams crypto c) => Data.Aeson.Types.ToJSON.ToJSON (Voting.Protocol.Tally.Tally crypto v c)
- Voting.Protocol.Tally: instance (GHC.Show.Show (Voting.Protocol.Arith.G crypto c), GHC.Show.Show (Voting.Protocol.Arith.G crypto c)) => GHC.Show.Show (Voting.Protocol.Tally.Tally crypto v c)
- Voting.Protocol.Tally: instance Control.DeepSeq.NFData (Voting.Protocol.Arith.G crypto c) => Control.DeepSeq.NFData (Voting.Protocol.Tally.DecryptionShare crypto v c)
- Voting.Protocol.Tally: instance Control.DeepSeq.NFData (Voting.Protocol.Arith.G crypto c) => Control.DeepSeq.NFData (Voting.Protocol.Tally.Tally crypto v c)
- Voting.Protocol.Tally: instance Data.Aeson.Types.ToJSON.ToJSON (Voting.Protocol.Arith.G crypto c) => Data.Aeson.Types.ToJSON.ToJSON (Voting.Protocol.Tally.DecryptionShare crypto v c)
- Voting.Protocol.Tally: instance GHC.Classes.Eq (Voting.Protocol.Arith.G crypto c) => GHC.Classes.Eq (Voting.Protocol.Tally.DecryptionShare crypto v c)
- Voting.Protocol.Tally: instance GHC.Classes.Eq (Voting.Protocol.Arith.G crypto c) => GHC.Classes.Eq (Voting.Protocol.Tally.Tally crypto v c)
- Voting.Protocol.Tally: instance GHC.Show.Show (Voting.Protocol.Arith.G crypto c) => GHC.Show.Show (Voting.Protocol.Tally.DecryptionShare crypto v c)
- Voting.Protocol.Tally: instance Voting.Protocol.Arith.GroupParams crypto c => Data.Aeson.Types.FromJSON.FromJSON (Voting.Protocol.Tally.DecryptionShare crypto v c)
- Voting.Protocol.Trustee.Indispensable: instance (GHC.Show.Show (Voting.Protocol.Arith.G crypto c), GHC.Show.Show (Voting.Protocol.Credential.PublicKey crypto c)) => GHC.Show.Show (Voting.Protocol.Trustee.Indispensable.TrusteePublicKey crypto v c)
- Voting.Protocol.Trustee.Indispensable: instance Control.DeepSeq.NFData (Voting.Protocol.Arith.G crypto c) => Control.DeepSeq.NFData (Voting.Protocol.Trustee.Indispensable.TrusteePublicKey crypto v c)
- Voting.Protocol.Trustee.Indispensable: instance Data.Aeson.Types.ToJSON.ToJSON (Voting.Protocol.Arith.G crypto c) => Data.Aeson.Types.ToJSON.ToJSON (Voting.Protocol.Trustee.Indispensable.TrusteePublicKey crypto v c)
- Voting.Protocol.Trustee.Indispensable: instance GHC.Classes.Eq (Voting.Protocol.Arith.G crypto c) => GHC.Classes.Eq (Voting.Protocol.Trustee.Indispensable.TrusteePublicKey crypto v c)
- Voting.Protocol.Trustee.Indispensable: instance Voting.Protocol.Arith.GroupParams crypto c => Data.Aeson.Types.FromJSON.FromJSON (Voting.Protocol.Trustee.Indispensable.TrusteePublicKey crypto v c)
+ Voting.Protocol.Arithmetic: (*) :: Semiring a => a -> a -> a
+ Voting.Protocol.Arithmetic: (+) :: Additive a => a -> a -> a
+ Voting.Protocol.Arithmetic: (-) :: Ring a => a -> a -> a
+ Voting.Protocol.Arithmetic: (/) :: EuclideanRing a => a -> a -> a
+ Voting.Protocol.Arithmetic: (^) :: forall crypto c. Reifies c crypto => Semiring (G crypto c) => G crypto c -> E crypto c -> G crypto c
+ Voting.Protocol.Arithmetic: E :: Natural -> E crypto c
+ Voting.Protocol.Arithmetic: G :: FieldElement crypto -> G crypto c
+ Voting.Protocol.Arithmetic: [unE] :: E crypto c -> Natural
+ Voting.Protocol.Arithmetic: [unG] :: G crypto c -> FieldElement crypto
+ Voting.Protocol.Arithmetic: bytesNat :: ToNatural n => n -> ByteString
+ Voting.Protocol.Arithmetic: class Additive a
+ Voting.Protocol.Arithmetic: class (EuclideanRing (G crypto c), FromNatural (G crypto c), ToNatural (G crypto c), Eq (G crypto c), Ord (G crypto c), Show (G crypto c), NFData (G crypto c), FromJSON (G crypto c), ToJSON (G crypto c), Reifies c crypto) => CryptoParams crypto c
+ Voting.Protocol.Arithmetic: class Ring a => EuclideanRing a
+ Voting.Protocol.Arithmetic: class FromNatural a
+ Voting.Protocol.Arithmetic: class ReifyCrypto crypto
+ Voting.Protocol.Arithmetic: class Semiring a => Ring a
+ Voting.Protocol.Arithmetic: class Additive a => Semiring a
+ Voting.Protocol.Arithmetic: class ToNatural a
+ Voting.Protocol.Arithmetic: fromNatural :: FromNatural a => Natural -> a
+ Voting.Protocol.Arithmetic: groupGen :: CryptoParams crypto c => G crypto c
+ Voting.Protocol.Arithmetic: groupGenInverses :: CryptoParams crypto c => [G crypto c]
+ Voting.Protocol.Arithmetic: groupGenPowers :: CryptoParams crypto c => [G crypto c]
+ Voting.Protocol.Arithmetic: groupOrder :: CryptoParams crypto c => Proxy c -> Natural
+ Voting.Protocol.Arithmetic: infixl 6 -
+ Voting.Protocol.Arithmetic: infixl 7 /
+ Voting.Protocol.Arithmetic: infixr 8 ^
+ Voting.Protocol.Arithmetic: instance Control.DeepSeq.NFData (Voting.Protocol.Arithmetic.E crypto c)
+ Voting.Protocol.Arithmetic: instance Data.Aeson.Types.ToJSON.ToJSON (Voting.Protocol.Arithmetic.E crypto c)
+ Voting.Protocol.Arithmetic: instance GHC.Classes.Eq (Voting.Protocol.Arithmetic.E crypto c)
+ Voting.Protocol.Arithmetic: instance GHC.Classes.Ord (Voting.Protocol.Arithmetic.E crypto c)
+ Voting.Protocol.Arithmetic: instance GHC.Show.Show (Voting.Protocol.Arithmetic.E crypto c)
+ Voting.Protocol.Arithmetic: instance Voting.Protocol.Arithmetic.Additive GHC.Integer.Type.Integer
+ Voting.Protocol.Arithmetic: instance Voting.Protocol.Arithmetic.Additive GHC.Natural.Natural
+ Voting.Protocol.Arithmetic: instance Voting.Protocol.Arithmetic.Additive GHC.Types.Int
+ Voting.Protocol.Arithmetic: instance Voting.Protocol.Arithmetic.CryptoParams crypto c => Data.Aeson.Types.FromJSON.FromJSON (Voting.Protocol.Arithmetic.E crypto c)
+ Voting.Protocol.Arithmetic: instance Voting.Protocol.Arithmetic.CryptoParams crypto c => GHC.Enum.Bounded (Voting.Protocol.Arithmetic.E crypto c)
+ Voting.Protocol.Arithmetic: instance Voting.Protocol.Arithmetic.CryptoParams crypto c => GHC.Enum.Enum (Voting.Protocol.Arithmetic.E crypto c)
+ Voting.Protocol.Arithmetic: instance Voting.Protocol.Arithmetic.CryptoParams crypto c => System.Random.Random (Voting.Protocol.Arithmetic.E crypto c)
+ Voting.Protocol.Arithmetic: instance Voting.Protocol.Arithmetic.CryptoParams crypto c => Voting.Protocol.Arithmetic.Additive (Voting.Protocol.Arithmetic.E crypto c)
+ Voting.Protocol.Arithmetic: instance Voting.Protocol.Arithmetic.CryptoParams crypto c => Voting.Protocol.Arithmetic.FromNatural (Voting.Protocol.Arithmetic.E crypto c)
+ Voting.Protocol.Arithmetic: instance Voting.Protocol.Arithmetic.CryptoParams crypto c => Voting.Protocol.Arithmetic.Ring (Voting.Protocol.Arithmetic.E crypto c)
+ Voting.Protocol.Arithmetic: instance Voting.Protocol.Arithmetic.CryptoParams crypto c => Voting.Protocol.Arithmetic.Semiring (Voting.Protocol.Arithmetic.E crypto c)
+ Voting.Protocol.Arithmetic: instance Voting.Protocol.Arithmetic.FromNatural GHC.Natural.Natural
+ Voting.Protocol.Arithmetic: instance Voting.Protocol.Arithmetic.Ring GHC.Integer.Type.Integer
+ Voting.Protocol.Arithmetic: instance Voting.Protocol.Arithmetic.Ring GHC.Types.Int
+ Voting.Protocol.Arithmetic: instance Voting.Protocol.Arithmetic.Semiring GHC.Integer.Type.Integer
+ Voting.Protocol.Arithmetic: instance Voting.Protocol.Arithmetic.Semiring GHC.Natural.Natural
+ Voting.Protocol.Arithmetic: instance Voting.Protocol.Arithmetic.Semiring GHC.Types.Int
+ Voting.Protocol.Arithmetic: instance Voting.Protocol.Arithmetic.ToNatural (Voting.Protocol.Arithmetic.E crypto c)
+ Voting.Protocol.Arithmetic: instance Voting.Protocol.Arithmetic.ToNatural GHC.Natural.Natural
+ Voting.Protocol.Arithmetic: inverse :: EuclideanRing a => a -> a
+ Voting.Protocol.Arithmetic: nat :: ToNatural a => a -> Natural
+ Voting.Protocol.Arithmetic: negate :: Ring a => a -> a
+ Voting.Protocol.Arithmetic: newtype E crypto c
+ Voting.Protocol.Arithmetic: newtype G crypto c
+ Voting.Protocol.Arithmetic: one :: Semiring a => a
+ Voting.Protocol.Arithmetic: reifyCrypto :: ReifyCrypto crypto => crypto -> (forall c. Reifies c crypto => CryptoParams crypto c => Proxy c -> r) -> r
+ Voting.Protocol.Arithmetic: sum :: (Additive a, Foldable f) => f a -> a
+ Voting.Protocol.Arithmetic: type family FieldElement crypto :: *
+ Voting.Protocol.Arithmetic: zero :: Additive a => a
+ Voting.Protocol.Cryptography: Base64SHA256 :: Text -> Base64SHA256
+ Voting.Protocol.Cryptography: DisjProof :: [Proof crypto v c] -> DisjProof crypto v c
+ Voting.Protocol.Cryptography: Encryption :: !G crypto c -> !G crypto c -> Encryption crypto v c
+ Voting.Protocol.Cryptography: ErrorVerifyEncryption_InvalidProofLength :: Natural -> Natural -> ErrorVerifyEncryption
+ Voting.Protocol.Cryptography: Hash :: E crypto c -> Hash crypto c
+ Voting.Protocol.Cryptography: HexSHA256 :: Text -> HexSHA256
+ Voting.Protocol.Cryptography: Proof :: !Challenge crypto c -> !E crypto c -> Proof crypto v c
+ Voting.Protocol.Cryptography: Signature :: !PublicKey crypto c -> !Proof crypto v c -> Signature crypto v c
+ Voting.Protocol.Cryptography: ZKP :: ByteString -> ZKP
+ Voting.Protocol.Cryptography: [encryption_nonce] :: Encryption crypto v c -> !G crypto c
+ Voting.Protocol.Cryptography: [encryption_vault] :: Encryption crypto v c -> !G crypto c
+ Voting.Protocol.Cryptography: [proof_challenge] :: Proof crypto v c -> !Challenge crypto c
+ Voting.Protocol.Cryptography: [proof_response] :: Proof crypto v c -> !E crypto c
+ Voting.Protocol.Cryptography: [signature_proof] :: Signature crypto v c -> !Proof crypto v c
+ Voting.Protocol.Cryptography: [signature_publicKey] :: Signature crypto v c -> !PublicKey crypto c
+ Voting.Protocol.Cryptography: base64SHA256 :: ByteString -> Base64SHA256
+ Voting.Protocol.Cryptography: booleanDisjunctions :: forall crypto c. CryptoParams crypto c => [Disjunction crypto c]
+ Voting.Protocol.Cryptography: commit :: forall crypto v c. Reifies v Version => CryptoParams crypto c => Proof crypto v c -> G crypto c -> G crypto c -> Commitment crypto c
+ Voting.Protocol.Cryptography: commitQuicker :: CryptoParams crypto c => Proof crypto v c -> G crypto c -> G crypto c -> Commitment crypto c
+ Voting.Protocol.Cryptography: data Encryption crypto v c
+ Voting.Protocol.Cryptography: data ErrorVerifyEncryption
+ Voting.Protocol.Cryptography: data Proof crypto v c
+ Voting.Protocol.Cryptography: data Signature crypto v c
+ Voting.Protocol.Cryptography: decodeBigEndian :: ByteString -> Natural
+ Voting.Protocol.Cryptography: encrypt :: Reifies v Version => CryptoParams crypto c => Monad m => RandomGen r => PublicKey crypto c -> E crypto c -> StateT r m (EncryptionNonce crypto c, Encryption crypto v c)
+ Voting.Protocol.Cryptography: encryptionCommitments :: Reifies v Version => CryptoParams crypto c => PublicKey crypto c -> Encryption crypto v c -> Disjunction crypto c -> Proof crypto v c -> [G crypto c]
+ Voting.Protocol.Cryptography: encryptionStatement :: CryptoParams crypto c => ZKP -> Encryption crypto v c -> ByteString
+ Voting.Protocol.Cryptography: fakeProof :: CryptoParams crypto c => Monad m => RandomGen r => StateT r m (Proof crypto v c)
+ Voting.Protocol.Cryptography: hash :: CryptoParams crypto c => ByteString -> [G crypto c] -> E crypto c
+ Voting.Protocol.Cryptography: hexSHA256 :: ByteString -> Text
+ Voting.Protocol.Cryptography: instance Control.DeepSeq.NFData (Voting.Protocol.Cryptography.Hash crypto c)
+ Voting.Protocol.Cryptography: instance Control.DeepSeq.NFData Voting.Protocol.Cryptography.Base64SHA256
+ Voting.Protocol.Cryptography: instance Control.DeepSeq.NFData Voting.Protocol.Cryptography.HexSHA256
+ Voting.Protocol.Cryptography: instance Data.Aeson.Types.FromJSON.FromJSON Voting.Protocol.Cryptography.Base64SHA256
+ Voting.Protocol.Cryptography: instance Data.Aeson.Types.FromJSON.FromJSON Voting.Protocol.Cryptography.HexSHA256
+ Voting.Protocol.Cryptography: instance Data.Aeson.Types.ToJSON.ToJSON Voting.Protocol.Cryptography.Base64SHA256
+ Voting.Protocol.Cryptography: instance Data.Aeson.Types.ToJSON.ToJSON Voting.Protocol.Cryptography.HexSHA256
+ Voting.Protocol.Cryptography: instance GHC.Classes.Eq (Voting.Protocol.Cryptography.Hash crypto c)
+ Voting.Protocol.Cryptography: instance GHC.Classes.Eq Voting.Protocol.Cryptography.Base64SHA256
+ Voting.Protocol.Cryptography: instance GHC.Classes.Eq Voting.Protocol.Cryptography.ErrorVerifyEncryption
+ Voting.Protocol.Cryptography: instance GHC.Classes.Eq Voting.Protocol.Cryptography.HexSHA256
+ Voting.Protocol.Cryptography: instance GHC.Classes.Ord (Voting.Protocol.Cryptography.Hash crypto c)
+ Voting.Protocol.Cryptography: instance GHC.Classes.Ord Voting.Protocol.Cryptography.Base64SHA256
+ Voting.Protocol.Cryptography: instance GHC.Classes.Ord Voting.Protocol.Cryptography.HexSHA256
+ Voting.Protocol.Cryptography: instance GHC.Generics.Generic Voting.Protocol.Cryptography.Base64SHA256
+ Voting.Protocol.Cryptography: instance GHC.Generics.Generic Voting.Protocol.Cryptography.HexSHA256
+ Voting.Protocol.Cryptography: instance GHC.Show.Show (Voting.Protocol.Cryptography.Hash crypto c)
+ Voting.Protocol.Cryptography: instance GHC.Show.Show Voting.Protocol.Cryptography.Base64SHA256
+ Voting.Protocol.Cryptography: instance GHC.Show.Show Voting.Protocol.Cryptography.ErrorVerifyEncryption
+ Voting.Protocol.Cryptography: instance GHC.Show.Show Voting.Protocol.Cryptography.HexSHA256
+ Voting.Protocol.Cryptography: instance forall crypto k (v :: k) c. Control.DeepSeq.NFData (Voting.Protocol.Cryptography.DisjProof crypto v c)
+ Voting.Protocol.Cryptography: instance forall crypto k (v :: k) c. Control.DeepSeq.NFData (Voting.Protocol.Cryptography.Proof crypto v c)
+ Voting.Protocol.Cryptography: instance forall crypto k (v :: k) c. GHC.Classes.Eq (Voting.Protocol.Cryptography.DisjProof crypto v c)
+ Voting.Protocol.Cryptography: instance forall crypto k (v :: k) c. GHC.Classes.Eq (Voting.Protocol.Cryptography.Proof crypto v c)
+ Voting.Protocol.Cryptography: instance forall crypto k (v :: k) c. GHC.Generics.Generic (Voting.Protocol.Cryptography.DisjProof crypto v c)
+ Voting.Protocol.Cryptography: instance forall crypto k (v :: k) c. GHC.Generics.Generic (Voting.Protocol.Cryptography.Encryption crypto v c)
+ Voting.Protocol.Cryptography: instance forall crypto k (v :: k) c. GHC.Generics.Generic (Voting.Protocol.Cryptography.Proof crypto v c)
+ Voting.Protocol.Cryptography: instance forall crypto k (v :: k) c. GHC.Generics.Generic (Voting.Protocol.Cryptography.Signature crypto v c)
+ Voting.Protocol.Cryptography: instance forall crypto k (v :: k) c. GHC.Show.Show (Voting.Protocol.Cryptography.DisjProof crypto v c)
+ Voting.Protocol.Cryptography: instance forall crypto k (v :: k) c. GHC.Show.Show (Voting.Protocol.Cryptography.Proof crypto v c)
+ Voting.Protocol.Cryptography: instance forall k (v :: k) crypto c. (Data.Reflection.Reifies v Voting.Protocol.Version.Version, Voting.Protocol.Arithmetic.CryptoParams crypto c) => Data.Aeson.Types.FromJSON.FromJSON (Voting.Protocol.Cryptography.DisjProof crypto v c)
+ Voting.Protocol.Cryptography: instance forall k (v :: k) crypto c. (Data.Reflection.Reifies v Voting.Protocol.Version.Version, Voting.Protocol.Arithmetic.CryptoParams crypto c) => Data.Aeson.Types.FromJSON.FromJSON (Voting.Protocol.Cryptography.Encryption crypto v c)
+ Voting.Protocol.Cryptography: instance forall k (v :: k) crypto c. (Data.Reflection.Reifies v Voting.Protocol.Version.Version, Voting.Protocol.Arithmetic.CryptoParams crypto c) => Data.Aeson.Types.FromJSON.FromJSON (Voting.Protocol.Cryptography.Signature crypto v c)
+ Voting.Protocol.Cryptography: instance forall k (v :: k) crypto c. (Data.Reflection.Reifies v Voting.Protocol.Version.Version, Voting.Protocol.Arithmetic.CryptoParams crypto c) => Data.Aeson.Types.ToJSON.ToJSON (Voting.Protocol.Cryptography.Encryption crypto v c)
+ Voting.Protocol.Cryptography: instance forall k (v :: k) crypto c. (Data.Reflection.Reifies v Voting.Protocol.Version.Version, Voting.Protocol.Arithmetic.CryptoParams crypto c) => Data.Aeson.Types.ToJSON.ToJSON (Voting.Protocol.Cryptography.Signature crypto v c)
+ Voting.Protocol.Cryptography: instance forall k (v :: k) crypto c. Data.Reflection.Reifies v Voting.Protocol.Version.Version => Data.Aeson.Types.ToJSON.ToJSON (Voting.Protocol.Cryptography.DisjProof crypto v c)
+ Voting.Protocol.Cryptography: instance forall k (v :: k) crypto c. Data.Reflection.Reifies v Voting.Protocol.Version.Version => Data.Aeson.Types.ToJSON.ToJSON (Voting.Protocol.Cryptography.Proof crypto v c)
+ Voting.Protocol.Cryptography: instance forall k crypto c (v :: k). (Control.DeepSeq.NFData crypto, Control.DeepSeq.NFData (Voting.Protocol.Arithmetic.G crypto c)) => Control.DeepSeq.NFData (Voting.Protocol.Cryptography.Signature crypto v c)
+ Voting.Protocol.Cryptography: instance forall k crypto c (v :: k). (GHC.Show.Show (Voting.Protocol.Arithmetic.G crypto c), GHC.Show.Show (Voting.Protocol.Arithmetic.G crypto c)) => GHC.Show.Show (Voting.Protocol.Cryptography.Encryption crypto v c)
+ Voting.Protocol.Cryptography: instance forall k crypto c (v :: k). (Voting.Protocol.Arithmetic.CryptoParams crypto c, Data.Reflection.Reifies v Voting.Protocol.Version.Version) => Data.Aeson.Types.FromJSON.FromJSON (Voting.Protocol.Cryptography.Proof crypto v c)
+ Voting.Protocol.Cryptography: instance forall k crypto c (v :: k). Control.DeepSeq.NFData (Voting.Protocol.Arithmetic.G crypto c) => Control.DeepSeq.NFData (Voting.Protocol.Cryptography.Encryption crypto v c)
+ Voting.Protocol.Cryptography: instance forall k crypto c (v :: k). GHC.Classes.Eq (Voting.Protocol.Arithmetic.G crypto c) => GHC.Classes.Eq (Voting.Protocol.Cryptography.Encryption crypto v c)
+ Voting.Protocol.Cryptography: instance forall k crypto c (v :: k). Voting.Protocol.Arithmetic.CryptoParams crypto c => Voting.Protocol.Arithmetic.Additive (Voting.Protocol.Cryptography.Encryption crypto v c)
+ Voting.Protocol.Cryptography: intervalDisjunctions :: forall crypto c. CryptoParams crypto c => Natural -> Natural -> [Disjunction crypto c]
+ Voting.Protocol.Cryptography: newtype Base64SHA256
+ Voting.Protocol.Cryptography: newtype DisjProof crypto v c
+ Voting.Protocol.Cryptography: newtype Hash crypto c
+ Voting.Protocol.Cryptography: newtype HexSHA256
+ Voting.Protocol.Cryptography: newtype ZKP
+ Voting.Protocol.Cryptography: prove :: forall crypto v c list m r. Reifies v Version => CryptoParams crypto c => Monad m => RandomGen r => Functor list => E crypto c -> list (G crypto c) -> Oracle list crypto c -> StateT r m (Proof crypto v c)
+ Voting.Protocol.Cryptography: proveEncryption :: Reifies v Version => CryptoParams crypto c => Monad m => RandomGen r => PublicKey crypto c -> ZKP -> ([Disjunction crypto c], [Disjunction crypto c]) -> (EncryptionNonce crypto c, Encryption crypto v c) -> StateT r m (DisjProof crypto v c)
+ Voting.Protocol.Cryptography: proveQuicker :: Reifies v Version => CryptoParams crypto c => Monad m => RandomGen r => Functor list => E crypto c -> list (G crypto c) -> Oracle list crypto c -> StateT r m (Proof crypto v c)
+ Voting.Protocol.Cryptography: random :: Monad m => RandomGen r => Random i => Bounded i => StateT r m i
+ Voting.Protocol.Cryptography: randomR :: Monad m => RandomGen r => Random i => Ring i => i -> StateT r m i
+ Voting.Protocol.Cryptography: type Challenge = E
+ Voting.Protocol.Cryptography: type Commitment = G
+ Voting.Protocol.Cryptography: type Disjunction = G
+ Voting.Protocol.Cryptography: type EncryptionNonce = E
+ Voting.Protocol.Cryptography: type Oracle list crypto c = list (Commitment crypto c) -> Challenge crypto c
+ Voting.Protocol.Cryptography: type PublicKey = G
+ Voting.Protocol.Cryptography: type SecretKey = E
+ Voting.Protocol.Cryptography: verifyEncryption :: Reifies v Version => CryptoParams crypto c => Monad m => PublicKey crypto c -> ZKP -> [Disjunction crypto c] -> (Encryption crypto v c, DisjProof crypto v c) -> ExceptT ErrorVerifyEncryption m Bool
+ Voting.Protocol.Election: ballotCommitments :: CryptoParams crypto c => ToNatural (G crypto c) => ZKP -> Commitment crypto c -> ByteString
+ Voting.Protocol.Election: ballotStatement :: CryptoParams crypto c => [Answer crypto v c] -> [G crypto c]
+ Voting.Protocol.Election: instance (Control.DeepSeq.NFData (Voting.Protocol.Arithmetic.G crypto c), Control.DeepSeq.NFData crypto) => Control.DeepSeq.NFData (Voting.Protocol.Election.Ballot crypto v c)
+ Voting.Protocol.Election: instance (Control.DeepSeq.NFData crypto, Control.DeepSeq.NFData (Voting.Protocol.Arithmetic.G crypto c)) => Control.DeepSeq.NFData (Voting.Protocol.Election.Election crypto v c)
+ Voting.Protocol.Election: instance (Data.Reflection.Reifies v Voting.Protocol.Version.Version, Voting.Protocol.Arithmetic.CryptoParams crypto c) => Data.Aeson.Types.FromJSON.FromJSON (Voting.Protocol.Election.Answer crypto v c)
+ Voting.Protocol.Election: instance (Data.Reflection.Reifies v Voting.Protocol.Version.Version, Voting.Protocol.Arithmetic.CryptoParams crypto c) => Data.Aeson.Types.FromJSON.FromJSON (Voting.Protocol.Election.Ballot crypto v c)
+ Voting.Protocol.Election: instance (Data.Reflection.Reifies v Voting.Protocol.Version.Version, Voting.Protocol.Arithmetic.CryptoParams crypto c) => Data.Aeson.Types.ToJSON.ToJSON (Voting.Protocol.Election.Answer crypto v c)
+ Voting.Protocol.Election: instance (Data.Reflection.Reifies v Voting.Protocol.Version.Version, Voting.Protocol.Arithmetic.CryptoParams crypto c, Data.Aeson.Types.ToJSON.ToJSON (Voting.Protocol.Arithmetic.G crypto c)) => Data.Aeson.Types.ToJSON.ToJSON (Voting.Protocol.Election.Ballot crypto v c)
+ Voting.Protocol.Election: instance (Data.Reflection.Reifies v Voting.Protocol.Version.Version, Voting.Protocol.Arithmetic.CryptoParams crypto c, Data.Aeson.Types.ToJSON.ToJSON crypto) => Data.Aeson.Types.ToJSON.ToJSON (Voting.Protocol.Election.Election crypto v c)
+ Voting.Protocol.Election: instance (GHC.Classes.Eq crypto, GHC.Classes.Eq (Voting.Protocol.Arithmetic.G crypto c)) => GHC.Classes.Eq (Voting.Protocol.Election.Election crypto v c)
+ Voting.Protocol.Election: instance (GHC.Show.Show (Voting.Protocol.Arithmetic.G crypto c), GHC.Show.Show (Voting.Protocol.Arithmetic.G crypto c)) => GHC.Show.Show (Voting.Protocol.Election.Answer crypto v c)
+ Voting.Protocol.Election: instance (GHC.Show.Show crypto, GHC.Show.Show (Voting.Protocol.Arithmetic.G crypto c)) => GHC.Show.Show (Voting.Protocol.Election.Election crypto v c)
+ Voting.Protocol.Election: instance Control.DeepSeq.NFData (Voting.Protocol.Arithmetic.G crypto c) => Control.DeepSeq.NFData (Voting.Protocol.Election.Answer crypto v c)
+ Voting.Protocol.Election: instance Data.Reflection.Reifies v Voting.Protocol.Version.Version => Data.Aeson.Types.FromJSON.FromJSON (Voting.Protocol.Election.Question v)
+ Voting.Protocol.Election: instance Data.Reflection.Reifies v Voting.Protocol.Version.Version => Data.Aeson.Types.ToJSON.ToJSON (Voting.Protocol.Election.Question v)
+ Voting.Protocol.Election: instance GHC.Classes.Eq (Voting.Protocol.Arithmetic.G crypto c) => GHC.Classes.Eq (Voting.Protocol.Election.Answer crypto v c)
+ Voting.Protocol.FFC: instance Control.DeepSeq.NFData (Voting.Protocol.Arithmetic.G Voting.Protocol.FFC.FFC c)
+ Voting.Protocol.FFC: instance Data.Aeson.Types.ToJSON.ToJSON (Voting.Protocol.Arithmetic.G Voting.Protocol.FFC.FFC c)
+ Voting.Protocol.FFC: instance Data.Reflection.Reifies c Voting.Protocol.FFC.FFC => Data.Aeson.Types.FromJSON.FromJSON (Voting.Protocol.Arithmetic.G Voting.Protocol.FFC.FFC c)
+ Voting.Protocol.FFC: instance Data.Reflection.Reifies c Voting.Protocol.FFC.FFC => System.Random.Random (Voting.Protocol.Arithmetic.G Voting.Protocol.FFC.FFC c)
+ Voting.Protocol.FFC: instance Data.Reflection.Reifies c Voting.Protocol.FFC.FFC => Voting.Protocol.Arithmetic.Additive (Voting.Protocol.Arithmetic.G Voting.Protocol.FFC.FFC c)
+ Voting.Protocol.FFC: instance Data.Reflection.Reifies c Voting.Protocol.FFC.FFC => Voting.Protocol.Arithmetic.CryptoParams Voting.Protocol.FFC.FFC c
+ Voting.Protocol.FFC: instance Data.Reflection.Reifies c Voting.Protocol.FFC.FFC => Voting.Protocol.Arithmetic.EuclideanRing (Voting.Protocol.Arithmetic.G Voting.Protocol.FFC.FFC c)
+ Voting.Protocol.FFC: instance Data.Reflection.Reifies c Voting.Protocol.FFC.FFC => Voting.Protocol.Arithmetic.FromNatural (Voting.Protocol.Arithmetic.G Voting.Protocol.FFC.FFC c)
+ Voting.Protocol.FFC: instance Data.Reflection.Reifies c Voting.Protocol.FFC.FFC => Voting.Protocol.Arithmetic.Ring (Voting.Protocol.Arithmetic.G Voting.Protocol.FFC.FFC c)
+ Voting.Protocol.FFC: instance Data.Reflection.Reifies c Voting.Protocol.FFC.FFC => Voting.Protocol.Arithmetic.Semiring (Voting.Protocol.Arithmetic.G Voting.Protocol.FFC.FFC c)
+ Voting.Protocol.FFC: instance GHC.Classes.Eq (Voting.Protocol.Arithmetic.G Voting.Protocol.FFC.FFC c)
+ Voting.Protocol.FFC: instance GHC.Classes.Ord (Voting.Protocol.Arithmetic.G Voting.Protocol.FFC.FFC c)
+ Voting.Protocol.FFC: instance GHC.Show.Show (Voting.Protocol.Arithmetic.G Voting.Protocol.FFC.FFC c)
+ Voting.Protocol.FFC: instance Voting.Protocol.Arithmetic.ReifyCrypto Voting.Protocol.FFC.FFC
+ Voting.Protocol.FFC: instance Voting.Protocol.Arithmetic.ToNatural (Voting.Protocol.Arithmetic.G Voting.Protocol.FFC.FFC c)
+ Voting.Protocol.Tally: instance (Data.Reflection.Reifies v Voting.Protocol.Version.Version, Data.Aeson.Types.ToJSON.ToJSON (Voting.Protocol.Arithmetic.G crypto c)) => Data.Aeson.Types.ToJSON.ToJSON (Voting.Protocol.Tally.DecryptionShare crypto v c)
+ Voting.Protocol.Tally: instance (Data.Reflection.Reifies v Voting.Protocol.Version.Version, Voting.Protocol.Arithmetic.CryptoParams crypto c) => Data.Aeson.Types.FromJSON.FromJSON (Voting.Protocol.Tally.DecryptionShare crypto v c)
+ Voting.Protocol.Tally: instance (Data.Reflection.Reifies v Voting.Protocol.Version.Version, Voting.Protocol.Arithmetic.CryptoParams crypto c) => Data.Aeson.Types.FromJSON.FromJSON (Voting.Protocol.Tally.Tally crypto v c)
+ Voting.Protocol.Tally: instance (Data.Reflection.Reifies v Voting.Protocol.Version.Version, Voting.Protocol.Arithmetic.CryptoParams crypto c) => Data.Aeson.Types.ToJSON.ToJSON (Voting.Protocol.Tally.Tally crypto v c)
+ Voting.Protocol.Tally: instance (GHC.Show.Show (Voting.Protocol.Arithmetic.G crypto c), GHC.Show.Show (Voting.Protocol.Arithmetic.G crypto c)) => GHC.Show.Show (Voting.Protocol.Tally.Tally crypto v c)
+ Voting.Protocol.Tally: instance Control.DeepSeq.NFData (Voting.Protocol.Arithmetic.G crypto c) => Control.DeepSeq.NFData (Voting.Protocol.Tally.DecryptionShare crypto v c)
+ Voting.Protocol.Tally: instance Control.DeepSeq.NFData (Voting.Protocol.Arithmetic.G crypto c) => Control.DeepSeq.NFData (Voting.Protocol.Tally.Tally crypto v c)
+ Voting.Protocol.Tally: instance GHC.Classes.Eq (Voting.Protocol.Arithmetic.G crypto c) => GHC.Classes.Eq (Voting.Protocol.Tally.DecryptionShare crypto v c)
+ Voting.Protocol.Tally: instance GHC.Classes.Eq (Voting.Protocol.Arithmetic.G crypto c) => GHC.Classes.Eq (Voting.Protocol.Tally.Tally crypto v c)
+ Voting.Protocol.Tally: instance GHC.Show.Show (Voting.Protocol.Arithmetic.G crypto c) => GHC.Show.Show (Voting.Protocol.Tally.DecryptionShare crypto v c)
+ Voting.Protocol.Trustee.Indispensable: instance (Data.Reflection.Reifies v Voting.Protocol.Version.Version, Data.Aeson.Types.ToJSON.ToJSON (Voting.Protocol.Arithmetic.G crypto c)) => Data.Aeson.Types.ToJSON.ToJSON (Voting.Protocol.Trustee.Indispensable.TrusteePublicKey crypto v c)
+ Voting.Protocol.Trustee.Indispensable: instance (Data.Reflection.Reifies v Voting.Protocol.Version.Version, Voting.Protocol.Arithmetic.CryptoParams crypto c) => Data.Aeson.Types.FromJSON.FromJSON (Voting.Protocol.Trustee.Indispensable.TrusteePublicKey crypto v c)
+ Voting.Protocol.Trustee.Indispensable: instance (GHC.Show.Show (Voting.Protocol.Arithmetic.G crypto c), GHC.Show.Show (Voting.Protocol.Cryptography.PublicKey crypto c)) => GHC.Show.Show (Voting.Protocol.Trustee.Indispensable.TrusteePublicKey crypto v c)
+ Voting.Protocol.Trustee.Indispensable: instance Control.DeepSeq.NFData (Voting.Protocol.Arithmetic.G crypto c) => Control.DeepSeq.NFData (Voting.Protocol.Trustee.Indispensable.TrusteePublicKey crypto v c)
+ Voting.Protocol.Trustee.Indispensable: instance GHC.Classes.Eq (Voting.Protocol.Arithmetic.G crypto c) => GHC.Classes.Eq (Voting.Protocol.Trustee.Indispensable.TrusteePublicKey crypto v c)
+ Voting.Protocol.Utils: instance System.Random.Random GHC.Natural.Natural
+ Voting.Protocol.Utils: parseReadP :: ReadP a -> String -> Maybe a
+ Voting.Protocol.Version: Version :: [Natural] -> [(Text, Natural)] -> Version
+ Voting.Protocol.Version: [version_branch] :: Version -> [Natural]
+ Voting.Protocol.Version: [version_tags] :: Version -> [(Text, Natural)]
+ Voting.Protocol.Version: class VersionBranchVal a
+ Voting.Protocol.Version: class VersionTagsVal a
+ Voting.Protocol.Version: data V (branch :: [Nat]) (tags :: [(Symbol, Nat)])
+ Voting.Protocol.Version: data Version
+ Voting.Protocol.Version: experimentalVersion :: Version
+ Voting.Protocol.Version: hasVersionTag :: Version -> Text -> Bool
+ Voting.Protocol.Version: instance (GHC.TypeLits.KnownSymbol s, GHC.TypeNats.KnownNat n, Voting.Protocol.Version.VersionTagsVal t) => Voting.Protocol.Version.VersionTagsVal ('(s, n) : t)
+ Voting.Protocol.Version: instance (GHC.TypeNats.KnownNat h, GHC.TypeNats.KnownNat hh, Voting.Protocol.Version.VersionBranchVal (hh : t)) => Voting.Protocol.Version.VersionBranchVal (h : hh : t)
+ Voting.Protocol.Version: instance (Voting.Protocol.Version.VersionBranchVal branch, Voting.Protocol.Version.VersionTagsVal tags) => Data.Reflection.Reifies (Voting.Protocol.Version.V branch tags) Voting.Protocol.Version.Version
+ Voting.Protocol.Version: instance Control.DeepSeq.NFData Voting.Protocol.Version.Version
+ Voting.Protocol.Version: instance Data.Aeson.Types.FromJSON.FromJSON Voting.Protocol.Version.Version
+ Voting.Protocol.Version: instance Data.Aeson.Types.ToJSON.ToJSON Voting.Protocol.Version.Version
+ Voting.Protocol.Version: instance Data.String.IsString Voting.Protocol.Version.Version
+ Voting.Protocol.Version: instance GHC.Classes.Eq Voting.Protocol.Version.Version
+ Voting.Protocol.Version: instance GHC.Classes.Ord Voting.Protocol.Version.Version
+ Voting.Protocol.Version: instance GHC.Generics.Generic Voting.Protocol.Version.Version
+ Voting.Protocol.Version: instance GHC.Show.Show Voting.Protocol.Version.Version
+ Voting.Protocol.Version: instance GHC.TypeNats.KnownNat h => Voting.Protocol.Version.VersionBranchVal '[h]
+ Voting.Protocol.Version: instance Voting.Protocol.Version.VersionTagsVal '[]
+ Voting.Protocol.Version: readVersion :: String -> Maybe Version
+ Voting.Protocol.Version: stableVersion :: Version
+ Voting.Protocol.Version: type ExperimentalVersion = V [1, 6] '['(VersionTagQuicker, 0)]
+ Voting.Protocol.Version: type StableVersion = V [1, 6] '[]
+ Voting.Protocol.Version: type VersionTagQuicker = "quicker"
+ Voting.Protocol.Version: versionBranchVal :: VersionBranchVal a => proxy a -> [Natural]
+ Voting.Protocol.Version: versionTagQuicker :: Text
+ Voting.Protocol.Version: versionTagsVal :: VersionTagsVal a => proxy a -> [(Text, Natural)]
- Voting.Protocol.Election: encryptAnswer :: Reifies v Version => GroupParams crypto c => Monad m => RandomGen r => PublicKey crypto c -> ZKP -> Question v -> [Bool] -> StateT r (ExceptT ErrorAnswer m) (Answer crypto v c)
+ Voting.Protocol.Election: encryptAnswer :: Reifies v Version => CryptoParams crypto c => Monad m => RandomGen r => PublicKey crypto c -> ZKP -> Question v -> [Bool] -> StateT r (ExceptT ErrorAnswer m) (Answer crypto v c)
- Voting.Protocol.Election: encryptBallot :: Reifies v Version => GroupParams crypto c => Key crypto => Monad m => RandomGen r => Election crypto v c -> Maybe (SecretKey crypto c) -> [[Bool]] -> StateT r (ExceptT ErrorBallot m) (Ballot crypto v c)
+ Voting.Protocol.Election: encryptBallot :: Reifies v Version => CryptoParams crypto c => Key crypto => Monad m => RandomGen r => Election crypto v c -> Maybe (SecretKey crypto c) -> [[Bool]] -> StateT r (ExceptT ErrorBallot m) (Ballot crypto v c)
- Voting.Protocol.Election: hashElection :: Reifies v Version => GroupParams crypto c => ToJSON crypto => Election crypto v c -> Base64SHA256
+ Voting.Protocol.Election: hashElection :: Reifies v Version => CryptoParams crypto c => ToJSON crypto => Election crypto v c -> Base64SHA256
- Voting.Protocol.Election: readElection :: forall crypto r. FromJSON crypto => ReifyCrypto crypto => FilePath -> (forall v c. Reifies v Version => GroupParams crypto c => Election crypto v c -> r) -> ExceptT String IO r
+ Voting.Protocol.Election: readElection :: forall crypto r. FromJSON crypto => ReifyCrypto crypto => FilePath -> (forall v c. Reifies v Version => CryptoParams crypto c => Election crypto v c -> r) -> ExceptT String IO r
- Voting.Protocol.Election: verifyAnswer :: Reifies v Version => GroupParams crypto c => PublicKey crypto c -> ZKP -> Question v -> Answer crypto v c -> Bool
+ Voting.Protocol.Election: verifyAnswer :: Reifies v Version => CryptoParams crypto c => PublicKey crypto c -> ZKP -> Question v -> Answer crypto v c -> Bool
- Voting.Protocol.Election: verifyBallot :: Reifies v Version => GroupParams crypto c => Election crypto v c -> Ballot crypto v c -> Bool
+ Voting.Protocol.Election: verifyBallot :: Reifies v Version => CryptoParams crypto c => Election crypto v c -> Ballot crypto v c -> Bool
- Voting.Protocol.Tally: decryptionShareStatement :: GroupParams crypto c => PublicKey crypto c -> ByteString
+ Voting.Protocol.Tally: decryptionShareStatement :: CryptoParams crypto c => PublicKey crypto c -> ByteString
- Voting.Protocol.Tally: emptyEncryptedTally :: GroupParams crypto c => (EncryptedTally crypto v c, Natural)
+ Voting.Protocol.Tally: emptyEncryptedTally :: CryptoParams crypto c => (EncryptedTally crypto v c, Natural)
- Voting.Protocol.Tally: encryptedTally :: GroupParams crypto c => [Ballot crypto v c] -> (EncryptedTally crypto v c, Natural)
+ Voting.Protocol.Tally: encryptedTally :: CryptoParams crypto c => [Ballot crypto v c] -> (EncryptedTally crypto v c, Natural)
- Voting.Protocol.Tally: insertEncryptedTally :: GroupParams crypto c => Ballot crypto v c -> (EncryptedTally crypto v c, Natural) -> (EncryptedTally crypto v c, Natural)
+ Voting.Protocol.Tally: insertEncryptedTally :: CryptoParams crypto c => Ballot crypto v c -> (EncryptedTally crypto v c, Natural) -> (EncryptedTally crypto v c, Natural)
- Voting.Protocol.Tally: proveDecryptionFactor :: Reifies v Version => GroupParams crypto c => Key crypto => Monad m => RandomGen r => SecretKey crypto c -> Encryption crypto v c -> StateT r m (DecryptionFactor crypto c, Proof crypto v c)
+ Voting.Protocol.Tally: proveDecryptionFactor :: Reifies v Version => CryptoParams crypto c => Key crypto => Monad m => RandomGen r => SecretKey crypto c -> Encryption crypto v c -> StateT r m (DecryptionFactor crypto c, Proof crypto v c)
- Voting.Protocol.Tally: proveDecryptionShare :: Reifies v Version => GroupParams crypto c => Key crypto => Monad m => RandomGen r => EncryptedTally crypto v c -> SecretKey crypto c -> StateT r m (DecryptionShare crypto v c)
+ Voting.Protocol.Tally: proveDecryptionShare :: Reifies v Version => CryptoParams crypto c => Key crypto => Monad m => RandomGen r => EncryptedTally crypto v c -> SecretKey crypto c -> StateT r m (DecryptionShare crypto v c)
- Voting.Protocol.Tally: proveTally :: GroupParams crypto c => (EncryptedTally crypto v c, Natural) -> [DecryptionShare crypto v c] -> DecryptionShareCombinator crypto v c -> Except ErrorTally (Tally crypto v c)
+ Voting.Protocol.Tally: proveTally :: CryptoParams crypto c => (EncryptedTally crypto v c, Natural) -> [DecryptionShare crypto v c] -> DecryptionShareCombinator crypto v c -> Except ErrorTally (Tally crypto v c)
- Voting.Protocol.Tally: verifyDecryptionShare :: Reifies v Version => GroupParams crypto c => Monad m => EncryptedTally crypto v c -> PublicKey crypto c -> DecryptionShare crypto v c -> ExceptT ErrorTally m ()
+ Voting.Protocol.Tally: verifyDecryptionShare :: Reifies v Version => CryptoParams crypto c => Monad m => EncryptedTally crypto v c -> PublicKey crypto c -> DecryptionShare crypto v c -> ExceptT ErrorTally m ()
- Voting.Protocol.Tally: verifyDecryptionShareByTrustee :: Reifies v Version => GroupParams crypto c => Monad m => EncryptedTally crypto v c -> [PublicKey crypto c] -> [DecryptionShare crypto v c] -> ExceptT ErrorTally m ()
+ Voting.Protocol.Tally: verifyDecryptionShareByTrustee :: Reifies v Version => CryptoParams crypto c => Monad m => EncryptedTally crypto v c -> [PublicKey crypto c] -> [DecryptionShare crypto v c] -> ExceptT ErrorTally m ()
- Voting.Protocol.Tally: verifyTally :: GroupParams crypto c => Tally crypto v c -> DecryptionShareCombinator crypto v c -> Except ErrorTally ()
+ Voting.Protocol.Tally: verifyTally :: CryptoParams crypto c => Tally crypto v c -> DecryptionShareCombinator crypto v c -> Except ErrorTally ()
- Voting.Protocol.Trustee.Indispensable: combineIndispensableDecryptionShares :: Reifies v Version => GroupParams crypto c => [PublicKey crypto c] -> DecryptionShareCombinator crypto v c
+ Voting.Protocol.Trustee.Indispensable: combineIndispensableDecryptionShares :: Reifies v Version => CryptoParams crypto c => [PublicKey crypto c] -> DecryptionShareCombinator crypto v c
- Voting.Protocol.Trustee.Indispensable: combineIndispensableTrusteePublicKeys :: GroupParams crypto c => [TrusteePublicKey crypto v c] -> PublicKey crypto c
+ Voting.Protocol.Trustee.Indispensable: combineIndispensableTrusteePublicKeys :: CryptoParams crypto c => [TrusteePublicKey crypto v c] -> PublicKey crypto c
- Voting.Protocol.Trustee.Indispensable: indispensableTrusteePublicKeyStatement :: GroupParams crypto c => PublicKey crypto c -> ByteString
+ Voting.Protocol.Trustee.Indispensable: indispensableTrusteePublicKeyStatement :: CryptoParams crypto c => PublicKey crypto c -> ByteString
- Voting.Protocol.Trustee.Indispensable: proveIndispensableTrusteePublicKey :: Reifies v Version => GroupParams crypto c => Key crypto => Monad m => RandomGen r => SecretKey crypto c -> StateT r m (TrusteePublicKey crypto v c)
+ Voting.Protocol.Trustee.Indispensable: proveIndispensableTrusteePublicKey :: Reifies v Version => CryptoParams crypto c => Key crypto => Monad m => RandomGen r => SecretKey crypto c -> StateT r m (TrusteePublicKey crypto v c)
- Voting.Protocol.Trustee.Indispensable: verifyIndispensableDecryptionShareByTrustee :: Reifies v Version => GroupParams crypto c => Monad m => EncryptedTally crypto v c -> [PublicKey crypto c] -> [DecryptionShare crypto v c] -> ExceptT ErrorTally m ()
+ Voting.Protocol.Trustee.Indispensable: verifyIndispensableDecryptionShareByTrustee :: Reifies v Version => CryptoParams crypto c => Monad m => EncryptedTally crypto v c -> [PublicKey crypto c] -> [DecryptionShare crypto v c] -> ExceptT ErrorTally m ()
- Voting.Protocol.Trustee.Indispensable: verifyIndispensableTrusteePublicKey :: Reifies v Version => GroupParams crypto c => Monad m => TrusteePublicKey crypto v c -> ExceptT ErrorTrusteePublicKey m ()
+ Voting.Protocol.Trustee.Indispensable: verifyIndispensableTrusteePublicKey :: Reifies v Version => CryptoParams crypto c => Monad m => TrusteePublicKey crypto v c -> ExceptT ErrorTrusteePublicKey m ()

Files

benchmarks/Election.hs view
@@ -13,7 +13,7 @@ makeElection ::  forall crypto v c.  Reifies v Version =>- GroupParams crypto c =>+ CryptoParams crypto c =>  Key crypto =>  JSON.ToJSON crypto =>  Int -> Int -> Election crypto v c@@ -47,7 +47,7 @@  makeBallot ::  Reifies v Version =>- GroupParams crypto c => Key crypto =>+ CryptoParams crypto c => Key crypto =>  Election crypto v c -> Ballot crypto v c makeBallot elec = 	case runExcept $ (`evalStateT` mkStdGen seed) $ do@@ -69,7 +69,7 @@  benchEncryptBallot ::  forall crypto v c.- GroupParams crypto c =>+ CryptoParams crypto c =>  Reifies v Version =>  Key crypto =>  JSON.ToJSON crypto =>@@ -86,7 +86,7 @@ benchVerifyBallot ::  forall crypto v c.  Reifies v Version =>- GroupParams crypto c =>+ CryptoParams crypto c =>  Key crypto =>  JSON.ToJSON crypto =>  NFData crypto =>
hjugement-protocol.cabal view
@@ -2,7 +2,7 @@ -- PVP:  +-+------- breaking API changes --       | | +----- non-breaking API additions --       | | | +--- code changes with no API change-version: 0.0.9.20191031+version: 0.0.10.20191104 category: Politic synopsis: A cryptographic protocol for the Majority Judgment. description:@@ -61,14 +61,16 @@   hs-source-dirs: src   exposed-modules:     Voting.Protocol-    Voting.Protocol.Arith+    Voting.Protocol.Arithmetic     Voting.Protocol.Credential+    Voting.Protocol.Cryptography     Voting.Protocol.Election     Voting.Protocol.FFC     Voting.Protocol.Tally     Voting.Protocol.Trustee     Voting.Protocol.Trustee.Indispensable     Voting.Protocol.Utils+    Voting.Protocol.Version   default-language: Haskell2010   default-extensions:     AllowAmbiguousTypes
src/Voting/Protocol.hs view
@@ -1,22 +1,26 @@ module Voting.Protocol- ( module Voting.Protocol.Arith- , module Voting.Protocol.FFC+ ( module Voting.Protocol.Arithmetic+ , module Voting.Protocol.Version+ , module Voting.Protocol.Cryptography  , module Voting.Protocol.Credential  , module Voting.Protocol.Election  , module Voting.Protocol.Tally  , module Voting.Protocol.Trustee+ , module Voting.Protocol.FFC  , Natural  , RandomGen  , Reifies(..), reify  , Proxy(..)  ) where -import Voting.Protocol.Arith-import Voting.Protocol.FFC+import Voting.Protocol.Arithmetic+import Voting.Protocol.Cryptography+import Voting.Protocol.Version import Voting.Protocol.Credential import Voting.Protocol.Election import Voting.Protocol.Tally import Voting.Protocol.Trustee+import Voting.Protocol.FFC  import Data.Proxy (Proxy(..)) import Data.Reflection (Reifies(..), reify)
− src/Voting/Protocol/Arith.hs
@@ -1,327 +0,0 @@-{-# LANGUAGE AllowAmbiguousTypes #-}-{-# LANGUAGE DeriveAnyClass #-}-{-# LANGUAGE DeriveGeneric #-}-{-# LANGUAGE DerivingStrategies #-}-{-# LANGUAGE GADTs #-}-{-# LANGUAGE OverloadedStrings #-}-{-# LANGUAGE Rank2Types #-} -- for ReifyCrypto-{-# LANGUAGE UndecidableInstances #-} -- for Reifies instances-{-# OPTIONS_GHC -fno-warn-orphans #-}--- | Arithmetic-module Voting.Protocol.Arith where--import Control.Arrow (first)-import Control.DeepSeq (NFData)-import Control.Monad (Monad(..))-import Data.Aeson (ToJSON(..),FromJSON(..))-import Data.Bits-import Data.Bool-import Data.Eq (Eq(..))-import Data.Foldable (Foldable, foldl')-import Data.Function (($), (.), id)-import Data.Functor ((<$>))-import Data.Int (Int)-import Data.Maybe (Maybe(..), fromJust)-import Data.Ord (Ord(..))-import Data.Proxy (Proxy(..))-import Data.Reflection (Reifies(..))-import Data.Semigroup (Semigroup(..))-import Data.String (IsString(..))-import Data.Text (Text)-import GHC.Generics (Generic)-import GHC.Natural (minusNaturalMaybe)-import Numeric.Natural (Natural)-import Prelude (Integer, Integral(..), fromIntegral, Enum(..))-import Text.Read (readMaybe)-import Text.Show (Show(..))-import qualified Control.Monad.Trans.State.Strict as S-import qualified Crypto.Hash as Crypto-import qualified Data.Aeson as JSON-import qualified Data.Aeson.Types as JSON-import qualified Data.ByteArray as ByteArray-import qualified Data.ByteString as BS-import qualified Data.ByteString.Base64 as BS64-import qualified Data.Char as Char-import qualified Data.List as List-import qualified Data.Text as Text-import qualified Data.Text.Encoding as Text-import qualified Data.Text.Lazy as TL-import qualified Data.Text.Lazy.Builder as TLB-import qualified Data.Text.Lazy.Builder.Int as TLB-import qualified Prelude as Num-import qualified System.Random as Random---- * Class 'Additive'-class Additive a where-	zero :: a-	(+) :: a -> a -> a; infixl 6 +-	sum :: Foldable f => f a -> a-	sum = foldl' (+) zero-instance Additive Natural where-	zero = 0-	(+)  = (Num.+)-instance Additive Integer where-	zero = 0-	(+)  = (Num.+)-instance Additive Int where-	zero = 0-	(+)  = (Num.+)---- ** Class 'Negable'-class Additive a => Negable a where-	neg :: a -> a-	(-) :: a -> a -> a; infixl 6 --	x-y = x + neg y-instance Negable Integer where-	neg  = Num.negate-instance Negable Int where-	neg  = Num.negate---- * Class 'Multiplicative'-class Multiplicative a where-	one :: a-	(*) :: a -> a -> a; infixl 7 *-instance Multiplicative Natural where-	one = 1-	(*) = (Num.*)-instance Multiplicative Integer where-	one = 1-	(*) = (Num.*)-instance Multiplicative Int where-	one = 1-	(*) = (Num.*)---- ** Class 'Invertible'-class Multiplicative a => Invertible a where-	inv :: a -> a-	(/) :: a -> a -> a; infixl 7 /-	x/y = x * inv y---- | @(b '^' e)@ returns the modular exponentiation of base 'b' by exponent 'e'.-(^) ::- forall crypto c.- Reifies c crypto =>- Multiplicative (G crypto c) =>- G crypto c -> E crypto c -> G crypto c-(^) b (E e)- | e == 0 = one- | otherwise = t * (b*b) ^ E (e`shiftR`1)-	where t | testBit e 0 = b-	        | otherwise   = one-infixr 8 ^---- * Class 'GroupParams' where-class- ( Multiplicative (G crypto c)- , Invertible     (G crypto c)- , FromNatural    (G crypto c)- , ToNatural      (G crypto c)- , Eq             (G crypto c)- , Ord            (G crypto c)- , Show           (G crypto c)- , NFData         (G crypto c)- , FromJSON       (G crypto c)- , ToJSON         (G crypto c)- , Reifies c crypto- ) => GroupParams crypto c where-	-- | A generator of the subgroup.-	groupGen   :: G crypto c-	-- | The order of the subgroup.-	groupOrder :: Proxy c -> Natural-	-	-- | 'groupGenPowers' returns the infinite list-	-- of powers of 'groupGen'.-	---	-- NOTE: In the 'GroupParams' class to keep-	-- computed values in memory across calls to 'groupGenPowers'.-	groupGenPowers :: [G crypto c]-	groupGenPowers = go one-		where go g = g : go (g * groupGen)-	-	-- | 'groupGenInverses' returns the infinite list-	-- of 'inv'erse powers of 'groupGen':-	-- @['groupGen' '^' 'neg' i | i <- [0..]]@,-	-- but by computing each value from the previous one.-	---	-- NOTE: In the 'GroupParams' class to keep-	-- computed values in memory across calls to 'groupGenInverses'.-	---	-- Used by 'intervalDisjunctions'.-	groupGenInverses :: [G crypto c]-	groupGenInverses = go one-		where-		invGen = inv $ groupGen-		go g = g : go (g * invGen)---- ** Class 'ReifyCrypto'-class ReifyCrypto crypto where-	-- | Like 'reify' but augmented with the 'GroupParams' constraint.-	reifyCrypto :: crypto -> (forall c. Reifies c crypto => GroupParams crypto c => Proxy c -> r) -> r---- ** Type 'G'--- | The type of the elements of a subgroup of a field.-newtype G crypto c = G { unG :: FieldElement crypto }---- *** Type family 'FieldElement'-type family FieldElement crypto :: *---- ** Type 'E'--- | An exponent of a (cyclic) subgroup of a field.--- The value is always in @[0..'groupOrder'-1]@.-newtype E crypto c = E { unE :: Natural }- deriving (Eq,Ord,Show)- deriving newtype NFData-instance ToJSON (E crypto c) where-	toJSON = JSON.toJSON . show . unE-instance GroupParams crypto c => FromJSON (E crypto c) where-	parseJSON (JSON.String s)-	 | Just (c0,_) <- Text.uncons s-	 , c0 /= '0'-	 , Text.all Char.isDigit s-	 , Just x <- readMaybe (Text.unpack s)-	 , x < groupOrder (Proxy @c)-	 = return (E x)-	parseJSON json = JSON.typeMismatch "Exponent" json-instance GroupParams crypto c => FromNatural (E crypto c) where-	fromNatural i =-		E $ abs $ i `mod` groupOrder (Proxy @c)-		where-		abs x | x < 0 = x + groupOrder (Proxy @c)-		      | otherwise = x-instance ToNatural (E crypto c) where-	nat = unE-instance GroupParams crypto c => Additive (E crypto c) where-	zero = E zero-	E x + E y = E $ (x + y) `mod` groupOrder (Proxy @c)-instance GroupParams crypto c => Negable (E crypto c) where-	neg (E x)-	 | x == 0 = zero-	 | otherwise = E $ fromJust $ nat (groupOrder (Proxy @c))`minusNaturalMaybe`x-instance GroupParams crypto c => Multiplicative (E crypto c) where-	one = E one-	E x * E y = E $ (x * y) `mod` groupOrder (Proxy @c)-instance GroupParams crypto c => Random.Random (E crypto c) where-	randomR (E lo, E hi) =-		first (E . fromIntegral) .-		Random.randomR-		 ( 0`max`toInteger lo-		 , toInteger hi`min`(toInteger (groupOrder (Proxy @c)) - 1) )-	random =-		first (E . fromIntegral) .-		Random.randomR (0, toInteger (groupOrder (Proxy @c)) - 1)-instance GroupParams crypto c => Enum (E crypto c) where-	toEnum = fromNatural . fromIntegral-	fromEnum = fromIntegral . nat-	enumFromTo lo hi = List.unfoldr-	 (\i -> if i<=hi then Just (i, i+one) else Nothing) lo---- * Class 'FromNatural'-class FromNatural a where-	fromNatural :: Natural -> a---- * Class 'ToNatural'-class ToNatural a where-	nat :: a -> Natural-instance ToNatural Natural where-	nat = id---- | @('bytesNat' x)@ returns the serialization of 'x'.-bytesNat :: ToNatural n => n -> BS.ByteString-bytesNat = fromString . show . nat---- * Type 'Hash'-newtype Hash crypto c = Hash (E crypto c)- deriving newtype (Eq,Ord,Show,NFData)---- | @('hash' bs gs)@ returns as a number in 'GroupExponent'--- the 'Crypto.SHA256' hash of the given 'BS.ByteString' 'bs'--- prefixing the decimal representation of given subgroup elements 'gs',--- with a comma (",") intercalated between them.------ NOTE: to avoid any collision when the 'hash' function is used in different contexts,--- a message 'gs' is actually prefixed by a 'bs' indicating the context.------ Used by 'proveEncryption' and 'verifyEncryption',--- where the 'bs' usually contains the 'statement' to be proven,--- and the 'gs' contains the 'commitments'.-hash :: GroupParams crypto c => BS.ByteString -> [G crypto c] -> E crypto c-hash bs gs = do-	let s = bs <> BS.intercalate (fromString ",") (bytesNat <$> gs)-	let h = Crypto.hashWith Crypto.SHA256 s-	fromNatural $-		decodeBigEndian $ ByteArray.convert h---- | @('decodeBigEndian' bs)@ interpret @bs@ as big-endian number.-decodeBigEndian :: BS.ByteString -> Natural-decodeBigEndian =-	BS.foldl'-	 (\acc b -> acc`shiftL`8 + fromIntegral b)-	 (0::Natural)---- ** Type 'Base64SHA256'-newtype Base64SHA256 = Base64SHA256 Text- deriving (Eq,Ord,Show,Generic)- deriving anyclass (ToJSON,FromJSON)- deriving newtype NFData---- | @('base64SHA256' bs)@ returns the 'Crypto.SHA256' hash--- of the given 'BS.ByteString' 'bs',--- as a 'Text' escaped in @base64@ encoding--- (<https://tools.ietf.org/html/rfc4648 RFC 4648>).-base64SHA256 :: BS.ByteString -> Base64SHA256-base64SHA256 bs =-	let h = Crypto.hashWith Crypto.SHA256 bs in-	Base64SHA256 $-		Text.takeWhile (/= '=') $ -- NOTE: no padding.-		Text.decodeUtf8 $ BS64.encode $ ByteArray.convert h---- ** Type 'HexSHA256'-newtype HexSHA256 = HexSHA256 Text- deriving (Eq,Ord,Show,Generic)- deriving anyclass (ToJSON,FromJSON)- deriving newtype NFData--- | @('hexSHA256' bs)@ returns the 'Crypto.SHA256' hash--- of the given 'BS.ByteString' 'bs', escaped in hexadecimal--- into a 'Text' of 32 lowercase characters.------ Used (in retro-dependencies of this library) to hash--- the 'PublicKey' of a voter or a trustee.-hexSHA256 :: BS.ByteString -> Text-hexSHA256 bs =-	let h = Crypto.hashWith Crypto.SHA256 bs in-	let n = decodeBigEndian $ ByteArray.convert h in-	-- NOTE: always set the 256 bit then remove it-	-- to always have leading zeros,-	-- and thus always 64 characters wide hashes.-	TL.toStrict $-	TL.tail $ TLB.toLazyText $ TLB.hexadecimal $-	setBit n 256---- * Random---- | @('randomR' i)@ returns a random integer in @[0..i-1]@.-randomR ::- Monad m =>- Random.RandomGen r =>- Random.Random i =>- Negable i =>- Multiplicative i =>- i -> S.StateT r m i-randomR i = S.StateT $ return . Random.randomR (zero, i-one)---- | @('random')@ returns a random integer--- in the range determined by its type.-random ::- Monad m =>- Random.RandomGen r =>- Random.Random i =>- Negable i =>- Multiplicative i =>- S.StateT r m i-random = S.StateT $ return . Random.random--instance Random.Random Natural where-	randomR (mini,maxi) =-		first (fromIntegral::Integer -> Natural) .-		Random.randomR (fromIntegral mini, fromIntegral maxi)-	random = first (fromIntegral::Integer -> Natural) . Random.random
+ src/Voting/Protocol/Arithmetic.hs view
@@ -0,0 +1,215 @@+{-# LANGUAGE AllowAmbiguousTypes #-}+{-# LANGUAGE DerivingStrategies #-}+{-# LANGUAGE GADTs #-}+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE Rank2Types #-} -- for ReifyCrypto+module Voting.Protocol.Arithmetic where++import Control.Arrow (first)+import Control.DeepSeq (NFData)+import Control.Monad (Monad(..))+import Data.Aeson (ToJSON(..),FromJSON(..))+import Data.Bits+import Data.Bool+import Data.Eq (Eq(..))+import Data.Foldable (Foldable, foldl')+import Data.Function (($), (.), id)+import Data.Int (Int)+import Data.Maybe (Maybe(..), fromJust)+import Data.Ord (Ord(..))+import Data.Proxy (Proxy(..))+import Data.Reflection (Reifies(..))+import Data.String (IsString(..))+import GHC.Natural (minusNaturalMaybe)+import Numeric.Natural (Natural)+import Prelude (Integer, Bounded(..), Integral(..), fromIntegral, Enum(..))+import Text.Read (readMaybe)+import Text.Show (Show(..))+import qualified Data.Aeson as JSON+import qualified Data.Aeson.Types as JSON+import qualified Data.ByteString as BS+import qualified Data.Char as Char+import qualified Data.List as List+import qualified Data.Text as Text+import qualified Prelude as Num+import qualified System.Random as Random++-- * Class 'CryptoParams' where+class+ ( EuclideanRing (G crypto c)+ , FromNatural   (G crypto c)+ , ToNatural     (G crypto c)+ , Eq            (G crypto c)+ , Ord           (G crypto c)+ , Show          (G crypto c)+ , NFData        (G crypto c)+ , FromJSON      (G crypto c)+ , ToJSON        (G crypto c)+ , Reifies c crypto+ ) => CryptoParams crypto c where+	-- | A generator of the subgroup.+	groupGen   :: G crypto c+	-- | The order of the subgroup.+	groupOrder :: Proxy c -> Natural+	+	-- | 'groupGenPowers' returns the infinite list+	-- of powers of 'groupGen'.+	--+	-- NOTE: In the 'CryptoParams' class to keep+	-- computed values in memory across calls to 'groupGenPowers'.+	groupGenPowers :: [G crypto c]+	groupGenPowers = go one+		where go g = g : go (g * groupGen)+	+	-- | 'groupGenInverses' returns the infinite list+	-- of 'inverse' powers of 'groupGen':+	-- @['groupGen' '^' 'negate' i | i <- [0..]]@,+	-- but by computing each value from the previous one.+	--+	-- NOTE: In the 'CryptoParams' class to keep+	-- computed values in memory across calls to 'groupGenInverses'.+	--+	-- Used by 'intervalDisjunctions'.+	groupGenInverses :: [G crypto c]+	groupGenInverses = go one+		where+		invGen = inverse groupGen+		go g = g : go (g * invGen)++-- ** Class 'ReifyCrypto'+class ReifyCrypto crypto where+	-- | Like 'reify' but augmented with the 'CryptoParams' constraint.+	reifyCrypto :: crypto -> (forall c. Reifies c crypto => CryptoParams crypto c => Proxy c -> r) -> r++-- * Class 'Additive'+-- | An additive semigroup.+class Additive a where+	zero :: a+	(+) :: a -> a -> a; infixl 6 ++	sum :: Foldable f => f a -> a+	sum = foldl' (+) zero+instance Additive Natural where+	zero = 0+	(+)  = (Num.+)+instance Additive Integer where+	zero = 0+	(+)  = (Num.+)+instance Additive Int where+	zero = 0+	(+)  = (Num.+)++-- * Class 'Semiring'+-- | A multiplicative semigroup, with an additive semigroup (aka. a semiring).+class Additive a => Semiring a where+	one :: a+	(*) :: a -> a -> a; infixl 7 *+instance Semiring Natural where+	one = 1+	(*) = (Num.*)+instance Semiring Integer where+	one = 1+	(*) = (Num.*)+instance Semiring Int where+	one = 1+	(*) = (Num.*)++-- | @(b '^' e)@ returns the modular exponentiation of base 'b' by exponent 'e'.+(^) ::+ forall crypto c.+ Reifies c crypto =>+ Semiring (G crypto c) =>+ G crypto c -> E crypto c -> G crypto c+(^) b (E e)+ | e == 0 = one+ | otherwise = t * (b*b) ^ E (e`shiftR`1)+	where t | testBit e 0 = b+	        | otherwise   = one+infixr 8 ^++-- ** Class 'Ring'+-- | A semiring that support substraction (aka. a ring).+class Semiring a => Ring a where+	negate :: a -> a+	(-) :: a -> a -> a; infixl 6 -+	x-y = x + negate y+instance Ring Integer where+	negate  = Num.negate+instance Ring Int where+	negate  = Num.negate++-- ** Class 'EuclideanRing'+-- | A commutative ring that support division (aka. an euclidean ring).+class Ring a => EuclideanRing a where+	inverse :: a -> a+	(/) :: a -> a -> a; infixl 7 /+	x/y = x * inverse y++-- ** Type 'G'+-- | The type of the elements of a subgroup of a field.+newtype G crypto c = G { unG :: FieldElement crypto }++-- *** Type family 'FieldElement'+type family FieldElement crypto :: *++-- ** Type 'E'+-- | An exponent of a (cyclic) subgroup of a field.+-- The value is always in @[0..'groupOrder'-1]@.+newtype E crypto c = E { unE :: Natural }+ deriving (Eq,Ord,Show)+ deriving newtype NFData+instance ToJSON (E crypto c) where+	toJSON = JSON.toJSON . show . unE+instance CryptoParams crypto c => FromJSON (E crypto c) where+	parseJSON (JSON.String s)+	 | Just (c0,_) <- Text.uncons s+	 , c0 /= '0'+	 , Text.all Char.isDigit s+	 , Just x <- readMaybe (Text.unpack s)+	 , x < groupOrder (Proxy @c)+	 = return (E x)+	parseJSON json = JSON.typeMismatch "Exponent" json+instance CryptoParams crypto c => FromNatural (E crypto c) where+	fromNatural n = E $ n `mod` groupOrder (Proxy @c)+instance ToNatural (E crypto c) where+	nat = unE+instance CryptoParams crypto c => Additive (E crypto c) where+	zero = E zero+	E x + E y = E $ (x + y) `mod` groupOrder (Proxy @c)+instance CryptoParams crypto c => Semiring (E crypto c) where+	one = E one+	E x * E y = E $ (x * y) `mod` groupOrder (Proxy @c)+instance CryptoParams crypto c => Ring (E crypto c) where+	negate (E x) = E $ fromJust $ groupOrder (Proxy @c)`minusNaturalMaybe`x+instance CryptoParams crypto c => Random.Random (E crypto c) where+	randomR (E lo, E hi) =+		first (E . fromIntegral) .+		Random.randomR+		 ( 0`max`toInteger lo+		 , toInteger hi`min`(toInteger (groupOrder (Proxy @c)) - 1) )+	random =+		first (E . fromIntegral) .+		Random.randomR (0, toInteger (groupOrder (Proxy @c)) - 1)+instance CryptoParams crypto c => Enum (E crypto c) where+	toEnum = fromNatural . fromIntegral+	fromEnum = fromIntegral . nat+	enumFromTo lo hi = List.unfoldr+	 (\i -> if i<=hi then Just (i, i+one) else Nothing) lo+instance CryptoParams crypto c => Bounded (E crypto c) where+	minBound = zero+	maxBound = E $ fromJust $ groupOrder (Proxy @c)`minusNaturalMaybe`1++-- * Class 'FromNatural'+class FromNatural a where+	fromNatural :: Natural -> a+instance FromNatural Natural where+	fromNatural = id++-- * Class 'ToNatural'+class ToNatural a where+	nat :: a -> Natural+instance ToNatural Natural where+	nat = id++-- | @('bytesNat' x)@ returns the serialization of 'x'.+bytesNat :: ToNatural n => n -> BS.ByteString+bytesNat = fromString . show . nat
src/Voting/Protocol/Credential.hs view
@@ -28,7 +28,8 @@ import qualified Data.Text as Text import qualified System.Random as Random -import Voting.Protocol.Arith+import Voting.Protocol.Arithmetic+import Voting.Protocol.Cryptography  -- * Class 'Key' class Key crypto where@@ -54,11 +55,6 @@ 	 SecretKey crypto c -> 	 PublicKey crypto c --- ** Type 'PublicKey'-type PublicKey = G--- ** Type 'SecretKey'-type SecretKey = E- -- * Type 'Credential' -- | A 'Credential' is a word of @('tokenLength'+1 '==' 15)@-characters -- from a base alphabet of (@'tokenBase' '==' 58)@ characters:@@ -91,7 +87,7 @@ 			( acc * tokenBase + d 			, charOfDigit d : ds ) 		 ) (zero::Int, []) rs-	let checksum = (neg tot + 53) `mod` 53 -- NOTE: why 53 and not 'tokenBase' ?+	let checksum = (negate tot + 53) `mod` 53 -- NOTE: why 53 and not 'tokenBase' ? 	return $ Credential $ Text.reverse $ Text.pack (charOfDigit checksum:cs) 	where 	charOfDigit = (credentialAlphabet List.!!)
+ src/Voting/Protocol/Cryptography.hs view
@@ -0,0 +1,590 @@+{-# LANGUAGE DataKinds #-}+{-# LANGUAGE PolyKinds #-}+{-# LANGUAGE DeriveAnyClass #-}+{-# LANGUAGE DeriveGeneric #-}+{-# LANGUAGE DerivingStrategies #-}+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE UndecidableInstances #-} -- for Reifies constraints in instances+module Voting.Protocol.Cryptography where++import Control.DeepSeq (NFData)+import Control.Monad (Monad(..), join, replicateM)+import Control.Monad.Trans.Except (ExceptT(..), throwE)+import Data.Aeson (ToJSON(..), FromJSON(..), (.:), (.=))+import Data.Bits+import Data.Bool+import Data.Eq (Eq(..))+import Data.Function (($), (.))+import Data.Functor (Functor, (<$>))+import Data.Maybe (Maybe(..), fromJust)+import Data.Ord (Ord(..))+import Data.Proxy (Proxy(..))+import Data.Reflection (Reifies(..))+import Data.Semigroup (Semigroup(..))+import Data.String (IsString(..))+import Data.Text (Text)+import GHC.Generics (Generic)+import GHC.Natural (minusNaturalMaybe)+import Numeric.Natural (Natural)+import Prelude (Bounded(..), fromIntegral)+import System.Random (RandomGen)+import Text.Show (Show(..))+import qualified Control.Monad.Trans.State.Strict as S+import qualified Crypto.Hash as Crypto+import qualified Data.Aeson as JSON+import qualified Data.ByteArray as ByteArray+import qualified Data.ByteString as BS+import qualified Data.ByteString.Base64 as BS64+import qualified Data.List as List+import qualified Data.Text as Text+import qualified Data.Text.Encoding as Text+import qualified Data.Text.Lazy as TL+import qualified Data.Text.Lazy.Builder as TLB+import qualified Data.Text.Lazy.Builder.Int as TLB+import qualified System.Random as Random++import Voting.Protocol.Utils+import Voting.Protocol.Arithmetic+import Voting.Protocol.Version++-- ** Type 'PublicKey'+type PublicKey = G+-- ** Type 'SecretKey'+type SecretKey = E++-- * Type 'Hash'+newtype Hash crypto c = Hash (E crypto c)+ deriving newtype (Eq,Ord,Show,NFData)++-- | @('hash' bs gs)@ returns as a number in 'E'+-- the 'Crypto.SHA256' hash of the given 'BS.ByteString' 'bs'+-- prefixing the decimal representation of given subgroup elements 'gs',+-- with a comma (",") intercalated between them.+--+-- NOTE: to avoid any collision when the 'hash' function is used in different contexts,+-- a message 'gs' is actually prefixed by a 'bs' indicating the context.+--+-- Used by 'proveEncryption' and 'verifyEncryption',+-- where the 'bs' usually contains the 'statement' to be proven,+-- and the 'gs' contains the 'commitments'.+hash :: CryptoParams crypto c => BS.ByteString -> [G crypto c] -> E crypto c+hash bs gs = do+	let s = bs <> BS.intercalate (fromString ",") (bytesNat <$> gs)+	let h = Crypto.hashWith Crypto.SHA256 s+	fromNatural $+		decodeBigEndian $ ByteArray.convert h++-- | @('decodeBigEndian' bs)@ interpret @bs@ as big-endian number.+decodeBigEndian :: BS.ByteString -> Natural+decodeBigEndian =+	BS.foldl'+	 (\acc b -> acc`shiftL`8 + fromIntegral b)+	 (0::Natural)++-- ** Type 'Base64SHA256'+newtype Base64SHA256 = Base64SHA256 Text+ deriving (Eq,Ord,Show,Generic)+ deriving anyclass (ToJSON,FromJSON)+ deriving newtype NFData++-- | @('base64SHA256' bs)@ returns the 'Crypto.SHA256' hash+-- of the given 'BS.ByteString' 'bs',+-- as a 'Text' escaped in @base64@ encoding+-- (<https://tools.ietf.org/html/rfc4648 RFC 4648>).+base64SHA256 :: BS.ByteString -> Base64SHA256+base64SHA256 bs =+	let h = Crypto.hashWith Crypto.SHA256 bs in+	Base64SHA256 $+		Text.takeWhile (/= '=') $ -- NOTE: no padding.+		Text.decodeUtf8 $ BS64.encode $ ByteArray.convert h++-- ** Type 'HexSHA256'+newtype HexSHA256 = HexSHA256 Text+ deriving (Eq,Ord,Show,Generic)+ deriving anyclass (ToJSON,FromJSON)+ deriving newtype NFData+-- | @('hexSHA256' bs)@ returns the 'Crypto.SHA256' hash+-- of the given 'BS.ByteString' 'bs', escaped in hexadecimal+-- into a 'Text' of 32 lowercase characters.+--+-- Used (in retro-dependencies of this library) to hash+-- the 'PublicKey' of a voter or a trustee.+hexSHA256 :: BS.ByteString -> Text+hexSHA256 bs =+	let h = Crypto.hashWith Crypto.SHA256 bs in+	let n = decodeBigEndian $ ByteArray.convert h in+	-- NOTE: always set the 256 bit then remove it+	-- to always have leading zeros,+	-- and thus always 64 characters wide hashes.+	TL.toStrict $+	TL.tail $ TLB.toLazyText $ TLB.hexadecimal $+	setBit n 256++-- * Random++-- | @('randomR' i)@ returns a random integer in @[0..i-1]@.+randomR ::+ Monad m =>+ Random.RandomGen r =>+ Random.Random i =>+ Ring i =>+ i -> S.StateT r m i+randomR i = S.StateT $ return . Random.randomR (zero, i-one)++-- | @('random')@ returns a random integer+-- in the range determined by its type.+random ::+ Monad m =>+ Random.RandomGen r =>+ Random.Random i =>+ Bounded i =>+ S.StateT r m i+random = S.StateT $ return . Random.random++-- * Type 'Encryption'+-- | ElGamal-like encryption.+-- Its security relies on the /Discrete Logarithm problem/.+--+-- Because ('groupGen' '^'encNonce '^'secKey '==' 'groupGen' '^'secKey '^'encNonce),+-- knowing @secKey@, one can divide 'encryption_vault' by @('encryption_nonce' '^'secKey)@+-- to decipher @('groupGen' '^'clear)@, then the @clear@ text must be small to be decryptable,+-- because it is encrypted as a power of 'groupGen' (hence the "-like" in "ElGamal-like")+-- to enable the additive homomorphism.+--+-- NOTE: Since @('encryption_vault' '*' 'encryption_nonce' '==' 'encryption_nonce' '^' (secKey '+' clear))@,+-- then: @(logBase 'encryption_nonce' ('encryption_vault' '*' 'encryption_nonce') '==' secKey '+' clear)@.+data Encryption crypto v c = Encryption+ { encryption_nonce :: !(G crypto c)+   -- ^ Public part of the randomness 'encNonce' used to 'encrypt' the 'clear' text,+   -- equal to @('groupGen' '^'encNonce)@+ , encryption_vault :: !(G crypto c)+   -- ^ Encrypted 'clear' text,+   -- equal to @('pubKey' '^'encNone '*' 'groupGen' '^'clear)@+ } deriving (Generic)+deriving instance Eq (G crypto c) => Eq (Encryption crypto v c)+deriving instance (Show (G crypto c), Show (G crypto c)) => Show (Encryption crypto v c)+deriving instance NFData (G crypto c) => NFData (Encryption crypto v c)+instance+ ( Reifies v Version+ , CryptoParams crypto c+ ) => ToJSON (Encryption crypto v c) where+	toJSON Encryption{..} =+		JSON.object+		 [ "alpha" .= encryption_nonce+		 , "beta"  .= encryption_vault+		 ]+	toEncoding Encryption{..} =+		JSON.pairs+		 (  "alpha" .= encryption_nonce+		 <> "beta"  .= encryption_vault+		 )+instance+ ( Reifies v Version+ , CryptoParams crypto c+ ) => FromJSON (Encryption crypto v c) where+	parseJSON = JSON.withObject "Encryption" $ \o -> do+		encryption_nonce <- o .: "alpha"+		encryption_vault <- o .: "beta"+		return Encryption{..}++-- | Additive homomorphism.+-- Using the fact that: @'groupGen' '^'x '*' 'groupGen' '^'y '==' 'groupGen' '^'(x'+'y)@.+instance CryptoParams crypto c => Additive (Encryption crypto v c) where+	zero = Encryption one one+	x+y = Encryption+	 (encryption_nonce x * encryption_nonce y)+	 (encryption_vault x * encryption_vault y)++-- *** Type 'EncryptionNonce'+type EncryptionNonce = E++-- | @('encrypt' pubKey clear)@ returns an ElGamal-like 'Encryption'.+--+-- WARNING: the secret encryption nonce (@encNonce@)+-- is returned alongside the 'Encryption'+-- in order to 'prove' the validity of the encrypted 'clear' text in 'proveEncryption',+-- but this secret @encNonce@ MUST be forgotten after that,+-- as it may be used to decipher the 'Encryption'+-- without the 'SecretKey' associated with 'pubKey'.+encrypt ::+ Reifies v Version =>+ CryptoParams crypto c =>+ Monad m => RandomGen r =>+ PublicKey crypto c -> E crypto c ->+ S.StateT r m (EncryptionNonce crypto c, Encryption crypto v c)+encrypt pubKey clear = do+	encNonce <- random+	-- NOTE: preserve the 'encNonce' for 'prove' in 'proveEncryption'.+	return $ (encNonce,)+		Encryption+		 { encryption_nonce = groupGen^encNonce+		 , encryption_vault = pubKey  ^encNonce * groupGen^clear+		 }++-- * Type 'Proof'+-- | Non-Interactive Zero-Knowledge 'Proof'+-- of knowledge of a discrete logarithm:+-- @(secret == logBase base (base^secret))@.+data Proof crypto v c = Proof+ { proof_challenge :: !(Challenge crypto c)+   -- ^ 'Challenge' sent by the verifier to the prover+   -- to ensure that the prover really has knowledge+   -- of the secret and is not replaying.+   -- Actually, 'proof_challenge' is not sent to the prover,+   -- but derived from the prover's 'Commitment's and statements+   -- with a collision resistant 'hash'.+   -- Hence the prover cannot chose the 'proof_challenge' to his/her liking.+ , proof_response :: !(E crypto c)+   -- ^ A discrete logarithm sent by the prover to the verifier,+   -- as a response to 'proof_challenge'.+   --+   -- If the verifier observes that @('proof_challenge' '==' 'hash' statement [commitment])@, where:+   --+   -- * @statement@ is a serialization of a tag, @base@ and @basePowSec@,+   -- * @commitment '==' 'commit' proof base basePowSec '=='+   --   base '^' 'proof_response' '*' basePowSec '^' 'proof_challenge'@,+   -- * and @basePowSec '==' base'^'sec@,+   --+   -- then, with overwhelming probability (due to the 'hash' function),+   -- the prover was not able to choose 'proof_challenge'+   -- yet was able to compute a 'proof_response' such that+   -- (@commitment '==' base '^' 'proof_response' '*' basePowSec '^' 'proof_challenge'@),+   -- that is to say: @('proof_response' '==' logBase base 'commitment' '-' sec '*' 'proof_challenge')@,+   -- therefore the prover knows 'sec'.+   --+   -- The prover choses 'commitment' to be a random power of @base@,+   -- to ensure that each 'prove' does not reveal any information+   -- about its secret.+ } deriving (Eq,Show,NFData,Generic)+instance Reifies v Version => ToJSON (Proof crypto v c) where+	toJSON Proof{..} =+		JSON.object+		 [ "challenge" .= proof_challenge+		 , "response"  .= proof_response+		 ]+	toEncoding Proof{..} =+		JSON.pairs+		 (  "challenge" .= proof_challenge+		 <> "response"  .= proof_response+		 )+instance+ ( CryptoParams crypto c+ , Reifies v Version+ ) => FromJSON (Proof crypto v c) where+	parseJSON = JSON.withObject "TrusteePublicKey" $ \o -> do+		proof_challenge <- o .: "challenge"+		proof_response  <- o .: "response"+		return Proof{..}++-- ** Type 'ZKP'+-- | Zero-knowledge proof.+--+-- A protocol is /zero-knowledge/ if the verifier+-- learns nothing from the protocol except that the prover+-- knows the secret.+--+-- DOC: Mihir Bellare and Phillip Rogaway. Random oracles are practical:+--      A paradigm for designing efficient protocols. In ACM-CCS’93, 1993.+newtype ZKP = ZKP BS.ByteString++-- ** Type 'Challenge'+type Challenge = E++-- ** Type 'Oracle'+-- An 'Oracle' returns the 'Challenge' of the 'Commitment's+-- by 'hash'ing them (eventually with other 'Commitment's).+--+-- Used in 'prove' it enables a Fiat-Shamir transformation+-- of an /interactive zero-knowledge/ (IZK) proof+-- into a /non-interactive zero-knowledge/ (NIZK) proof.+-- That is to say that the verifier does not have+-- to send a 'Challenge' to the prover.+-- Indeed, the prover now handles the 'Challenge'+-- which becomes a (collision resistant) 'hash'+-- of the prover's commitments (and statements to be a stronger proof).+type Oracle list crypto c = list (Commitment crypto c) -> Challenge crypto c++-- | @('prove' sec commitmentBases oracle)@+-- returns a 'Proof' that @sec@ is known+-- (by proving the knowledge of its discrete logarithm).+--+-- The 'Oracle' is given 'Commitment's equal to the 'commitmentBases'+-- raised to the power of the secret nonce of the 'Proof',+-- as those are the 'Commitment's that the verifier will obtain+-- when composing the 'proof_challenge' and 'proof_response' together+-- (with 'commit').+--+-- WARNING: for 'prove' to be a so-called /strong Fiat-Shamir transformation/ (not a weak):+-- the statement must be included in the 'hash' (along with the commitments).+--+-- NOTE: a 'random' @nonce@ is used to ensure each 'prove'+-- does not reveal any information regarding the secret @sec@,+-- because two 'Proof's using the same 'Commitment'+-- can be used to deduce @sec@ (using the special-soundness).+prove ::+ forall crypto v c list m r.+ Reifies v Version =>+ CryptoParams crypto c =>+ Monad m => RandomGen r => Functor list =>+ E crypto c ->+ list (G crypto c) ->+ Oracle list crypto c ->+ S.StateT r m (Proof crypto v c)+prove sec commitmentBases oracle = do+	nonce <- random+	let commitments = (^ nonce) <$> commitmentBases+	let proof_challenge = oracle commitments+	return Proof+	 { proof_challenge+	 , proof_response = nonce `op` (sec*proof_challenge)+	 }+	where+	-- | See comments in 'commit'.+	op =+		if reflect (Proxy @v) `hasVersionTag` versionTagQuicker+		then (-)+		else (+)++-- | Like 'prove' but quicker. It chould replace 'prove' entirely+-- when Helios-C specifications will be fixed.+proveQuicker ::+ Reifies v Version =>+ CryptoParams crypto c =>+ Monad m => RandomGen r => Functor list =>+ E crypto c ->+ list (G crypto c) ->+ Oracle list crypto c ->+ S.StateT r m (Proof crypto v c)+proveQuicker sec commitmentBases oracle = do+	nonce <- random+	let commitments = (^ nonce) <$> commitmentBases+	let proof_challenge = oracle commitments+	return Proof+	 { proof_challenge+	 , proof_response = nonce - sec*proof_challenge+	 }++-- | @('fakeProof')@ returns a 'Proof'+-- whose 'proof_challenge' and 'proof_response' are uniformly chosen at random,+-- instead of @('proof_challenge' '==' 'hash' statement commitments)@+-- and @('proof_response' '==' nonce '+' sec '*' 'proof_challenge')@+-- as a 'Proof' returned by 'prove'.+--+-- Used in 'proveEncryption' to fill the returned 'DisjProof'+-- with fake 'Proof's for all 'Disjunction's but the encrypted one.+fakeProof ::+ CryptoParams crypto c =>+ Monad m => RandomGen r =>+ S.StateT r m (Proof crypto v c)+fakeProof = do+	proof_challenge <- random+	proof_response  <- random+	return Proof{..}++-- ** Type 'Commitment'+-- | A commitment from the prover to the verifier.+-- It's a power of 'groupGen' chosen randomly by the prover+-- when making a 'Proof' with 'prove'.+type Commitment = G++-- | @('commit' proof base basePowSec)@ returns a 'Commitment'+-- from the given 'Proof' with the knowledge of the verifier.+commit ::+ forall crypto v c.+ Reifies v Version =>+ CryptoParams crypto c =>+ Proof crypto v c ->+ G crypto c ->+ G crypto c ->+ Commitment crypto c+commit Proof{..} base basePowSec =+	(base^proof_response) `op`+	(basePowSec^proof_challenge)+	where+	op =+		if reflect (Proxy @v) `hasVersionTag` versionTagQuicker+		then (*)+		else (/)+  -- TODO: contrary to some textbook presentations,+  -- @('*')@ should be used instead of @('/')@ to avoid the performance cost+  -- of a modular exponentiation @('^' ('groupOrder' '-' 'one'))@,+  -- this is compensated by using @('-')@ instead of @('+')@ in 'prove'.+{-# INLINE commit #-}++-- | Like 'commit' but quicker. It chould replace 'commit' entirely+-- when Helios-C specifications will be fixed.+commitQuicker ::+ CryptoParams crypto c =>+ Proof crypto v c ->+ G crypto c ->+ G crypto c ->+ Commitment crypto c+commitQuicker Proof{..} base basePowSec =+	base^proof_response *+	basePowSec^proof_challenge++-- * Type 'Disjunction'+-- | A 'Disjunction' is an 'inverse'd @('groupGen' '^'opinion)@+-- it's used in 'proveEncryption' to generate a 'Proof'+-- that an 'encryption_vault' contains a given @('groupGen' '^'opinion)@,+type Disjunction = G++booleanDisjunctions ::+ forall crypto c.+ CryptoParams crypto c =>+ [Disjunction crypto c]+booleanDisjunctions = List.take 2 $ groupGenInverses @crypto++intervalDisjunctions ::+ forall crypto c.+ CryptoParams crypto c =>+ Natural -> Natural -> [Disjunction crypto c]+intervalDisjunctions mini maxi =+	List.genericTake (fromJust $ (nat maxi + 1)`minusNaturalMaybe`nat mini) $+	List.genericDrop (nat mini) $+	groupGenInverses @crypto++-- ** Type 'DisjProof'+-- | A list of 'Proof's to prove that the opinion within an 'Encryption'+-- is indexing a 'Disjunction' within a list of them,+-- without revealing which opinion it is.+newtype DisjProof crypto v c = DisjProof [Proof crypto v c]+ deriving (Eq,Show,Generic)+ deriving newtype (NFData)+deriving newtype instance Reifies v Version => ToJSON (DisjProof crypto v c)+deriving newtype instance (Reifies v Version, CryptoParams crypto c) => FromJSON (DisjProof crypto v c)++-- | @('proveEncryption' elecPubKey voterZKP (prevDisjs,nextDisjs) (encNonce,enc))@+-- returns a 'DisjProof' that 'enc' 'encrypt's+-- the 'Disjunction' 'd' between 'prevDisjs' and 'nextDisjs'.+--+-- The prover proves that it knows an 'encNonce', such that:+-- @(enc '==' Encryption{encryption_nonce='groupGen' '^'encNonce, encryption_vault=elecPubKey'^'encNonce '*' groupGen'^'d})@+--+-- A /NIZK Disjunctive Chaum Pedersen Logarithm Equality/ is used.+--+-- DOC: Pierrick Gaudry. <https://hal.inria.fr/hal-01576379 Some ZK security proofs for Belenios>, 2017.+proveEncryption ::+ Reifies v Version =>+ CryptoParams crypto c =>+ Monad m => RandomGen r =>+ PublicKey crypto c -> ZKP ->+ ([Disjunction crypto c],[Disjunction crypto c]) ->+ (EncryptionNonce crypto c, Encryption crypto v c) ->+ S.StateT r m (DisjProof crypto v c)+proveEncryption elecPubKey voterZKP (prevDisjs,nextDisjs) (encNonce,enc) = do+	-- Fake proofs for all 'Disjunction's except the genuine one.+	prevFakeProofs <- replicateM (List.length prevDisjs) fakeProof+	nextFakeProofs <- replicateM (List.length nextDisjs) fakeProof+	let fakeChallengeSum =+		sum (proof_challenge <$> prevFakeProofs) ++		sum (proof_challenge <$> nextFakeProofs)+	let statement = encryptionStatement voterZKP enc+	genuineProof <- prove encNonce [groupGen, elecPubKey] $ \genuineCommitments ->+		let validCommitments = List.zipWith (encryptionCommitments elecPubKey enc) in+		let prevCommitments = validCommitments prevDisjs prevFakeProofs in+		let nextCommitments = validCommitments nextDisjs nextFakeProofs in+		let commitments = join prevCommitments <> genuineCommitments <> join nextCommitments in+		let challenge = hash statement commitments in+		let genuineChallenge = challenge - fakeChallengeSum in+		genuineChallenge+		-- NOTE: here by construction (genuineChallenge == challenge - fakeChallengeSum)+		-- thus (sum (proof_challenge <$> proofs) == challenge)+		-- as checked in 'verifyEncryption'.+	let proofs = prevFakeProofs <> (genuineProof : nextFakeProofs)+	return (DisjProof proofs)++verifyEncryption ::+ Reifies v Version =>+ CryptoParams crypto c =>+ Monad m =>+ PublicKey crypto c -> ZKP ->+ [Disjunction crypto c] -> (Encryption crypto v c, DisjProof crypto v c) ->+ ExceptT ErrorVerifyEncryption m Bool+verifyEncryption elecPubKey voterZKP disjs (enc, DisjProof proofs) =+	case isoZipWith (encryptionCommitments elecPubKey enc) disjs proofs of+	 Nothing ->+		throwE $ ErrorVerifyEncryption_InvalidProofLength+		 (fromIntegral $ List.length proofs)+		 (fromIntegral $ List.length disjs)+	 Just commitments ->+		return $ challengeSum ==+			hash (encryptionStatement voterZKP enc) (join commitments)+	where+	challengeSum = sum (proof_challenge <$> proofs)++-- ** Hashing+encryptionStatement ::+ CryptoParams crypto c =>+ ZKP -> Encryption crypto v c -> BS.ByteString+encryptionStatement (ZKP voterZKP) Encryption{..} =+	"prove|"<>voterZKP<>"|"+	 <> bytesNat encryption_nonce<>","+	 <> bytesNat encryption_vault<>"|"++-- | @('encryptionCommitments' elecPubKey enc disj proof)@+-- returns the 'Commitment's with only the knowledge of the verifier.+--+-- For the prover the 'Proof' comes from @fakeProof@,+-- and for the verifier the 'Proof' comes from the prover.+encryptionCommitments ::+ Reifies v Version =>+ CryptoParams crypto c =>+ PublicKey crypto c -> Encryption crypto v c ->+ Disjunction crypto c -> Proof crypto v c -> [G crypto c]+encryptionCommitments elecPubKey Encryption{..} disj proof =+	[ commit proof groupGen encryption_nonce+	  -- == groupGen ^ nonce if 'Proof' comes from 'prove'.+	  -- base==groupGen, basePowSec==groupGen^encNonce.+	, commit proof elecPubKey (encryption_vault*disj)+	  -- == elecPubKey ^ nonce if 'Proof' comes from 'prove'+	  -- and 'encryption_vault' encrypts (- logBase groupGen disj).+	  -- base==elecPubKey, basePowSec==elecPubKey^encNonce.+	]++-- ** Type 'ErrorVerifyEncryption'+-- | Error raised by 'verifyEncryption'.+data ErrorVerifyEncryption+ =   ErrorVerifyEncryption_InvalidProofLength Natural Natural+     -- ^ When the number of proofs is different than+     -- the number of 'Disjunction's.+ deriving (Eq,Show)++-- * Type 'Signature'+-- | Schnorr-like signature.+--+-- Used by each voter to sign his/her encrypted 'Ballot'+-- using his/her 'Credential',+-- in order to avoid ballot stuffing.+data Signature crypto v c = Signature+ { signature_publicKey :: !(PublicKey crypto c)+   -- ^ Verification key.+ , signature_proof     :: !(Proof crypto v c)+ } deriving (Generic)+deriving instance (NFData crypto, NFData (G crypto c)) => NFData (Signature crypto v c)+instance+ ( Reifies v Version+ , CryptoParams crypto c+ ) => ToJSON (Signature crypto v c) where+	toJSON (Signature pubKey Proof{..}) =+		JSON.object+		 [ "public_key" .= pubKey+		 , "challenge"  .= proof_challenge+		 , "response"   .= proof_response+		 ]+	toEncoding (Signature pubKey Proof{..}) =+		JSON.pairs+		 (  "public_key" .= pubKey+		 <> "challenge"  .= proof_challenge+		 <> "response"   .= proof_response+		 )+instance+ ( Reifies v Version+ , CryptoParams crypto c+ ) => FromJSON (Signature crypto v c) where+	parseJSON = JSON.withObject "Signature" $ \o -> do+		signature_publicKey <- o .: "public_key"+		proof_challenge     <- o .: "challenge"+		proof_response      <- o .: "response"+		let signature_proof = Proof{..}+		return Signature{..}
src/Voting/Protocol/Election.hs view
@@ -3,29 +3,28 @@ {-# LANGUAGE DerivingStrategies #-} {-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE Rank2Types #-} -- for readElection-{-# LANGUAGE UndecidableInstances #-} -- for Reifies instances+{-# LANGUAGE UndecidableInstances #-} -- for Reifies constraints in instances module Voting.Protocol.Election where -import Control.Applicative (Applicative(..), Alternative(..)) import Control.DeepSeq (NFData)-import Control.Monad (Monad(..), join, mapM, replicateM, zipWithM)+import Control.Monad (Monad(..), mapM, zipWithM) import Control.Monad.Trans.Class (MonadTrans(..)) import Control.Monad.Trans.Except (ExceptT(..), runExcept, throwE, withExceptT) import Data.Aeson (ToJSON(..),FromJSON(..),(.:),(.:?),(.=)) import Data.Bool import Data.Either (either) import Data.Eq (Eq(..))-import Data.Foldable (Foldable, foldMap, and)+import Data.Foldable (foldMap, and) import Data.Function (($), (.), id, const)-import Data.Functor (Functor, (<$>), (<$))+import Data.Functor ((<$>)) import Data.Functor.Identity (Identity(..))-import Data.Maybe (Maybe(..), maybe, fromJust, fromMaybe, listToMaybe)+import Data.Maybe (Maybe(..), maybe, fromJust, fromMaybe) import Data.Monoid (Monoid(..)) import Data.Ord (Ord(..)) import Data.Proxy (Proxy(..)) import Data.Reflection (Reifies(..), reify) import Data.Semigroup (Semigroup(..))-import Data.String (String, IsString(..))+import Data.String (String) import Data.Text (Text) import Data.Traversable (Traversable(..)) import Data.Tuple (fst, snd)@@ -35,7 +34,7 @@ import Prelude (fromIntegral) import System.IO (IO, FilePath) import System.Random (RandomGen)-import Text.Show (Show(..), showChar, showString)+import Text.Show (Show(..)) import qualified Control.Monad.Trans.State.Strict as S import qualified Data.Aeson as JSON import qualified Data.Aeson.Encoding as JSON@@ -44,424 +43,13 @@ import qualified Data.Aeson.Types as JSON import qualified Data.ByteString as BS import qualified Data.ByteString.Lazy as BSL-import qualified Data.Char as Char import qualified Data.List as List-import qualified Data.Text as Text-import qualified Text.ParserCombinators.ReadP as Read-import qualified Text.Read as Read  import Voting.Protocol.Utils-import Voting.Protocol.Arith+import Voting.Protocol.Arithmetic+import Voting.Protocol.Version import Voting.Protocol.Credential---- * Type 'Encryption'--- | ElGamal-like encryption.--- Its security relies on the /Discrete Logarithm problem/.------ Because ('groupGen' '^'encNonce '^'secKey '==' 'groupGen' '^'secKey '^'encNonce),--- knowing @secKey@, one can divide 'encryption_vault' by @('encryption_nonce' '^'secKey)@--- to decipher @('groupGen' '^'clear)@, then the @clear@ text must be small to be decryptable,--- because it is encrypted as a power of 'groupGen' (hence the "-like" in "ElGamal-like")--- to enable the additive homomorphism.------ NOTE: Since @('encryption_vault' '*' 'encryption_nonce' '==' 'encryption_nonce' '^' (secKey '+' clear))@,--- then: @(logBase 'encryption_nonce' ('encryption_vault' '*' 'encryption_nonce') '==' secKey '+' clear)@.-data Encryption crypto v c = Encryption- { encryption_nonce :: !(G crypto c)-   -- ^ Public part of the randomness 'encNonce' used to 'encrypt' the 'clear' text,-   -- equal to @('groupGen' '^'encNonce)@- , encryption_vault :: !(G crypto c)-   -- ^ Encrypted 'clear' text,-   -- equal to @('pubKey' '^'encNone '*' 'groupGen' '^'clear)@- } deriving (Generic)-deriving instance Eq (G crypto c) => Eq (Encryption crypto v c)-deriving instance (Show (G crypto c), Show (G crypto c)) => Show (Encryption crypto v c)-deriving instance NFData (G crypto c) => NFData (Encryption crypto v c)-instance- ( Reifies v Version- , GroupParams crypto c- ) => ToJSON (Encryption crypto v c) where-	toJSON Encryption{..} =-		JSON.object-		 [ "alpha" .= encryption_nonce-		 , "beta"  .= encryption_vault-		 ]-	toEncoding Encryption{..} =-		JSON.pairs-		 (  "alpha" .= encryption_nonce-		 <> "beta"  .= encryption_vault-		 )-instance- ( Reifies v Version- , GroupParams crypto c- ) => FromJSON (Encryption crypto v c) where-	parseJSON = JSON.withObject "Encryption" $ \o -> do-		encryption_nonce <- o .: "alpha"-		encryption_vault <- o .: "beta"-		return Encryption{..}---- | Additive homomorphism.--- Using the fact that: @'groupGen' '^'x '*' 'groupGen' '^'y '==' 'groupGen' '^'(x'+'y)@.-instance GroupParams crypto c => Additive (Encryption crypto v c) where-	zero = Encryption one one-	x+y = Encryption-	 (encryption_nonce x * encryption_nonce y)-	 (encryption_vault x * encryption_vault y)---- *** Type 'EncryptionNonce'-type EncryptionNonce = E---- | @('encrypt' pubKey clear)@ returns an ElGamal-like 'Encryption'.------ WARNING: the secret encryption nonce (@encNonce@)--- is returned alongside the 'Encryption'--- in order to 'prove' the validity of the encrypted 'clear' text in 'proveEncryption',--- but this secret @encNonce@ MUST be forgotten after that,--- as it may be used to decipher the 'Encryption'--- without the 'SecretKey' associated with 'pubKey'.-encrypt ::- Reifies v Version =>- GroupParams crypto c =>- Monad m => RandomGen r =>- PublicKey crypto c -> E crypto c ->- S.StateT r m (EncryptionNonce crypto c, Encryption crypto v c)-encrypt pubKey clear = do-	encNonce <- random-	-- NOTE: preserve the 'encNonce' for 'prove' in 'proveEncryption'.-	return $ (encNonce,)-		Encryption-		 { encryption_nonce = groupGen^encNonce-		 , encryption_vault = pubKey  ^encNonce * groupGen^clear-		 }---- * Type 'Proof'--- | Non-Interactive Zero-Knowledge 'Proof'--- of knowledge of a discrete logarithm:--- @(secret == logBase base (base^secret))@.-data Proof crypto v c = Proof- { proof_challenge :: !(Challenge crypto c)-   -- ^ 'Challenge' sent by the verifier to the prover-   -- to ensure that the prover really has knowledge-   -- of the secret and is not replaying.-   -- Actually, 'proof_challenge' is not sent to the prover,-   -- but derived from the prover's 'Commitment's and statements-   -- with a collision resistant 'hash'.-   -- Hence the prover cannot chose the 'proof_challenge' to his/her liking.- , proof_response :: !(E crypto c)-   -- ^ A discrete logarithm sent by the prover to the verifier,-   -- as a response to 'proof_challenge'.-   ---   -- If the verifier observes that @('proof_challenge' '==' 'hash' statement [commitment])@, where:-   ---   -- * @statement@ is a serialization of a tag, @base@ and @basePowSec@,-   -- * @commitment '==' 'commit' proof base basePowSec '=='-   --   base '^' 'proof_response' '*' basePowSec '^' 'proof_challenge'@,-   -- * and @basePowSec '==' base'^'sec@,-   ---   -- then, with overwhelming probability (due to the 'hash' function),-   -- the prover was not able to choose 'proof_challenge'-   -- yet was able to compute a 'proof_response' such that-   -- (@commitment '==' base '^' 'proof_response' '*' basePowSec '^' 'proof_challenge'@),-   -- that is to say: @('proof_response' '==' logBase base 'commitment' '-' sec '*' 'proof_challenge')@,-   -- therefore the prover knows 'sec'.-   ---   -- The prover choses 'commitment' to be a random power of @base@,-   -- to ensure that each 'prove' does not reveal any information-   -- about its secret.- } deriving (Eq,Show,NFData,Generic)-instance ToJSON (Proof crypto v c) where-	toJSON Proof{..} =-		JSON.object-		 [ "challenge" .= proof_challenge-		 , "response"  .= proof_response-		 ]-	toEncoding Proof{..} =-		JSON.pairs-		 (  "challenge" .= proof_challenge-		 <> "response"  .= proof_response-		 )-instance GroupParams crypto c => FromJSON (Proof crypto v c) where-	parseJSON = JSON.withObject "TrusteePublicKey" $ \o -> do-		proof_challenge <- o .: "challenge"-		proof_response  <- o .: "response"-		return Proof{..}---- ** Type 'ZKP'--- | Zero-knowledge proof.------ A protocol is /zero-knowledge/ if the verifier--- learns nothing from the protocol except that the prover--- knows the secret.------ DOC: Mihir Bellare and Phillip Rogaway. Random oracles are practical:---      A paradigm for designing efficient protocols. In ACM-CCS’93, 1993.-newtype ZKP = ZKP BS.ByteString---- ** Type 'Challenge'-type Challenge = E---- ** Type 'Oracle'--- An 'Oracle' returns the 'Challenge' of the 'Commitment's--- by 'hash'ing them (eventually with other 'Commitment's).------ Used in 'prove' it enables a Fiat-Shamir transformation--- of an /interactive zero-knowledge/ (IZK) proof--- into a /non-interactive zero-knowledge/ (NIZK) proof.--- That is to say that the verifier does not have--- to send a 'Challenge' to the prover.--- Indeed, the prover now handles the 'Challenge'--- which becomes a (collision resistant) 'hash'--- of the prover's commitments (and statements to be a stronger proof).-type Oracle list crypto c = list (Commitment crypto c) -> Challenge crypto c---- | @('prove' sec commitmentBases oracle)@--- returns a 'Proof' that @sec@ is known--- (by proving the knowledge of its discrete logarithm).------ The 'Oracle' is given 'Commitment's equal to the 'commitmentBases'--- raised to the power of the secret nonce of the 'Proof',--- as those are the 'Commitment's that the verifier will obtain--- when composing the 'proof_challenge' and 'proof_response' together--- (with 'commit').------ WARNING: for 'prove' to be a so-called /strong Fiat-Shamir transformation/ (not a weak):--- the statement must be included in the 'hash' (along with the commitments).------ NOTE: a 'random' @nonce@ is used to ensure each 'prove'--- does not reveal any information regarding the secret @sec@,--- because two 'Proof's using the same 'Commitment'--- can be used to deduce @sec@ (using the special-soundness).-prove ::- forall crypto v c list m r.- Reifies v Version =>- GroupParams crypto c =>- Monad m => RandomGen r => Functor list =>- E crypto c ->- list (G crypto c) ->- Oracle list crypto c ->- S.StateT r m (Proof crypto v c)-prove sec commitmentBases oracle = do-	nonce <- random-	let commitments = (^ nonce) <$> commitmentBases-	let proof_challenge = oracle commitments-	return Proof-	 { proof_challenge-	 , proof_response = nonce `op` (sec*proof_challenge)-	 }-	where-	-- | See comments in 'commit'.-	op =-		if reflect (Proxy @v) `hasVersionTag` versionTagQuicker-		then (-)-		else (+)---- | Like 'prove' but quicker. It chould replace 'prove' entirely--- when Helios-C specifications will be fixed.-proveQuicker ::- Reifies v Version =>- GroupParams crypto c =>- Monad m => RandomGen r => Functor list =>- E crypto c ->- list (G crypto c) ->- Oracle list crypto c ->- S.StateT r m (Proof crypto v c)-proveQuicker sec commitmentBases oracle = do-	nonce <- random-	let commitments = (^ nonce) <$> commitmentBases-	let proof_challenge = oracle commitments-	return Proof-	 { proof_challenge-	 , proof_response = nonce - sec*proof_challenge-	 }---- | @('fakeProof')@ returns a 'Proof'--- whose 'proof_challenge' and 'proof_response' are uniformly chosen at random,--- instead of @('proof_challenge' '==' 'hash' statement commitments)@--- and @('proof_response' '==' nonce '+' sec '*' 'proof_challenge')@--- as a 'Proof' returned by 'prove'.------ Used in 'proveEncryption' to fill the returned 'DisjProof'--- with fake 'Proof's for all 'Disjunction's but the encrypted one.-fakeProof ::- GroupParams crypto c =>- Monad m => RandomGen r =>- S.StateT r m (Proof crypto v c)-fakeProof = do-	proof_challenge <- random-	proof_response  <- random-	return Proof{..}---- ** Type 'Commitment'--- | A commitment from the prover to the verifier.--- It's a power of 'groupGen' chosen randomly by the prover--- when making a 'Proof' with 'prove'.-type Commitment = G---- | @('commit' proof base basePowSec)@ returns a 'Commitment'--- from the given 'Proof' with the knowledge of the verifier.-commit ::- forall crypto v c.- Reifies v Version =>- GroupParams crypto c =>- Proof crypto v c ->- G crypto c ->- G crypto c ->- Commitment crypto c-commit Proof{..} base basePowSec =-	(base^proof_response) `op`-	(basePowSec^proof_challenge)-	where-	op =-		if reflect (Proxy @v) `hasVersionTag` versionTagQuicker-		then (*)-		else (/)-  -- TODO: contrary to some textbook presentations,-  -- @('*')@ should be used instead of @('/')@ to avoid the performance cost-  -- of a modular exponentiation @('^' ('groupOrder' '-' 'one'))@,-  -- this is compensated by using @('-')@ instead of @('+')@ in 'prove'.-{-# INLINE commit #-}---- | Like 'commit' but quicker. It chould replace 'commit' entirely--- when Helios-C specifications will be fixed.-commitQuicker ::- GroupParams crypto c =>- Proof crypto v c ->- G crypto c ->- G crypto c ->- Commitment crypto c-commitQuicker Proof{..} base basePowSec =-	base^proof_response *-	basePowSec^proof_challenge---- * Type 'Disjunction'--- | A 'Disjunction' is an 'inv'ersed @('groupGen' '^'opinion)@--- it's used in 'proveEncryption' to generate a 'Proof'--- that an 'encryption_vault' contains a given @('groupGen' '^'opinion)@,-type Disjunction = G--booleanDisjunctions ::- forall crypto c.- GroupParams crypto c =>- [Disjunction crypto c]-booleanDisjunctions = List.take 2 $ groupGenInverses @crypto--intervalDisjunctions ::- forall crypto c.- GroupParams crypto c =>- Natural -> Natural -> [Disjunction crypto c]-intervalDisjunctions mini maxi =-	List.genericTake (fromJust $ (nat maxi + 1)`minusNaturalMaybe`nat mini) $-	List.genericDrop (nat mini) $-	groupGenInverses @crypto---- ** Type 'Opinion'--- | Index of a 'Disjunction' within a list of them.--- It is encrypted as a 'GroupExponent' by 'encrypt'.-type Opinion = E---- ** Type 'DisjProof'--- | A list of 'Proof's to prove that the 'Opinion' within an 'Encryption'--- is indexing a 'Disjunction' within a list of them,--- without revealing which 'Opinion' it is.-newtype DisjProof crypto v c = DisjProof [Proof crypto v c]- deriving (Eq,Show,Generic)- deriving newtype (NFData,ToJSON,FromJSON)---- | @('proveEncryption' elecPubKey voterZKP (prevDisjs,nextDisjs) (encNonce,enc))@--- returns a 'DisjProof' that 'enc' 'encrypt's--- the 'Disjunction' 'd' between 'prevDisjs' and 'nextDisjs'.------ The prover proves that it knows an 'encNonce', such that:--- @(enc '==' Encryption{encryption_nonce='groupGen' '^'encNonce, encryption_vault=elecPubKey'^'encNonce '*' groupGen'^'d})@------ A /NIZK Disjunctive Chaum Pedersen Logarithm Equality/ is used.------ DOC: Pierrick Gaudry. <https://hal.inria.fr/hal-01576379 Some ZK security proofs for Belenios>, 2017.-proveEncryption ::- Reifies v Version =>- GroupParams crypto c =>- Monad m => RandomGen r =>- PublicKey crypto c -> ZKP ->- ([Disjunction crypto c],[Disjunction crypto c]) ->- (EncryptionNonce crypto c, Encryption crypto v c) ->- S.StateT r m (DisjProof crypto v c)-proveEncryption elecPubKey voterZKP (prevDisjs,nextDisjs) (encNonce,enc) = do-	-- Fake proofs for all 'Disjunction's except the genuine one.-	prevFakeProofs <- replicateM (List.length prevDisjs) fakeProof-	nextFakeProofs <- replicateM (List.length nextDisjs) fakeProof-	let fakeChallengeSum =-		sum (proof_challenge <$> prevFakeProofs) +-		sum (proof_challenge <$> nextFakeProofs)-	let statement = encryptionStatement voterZKP enc-	genuineProof <- prove encNonce [groupGen, elecPubKey] $ \genuineCommitments ->-		let validCommitments = List.zipWith (encryptionCommitments elecPubKey enc) in-		let prevCommitments = validCommitments prevDisjs prevFakeProofs in-		let nextCommitments = validCommitments nextDisjs nextFakeProofs in-		let commitments = join prevCommitments <> genuineCommitments <> join nextCommitments in-		let challenge = hash statement commitments in-		let genuineChallenge = challenge - fakeChallengeSum in-		genuineChallenge-		-- NOTE: here by construction (genuineChallenge == challenge - fakeChallengeSum)-		-- thus (sum (proof_challenge <$> proofs) == challenge)-		-- as checked in 'verifyEncryption'.-	let proofs = prevFakeProofs <> (genuineProof : nextFakeProofs)-	return (DisjProof proofs)--verifyEncryption ::- Reifies v Version =>- GroupParams crypto c =>- Monad m =>- PublicKey crypto c -> ZKP ->- [Disjunction crypto c] -> (Encryption crypto v c, DisjProof crypto v c) ->- ExceptT ErrorVerifyEncryption m Bool-verifyEncryption elecPubKey voterZKP disjs (enc, DisjProof proofs) =-	case isoZipWith (encryptionCommitments elecPubKey enc) disjs proofs of-	 Nothing ->-		throwE $ ErrorVerifyEncryption_InvalidProofLength-		 (fromIntegral $ List.length proofs)-		 (fromIntegral $ List.length disjs)-	 Just commitments ->-		return $ challengeSum ==-			hash (encryptionStatement voterZKP enc) (join commitments)-	where-	challengeSum = sum (proof_challenge <$> proofs)---- ** Hashing-encryptionStatement ::- GroupParams crypto c =>- ZKP -> Encryption crypto v c -> BS.ByteString-encryptionStatement (ZKP voterZKP) Encryption{..} =-	"prove|"<>voterZKP<>"|"-	 <> bytesNat encryption_nonce<>","-	 <> bytesNat encryption_vault<>"|"---- | @('encryptionCommitments' elecPubKey enc disj proof)@--- returns the 'Commitment's with only the knowledge of the verifier.------ For the prover the 'Proof' comes from @fakeProof@,--- and for the verifier the 'Proof' comes from the prover.-encryptionCommitments ::- Reifies v Version =>- GroupParams crypto c =>- PublicKey crypto c -> Encryption crypto v c ->- Disjunction crypto c -> Proof crypto v c -> [G crypto c]-encryptionCommitments elecPubKey Encryption{..} disj proof =-	[ commit proof groupGen encryption_nonce-	  -- == groupGen ^ nonce if 'Proof' comes from 'prove'.-	  -- base==groupGen, basePowSec==groupGen^encNonce.-	, commit proof elecPubKey (encryption_vault*disj)-	  -- == elecPubKey ^ nonce if 'Proof' comes from 'prove'-	  -- and 'encryption_vault' encrypts (- logBase groupGen disj).-	  -- base==elecPubKey, basePowSec==elecPubKey^encNonce.-	]---- ** Type 'ErrorVerifyEncryption'--- | Error raised by 'verifyEncryption'.-data ErrorVerifyEncryption- =   ErrorVerifyEncryption_InvalidProofLength Natural Natural-     -- ^ When the number of proofs is different than-     -- the number of 'Disjunction's.- deriving (Eq,Show)+import Voting.Protocol.Cryptography  -- * Type 'Question' data Question v = Question@@ -509,7 +97,7 @@ deriving instance NFData (G crypto c) => NFData (Answer crypto v c) instance  ( Reifies v Version- , GroupParams crypto c+ , CryptoParams crypto c  ) => ToJSON (Answer crypto v c) where 	toJSON Answer{..} = 		let (answer_choices, answer_individual_proofs) =@@ -529,7 +117,7 @@ 		 ) instance  ( Reifies v Version- , GroupParams crypto c+ , CryptoParams crypto c  ) => FromJSON (Answer crypto v c) where 	parseJSON = JSON.withObject "Answer" $ \o -> do 		answer_choices <- o .: "choices"@@ -543,7 +131,7 @@ -- unless an 'ErrorAnswer' is returned. encryptAnswer ::  Reifies v Version =>- GroupParams crypto c =>+ CryptoParams crypto c =>  Monad m => RandomGen r =>  PublicKey crypto c -> ZKP ->  Question v -> [Bool] ->@@ -584,7 +172,7 @@  verifyAnswer ::  Reifies v Version =>- GroupParams crypto c =>+ CryptoParams crypto c =>  PublicKey crypto c -> ZKP ->  Question v -> Answer crypto v c -> Bool verifyAnswer (elecPubKey::PublicKey crypto c) zkp Question{..} Answer{..}@@ -611,6 +199,11 @@      -- of 'question_mini' and 'question_maxi'.  deriving (Eq,Show,Generic,NFData) +-- ** Type 'Opinion'+-- | Index of a 'Disjunction' within a list of them.+-- It is encrypted as a 'GroupExponent' by 'encrypt'.+type Opinion = E+ -- * Type 'Election' data Election crypto v c = Election  { election_name        :: !Text@@ -627,7 +220,7 @@ deriving instance (NFData crypto, NFData (G crypto c)) => NFData (Election crypto v c) instance  ( Reifies v Version- , GroupParams crypto c+ , CryptoParams crypto c  , ToJSON crypto  ) => ToJSON (Election crypto v c) where 	toJSON Election{..} =@@ -657,7 +250,7 @@  hashElection ::  Reifies v Version =>- GroupParams crypto c =>+ CryptoParams crypto c =>  ToJSON crypto =>  Election crypto v c -> Base64SHA256 hashElection = base64SHA256 . BSL.toStrict . JSON.encode@@ -669,7 +262,7 @@  FilePath ->  (forall v c. 	Reifies v Version =>-	GroupParams crypto c =>+	CryptoParams crypto c => 	Election crypto v c -> r) ->  ExceptT String IO r readElection filePath k = do@@ -713,7 +306,7 @@ deriving instance (NFData (G crypto c), NFData crypto) => NFData (Ballot crypto v c) instance  ( Reifies v Version- , GroupParams crypto c+ , CryptoParams crypto c  , ToJSON (G crypto c)  ) => ToJSON (Ballot crypto v c) where 	toJSON Ballot{..} =@@ -732,7 +325,7 @@ 		 maybe mempty ("signature" .=) ballot_signature instance  ( Reifies v Version- , GroupParams crypto c+ , CryptoParams crypto c  ) => FromJSON (Ballot crypto v c) where 	parseJSON = JSON.withObject "Ballot" $ \o -> do 		ballot_answers       <- o .: "answers"@@ -747,7 +340,7 @@ -- on each 'question_choices' of each 'election_questions'. encryptBallot ::  Reifies v Version =>- GroupParams crypto c => Key crypto =>+ CryptoParams crypto c => Key crypto =>  Monad m => RandomGen r =>  Election crypto v c ->  Maybe (SecretKey crypto c) -> [[Bool]] ->@@ -780,8 +373,8 @@ 				 -- NOTE: the order is unusual, the commitments are first 				 -- then comes the statement. Best guess is that 				 -- this is easier to code due to their respective types.-				 (signatureCommitments @crypto voterZKP commitment)-				 (signatureStatement @crypto ballot_answers)+				 (ballotCommitments @crypto voterZKP commitment)+				 (ballotStatement @crypto ballot_answers) 		return $ Just Signature{..} 	return Ballot 	 { ballot_answers@@ -792,7 +385,7 @@  verifyBallot ::  Reifies v Version =>- GroupParams crypto c =>+ CryptoParams crypto c =>  Election crypto v c ->  Ballot crypto v c -> Bool verifyBallot (Election{..}::Election crypto v c) Ballot{..} =@@ -806,72 +399,14 @@ 			let zkp = ZKP (bytesNat signature_publicKey) in 			(, zkp) $ 				proof_challenge signature_proof == hash-				 (signatureCommitments @crypto zkp (commitQuicker signature_proof groupGen signature_publicKey))-				 (signatureStatement @crypto ballot_answers)+				 (ballotCommitments @crypto zkp (commitQuicker signature_proof groupGen signature_publicKey))+				 (ballotStatement @crypto ballot_answers) 	in 	and $ isValidSign : 		List.zipWith (verifyAnswer election_public_key zkpSign) 		 election_questions ballot_answers --- ** Type 'Signature'--- | Schnorr-like signature.------ Used by each voter to sign his/her encrypted 'Ballot'--- using his/her 'Credential',--- in order to avoid ballot stuffing.-data Signature crypto v c = Signature- { signature_publicKey :: !(PublicKey crypto c)-   -- ^ Verification key.- , signature_proof     :: !(Proof crypto v c)- } deriving (Generic)-deriving instance (NFData crypto, NFData (G crypto c)) => NFData (Signature crypto v c)-instance- ( Reifies v Version- , GroupParams crypto c- ) => ToJSON (Signature crypto v c) where-	toJSON (Signature pubKey Proof{..}) =-		JSON.object-		 [ "public_key" .= pubKey-		 , "challenge"  .= proof_challenge-		 , "response"   .= proof_response-		 ]-	toEncoding (Signature pubKey Proof{..}) =-		JSON.pairs-		 (  "public_key" .= pubKey-		 <> "challenge"  .= proof_challenge-		 <> "response"   .= proof_response-		 )-instance- ( Reifies v Version- , GroupParams crypto c- ) => FromJSON (Signature crypto v c) where-	parseJSON = JSON.withObject "Signature" $ \o -> do-		signature_publicKey <- o .: "public_key"-		proof_challenge     <- o .: "challenge"-		proof_response      <- o .: "response"-		let signature_proof = Proof{..}-		return Signature{..} --- *** Hashing---- | @('signatureStatement' answers)@--- returns the encrypted material to be signed:--- all the 'encryption_nonce's and 'encryption_vault's of the given @answers@.-signatureStatement :: GroupParams crypto c => Foldable f => f (Answer crypto v c) -> [G crypto c]-signatureStatement =-	foldMap $ \Answer{..} ->-		(`foldMap` answer_opinions) $ \(Encryption{..}, _proof) ->-			[encryption_nonce, encryption_vault]---- | @('signatureCommitments' voterZKP commitment)@-signatureCommitments ::- GroupParams crypto c =>- ToNatural (G crypto c) =>- ZKP -> Commitment crypto c -> BS.ByteString-signatureCommitments (ZKP voterZKP) commitment =-	"sig|"<>voterZKP<>"|" -- NOTE: this is actually part of the statement-	 <> bytesNat commitment<>"|"- -- ** Type 'ErrorBallot' -- | Error raised by 'encryptBallot'. data ErrorBallot@@ -884,58 +419,22 @@      -- ^ TODO: to be more precise.  deriving (Eq,Show,Generic,NFData) --- * Type 'Version'--- | Version of the Helios-C protocol.-data Version = Version- { version_branch :: [Natural]- , version_tags   :: [(Text, Natural)]- } deriving (Eq,Ord,Generic,NFData)-instance IsString Version where-	fromString = fromJust . readVersion-instance Show Version where-	showsPrec _p Version{..} =-		List.foldr (.) id-		 (List.intersperse (showChar '.') $-			showsPrec 0 <$> version_branch) .-		List.foldr (.) id-		 ((\(t,n) -> showChar '-' . showString (Text.unpack t) .-			if n > 0 then showsPrec 0 n else id)-		 <$> version_tags)-instance ToJSON Version where-	toJSON     = toJSON     . show-	toEncoding = toEncoding . show-instance FromJSON Version where-	parseJSON (JSON.String s)-	 | Just v <- readVersion (Text.unpack s)-	 = return v-	parseJSON json = JSON.typeMismatch "Version" json--hasVersionTag :: Version -> Text -> Bool-hasVersionTag v tag = List.any (\(t,_n) -> t == tag) (version_tags v)--experimentalVersion :: Version-experimentalVersion = stableVersion- {version_tags = [(versionTagQuicker,0)]}--stableVersion :: Version-stableVersion = "1.6"--versionTagQuicker :: Text-versionTagQuicker = "quicker"+-- ** Hashing -readVersion :: String -> Maybe Version-readVersion = parseReadP $ do-	version_branch <- Read.sepBy1-	 (Read.read <$> Read.munch1 Char.isDigit)-	 (Read.char '.')-	version_tags <- Read.many $ (,)-		 <$> (Text.pack <$ Read.char '-' <*> Read.munch1 Char.isAlpha)-		 <*> (Read.read <$> Read.munch1 Char.isDigit <|> return 0)-	return Version{..}+-- | @('ballotStatement' ballot)@+-- returns the encrypted material to be signed:+-- all the 'encryption_nonce's and 'encryption_vault's of the given 'ballot_answers'.+ballotStatement :: CryptoParams crypto c => [Answer crypto v c] -> [G crypto c]+ballotStatement =+	foldMap $ \Answer{..} ->+		(`foldMap` answer_opinions) $ \(Encryption{..}, _proof) ->+			[encryption_nonce, encryption_vault] -parseReadP :: Read.ReadP a -> String -> Maybe a-parseReadP p s =-	let p' = Read.readP_to_S p in-	listToMaybe $ do-		(x, "") <- p' s-		return x+-- | @('ballotCommitments' voterZKP commitment)@+ballotCommitments ::+ CryptoParams crypto c =>+ ToNatural (G crypto c) =>+ ZKP -> Commitment crypto c -> BS.ByteString+ballotCommitments (ZKP voterZKP) commitment =+	"sig|"<>voterZKP<>"|" -- NOTE: this is actually part of the statement+	 <> bytesNat commitment<>"|"
src/Voting/Protocol/FFC.hs view
@@ -14,7 +14,7 @@ import Control.Arrow (first) import Control.DeepSeq (NFData) import Control.Monad (Monad(..), unless)-import Data.Aeson (ToJSON(..),FromJSON(..),(.:),(.:?),(.=))+import Data.Aeson (ToJSON(..), FromJSON(..), (.:), (.:?), (.=)) import Data.Bool import Data.Either (Either(..)) import Data.Eq (Eq(..))@@ -41,7 +41,8 @@ import qualified Data.Text.Encoding as Text import qualified System.Random as Random -import Voting.Protocol.Arith+import Voting.Protocol.Arithmetic+import Voting.Protocol.Cryptography import Voting.Protocol.Credential  -- * Type 'FFC'@@ -62,12 +63,12 @@      -- ^ The prime number characteristic of a Finite Prime Field.      --      -- ElGamal's hardness to decrypt requires a large prime number-     -- to form the 'Multiplicative' subgroup.+     -- to form the multiplicative subgroup.  ,   ffc_groupGen :: !Natural-     -- ^ A generator of the 'Multiplicative' subgroup of the Finite Prime Field.+     -- ^ A generator of the multiplicative subgroup of the Finite Prime Field.      --      -- NOTE: since 'ffc_fieldCharac' is prime,-     -- the 'Multiplicative' subgroup is cyclic,+     -- the multiplicative subgroup is cyclic,      -- and there are phi('fieldCharac'-1) many choices for the generator of the group,      -- where phi is the Euler totient function.  ,   ffc_groupOrder :: !Natural@@ -116,7 +117,7 @@ 		unless (fromJust (ffc_fieldCharac`minusNaturalMaybe`one) `rem` ffc_groupOrder == 0) $ 			JSON.typeMismatch "FFC: groupOrder does not divide fieldCharac-1" (JSON.Object o) 		return FFC{..}-instance Reifies c FFC => GroupParams FFC c where+instance Reifies c FFC => CryptoParams FFC c where 	groupGen = G $ ffc_groupGen $ reflect (Proxy::Proxy c) 	groupOrder c = ffc_groupOrder $ reflect c instance ReifyCrypto FFC where@@ -151,7 +152,7 @@  -- | Parameters used in Belenios. -- A 2048-bit 'fieldCharac' of a Finite Prime Field,--- with a 256-bit 'groupOrder' for a 'Multiplicative' subgroup+-- with a 256-bit 'groupOrder' for a multiplicative subgroup -- generated by 'groupGen'. beleniosFFC :: FFC beleniosFFC = FFC@@ -166,10 +167,10 @@ -- A field must satisfy the following properties: -- -- * @(f, ('+'), 'zero')@ forms an abelian group,---   called the 'Additive' group of 'f'.+--   called the additive group of 'f'. -- -- * @('NonNull' f, ('*'), 'one')@ forms an abelian group,---   called the 'Multiplicative' group of 'f'.+--   called the multiplicative group of 'f'. -- -- * ('*') is associative: --   @(a'*'b)'*'c == a'*'(b'*'c)@ and@@ -212,13 +213,16 @@ instance Reifies c FFC => Additive (G FFC c) where 	zero = G 0 	G x + G y = G $ (x + y) `mod` fieldCharac @c-instance Reifies c FFC => Negable (G FFC c) where-	neg (G x)-	 | x == 0 = zero-	 | otherwise = G $ fromJust $ nat (fieldCharac @c)`minusNaturalMaybe`x-instance Reifies c FFC => Multiplicative (G FFC c) where+instance Reifies c FFC => Semiring (G FFC c) where 	one = G 1 	G x * G y = G $ (x * y) `mod` fieldCharac @c+instance Reifies c FFC => Ring (G FFC c) where+	negate (G x)+	 | x == 0 = zero+	 | otherwise = G $ fromJust $ nat (fieldCharac @c)`minusNaturalMaybe`x+instance Reifies c FFC => EuclideanRing (G FFC c) where+	-- | NOTE: add 'groupOrder' so the exponent given to (^) is positive.+	inverse = (^ E (fromJust $ groupOrder @FFC (Proxy @c)`minusNaturalMaybe`1)) instance Reifies c FFC => Random.Random (G FFC c) where 	randomR (G lo, G hi) = 		first (G . fromIntegral) .@@ -228,6 +232,3 @@ 	random = 		first (G . fromIntegral) . 		Random.randomR (0, toInteger (fieldCharac @c) - 1)-instance Reifies c FFC => Invertible (G FFC c) where-	-- | NOTE: add 'groupOrder' so the exponent given to (^) is positive.-	inv = (^ E (fromJust $ groupOrder @FFC (Proxy @c)`minusNaturalMaybe`1))
src/Voting/Protocol/Tally.hs view
@@ -8,7 +8,7 @@ import Control.DeepSeq (NFData) import Control.Monad (Monad(..), mapM, unless) import Control.Monad.Trans.Except (Except, ExceptT, throwE)-import Data.Aeson (ToJSON(..),FromJSON(..),(.:),(.=))+import Data.Aeson (ToJSON(..), FromJSON(..), (.:), (.=)) import Data.Eq (Eq(..)) import Data.Function (($), (.)) import Data.Functor ((<$>))@@ -29,7 +29,9 @@ import qualified Data.Map.Strict as Map  import Voting.Protocol.Utils-import Voting.Protocol.Arith+import Voting.Protocol.Arithmetic+import Voting.Protocol.Version+import Voting.Protocol.Cryptography import Voting.Protocol.Credential import Voting.Protocol.Election @@ -54,7 +56,7 @@ deriving instance NFData (G crypto c) => NFData (Tally crypto v c) instance  ( Reifies v Version- , GroupParams crypto c+ , CryptoParams crypto c  ) => ToJSON (Tally crypto v c) where 	toJSON Tally{..} = 		JSON.object@@ -72,7 +74,7 @@ 		 ) instance  ( Reifies v Version- , GroupParams crypto c+ , CryptoParams crypto c  ) => FromJSON (Tally crypto v c) where 	parseJSON = JSON.withObject "Tally" $ \o -> do 		tally_countMax             <- o .: "num_tallied"@@ -89,13 +91,13 @@ -- returns the sum of the 'Encryption's of the given @ballots@, -- along with the number of 'Ballot's. encryptedTally ::- GroupParams crypto c =>+ CryptoParams crypto c =>  [Ballot crypto v c] -> (EncryptedTally crypto v c, Natural) encryptedTally = List.foldr insertEncryptedTally emptyEncryptedTally  -- | The initial 'EncryptedTally' which tallies no 'Ballot'. emptyEncryptedTally ::- GroupParams crypto c =>+ CryptoParams crypto c =>  (EncryptedTally crypto v c, Natural) emptyEncryptedTally = (List.repeat (List.repeat zero), 0) @@ -103,7 +105,7 @@ -- returns the 'EncryptedTally' adding the votes of the given @(ballot)@ -- to those of the given @(encTally)@. insertEncryptedTally ::- GroupParams crypto c =>+ CryptoParams crypto c =>  Ballot crypto v c ->  (EncryptedTally crypto v c, Natural) ->  (EncryptedTally crypto v c, Natural)@@ -122,7 +124,7 @@  Except ErrorTally [[DecryptionFactor crypto c]]  proveTally ::- GroupParams crypto c =>+ CryptoParams crypto c =>  (EncryptedTally crypto v c, Natural) -> [DecryptionShare crypto v c] ->  DecryptionShareCombinator crypto v c -> Except ErrorTally (Tally crypto v c) proveTally@@ -146,7 +148,7 @@ 	return Tally{..}  verifyTally ::- GroupParams crypto c =>+ CryptoParams crypto c =>  Tally crypto v c ->  DecryptionShareCombinator crypto v c ->  Except ErrorTally ()@@ -171,7 +173,10 @@ deriving instance Eq (G crypto c) => Eq (DecryptionShare crypto v c) deriving instance Show (G crypto c) => Show (DecryptionShare crypto v c) deriving newtype instance NFData (G crypto c) => NFData (DecryptionShare crypto v c)-instance ToJSON (G crypto c) => ToJSON (DecryptionShare crypto v c) where+instance+ ( Reifies v Version+ , ToJSON (G crypto c)+ ) => ToJSON (DecryptionShare crypto v c) where 	toJSON (DecryptionShare decByChoiceByQuest) = 		JSON.object 		 [ "decryption_factors" .=@@ -185,7 +190,10 @@ 			 (JSON.list (JSON.list (toEncoding . fst)) decByChoiceByQuest) <> 			JSON.pair "decryption_proofs" 			 (JSON.list (JSON.list (toEncoding . snd)) decByChoiceByQuest)-instance GroupParams crypto c => FromJSON (DecryptionShare crypto v c) where+instance+ ( Reifies v Version+ , CryptoParams crypto c+ ) => FromJSON (DecryptionShare crypto v c) where 	parseJSON = JSON.withObject "DecryptionShare" $ \o -> do 		decFactors <- o .: "decryption_factors" 		decProofs  <- o .: "decryption_proofs"@@ -203,7 +211,7 @@ -- @('proveDecryptionShare' encByChoiceByQuest trusteeSecKey)@ proveDecryptionShare ::  Reifies v Version =>- GroupParams crypto c =>+ CryptoParams crypto c =>  Key crypto =>  Monad m => RandomGen r =>  EncryptedTally crypto v c -> SecretKey crypto c -> S.StateT r m (DecryptionShare crypto v c)@@ -213,7 +221,7 @@  proveDecryptionFactor ::  Reifies v Version => - GroupParams crypto c =>+ CryptoParams crypto c =>  Key crypto =>  Monad m => RandomGen r =>  SecretKey crypto c -> Encryption crypto v c -> S.StateT r m (DecryptionFactor crypto c, Proof crypto v c)@@ -222,7 +230,7 @@ 	return (encryption_nonce^trusteeSecKey, proof) 	where zkp = decryptionShareStatement (publicKey trusteeSecKey) -decryptionShareStatement :: GroupParams crypto c => PublicKey crypto c -> BS.ByteString+decryptionShareStatement :: CryptoParams crypto c => PublicKey crypto c -> BS.ByteString decryptionShareStatement pubKey = 	"decrypt|"<>bytesNat pubKey<>"|" @@ -248,7 +256,7 @@ -- is valid with respect to the 'EncryptedTally' 'encTally'. verifyDecryptionShare ::  Reifies v Version =>- GroupParams crypto c =>+ CryptoParams crypto c =>  Monad m =>  EncryptedTally crypto v c -> PublicKey crypto c -> DecryptionShare crypto v c ->  ExceptT ErrorTally m ()@@ -266,7 +274,7 @@  verifyDecryptionShareByTrustee ::  Reifies v Version =>- GroupParams crypto c =>+ CryptoParams crypto c =>  Monad m =>  EncryptedTally crypto v c -> [PublicKey crypto c] -> [DecryptionShare crypto v c] ->  ExceptT ErrorTally m ()
src/Voting/Protocol/Trustee/Indispensable.hs view
@@ -7,7 +7,7 @@ import Control.DeepSeq (NFData) import Control.Monad (Monad(..), foldM, unless) import Control.Monad.Trans.Except (ExceptT(..), throwE)-import Data.Aeson (ToJSON(..),FromJSON(..),(.:),(.=))+import Data.Aeson (ToJSON(..), FromJSON(..), (.:), (.=)) import Data.Eq (Eq(..)) import Data.Function (($)) import Data.Functor ((<$>))@@ -24,9 +24,10 @@ import qualified Data.List as List  import Voting.Protocol.Utils-import Voting.Protocol.Arith+import Voting.Protocol.Arithmetic+import Voting.Protocol.Version+import Voting.Protocol.Cryptography import Voting.Protocol.Credential-import Voting.Protocol.Election import Voting.Protocol.Tally  -- * Type 'TrusteePublicKey'@@ -50,7 +51,10 @@ deriving instance Eq (G crypto c) => Eq (TrusteePublicKey crypto v c) deriving instance (Show (G crypto c), Show (PublicKey crypto c)) => Show (TrusteePublicKey crypto v c) deriving instance NFData (G crypto c) => NFData (TrusteePublicKey crypto v c)-instance ToJSON (G crypto c) => ToJSON (TrusteePublicKey crypto v c) where+instance+ ( Reifies v Version+ , ToJSON (G crypto c)+ ) => ToJSON (TrusteePublicKey crypto v c) where 	toJSON TrusteePublicKey{..} = 		JSON.object 		 [ "pok"        .= trustee_SecretKeyProof@@ -61,7 +65,10 @@ 		 (  "pok"        .= trustee_SecretKeyProof 		 <> "public_key" .= trustee_PublicKey 		 )-instance GroupParams crypto c => FromJSON (TrusteePublicKey crypto v c) where+instance+ ( Reifies v Version+ , CryptoParams crypto c+ ) => FromJSON (TrusteePublicKey crypto v c) where 	parseJSON = JSON.withObject "TrusteePublicKey" $ \o -> do 		trustee_PublicKey <- o .: "public_key" 		trustee_SecretKeyProof <- o .: "pok"@@ -74,7 +81,7 @@ -- and a 'Proof' of its knowledge. proveIndispensableTrusteePublicKey ::  Reifies v Version =>- GroupParams crypto c =>+ CryptoParams crypto c =>  Key crypto =>  Monad m => RandomGen r =>  SecretKey crypto c -> S.StateT r m (TrusteePublicKey crypto v c)@@ -93,7 +100,7 @@ -- the given 'trustee_PublicKey' is known by the trustee. verifyIndispensableTrusteePublicKey ::  Reifies v Version =>- GroupParams crypto c =>+ CryptoParams crypto c =>  Monad m =>  TrusteePublicKey crypto v c ->  ExceptT ErrorTrusteePublicKey m ()@@ -113,7 +120,7 @@  -- ** Hashing indispensableTrusteePublicKeyStatement ::- GroupParams crypto c =>+ CryptoParams crypto c =>  PublicKey crypto c -> BS.ByteString indispensableTrusteePublicKeyStatement trustPubKey = 	"pok|"<>bytesNat trustPubKey<>"|"@@ -123,7 +130,7 @@ -- ** Generating an 'Election''s 'PublicKey' from multiple 'TrusteePublicKey's.  combineIndispensableTrusteePublicKeys ::- GroupParams crypto c =>+ CryptoParams crypto c =>  [TrusteePublicKey crypto v c] -> PublicKey crypto c combineIndispensableTrusteePublicKeys = 	List.foldr (\TrusteePublicKey{..} -> (trustee_PublicKey *)) one@@ -132,7 +139,7 @@  verifyIndispensableDecryptionShareByTrustee ::  Reifies v Version =>- GroupParams crypto c =>+ CryptoParams crypto c =>  Monad m =>  EncryptedTally crypto v c -> [PublicKey crypto c] -> [DecryptionShare crypto v c] ->  ExceptT ErrorTally m ()@@ -146,7 +153,7 @@ -- returns the 'DecryptionFactor's by choice by 'Question' combineIndispensableDecryptionShares ::  Reifies v Version =>- GroupParams crypto c =>+ CryptoParams crypto c =>  [PublicKey crypto c] -> DecryptionShareCombinator crypto v c combineIndispensableDecryptionShares  pubKeyByTrustee
src/Voting/Protocol/Utils.hs view
@@ -1,18 +1,25 @@+{-# OPTIONS_GHC -fno-warn-orphans #-} module Voting.Protocol.Utils where  import Control.Applicative (Applicative(..))+import Control.Arrow (first) import Data.Bool import Data.Either (Either(..), either) import Data.Eq (Eq(..)) import Data.Foldable (sequenceA_) import Data.Function (($), (.)) import Data.Functor ((<$))-import Data.Maybe (Maybe(..), maybe)+import Data.Maybe (Maybe(..), maybe, listToMaybe) import Data.String (String) import Data.Traversable (Traversable(..)) import Data.Tuple (uncurry)+import Numeric.Natural (Natural)+import Prelude (Integer, fromIntegral) import qualified Data.Aeson.Internal as JSON import qualified Data.List as List+import qualified System.Random as Random+import qualified Text.ParserCombinators.ReadP as Read+import qualified Text.Read as Read  -- | Like ('.') but with two arguments. o2 :: (c -> d) -> (a -> b -> c) -> a -> b -> d@@ -62,8 +69,25 @@ 	maybe err sequenceA_ $ 		isoZipWith3 f as bs cs +-- * JSON utils+ -- | Copied from 'Data.Aeson''s 'eitherFormatError' -- which is not exported. jsonEitherFormatError :: Either (JSON.JSONPath, String) a -> Either String a jsonEitherFormatError = either (Left . uncurry JSON.formatError) Right {-# INLINE jsonEitherFormatError #-}++instance Random.Random Natural where+	randomR (mini,maxi) =+		first (fromIntegral::Integer -> Natural) .+		Random.randomR (fromIntegral mini, fromIntegral maxi)+	random = first (fromIntegral::Integer -> Natural) . Random.random++-- * Parsing utils++parseReadP :: Read.ReadP a -> String -> Maybe a+parseReadP p s =+	let p' = Read.readP_to_S p in+	listToMaybe $ do+		(x, "") <- p' s+		pure x
+ src/Voting/Protocol/Version.hs view
@@ -0,0 +1,148 @@+{-# LANGUAGE DataKinds #-}+{-# LANGUAGE PolyKinds #-}+{-# LANGUAGE DeriveAnyClass #-}+{-# LANGUAGE DeriveGeneric #-}+{-# LANGUAGE DerivingStrategies #-}+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE UndecidableInstances #-} -- for Reifies constraints in instances+module Voting.Protocol.Version where++import Control.Applicative (Applicative(..), Alternative(..))+import Control.DeepSeq (NFData)+import Control.Monad (Monad(..), join, replicateM)+import Control.Monad.Trans.Except (ExceptT(..), throwE)+import Data.Aeson (ToJSON(..), FromJSON(..), (.:), (.=))+import Data.Bits+import Data.Bool+import Data.Eq (Eq(..))+import Data.Function (($), (.), id)+import Data.Functor (Functor, (<$>), (<$))+import Data.Maybe (Maybe(..), fromJust, listToMaybe)+import Data.Ord (Ord(..))+import Data.Proxy (Proxy(..))+import Data.Reflection (Reifies(..))+import Data.Semigroup (Semigroup(..))+import Data.String (String, IsString(..))+import Data.Text (Text)+import GHC.Generics (Generic)+import GHC.Natural (minusNaturalMaybe)+import GHC.TypeLits (Nat, Symbol, natVal, symbolVal, KnownNat, KnownSymbol)+import Numeric.Natural (Natural)+import Prelude (Bounded(..), fromIntegral)+import System.Random (RandomGen)+import Text.Show (Show(..), showChar, showString, shows)+import qualified Control.Monad.Trans.State.Strict as S+import qualified Crypto.Hash as Crypto+import qualified Data.Aeson as JSON+import qualified Data.Aeson.Types as JSON+import qualified Data.ByteArray as ByteArray+import qualified Data.ByteString as BS+import qualified Data.ByteString.Base64 as BS64+import qualified Data.Char as Char+import qualified Data.List as List+import qualified Data.Text as Text+import qualified Data.Text.Encoding as Text+import qualified Data.Text.Lazy as TL+import qualified Data.Text.Lazy.Builder as TLB+import qualified Data.Text.Lazy.Builder.Int as TLB+import qualified System.Random as Random+import qualified Text.ParserCombinators.ReadP as Read+import qualified Text.Read as Read++import Voting.Protocol.Utils+import Voting.Protocol.Arithmetic++-- * Type 'Version'+-- | Version of the Helios-C protocol.+data Version = Version+ { version_branch :: [Natural]+ , version_tags   :: [(Text, Natural)]+ } deriving (Eq,Ord,Generic,NFData)+instance IsString Version where+	fromString = fromJust . readVersion+instance Show Version where+	showsPrec _p Version{..} =+		List.foldr (.) id+		 (List.intersperse (showChar '.') $+			shows <$> version_branch) .+		List.foldr (.) id+		 ((\(t,n) -> showChar '-' . showString (Text.unpack t) .+			if n > 0 then shows n else id)+		 <$> version_tags)+instance ToJSON Version where+	toJSON     = toJSON     . show+	toEncoding = toEncoding . show+instance FromJSON Version where+	parseJSON (JSON.String s)+	 | Just v <- readVersion (Text.unpack s)+	 = return v+	parseJSON json = JSON.typeMismatch "Version" json++hasVersionTag :: Version -> Text -> Bool+hasVersionTag v tag = List.any (\(t,_n) -> t == tag) (version_tags v)++-- ** Type 'ExperimentalVersion'+type ExperimentalVersion = V [1,6] '[ '(VersionTagQuicker,0)]+experimentalVersion :: Version+experimentalVersion = stableVersion{version_tags = [(versionTagQuicker,0)]}++-- ** Type 'StableVersion'+type StableVersion = V [1,6] '[]+stableVersion :: Version+stableVersion = "1.6"++-- ** Type 'VersionTagQuicker'+type VersionTagQuicker = "quicker"+versionTagQuicker :: Text+versionTagQuicker = "quicker"++readVersion :: String -> Maybe Version+readVersion = parseReadP $ do+	version_branch <- Read.sepBy1+	 (Read.read <$> Read.munch1 Char.isDigit)+	 (Read.char '.')+	version_tags <- Read.many $ (,)+		 <$> (Text.pack <$ Read.char '-' <*> Read.munch1 Char.isAlpha)+		 <*> (Read.read <$> Read.munch1 Char.isDigit <|> return 0)+	return Version{..}++-- ** Type 'V'+-- | Type-level representation of a specific 'Version'.+data V (branch::[Nat]) (tags::[(Symbol,Nat)])+-- | Like a normal 'reflect' but this one takes+-- its 'Version' from a type-level 'V'ersion+-- instead of a term-level 'Version'.+instance (VersionBranchVal branch, VersionTagsVal tags) => Reifies (V branch tags) Version where+	reflect _ = Version+	 { version_branch = versionBranchVal (Proxy @branch)+	 , version_tags   = versionTagsVal (Proxy @tags)+	 }++-- *** Class 'VersionBranchVal'+class VersionBranchVal a where+	versionBranchVal :: proxy a -> [Natural]+instance KnownNat h => VersionBranchVal '[h] where+	versionBranchVal _ = [fromIntegral (natVal (Proxy @h))]+instance+ ( KnownNat h+ , KnownNat hh+ , VersionBranchVal (hh ':t)+ ) => VersionBranchVal (h ': hh ': t) where+	versionBranchVal _ =+		fromIntegral (natVal (Proxy @h)) :+		versionBranchVal (Proxy @(hh ':t))++-- *** Class 'VersionTagsVal'+class VersionTagsVal a where+	versionTagsVal :: proxy a -> [(Text,Natural)]+instance VersionTagsVal '[] where+	versionTagsVal _ = []+instance+ ( KnownSymbol s+ , KnownNat n+ , VersionTagsVal t+ ) => VersionTagsVal ('(s,n) ': t) where+	versionTagsVal _ =+		( Text.pack (symbolVal (Proxy @s))+		, fromIntegral (natVal (Proxy @n))+		) : versionTagsVal (Proxy :: Proxy t)
tests/HUnit/Election.hs view
@@ -19,11 +19,11 @@ 	 [ testCase "WeakParams" $ 		reify weakFFC $ \(Proxy::Proxy c) -> 			List.take 10 (groupGenInverses @_ @c) @?=-				[groupGen^neg (fromNatural n) | n <- [0..9]]+				[groupGen^negate (fromNatural n) | n <- [0..9]] 	 , testCase "BeleniosParams" $ 		reify beleniosFFC $ \(Proxy::Proxy c) -> 			List.take 10 (groupGenInverses @_ @c) @?=-				[groupGen^neg (fromNatural n) | n <- [0..9]]+				[groupGen^negate (fromNatural n) | n <- [0..9]] 	 ]  , testGroup "encryptBallot" $ 	 [ hunitsEncryptBallot v weakFFC
tests/HUnit/FFC.hs view
@@ -10,7 +10,7 @@  hunit :: Reifies v Version => Proxy v -> TestTree hunit _v = testGroup "FFC"- [ testGroup "inv"+ [ testGroup "inverse" 	 [ hunitInv weakFFC 	 , hunitInv beleniosFFC 	 ]@@ -44,6 +44,6 @@ 	testGroup (Text.unpack $ cryptoName crypto) 	 [ testCase "groupGen" $ 			reifyCrypto crypto $ \(_c::Proxy c) ->-				inv (groupGen :: G crypto c) @?=+				inverse (groupGen :: G crypto c) @?= 					groupGen ^ E (fromJust $ groupOrder (Proxy @c) `minusNaturalMaybe` one) 	 ]
tests/HUnit/Trustee/Indispensable.hs view
@@ -107,7 +107,7 @@  encryptTallyResult ::  Reifies v Version =>- GroupParams crypto c =>+ CryptoParams crypto c =>  Monad m => RandomGen r =>  PublicKey crypto c -> [[Natural]] -> StateT r m (EncryptedTally crypto v c, Natural) encryptTallyResult pubKey countByChoiceByQuest =
tests/QuickCheck/Election.hs view
@@ -35,7 +35,7 @@  quickcheckElection ::  Reifies v Version => - GroupParams crypto c =>+ CryptoParams crypto c =>  Key crypto => JSON.ToJSON crypto => Show crypto =>  Proxy v -> Proxy c -> TestTree quickcheckElection (_v::Proxy v) (c::Proxy c) =@@ -53,11 +53,11 @@ instance Reifies c FFC => Arbitrary (F c) where 	arbitrary = F <$> choose (zero, fromJust $ fieldCharac @c `minusNaturalMaybe` one) -}-instance GroupParams crypto c => Arbitrary (G crypto c) where+instance CryptoParams crypto c => Arbitrary (G crypto c) where 	arbitrary = do 		m <- arbitrary 		return (groupGen ^ m)-instance GroupParams crypto c => Arbitrary (E crypto c) where+instance CryptoParams crypto c => Arbitrary (E crypto c) where 	arbitrary = E <$> choose (zero, fromJust $ groupOrder @crypto (Proxy @c) `minusNaturalMaybe` one) instance Arbitrary UUID where 	arbitrary = do@@ -66,7 +66,7 @@ 			randomUUID instance  ( Reifies v Version- , GroupParams crypto c+ , CryptoParams crypto c  , Arbitrary (E crypto c)  ) => Arbitrary (Proof crypto v c) where 	arbitrary = do@@ -90,7 +90,7 @@ 		] instance  ( Reifies v Version- , GroupParams crypto c+ , CryptoParams crypto c  , Key crypto  , JSON.ToJSON crypto  ) => Arbitrary (Election crypto v c) where@@ -138,7 +138,7 @@ 		] instance  ( Reifies v Version- , GroupParams crypto c+ , CryptoParams crypto c  , Key crypto  , JSON.ToJSON crypto  ) => Arbitrary (Election crypto v c :> [[Bool]]) where
tests/QuickCheck/Trustee.hs view
@@ -22,7 +22,7 @@  testIndispensableTrusteePublicKey ::  Reifies v Version =>- GroupParams crypto c =>+ CryptoParams crypto c =>  Key crypto =>  Proxy v -> Proxy c -> TestTree testIndispensableTrusteePublicKey (_v::Proxy v) (c::Proxy c) =@@ -38,7 +38,7 @@  instance  ( Reifies v Version- , GroupParams crypto c+ , CryptoParams crypto c  ) => Arbitrary (TrusteePublicKey crypto v c) where 	arbitrary = do 		trustee_PublicKey <- arbitrary