module Crypto.PVSS.DLEQ
( DLEQ(..)
, Proof(..)
, ParallelProof(..)
, ParallelProofs(..)
, Challenge
, generate
, verify
, generateParallel
, verifyParallel
) where
import Control.DeepSeq
import Crypto.PVSS.ECC
import Data.Binary
import Data.Binary.Get (getByteString)
import Data.Binary.Put (putByteString)
import Data.ByteString (ByteString)
import GHC.Generics
data DLEQ = DLEQ
{ dleq_g1 :: !Point
, dleq_h1 :: !Point
, dleq_g2 :: !Point
, dleq_h2 :: !Point
} deriving (Show,Eq,Generic)
instance NFData DLEQ
newtype Challenge = Challenge ByteString
deriving (Show,Eq,NFData)
instance Binary Challenge where
put (Challenge c) = putByteString c
get = Challenge <$> getByteString 32
data Proof = Proof
{ proof_c :: !Challenge
, proof_z :: !Scalar
} deriving (Show,Eq,Generic)
instance Binary Proof
instance NFData Proof
newtype ParallelProof = ParallelProof { parallelProof_z :: Scalar }
deriving (Show,Eq,Generic)
instance Binary ParallelProof
instance NFData ParallelProof
data ParallelProofs = ParallelProofs
{ parallelProofsChallenge :: !Challenge
, parallelProofsValues :: ![ParallelProof]
} deriving (Show,Eq,Generic)
instance Binary ParallelProofs
instance NFData ParallelProofs
generate :: Scalar
-> Scalar
-> DLEQ
-> Proof
generate w a (DLEQ g1 h1 g2 h2) = Proof (Challenge c) r
where
a1 = g1 .* w
a2 = g2 .* w
c = hashPoints [h1,h2,a1,a2]
r = w #+ (a #* keyFromBytes c)
verify :: DLEQ
-> Proof
-> Bool
verify (DLEQ g1 h1 g2 h2) (Proof (Challenge ch) r) = ch == hashPoints [h1,h2,a1,a2]
where
r1 = g1 .* r
r2 = g2 .* r
c = keyFromBytes ch
a1 = r1 .- (h1 .* c)
a2 = r2 .- (h2 .* c)
generateParallel :: [(Scalar, Scalar, DLEQ)]
-> ParallelProofs
generateParallel l =
let as = map (\(r, _, (DLEQ g1 _ g2 _)) -> (g1 .* r, g2 .* r)) l
h = concatMap (\(_, _, (DLEQ _ v1 _ v2)) -> [v1,v2]) l
++ concatMap (\(a1, a2) -> [a1,a2]) as
challenge = hashPoints h
c = keyFromBytes challenge
in ParallelProofs
{ parallelProofsChallenge = Challenge challenge
, parallelProofsValues = map (\(w, a, _) -> ParallelProof (w #+ (a #* c))) l
}
verifyParallel :: [DLEQ]
-> ParallelProofs
-> Bool
verifyParallel dleqs proofs =
let computed = zipWith verifyOne dleqs (parallelProofsValues proofs)
in ch == hashPoints (concatMap fst computed ++ concatMap snd computed)
where
(Challenge ch) = parallelProofsChallenge proofs
verifyOne :: DLEQ -> ParallelProof -> ([Point], [Point])
verifyOne (DLEQ g1 h1 g2 h2) (ParallelProof r) = ([h1,h2], [a1,a2])
where
r1 = g1 .* r
r2 = g2 .* r
c = keyFromBytes ch
a1 = r1 .- (h1 .* c)
a2 = r2 .- (h2 .* c)