lol-apps 0.1.1.0 → 0.2.0.0
raw patch · 38 files changed
+2955/−1229 lines, 38 filesdep +containersdep +filepathdep +lol-benchesdep ~MonadRandomdep ~QuickCheckdep ~basenew-component:exe:homomprfnew-component:exe:khprfnew-component:exe:symmshe
Dependencies added: containers, filepath, lol-benches, lol-cpp, lol-repa, lol-tests, protocol-buffers, protocol-buffers-descriptor, split, time
Dependency ranges changed: MonadRandom, QuickCheck, base, deepseq, lol, numeric-prelude, test-framework, test-framework-quickcheck2
Files
- CHANGES.md +11/−0
- Crypto/Lol/Applications/HomomPRF.hs +530/−0
- Crypto/Lol/Applications/KeyHomomorphicPRF.hs +243/−0
- Crypto/Lol/Applications/SymmSHE.hs +232/−94
- Crypto/Proto/HomomPRF.hs +23/−0
- Crypto/Proto/HomomPRF/LinearFuncChain.hs +79/−0
- Crypto/Proto/HomomPRF/RoundHintChain.hs +79/−0
- Crypto/Proto/HomomPRF/TunnelInfoChain.hs +79/−0
- Crypto/Proto/SHE.hs +23/−0
- Crypto/Proto/SHE/KSHint.hs +88/−0
- Crypto/Proto/SHE/RqPolynomial.hs +79/−0
- Crypto/Proto/SHE/SecretKey.hs +87/−0
- Crypto/Proto/SHE/TunnelInfo.hs +128/−0
- HomomPRF.proto +26/−0
- README +12/−0
- SHE.proto +33/−0
- benchmarks/BenchAppsMain.hs +125/−0
- benchmarks/KHPRFBenches.hs +74/−0
- benchmarks/Main.hs +0/−9
- benchmarks/SHEBenches.hs +125/−110
- examples/HomomPRFMain.hs +185/−0
- examples/HomomPRFParams.hs +55/−0
- examples/KHPRFMain.hs +67/−0
- examples/SHEMain.hs +95/−0
- examples/SymmSHE/SimpleSHE.hs +0/−81
- lol-apps.cabal +100/−35
- tests/KHPRFTests.hs +63/−0
- tests/Main.hs +0/−10
- tests/SHETests.hs +199/−241
- tests/TestAppsMain.hs +115/−0
- utils/Apply.hs +0/−17
- utils/Apply/SHE.hs +0/−235
- utils/Benchmarks.hs +0/−44
- utils/GenArgs.hs +0/−31
- utils/GenArgs/SHE.hs +0/−110
- utils/TestTypes.hs +0/−38
- utils/Tests.hs +0/−47
- utils/Utils.hs +0/−127
CHANGES.md view
@@ -3,7 +3,18 @@ 0.2.0.0 ----+ * Added [BPF14] key-homomorphic PRF.+ * Added homomorphic evaluation of PRF.+ * Simpler benchmarks and tests.+ * SHE: Made hints for key switching and ring tunneling explicit.+ * SHE: Protocol buffer formats for tunneling, key-switch hints, secret keys, etc.+ Note that this provides an easy way to save expensive precomputation. See+ the HomomPRF example for more details.++0.1.1.0+---- * Updated documentation with MathJax+ * Added 0.1.0.0 -----
+ Crypto/Lol/Applications/HomomPRF.hs view
@@ -0,0 +1,530 @@+{-|+Module : Crypto.Lol.Applications.HomomPRF+Description : Homomorphic evaluation of the PRF from <http://web.eecs.umich.edu/~cpeikert/pubs/kh-prf.pdf [BP14]>.+Copyright : (c) Eric Crockett, 2011-2017+ Chris Peikert, 2011-2017+License : GPL-2+Maintainer : ecrockett0@email.com+Stability : experimental+Portability : POSIX++ \( \def\Z{\mathbb{Z}} \)++Homomorphic evaluation of the PRF from <http://web.eecs.umich.edu/~cpeikert/pubs/kh-prf.pdf [BP14]>.+-}++{-# LANGUAGE ConstraintKinds #-}+{-# LANGUAGE DataKinds #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE GADTs #-}+{-# LANGUAGE MultiParamTypeClasses #-}+{-# LANGUAGE PartialTypeSignatures #-}+{-# LANGUAGE PolyKinds #-}+{-# LANGUAGE RebindableSyntax #-}+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE TypeFamilies #-}+{-# LANGUAGE TypeOperators #-}+{-# LANGUAGE UndecidableInstances #-}++module Crypto.Lol.Applications.HomomPRF+(homomPRF, homomPRFM+,RoundHints(..), roundHints+,TunnelInfoChain(..), tunnelInfoChain+,EvalHints(..)+,MultiTunnelCtx, ZqUp, ZqDown+,TwoOf+,Tunnel, PTRound, ZqResult+,PTRings, PTTunnel(..), TunnelFuncs(..)) where++import Control.DeepSeq+import Control.Monad+import Control.Monad.Except+import Control.Monad.Random hiding (fromList)+import Control.Monad.Reader+import Control.Monad.State++import Crypto.Lol+import Crypto.Lol.Applications.KeyHomomorphicPRF+import Crypto.Lol.Reflects+import Crypto.Lol.Types++import Crypto.Lol.Applications.SymmSHE+import Crypto.Lol.Types.ZPP+import Crypto.Lol.Cyclotomic.Tensor+import Crypto.Lol.Types.Proto+import qualified Crypto.Proto.HomomPRF.LinearFuncChain as P+import qualified Crypto.Proto.HomomPRF.RoundHintChain as P+import qualified Crypto.Proto.HomomPRF.TunnelInfoChain as P+import qualified Crypto.Proto.Lol.RqProduct as P+import qualified Crypto.Proto.SHE.TunnelInfo as P++import Data.List.Split (chunksOf)+import Data.Promotion.Prelude++import GHC.TypeLits hiding (type (*))++import MathObj.Matrix (columns)++import Data.Sequence (empty, (<|), ViewL(..), viewl)++-- | The element before @zq@ in type list @zqs@.+type ZqUp zq zqs = NextListElt zq (Reverse zqs)+-- | The element after @zq@ in type list @zqs@.+type ZqDown zq zqs = NextListElt zq zqs++type family NextListElt (x :: k) (xs :: [k]) :: k where+ NextListElt x (x ': y ': ys) = y+ NextListElt x '[x] = TypeError ('Text "There is no 'next'/'prev' list element for " ':<>: 'ShowType x ':<>: 'Text "!" ':$$:+ 'Text "Try adding more moduli to the ciphertext modulus list")+ NextListElt x (y ': ys) = NextListElt x ys+ NextListElt x '[] = TypeError ('Text "Could not find type " ':<>: 'ShowType x ':<>: 'Text " in the list." ':$$:+ 'Text "You must use parameters that are in the type lists!")++-- | The offline data needed for homomorphic PRF evaluation.+data EvalHints t rngs z zp zq zqs gad where+ Hints :: (UnPP (CharOf zp) ~ '(Prime2, e))+ => TunnelInfoChain gad t rngs zp (ZqUp zq zqs)+ -> RoundHints t (Fst (Last rngs)) (Snd (Last rngs)) z e zp (ZqDown zq zqs) zqs gad+ -> EvalHints t rngs z zp zq zqs gad++instance (UnPP (CharOf zp) ~ '(Prime2, e),+ NFData (TunnelInfoChain gad t rngs zp (ZqUp zq zqs)),+ NFData (RoundHints t (Fst (Last rngs)) (Snd (Last rngs)) z e zp (ZqDown zq zqs) zqs gad))+ => NFData (EvalHints t rngs z zp zq zqs gad) where+ rnf (Hints t r) = rnf t `seq` rnf r++-- | Monadic version of 'homomPRF'+homomPRFM ::+ (MonadReader (EvalHints t rngs z zp zq zqs gad) mon,+ MonadState (PRFState (Cyc t r zp) (Cyc t r (TwoOf zp))) mon,+ MulPublicCtx t r r' zp zq,+ MultiTunnelCtx rngs r r' s s' t z zp zq gad zqs,+ PTRound t s s' e zp (ZqDown zq zqs) z gad zqs)+ => CT r zp (Cyc t r' zq) -- encryption of PRF secret+ -> Int -- PRF input+ -> mon (CT s (TwoOf zp) (Cyc t s' (ZqResult e (ZqDown zq zqs) zqs)))+homomPRFM ct x = do+ hints <- ask+ state $ homomPRF' hints ct x++-- | Evaluates the PRF family indexed by the encrypted secret on the input,+-- relative to some PRF state. Note that the algorithm in+-- <http://web.eecs.umich.edu/~cpeikert/pubs/kh-prf.pdf [BP14]> outputs a+-- /vector/; this function only outputs the encryption of the first coefficient+-- of that vector.+homomPRF :: (MulPublicCtx t r r' zp zq,+ MultiTunnelCtx rngs r r' s s' t z zp zq gad zqs,+ PTRound t s s' e zp (ZqDown zq zqs) z gad zqs)+ => EvalHints t rngs z zp zq zqs gad+ -> CT r zp (Cyc t r' zq)+ -> Int+ -> PRFState (Cyc t r zp) (Cyc t r (TwoOf zp))+ -> CT s (TwoOf zp) (Cyc t s' (ZqResult e (ZqDown zq zqs) zqs))+homomPRF hs ct x = fst . homomPRF' hs ct x++homomPRF' :: forall t e r s r' s' rngs z zp zq zqs gad .+ (MulPublicCtx t r r' zp zq,+ MultiTunnelCtx rngs r r' s s' t z zp zq gad zqs,+ PTRound t s s' e zp (ZqDown zq zqs) z gad zqs)+ => EvalHints t rngs z zp zq zqs gad+ -> CT r zp (Cyc t r' zq)+ -> Int+ -> PRFState (Cyc t r zp) (Cyc t r (TwoOf zp))+ -> (CT s (TwoOf zp) (Cyc t s' (ZqResult e (ZqDown zq zqs) zqs)),+ PRFState (Cyc t r zp) (Cyc t r (TwoOf zp)))+homomPRF' (Hints tHints rHints) ct x st =+ let (atx,st') = evalTree x st+ firstElt = head $ head $ columns atx+ ctMatrix1 = mulPublic firstElt ct+ ctMatrix2 = tunnel (Proxy::Proxy zqs) tHints ctMatrix1+ in (ptRound rHints ctMatrix2, st')++-- | \(\Z_2\) for ZqBasic with a 'PrimePower' modulus+type family TwoOf (a :: k) :: k+type instance TwoOf (ZqBasic (q :: PrimePower) i) = ZqBasic PP2 i++-- For rounding+type family Div2 (a :: k) :: k+type instance Div2 (ZqBasic q i) = ZqBasic (Div2 q) i+type instance Div2 (pp :: PrimePower) = Head (UnF (PpToF pp / F2))++-- type-restricted versions of rescaleLinearCT+roundCTUp :: (RescaleCyc (Cyc t) zq (ZqUp zq zqs), ToSDCtx t m' zp zq)+ => Proxy zqs -> CT m zp (Cyc t m' zq) -> CT m zp (Cyc t m' (ZqUp zq zqs))+roundCTUp _ = rescaleLinearCT++roundCTDown :: (RescaleCyc (Cyc t) zq (ZqDown zq zqs), ToSDCtx t m' zp zq)+ => Proxy zqs -> CT m zp (Cyc t m' zq) -> CT m zp (Cyc t m' (ZqDown zq zqs))+roundCTDown _ = rescaleLinearCT+++++++++++++++++++-- | Quadratic key switch hints for the rounding phase of PRF evaluation.+data RoundHints t m m' z e zp zq zqs gad where+ RHNil :: RoundHints t m m' z e zp zq zqs gad+ RHCons :: KSQuadCircHint gad (Cyc t m' (ZqUp zq zqs))+ -> RoundHints t m m' z e (Div2 zp) (ZqDown zq zqs) zqs gad+ -> RoundHints t m m' z ('S e) zp zq zqs gad++instance NFData (RoundHints t m m' z P1 zp zq zqs gad) where+ rnf RHNil = ()++instance (NFData (KSQuadCircHint gad (Cyc t m' (ZqUp zq zqs))),+ NFData (RoundHints t m m' z e (Div2 zp) (ZqDown zq zqs) zqs gad))+ => NFData (RoundHints t m m' z ('S e) zp zq zqs gad) where+ rnf (RHCons h hs) = rnf h `seq` rnf hs++instance Protoable (RoundHints t m m' z P1 zp zq zqs gad) where+ type ProtoType (RoundHints t m m' z P1 zp zq zqs gad) = P.RoundHintChain+ toProto RHNil = P.RoundHintChain empty+ fromProto (P.RoundHintChain xs) | xs == empty = return RHNil+ fromProto _ = throwError $ "Got non-empty chain on fromProto for RoundHints"++instance (Protoable (KSQuadCircHint gad (Cyc t m' (ZqUp zq zqs))),+ Protoable (RoundHints t m m' z e (Div2 zp) (ZqDown zq zqs) zqs gad),+ ProtoType (RoundHints t m m' z e (Div2 zp) (ZqDown zq zqs) zqs gad) ~ P.RoundHintChain)+ => Protoable (RoundHints t m m' z ('S e) zp zq zqs gad) where+ type ProtoType (RoundHints t m m' z ('S e) zp zq zqs gad) = P.RoundHintChain+ toProto (RHCons f fs) =+ let f' = toProto f+ (P.RoundHintChain fs') = toProto fs+ in P.RoundHintChain $ f' <| fs'+ fromProto (P.RoundHintChain fs) = do+ when (fs == empty) $ throwError "fromProto RoundHints: expected at least one element"+ let (a :< as) = viewl fs+ b <- fromProto a+ bs <- fromProto $ P.RoundHintChain as+ return $ RHCons b bs++-- | Functions related to homomorphically rounding from 2^k to 2+class (UnPP (CharOf zp) ~ '(Prime2,e)) => PTRound t m m' e zp zq z gad zqs where+ type ZqResult e zq (zqs :: [*])++ -- | Generate hints for rounding from \(R_p=R_{2^k}\) to \(R_2\)+ roundHints :: (MonadRandom rnd)+ => SK (Cyc t m' z) -> rnd (RoundHints t m m' z e zp zq zqs gad)++ -- round(q/p*x) (with "towards infinity tiebreaking")+ -- = msb(x+q/4) = floor((x+q/4)/(q/2))+ -- | Round coeffs in CRT slots near 0 to 0 and near q/2 to 1, with a short-cut+ -- on the first level of the rounding tree.+ ptRound :: RoundHints t m m' z e zp zq zqs gad -> CT m zp (Cyc t m' zq) -> CT m (TwoOf zp) (Cyc t m' (ZqResult e zq zqs))++ -- | All levels other than the first level of the rounding tree.+ ptRoundInternal :: RoundHints t m m' z e zp zq zqs gad -> [CT m zp (Cyc t m' zq)] -> CT m (TwoOf zp) (Cyc t m' (ZqResult e zq zqs))++instance PTRound t m m' P1 (ZqBasic PP2 i) zq z gad zqs where+ type ZqResult P1 zq zqs = zq++ roundHints _ = return RHNil++ ptRound RHNil x = x++ ptRoundInternal RHNil [x] = x++instance (UnPP p ~ '(Prime2, 'S e), -- superclass constraint+ zqup ~ ZqUp zq zqs, zq' ~ ZqDown zq zqs, zp ~ ZqBasic p i, zp' ~ Div2 zp, -- convenience synonyms+ AddPublicCtx t m m' zp zq, AddPublicCtx t m m' zp zq', -- addPublic+ KeySwitchCtx gad t m' zp zq zqup, KSHintCtx gad t m' z zqup, -- for quadratic key switch+ Reflects p Int, -- value+ Ring (CT m zp (Cyc t m' zq)), -- (*)+ RescaleCyc (Cyc t) zq zq', ToSDCtx t m' zp zq, -- rescaleLinearCT+ ModSwitchPTCtx t m' zp zp' zq', -- modSwitchPT+ PTRound t m m' e zp' zq' z gad zqs, -- recursive call+ Protoable (KSQuadCircHint gad (Cyc t m' (ZqUp zq zqs)))) -- toProto+ => PTRound t m m' ('S e) (ZqBasic p i) (zq :: *) z gad zqs where+ type ZqResult ('S e) zq zqs = ZqResult e (ZqDown zq zqs) zqs++ roundHints sk = do+ ksq <- ksQuadCircHint sk+ rest <- roundHints sk+ return $ RHCons ksq rest++ ptRound (RHCons ksqHint rest) x =+ let x' = addPublic one x+ xprod = rescaleLinearCT $ keySwitchQuadCirc ksqHint $ x*x'+ p = proxy value (Proxy::Proxy p)+ xs = map (\y->modSwitchPT $ addPublic (fromInteger $ y*(-y+1)) xprod) [1..] :: [CT m zp' (Cyc t m' zq')]+ in ptRoundInternal rest $ take (p `div` 4) xs++ ptRoundInternal (RHCons ksqHint rest) (xs :: [CT m (ZqBasic p i) (Cyc t m' zq)]) =+ let pairs = chunksOf 2 xs+ go [a,b] = modSwitchPT $ rescaleLinearCT $ keySwitchQuadCirc ksqHint $ a*b :: CT m zp' (Cyc t m' zq')+ in ptRoundInternal rest (map go pairs)++++++++++++++++++++++++++++++++++++++++-- For (homomorphic) tunneling++-- | Sequence of 'TunnelInfo' for consecutive ring tunnels.+data TunnelInfoChain gad t xs zp zq where+ THNil :: TunnelInfoChain gad t '[ '(m,m') ] zp zq+ THCons :: (xs ~ ('(r,r') ': '(s,s') ': rngs), e' ~ (e * (r' / r)), e ~ FGCD r s)+ => TunnelInfo gad t e r s e' r' s' zp zq+ -> TunnelInfoChain gad t (Tail xs) zp zq+ -> TunnelInfoChain gad t xs zp zq++instance NFData (TunnelInfoChain gad t '[ '(m,m') ] zp zq) where+ rnf THNil = ()++instance (e' ~ (e * (r' / r)), e ~ FGCD r s,+ NFData (TunnelInfo gad t e r s e' r' s' zp zq),+ NFData (TunnelInfoChain gad t ('(s,s') ': rngs) zp zq))+ => NFData (TunnelInfoChain gad t ('(r,r') ': '(s,s') ': rngs) zp zq) where+ rnf (THCons t ts) = rnf t `seq` rnf ts++instance Protoable (TunnelInfoChain gad t '[ '(m,m') ] zp zq) where+ type ProtoType (TunnelInfoChain gad t '[ '(m,m') ] zp zq) = P.TunnelInfoChain+ toProto THNil = P.TunnelInfoChain empty+ fromProto (P.TunnelInfoChain xs) | xs == empty = return THNil+ fromProto _ = throwError $ "Got non-empty chain on fromProto for TunnelInfoChain"++instance (e' ~ (e * (r' / r)), e ~ FGCD r s,+ Protoable (TunnelInfo gad t e r s e' r' s' zp zq),+ Protoable (TunnelInfoChain gad t ('(s,s') ': rngs) zp zq),+ ProtoType (TunnelInfoChain gad t ('(s,s') ': rngs) zp zq) ~ P.TunnelInfoChain)+ => Protoable (TunnelInfoChain gad t ('(r,r') ': '(s,s') ': rngs) zp zq) where+ type ProtoType (TunnelInfoChain gad t ('(r,r') ': '(s,s') ': rngs) zp zq) = P.TunnelInfoChain+ toProto (THCons hint rest) =+ let h' = toProto hint+ (P.TunnelInfoChain hs') = toProto rest+ in P.TunnelInfoChain $ h' <| hs'++ fromProto (P.TunnelInfoChain zs) = do+ when (zs == empty) $ throwError "fromProto TunnelInfo: expected at least one element"+ let (x :< xs) = viewl zs+ y <- fromProto x+ ys <- fromProto $ P.TunnelInfoChain xs+ return $ THCons y ys++-- | Functions related to homomorphic ring tunneling.+class Tunnel xs t zp zq gad where++ -- | Generates 'TunnelInfo' for each tunnel step from @Head xs@ to @Last xs@.+ tunnelInfoChain :: (MonadRandom rnd, Head xs ~ '(r,r'), Last xs ~ '(s,s'),+ Lift zp z, CElt t z, ToInteger z, Reduce z zq) -- constraints involving 'z' from GenTunnelInfoCtx+ => SK (Cyc t r' z) -> rnd (TunnelInfoChain gad t xs zp zq, SK (Cyc t s' z)) -- , TunnelFuncs t (PTRings xs) zp++ -- | Tunnel from @Head xs@ to @Last xs@.+ tunnelInternal :: (Head xs ~ '(r,r'), Last xs ~ '(s,s')) =>+ TunnelInfoChain gad t xs zp zq -> CT r zp (Cyc t r' zq) -> CT s zp (Cyc t s' zq)++instance Tunnel '[ '(m,m') ] t zp zq gad where++ tunnelInfoChain sk = return (THNil,sk)++ tunnelInternal _ = id++-- EAC: I expand the GenTunnelInfoCtx synonym here to remove all occurrences of 'z',+-- which instead only occur in the context of tunnelInfoChain. This is because 'z' is+-- not relevant for tunnelInternal nor TunnelInfoChain, so we would have to pass+-- a proxy for 'z'. This is a problem I have had many times, and still don't have a+-- good solution for: the class exists only to match on the type list, all of+-- of the other class params exist only so I can write constrints involving the changing+-- params (here, the cyc indices) and the static params (here, the moduli/base rings).+-- One solution is to split the class in two: one with a 'z' param, and one without.+-- Another option is to pass in a meaningless proxy for 'z' to functions that don't need it.+-- Neither of these are good solutions, so instead I took a third approach: factor 'z'+-- out of the constraint synonyms. This requires explicitly listing the remaining+-- constraints, which is also ugly.+-- The root of this problem seems to be that the functions hold constant some+-- parameters, but change others, while the constraint synonyms refer to all of+-- them, even though some are orthogonal constraints.+instance (ExtendLinIdx e r s e' r' s', -- tunnelInfoChain+ e' ~ (e * (r' / r)), -- tunnelInfoChain+ e' `Divides` r', -- tunnelInfoChain+ CElt t zp, Ring zq, Random zq, CElt t zq, -- tunnelInfoChain+ Reduce (DecompOf zq) zq, Gadget gad zq, -- tunnelInfoChain+ NFElt zq, CElt t (DecompOf zq), -- tunnelInfoChain+ TunnelCtx t r s e' r' s' zp zq gad, -- tunnelCT+ e ~ FGCD r s, e `Divides` r, e `Divides` s, -- linearDec+ ZPP zp, TElt t (ZpOf zp), -- crtSet+ Tunnel ('(s,s') ': rngs) t zp zq gad, -- recursive call+ Protoable (TunnelInfo gad t e r s e' r' s' zp zq),+ ProtoType (TunnelInfo gad t e r s e' r' s' zp zq) ~ P.TunnelInfo) -- toProto+ => Tunnel ('(r,r') ': '(s,s') ': rngs) t zp zq gad where++ tunnelInfoChain sk = do+ skout <- genSKWithVar sk+ let crts = proxy crtSet (Proxy::Proxy e)+ r = proxy totientFact (Proxy::Proxy r)+ e = proxy totientFact (Proxy::Proxy e)+ dim = r `div` e+ -- only take as many crts as we need+ -- otherwise linearDec fails+ linf = linearDec (take dim crts) :: Linear t zp e r s+ thint :: TunnelInfo gad t e r s e' r' s' zp zq <- tunnelInfo linf skout sk+ (thints,sk') <- tunnelInfoChain skout+ return (THCons thint thints, sk')++ tunnelInternal (THCons thint rest) = tunnelInternal rest . tunnelCT thint++-- | Context for multi-step homomorphic tunneling.+type MultiTunnelCtx rngs r r' s s' t z zp zq gad zqs =+ (Head rngs ~ '(r,r'), Last rngs ~ '(s,s'), Tunnel rngs t zp (ZqUp zq zqs) gad, ZqDown (ZqUp zq zqs) zqs ~ zq,+ RescaleCyc (Cyc t) zq (ZqUp zq zqs), RescaleCyc (Cyc t) (ZqUp zq zqs) zq, RescaleCyc (Cyc t) zq (ZqDown zq zqs),+ ToSDCtx t r' zp zq, ToSDCtx t s' zp (ZqUp zq zqs))++-- EAC: why round down twice? We bump the modulus up to begin with to handle+-- the key switches, so we knock thatt off, then another for accumulated noise+-- | End-to-end multi-step homomorphic tunneling. First add a modulus to the+-- ciphertext for the key switches, then 'tunnelInternal', then round down twice:+-- once to remove the key switch modulus, and once to dampen the noise incurred+-- while tunneling.+tunnel :: forall rngs r r' s s' t z zp zq gad zqs . (MultiTunnelCtx rngs r r' s s' t z zp zq gad zqs)+ => Proxy zqs -> TunnelInfoChain gad t rngs zp (ZqUp zq zqs) -> CT r zp (Cyc t r' zq) -> CT s zp (Cyc t s' (ZqDown zq zqs))+tunnel pzqs hints x =+ let y = tunnelInternal hints $ roundCTUp pzqs x+ in roundCTDown pzqs $ roundCTDown pzqs y+++++++++++++++++++++++++++++-- | Linear functions used for in-the-clear tunneling+data TunnelFuncs t xs zp where+ TFNil :: TunnelFuncs t '[m] zp+ TFCons :: (xs ~ (r ': s ': rngs))+ => Linear t zp (FGCD r s) r s+ -> TunnelFuncs t (Tail xs) zp+ -> TunnelFuncs t xs zp++instance NFData (TunnelFuncs t '[m] zp) where+ rnf TFNil = ()++instance (NFData (Linear t zp (FGCD r s) r s), NFData (TunnelFuncs t (s ': xs) zp))+ => NFData (TunnelFuncs t (r ': s ': xs) zp) where+ rnf (TFCons f fs) = rnf f `seq` rnf fs++instance Protoable (TunnelFuncs t '[m] zp) where+ type ProtoType (TunnelFuncs t '[m] zp) = P.LinearFuncChain+ toProto TFNil = P.LinearFuncChain empty+ fromProto (P.LinearFuncChain s) | s == empty = return TFNil+ fromProto _ = throwError $ "Got non-empty chain on fromProto for TunnelFuncs"++instance (ProtoType (t s zp) ~ P.RqProduct,+ Protoable (Linear t zp e r s),+ Protoable (TunnelFuncs t (s ': rngs) zp),+ ProtoType (TunnelFuncs t (s ': rngs) zp) ~ P.LinearFuncChain,+ Tensor t, e ~ FGCD r s, Fact e, Fact r, Fact s)+ => Protoable (TunnelFuncs t (r ': s ': rngs) zp) where+ type ProtoType (TunnelFuncs t (r ': s ': rngs) zp) = P.LinearFuncChain+ toProto (TFCons f fs) =+ let f' = toProto f+ (P.LinearFuncChain fs') = toProto fs+ in P.LinearFuncChain $ f' <| fs'+ fromProto (P.LinearFuncChain fs) = do+ when (fs == empty) $ throwError "fromProto TunnelFuncs: expected at least one element"+ let (a :< as) = viewl fs+ b <- fromProto a+ bs <- fromProto $ P.LinearFuncChain as+ return $ TFCons b bs++-- | The plaintext rings for a list of plaintext/ciphertext ring pairs.+type family PTRings xs where+ PTRings '[] = '[]+ PTRings ( '(a,b) ': rest ) = a ': (PTRings rest)++-- | Functions for in-the-clear tunneling, needed to test the correctness of+-- homomorphic PRF evaluation.+class PTTunnel t xs zp where+ -- | Generate the linear functions to apply when tunneling from @Head xs@ to @Last xs@.+ ptTunnelFuncs :: TunnelFuncs t xs zp+ -- | Tunnel a ring element from @Head xs@ to @Last xs@.+ ptTunnel :: (Head xs ~ r, Last xs ~ s) => TunnelFuncs t xs zp -> Cyc t r zp -> Cyc t s zp++instance PTTunnel t '[r] z where+ ptTunnelFuncs = TFNil+ ptTunnel TFNil = id++instance (e ~ FGCD r s, e `Divides` r, e `Divides` s, PTTunnel t (s ': rngs) zp,+ CElt t zp, -- evalLin+ ZPP zp, TElt t (ZpOf zp) -- crtSet+ )+ => PTTunnel t (r ': s ': rngs) zp where+ ptTunnelFuncs =+ let crts = proxy crtSet (Proxy::Proxy e)+ r = proxy totientFact (Proxy::Proxy r)+ e = proxy totientFact (Proxy::Proxy e)+ dim = r `div` e+ -- only take as many crts as we need+ -- otherwise linearDec fails+ linf = linearDec (take dim crts) :: Linear t zp e r s+ linfs = ptTunnelFuncs+ in TFCons linf linfs+ ptTunnel (TFCons linf fs) = ptTunnel fs . evalLin linf
+ Crypto/Lol/Applications/KeyHomomorphicPRF.hs view
@@ -0,0 +1,243 @@+{-|+Module : Crypto.Lol.Applications.KeyHomomorphicPRF+Description : Key-homomorphic PRF from <http://web.eecs.umich.edu/~cpeikert/pubs/kh-prf.pdf [BP14]>.+Copyright : (c) Eric Crockett, 2011-2017+ Chris Peikert, 2011-2017+License : GPL-2+Maintainer : ecrockett0@email.com+Stability : experimental+Portability : POSIX++Key-homomorphic PRF from <http://web.eecs.umich.edu/~cpeikert/pubs/kh-prf.pdf [BP14]>.+-}++{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE GADTs #-}+{-# LANGUAGE NoImplicitPrelude #-}+{-# LANGUAGE ScopedTypeVariables #-}++module Crypto.Lol.Applications.KeyHomomorphicPRF+(FullBinTree(..), evalTree+,randomTree, balancedTree, leftSpineTree, rightSpineTree+,PRFFamily, makeFamily, randomFamily+,grayCode+,PRFState, prfState+,latticePRF, latticePRFM+,ringPRF, ringPRFM+) where++import Control.Applicative ((<$>))+import Control.DeepSeq+import Control.Monad.Random hiding (fromList)+import Control.Monad.State++import Crypto.Lol++import Data.Bits+import Data.Maybe (fromMaybe)++import MathObj.Matrix++-- | Full binary tree.+data FullBinTree = L+ | I Int FullBinTree FullBinTree++instance NFData FullBinTree where+ rnf L = ()+ rnf (I i t1 t2) = rnf i `seq` rnf t1 `seq` rnf t2++-- | Parameters for PRF+data PRFFamily gad rq rp =+ Params+ (Matrix rq) -- a0+ (Matrix rq) -- a1+ FullBinTree -- tree++instance (NFData rq) => NFData (PRFFamily gad rq rp) where+ rnf (Params m1 m2 t) = rnf m1 `seq` rnf m2 `seq` rnf t++-- | Smart constructor+makeFamily :: forall rq rp gad . (Gadget gad rq)+ => Matrix rq -> Matrix rq -> FullBinTree -> PRFFamily gad rq rp+makeFamily a0 a1+ | numRows a0 /= numRows a1 = error $ "a0 has " ++ show (numRows a0) +++ " rows, but a1 has " ++ show (numRows a1) ++ " rows."+ | numColumns a0 /= (numRows a0)*(length $ untag (gadget :: Tagged gad [rq])) =+ error $ "Expected " ++ show ((numRows a0)*(length $ untag (gadget :: Tagged gad [rq]))) +++ " columns in a0, but there are " ++ show (numColumns a0) ++ "."+ | numColumns a1 /= (numRows a1)*(length $ untag (gadget :: Tagged gad [rq])) =+ error $ "Expected " ++ show ((numRows a1)*(length $ untag (gadget :: Tagged gad [rq]))) +++ " columns in a1, but there are " ++ show (numColumns a1) ++ "."+ | otherwise = Params a0 a1++-- not exported,+data DecoratedTree r =+ -- input bit, output+ DL Int (Matrix r)+ -- numleaves, input value, output, left subtree, decomposed result of right subtree, right subtree+ | DI Int Int (Matrix r) (DecoratedTree r) (Matrix r) (DecoratedTree r)++instance (NFData r) => NFData (DecoratedTree r) where+ rnf (DL i m) = rnf i `seq` rnf m+ rnf (DI i1 i2 m1 d1 m2 d2) = rnf i1 `seq` rnf i2 `seq` rnf m1 `seq` rnf d1 `seq` rnf m2 `seq` rnf d2++-- | State of the PRF computation. This permits incremental computation.+data PRFState rq rp where+ PRFState :: (Decompose gad rq)+ => Proxy gad -> Matrix rq -> Matrix rq -> DecoratedTree rq -> PRFState rq rp++instance (NFData rq) => NFData (PRFState rq rp) where+ rnf (PRFState Proxy m1 m2 d) = rnf m1 `seq` rnf m2 `seq` rnf d++-- | Given PRF parameters and an optional inital input value (default is 0),+-- produces an initial PRF state.+prfState :: forall gad rq rp . (Decompose gad rq)+ => PRFFamily gad rq rp -> Maybe Int -> PRFState rq rp+prfState p@(Params a0 a1 t) initInput =+ let treelen = case t of+ L -> 1+ (I s _ _) -> s+ input = fromMaybe 0 initInput -- default input is 0+ inputGuard = input >= 0 && input < 2^treelen+ pgad = Proxy::Proxy gad+ in if inputGuard+ then PRFState pgad a0 a1 $ buildDecTree pgad input p+ else+ error $ "prfState: Input tree has " ++ show treelen +++ " leaves, but input " ++ show input ++ " has " +++ show (logBase 2 (fromIntegral input) :: Double) ++ " bits."++-- given validated parameters, constructs a decorated tree with the given input+buildDecTree :: (Decompose gad rq)+ => Proxy gad -> Int -> PRFFamily gad rq rp -> DecoratedTree rq+buildDecTree pgad y (Params a0 a1 t) =+ let getNumLeaves L = 1+ getNumLeaves (I x _ _) = x+ go 0 L = (a0, DL 0 a0)+ go 1 L = (a1, DL 1 a1)+ go x (I numLeaves ltree rtree) =+ let numRightLeaves = getNumLeaves rtree+ rbits = x .&. ((2^numRightLeaves)-1) -- mask high bits+ lbits = shift x (-numRightLeaves) -- negate to shift right+ (lval, ltree') = go lbits ltree+ (rval, rtree') = go rbits rtree+ decompr = fmap reduce $ proxy (decomposeMatrix rval) pgad+ val = lval * decompr+ in (val, DI numLeaves x val ltree' decompr rtree')+ in snd $ go y t++-- | Evaluates the tree at the new input, reusing as much prior work as possible.+evalTree :: Int -> PRFState rq rp -> (Matrix rq, PRFState rq rp)+evalTree y (PRFState pgad a0 a1 t) =+ let getNumLeaves (DL _ _) = 1+ getNumLeaves (DI i _ _ _ _ _) = i+ -- outputs result, new state, and flag indicating whether the state changed+ go 0 (DL _ _) = (a0, DL 0 a0, False)+ go 1 (DL _ _) = (a1, DL 1 a1, False)+ go i n@(DI numLeaves x val ltree decompr rtree)+ | i == x = (val,n, False)+ | otherwise =+ let numRightLeaves = getNumLeaves rtree+ rbits = x .&. ((2^numRightLeaves)-1) -- mask high bits+ lbits = shift x (-numRightLeaves) -- negate to shift right+ (lval, ltree', _) = go lbits ltree+ (rval, rtree', changed) = go rbits rtree+ decompr' = if changed+ then fmap reduce $ proxy (decomposeMatrix rval) pgad+ else decompr+ val' = lval * decompr'+ in (val', DI numLeaves i val' ltree' decompr' rtree', True)+ (res, t', _) = go y t+ in (res, PRFState pgad a0 a1 t')++-- | Equation (2.3) in <http://web.eecs.umich.edu/~cpeikert/pubs/kh-prf.pdf [BP14]>.+latticePRF' :: (Rescale zq zp)+ => Matrix zq -> Int -> PRFState zq zp -> (Matrix zp, PRFState zq zp)+latticePRF' s x state1@(PRFState _ a0 _ _)+ | numRows s /= 1 = error "Secret key must have one row."+ | numColumns s /= numRows a0 = error $ "Secret key has " +++ show (numColumns s) ++ " columns, but a0 has " +++ show (numRows a0) ++ " rows."+ | otherwise = let (res,state2) = evalTree x state1+ in (rescale <$> s*res, state2)++-- | Single-ouptut lattice PRF.+latticePRF :: (Rescale zq zp)+ => Matrix zq -> Int -> PRFState zq zp -> Matrix zp+latticePRF s x = fst. latticePRF' s x++-- | Multi-output lattice PRF with monadic memoized internal state.+latticePRFM :: (MonadState (PRFState zq zp) mon, Rescale zq zp)+ => Matrix zq -> Int -> mon (Matrix zp)+latticePRFM s x = state $ latticePRF' s x++-- | Equation (2.10) in <http://web.eecs.umich.edu/~cpeikert/pubs/kh-prf.pdf [BP14]>.+ringPRF' :: (Fact m, RescaleCyc (Cyc t) zq zp, Ring rq,+ rq ~ Cyc t m zq, rp ~ Cyc t m zp)+ => rq -> Int -> PRFState rq rp -> (Matrix rp, PRFState rq rp)+ringPRF' s x state1 =+ let (res,state2) = evalTree x state1+ in ((rescaleDec . (s*)) <$> res, state2)++-- | Single-output ring PRF.+ringPRF :: (Fact m, RescaleCyc (Cyc t) zq zp, Ring rq,+ rq ~ Cyc t m zq, rp ~ Cyc t m zp)+ => rq -> Int -> PRFState rq rp -> Matrix rp+ringPRF s x = fst . ringPRF' s x++-- | Multi-output ring PRF with monadic memoized internal state.+ringPRFM :: (MonadState (PRFState rq rp) mon, Fact m,+ RescaleCyc (Cyc t) zq zp, Ring rq,+ rq ~ Cyc t m zq, rp ~ Cyc t m zp)+ => rq -> Int -> mon (Matrix rp)+ringPRFM s x = state $ ringPRF' s x++-- convenience functions++-- | Given the desired number of leaves, produces a random full binary tree.+randomTree :: (MonadRandom rnd) => Int -> rnd FullBinTree+randomTree 1 = return L+randomTree i = do+ leftSize <- getRandomR (1,i-1)+ left <- randomTree leftSize+ right <- randomTree $ i-leftSize+ return $ I i left right++-- | Given the desired number of leaves, produces a full binary right-spine tree.+leftSpineTree :: Int -> FullBinTree+leftSpineTree 1 = L+leftSpineTree i = I i (leftSpineTree $ i-1) L++-- | Given the desired number of leaves, produces a full binary left-spine tree.+rightSpineTree :: Int -> FullBinTree+rightSpineTree 1 = L+rightSpineTree i = I i L (rightSpineTree $ i-1)++-- | Given the desired number of leaves, produces a full binary tree+-- which is complete, except possibly for the last level, which is left-biased.+balancedTree :: Int -> FullBinTree+balancedTree 1 = L+balancedTree i =+ let lastFullLevelSize = 2^(floor (logBase 2 (fromIntegral i) :: Double) :: Int)+ lsize = min lastFullLevelSize $ i-(lastFullLevelSize `div` 2)+ rsize = i-lsize+ in I i (balancedTree lsize) (balancedTree rsize)++-- | Randomly generate ring-based PRF family.+randomFamily :: forall gad rnd rq rp . (MonadRandom rnd, Random rq, Gadget gad rq)+ => Int -> rnd (PRFFamily gad rq rp)+randomFamily size = do -- in rnd+ t <- randomTree size+ let len = length $ untag (gadget :: Tagged gad [rq])+ a0 <- fromList 1 len <$> take len <$> getRandoms+ a1 <- fromList 1 len <$> take len <$> getRandoms+ return $ makeFamily a0 a1 t++-- | Constructs an n-bit Gray code, useful for efficiently evaluating the PRF.+grayCode :: Int -> [Int]+grayCode 1 = [0,1]+grayCode n =+ let gc' = grayCode (n-1)+ pow2 = 2^(n-1)+ rightHalf = map (+pow2) $ reverse gc'+ in gc' ++ rightHalf
Crypto/Lol/Applications/SymmSHE.hs view
@@ -1,34 +1,58 @@-{-# LANGUAGE ConstraintKinds, DataKinds, FlexibleContexts,- FlexibleInstances, GADTs, MultiParamTypeClasses,- NoImplicitPrelude, ScopedTypeVariables, TypeFamilies,- TypeOperators, UndecidableInstances #-}+{-|+Module : Crypto.Lol.Applications.SymmSHE+Description : Symmetric-key homomorphic encryption.+Copyright : (c) Eric Crockett, 2011-2017+ Chris Peikert, 2011-2017+License : GPL-2+Maintainer : ecrockett0@email.com+Stability : experimental+Portability : POSIX --- | Symmetric-key somewhat homomorphic encryption. See Section 4 of--- http://eprint.iacr.org/2015/1134 for mathematical description.+ \( \def\O{\mathcal{O}} \) +Symmetric-key somewhat homomorphic encryption. See Section 4 of+<http://eprint.iacr.org/2015/1134> for mathematical description.+-}++{-# LANGUAGE ConstraintKinds #-}+{-# LANGUAGE DataKinds #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE GADTs #-}+{-# LANGUAGE GeneralizedNewtypeDeriving #-}+{-# LANGUAGE MultiParamTypeClasses #-}+{-# LANGUAGE NoImplicitPrelude #-}+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE TypeFamilies #-}+{-# LANGUAGE TypeOperators #-}+{-# LANGUAGE UndecidableInstances #-}+ module Crypto.Lol.Applications.SymmSHE ( -- * Data types SK, PT, CT -- don't export constructors! -- * Keygen, encryption, decryption-, genSK+, genSK, genSKWithVar , encrypt , errorTerm, errorTermUnrestricted, decrypt, decryptUnrestricted -- * Arithmetic with public values-, addScalar, addPublic, mulPublic+, addScalar, addPublic, mulScalar, mulPublic -- * Modulus switching , rescaleLinearCT, modSwitchPT -- * Key switching+, KSLinearHint, KSQuadCircHint+, ksLinearHint, ksQuadCircHint , keySwitchLinear, keySwitchQuadCirc -- * Ring switching , embedSK, embedCT, twaceCT+, TunnelInfo, tunnelInfo , tunnelCT -- * Constraint synonyms , GenSKCtx, EncryptCtx, ToSDCtx, ErrorTermCtx , DecryptCtx, DecryptUCtx-, AddScalarCtx, AddPublicCtx, MulPublicCtx, ModSwitchPTCtx+, AddScalarCtx, AddPublicCtx, MulScalarCtx, MulPublicCtx, ModSwitchPTCtx , KeySwitchCtx, KSHintCtx-, TunnelCtx+, GenTunnelInfoCtx, TunnelCtx , SwitchCtx, LWECtx -- these are internal, but exported for better docs ) where @@ -37,13 +61,22 @@ import Crypto.Lol as LP hiding (sin) import Crypto.Lol.Cyclotomic.UCyc (D, UCyc)+import Crypto.Lol.Reflects+import Crypto.Lol.Types.Proto+import Crypto.Proto.Lol.R (R)+import Crypto.Proto.Lol.RqProduct (RqProduct)+import qualified Crypto.Proto.SHE.KSHint as P+import qualified Crypto.Proto.SHE.RqPolynomial as P+import qualified Crypto.Proto.SHE.SecretKey as P+import qualified Crypto.Proto.SHE.TunnelInfo as P import Control.Applicative hiding ((*>)) import Control.DeepSeq import Control.Monad as CM-import Control.Monad.Random+import Control.Monad.Random hiding (lift) import Data.Maybe import Data.Traversable as DT+import Data.Typeable import MathObj.Polynomial as P @@ -85,9 +118,15 @@ -- | Generates a secret key with (index-independent) scaled variance -- parameter \( v \); see 'errorRounded'. genSK :: (GenSKCtx t m z v, MonadRandom rnd)- => v -> rnd (SK (Cyc t m z))+ => v -> rnd (SK (Cyc t m z)) genSK v = liftM (SK v) $ errorRounded v +-- | Generates a secret key with the same scaled variance+-- as the input secret key.+genSKWithVar :: (ToInteger z, Fact m, CElt t z, MonadRandom rnd)+ => SK a -> rnd (SK (Cyc t m z))+genSKWithVar (SK v _) = genSK v+ -- | Constraint synonym for encryption. type EncryptCtx t m m' z zp zq = (Mod zp, Ring zp, Ring zq, Lift zp (ModRep zp), Random zq,@@ -220,7 +259,7 @@ ---------- Key switching ---------- --- | Constraint synonym for generating an LWE sample.+-- | Constraint synonym for generating a ring-LWE sample. type LWECtx t m' z zq = (ToInteger z, Reduce z zq, Ring zq, Random zq, Fact m', CElt t z, CElt t zq) @@ -279,35 +318,46 @@ (RescaleCyc (Cyc t) zq' zq, RescaleCyc (Cyc t) zq zq', ToSDCtx t m' zp zq, SwitchCtx gad t m' zq') --- | Switch a linear ciphertext under \( s_{\text{in}} \) to a linear+-- | Hint for a linear key switch+newtype KSLinearHint gad r'q' = KSLHint (Tagged gad [Polynomial r'q']) deriving (NFData)++-- | Hint for a circular quadratic key switch.+newtype KSQuadCircHint gad r'q' = KSQHint (Tagged gad [Polynomial r'q']) deriving (NFData)++-- | A hint to switch a linear ciphertext under \( s_{\text{in}} \) to a linear -- one under \( s_{\text{out}} \).-keySwitchLinear :: forall gad t m' zp zq zq' z rnd m .- (KeySwitchCtx gad t m' zp zq zq', KSHintCtx gad t m' z zq', MonadRandom rnd)- => SK (Cyc t m' z) -- sout- -> SK (Cyc t m' z) -- sin- -> TaggedT (gad, zq') rnd (CT m zp (Cyc t m' zq) -> CT m zp (Cyc t m' zq))-keySwitchLinear skout (SK _ sin) = tagT $ do- hint :: Tagged gad [Polynomial (Cyc t m' zq')] <- ksHint skout sin- return $! hint `seq`- (\ct -> let CT MSD k l c = toMSD ct- [c0,c1] = coeffs c- c1' = rescalePow c1- in CT MSD k l $ P.const c0 + rescaleLinearMSD (switch hint c1'))+ksLinearHint :: (KSHintCtx gad t m' z zq', MonadRandom rnd)+ => SK (Cyc t m' z) -- sout+ -> SK (Cyc t m' z) -- sin+ -> rnd (KSLinearHint gad (Cyc t m' zq'))+ksLinearHint skout (SK _ sin) = KSLHint <$> ksHint skout sin --- | Switch a quadratic ciphertext (i.e., one with three components)--- to a linear one under the /same/ key.-keySwitchQuadCirc :: forall gad t m' zp zq zq' z m rnd .- (KeySwitchCtx gad t m' zp zq zq', KSHintCtx gad t m' z zq', MonadRandom rnd)+-- | Switch a linear ciphertext using the supplied hint.+keySwitchLinear :: (KeySwitchCtx gad t m' zp zq zq')+ => KSLinearHint gad (Cyc t m' zq') -> CT m zp (Cyc t m' zq) -> CT m zp (Cyc t m' zq)+keySwitchLinear (KSLHint hint) ct =+ let CT MSD k l c = toMSD ct+ [c0,c1] = coeffs c+ c1' = rescalePow c1+ in CT MSD k l $ P.const c0 + rescaleLinearMSD (switch hint c1')++-- | A hint to switch a quadratic ciphertext to a linear+-- one under the same key.+ksQuadCircHint :: (KSHintCtx gad t m' z zq', MonadRandom rnd) => SK (Cyc t m' z)- -> TaggedT (gad, zq') rnd (CT m zp (Cyc t m' zq) -> CT m zp (Cyc t m' zq))-keySwitchQuadCirc sk@(SK _ s) = tagT $ do- hint :: Tagged gad [Polynomial (Cyc t m' zq')] <- ksHint sk (s*s)- return $ hint `seq` (\ct ->- let CT MSD k l c = toMSD ct- [c0,c1,c2] = coeffs c- c2' = rescalePow c2- in CT MSD k l $ P.fromCoeffs [c0,c1] + rescaleLinearMSD (switch hint c2'))+ -> rnd (KSQuadCircHint gad (Cyc t m' zq'))+ksQuadCircHint sk@(SK _ s) = KSQHint <$> ksHint sk (s*s) +-- | Switch a quadratic ciphertext (i.e., one with three components)+-- to a linear one under the /same/ key using the supplied hint.+keySwitchQuadCirc :: (KeySwitchCtx gad t m' zp zq zq')+ => KSQuadCircHint gad (Cyc t m' zq') -> CT m zp (Cyc t m' zq) -> CT m zp (Cyc t m' zq)+keySwitchQuadCirc (KSQHint hint) ct =+ let CT MSD k l c = toMSD ct+ [c0,c1,c2] = coeffs c+ c2' = rescalePow c2+ in CT MSD k l $ P.fromCoeffs [c0,c1] + rescaleLinearMSD (switch hint c2')+ ---------- Misc homomorphic operations ---------- -- | Constraint synonym for adding a public scalar to a ciphertext. type AddScalarCtx t m' zp zq =@@ -323,9 +373,7 @@ in CT LSD k l $ c + (P.const $ reduce $ liftPow b') -- | Constraint synonym for adding a public value to an encrypted value.-type AddPublicCtx t m m' zp zq =- (Lift' zp, Reduce (LiftOf zp) zq, m `Divides` m',- CElt t zp, CElt t (LiftOf zp), ToSDCtx t m' zp zq)+type AddPublicCtx t m m' zp zq = (AddScalarCtx t m' zp zq, m `Divides` m') -- | Homomorphically add a public \( R_p \) value to an encrypted -- value.@@ -338,10 +386,22 @@ b' :: Cyc t m zq = reduce $ liftPow $ linv * (iterate mulG b !! k) in CT LSD k l $ c + P.const (embed b') +-- | Constraint synonym for multiplying a public scalar value with+-- an encrypted value.+type MulScalarCtx t m' zp zq =+ (Lift' zp, Reduce (LiftOf zp) zq, Fact m', CElt t zq)++-- | Homomorphically multiply a public \(\mathbb{Z}_p\) value to an+-- encrypted value.+mulScalar :: (MulScalarCtx t m' zp zq)+ => zp -> CT m zp (Cyc t m' zq) -> CT m zp (Cyc t m' zq)+mulScalar a (CT enc k l c) =+ let a' = scalarCyc $ reduce $ lift a+ in CT enc k l $ (a' *) <$> c+ -- | Constraint synonym for multiplying a public value with an encrypted value. type MulPublicCtx t m m' zp zq =- (Lift' zp, Reduce (LiftOf zp) zq, Ring zq, m `Divides` m',- CElt t zp, CElt t (LiftOf zp), CElt t zq)+ (MulScalarCtx t m' zp zq, m `Divides` m', CElt t zp, CElt t (LiftOf zp)) -- | Homomorphically multiply an encrypted value by a public \( R_p \) -- value.@@ -359,21 +419,21 @@ ---------- NumericPrelude instances ---------- -instance (Eq zp, m `Divides` m', ToSDCtx t m' zp zq)+instance (Eq zp, MulScalarCtx t m' zp zq, m `Divides` m', ToSDCtx t m' zp zq) => Additive.C (CT m zp (Cyc t m' zq)) where zero = CT LSD 0 one zero -- the scales, g-exponents of ciphertexts, and MSD/LSD types must match. ct1@(CT enc1 k1 l1 c1) + ct2@(CT enc2 k2 l2 c2)- -- for simplicity, we don't currently support this. Shouldn't be- -- too complicated though.- | l1 /= l2 = error "Cannot add ciphertexts with different scale values"- | k1 < k2 = iterate mulGCT ct1 !! (k2-k1) + ct2- | k1 > k2 = ct1 + iterate mulGCT ct2 !! (k1-k2)- | enc1 == LSD && enc2 == MSD = toMSD ct1 + ct2- | enc1 == MSD && enc2 == LSD = ct1 + toMSD ct2- | otherwise = CT enc1 k1 l1 $ c1 + c2+ | l1 /= l2 =+ let (CT enc' k' _ c') = mulScalar (l1*(recip l2)) ct1+ in (CT enc' k' l2 c') + ct2+ | k1 < k2 = iterate mulGCT ct1 !! (k2-k1) + ct2+ | k1 > k2 = ct1 + iterate mulGCT ct2 !! (k1-k2)+ | enc1 == LSD && enc2 == MSD = toMSD ct1 + ct2+ | enc1 == MSD && enc2 == LSD = ct1 + toMSD ct2+ | otherwise = CT enc1 k1 l1 $ c1 + c2 negate (CT enc k l c) = CT enc k l $ negate <$> c @@ -395,6 +455,7 @@ ---------- Ring switching ---------- +-- | Constraint synonym for 'absorbGFactors'. type AbsorbGCtx t m' zp zq = (Lift' zp, IntegralDomain zp, Reduce (LiftOf zp) zq, Ring zq, Fact m', CElt t (LiftOf zp), CElt t zp, CElt t zq)@@ -443,51 +504,128 @@ twaceCT (CT d 0 l c) = CT d 0 l (twace <$> c) twaceCT _ = error "twaceCT requires 0 factors of g; call absorbGFactors first" +-- | Auxilliary data needed to tunnel from \(\O_{r'}\) to \(\O_{s'}\).+data TunnelInfo gad t (e :: Factored) (r :: Factored) (s :: Factored) e' r' s' zp zq =+ TInfo (Linear t zq e' r' s') [Tagged gad [Polynomial (Cyc t s' zq)]] +instance (NFData (Linear t zq e' r' s'), NFData (Cyc t s' zq))+ => NFData (TunnelInfo gad t e r s e' r' s' zp zq) where+ rnf (TInfo l t) = rnf l `seq` rnf t++-- EAC: `e' ~ (e * ...) is not needed in this module, but it is needed as use sites...+-- | Constraint synonym for generating 'TunnelInfo'.+type GenTunnelInfoCtx t e r s e' r' s' z zp zq gad =+ (ExtendLinIdx e r s e' r' s', -- extendLin+ e' ~ (e * (r' / r)), -- convenience; implied by prev constraint+ KSHintCtx gad t r' z zq, -- ksHint+ Lift zp z, CElt t zp, -- liftLin+ CElt t z, e' `Divides` r') -- powBasis++-- | Generates auxilliary data needed to tunnel from \(\O_{r'}\) to \(\O_{s'}\).+tunnelInfo :: forall gad t e r s e' r' s' z zp zq rnd .+ (MonadRandom rnd, GenTunnelInfoCtx t e r s e' r' s' z zp zq gad)+ => Linear t zp e r s+ -> SK (Cyc t s' z)+ -> SK (Cyc t r' z)+ -> rnd (TunnelInfo gad t e r s e' r' s' zp zq)+tunnelInfo f skout (SK _ sin) = -- generate hints+ (let f' = extendLin $ lift f :: Linear t z e' r' s'+ f'q = reduce f' :: Linear t zq e' r' s'+ -- choice of basis here must match coeffs* basis below+ ps = proxy powBasis (Proxy::Proxy e')+ comps = (evalLin f' . (adviseCRT sin *)) <$> ps+ in TInfo f'q <$> CM.mapM (ksHint skout) comps)+ \\ lcmDivides (Proxy::Proxy r) (Proxy::Proxy e')+ -- | Constraint synonym for ring tunneling.-type TunnelCtx t e r s e' r' s' z zp zq gad =- (ExtendLinIdx e r s e' r' s', -- liftLin- e' ~ (e * (r' / r)), -- convenience; implied by prev constraint- ToSDCtx t r' zp zq, -- toMSD- KSHintCtx gad t r' z zq, -- ksHint- Reduce z zq, -- Reduce on Linear- Lift zp z, -- liftLin- IntegralDomain zp, -- absorbGFactors- CElt t zp, -- liftLin- SwitchCtx gad t s' zq) -- switch+type TunnelCtx t r s e' r' s' zp zq gad =+ (Fact r, Fact s, e' `Divides` r', e' `Divides` s', CElt t zp, -- evalLin+ ToSDCtx t r' zp zq, -- toMSD+ AbsorbGCtx t r' zp zq, -- absorbGFactors+ SwitchCtx gad t s' zq) -- switch -- | Homomorphically apply the \( E \)-linear function that maps the -- elements of the decoding basis of \( R/E \) to the corresponding -- \( S \)-elements in the input array.-tunnelCT :: forall gad t e r s e' r' s' z zp zq rnd .- (TunnelCtx t e r s e' r' s' z zp zq gad,- MonadRandom rnd)- => Linear t zp e r s- -> SK (Cyc t s' z)- -> SK (Cyc t r' z)- -> TaggedT gad rnd (CT r zp (Cyc t r' zq) -> CT s zp (Cyc t s' zq))-tunnelCT f skout (SK _ sin) = tagT $ (do -- in rnd- -- generate hints- let f' = extendLin $ lift f :: Linear t z e' r' s'- f'q = reduce f' :: Linear t zq e' r' s'- -- choice of basis here must match coeffs* basis below- ps = proxy powBasis (Proxy::Proxy e')- comps = (evalLin f' . (adviseCRT sin *)) <$> ps- hints :: [Tagged gad [Polynomial (Cyc t s' zq)]] <- CM.mapM (ksHint skout) comps- return $ hints `deepseq` \ct ->- let CT MSD 0 s c = toMSD $ absorbGFactors ct- [c0,c1] = coeffs c- -- apply E-linear function to constant term c0- c0' = evalLin f'q c0- -- apply E-linear function to c1 via key-switching- -- this basis must match the basis used above to generate the hints- c1s = coeffsPow c1 :: [Cyc t e' zq]- -- CJP: don't embed the c1s before decomposing them (inside- -- switch); instead decompose in smaller ring before- -- embedding (it matters).- -- We may need to generalize switch or define an- -- alternative.- c1s' = zipWith switch hints (embed <$> c1s)- c1' = sum c1s'- in CT MSD 0 s $ P.const c0' + c1')- \\ lcmDivides (Proxy::Proxy r) (Proxy::Proxy e')+tunnelCT :: forall gad t e r s e' r' s' zp zq .+ (TunnelCtx t r s e' r' s' zp zq gad, e ~ FGCD r s)+ => TunnelInfo gad t e r s e' r' s' zp zq+ -> CT r zp (Cyc t r' zq)+ -> CT s zp (Cyc t s' zq)+tunnelCT (TInfo f'q hints) ct =+ (let CT MSD 0 s c = toMSD $ absorbGFactors ct+ [c0,c1] = coeffs c+ -- apply E-linear function to constant term c0+ c0' = evalLin f'q c0+ -- apply E-linear function to c1 via key-switching+ -- this basis must match the basis used above to generate the hints+ c1s = coeffsPow c1 :: [Cyc t e' zq]+ -- CJP: don't embed the c1s before decomposing them (inside+ -- switch); instead decompose in smaller ring before+ -- embedding (it matters).+ -- We may need to generalize switch or define an+ -- alternative.+ c1s' = zipWith switch hints (embed <$> c1s)+ c1' = sum c1s'+ in CT MSD 0 s $ P.const c0' + c1')+ \\ lcmDivides (Proxy::Proxy r) (Proxy::Proxy e')++instance (Protoable r, ProtoType r ~ R) => Protoable (SK r) where+ type ProtoType (SK r) = P.SecretKey+ toProto (SK v r) = P.SecretKey (toProto r) (realToField v)+ fromProto (P.SecretKey r v) = (SK v) <$> fromProto r++instance (Protoable rq, ProtoType rq ~ RqProduct) => Protoable (Polynomial rq) where+ type ProtoType (Polynomial rq) = P.RqPolynomial+ toProto = P.RqPolynomial . toProto . coeffs+ fromProto (P.RqPolynomial x) = fromCoeffs <$> fromProto x++instance (Typeable gad, Protoable r'q', ProtoType r'q' ~ RqProduct)+ => Protoable (KSLinearHint gad r'q') where+ type ProtoType (KSLinearHint gad r'q') = P.KSHint+ toProto (KSLHint cs) =+ P.KSHint+ (toProto $ proxy cs (Proxy::Proxy gad))+ (toProto $ typeRepFingerprint $ typeRep (Proxy::Proxy gad))+ fromProto (P.KSHint poly gadrepr') = do+ let gadrepr = toProto $ typeRepFingerprint $ typeRep (Proxy::Proxy gad)+ if gadrepr == gadrepr'+ then (KSLHint . tag) <$> fromProto poly+ else error $ "Expected gadget " ++ (show $ typeRep (Proxy::Proxy gad))++instance (Typeable gad, Protoable r'q', ProtoType r'q' ~ RqProduct)+ => Protoable (KSQuadCircHint gad r'q') where+ type ProtoType (KSQuadCircHint gad r'q') = P.KSHint+ toProto (KSQHint x) = toProto $ KSLHint x+ fromProto y = do+ (KSLHint x) <- fromProto y+ return $ KSQHint x++instance (Mod zp, Typeable gad,+ Protoable (Linear t zq e' r' s'),+ Protoable (KSLinearHint gad (Cyc t s' zq)), Reflects s Int, Reflects r Int, Reflects e Int)+ => Protoable (TunnelInfo gad t e r s e' r' s' zp zq) where+ type ProtoType (TunnelInfo gad t e r s e' r' s' zp zq) = P.TunnelInfo+ toProto (TInfo linf hints) =+ P.TunnelInfo+ (toProto linf)+ (toProto $ KSLHint <$> hints)+ (fromIntegral (proxy value (Proxy::Proxy e) :: Int))+ (fromIntegral (proxy value (Proxy::Proxy r) :: Int))+ (fromIntegral (proxy value (Proxy::Proxy s) :: Int))+ (fromIntegral $ proxy modulus (Proxy::Proxy zp))+ fromProto (P.TunnelInfo linf hints e r s p) =+ let e' = fromIntegral $ (proxy value (Proxy::Proxy e) :: Int)+ r' = fromIntegral $ (proxy value (Proxy::Proxy r) :: Int)+ s' = fromIntegral $ (proxy value (Proxy::Proxy s) :: Int)+ p' = fromIntegral $ proxy modulus (Proxy::Proxy zp)+ in if p' == p && e' == e && r' == r && s' == s+ then do+ linf' <- fromProto linf+ hs <- (map (\(KSLHint x) -> x)) <$> fromProto hints+ return $ TInfo linf' hs+ else error $ "Error reading TunnelInfo proto data:" +++ "\nexpected p=" ++ show p' ++ ", got " ++ show p +++ "\nexpected e=" ++ show e' ++ ", got " ++ show e +++ "\nexpected r=" ++ show r' ++ ", got " ++ show r +++ "\nexpected s=" ++ show s' ++ ", got " ++ show s
+ Crypto/Proto/HomomPRF.hs view
@@ -0,0 +1,23 @@+{-# LANGUAGE BangPatterns, DeriveDataTypeable, DeriveGeneric, FlexibleInstances, MultiParamTypeClasses #-}+{-# OPTIONS_GHC -fno-warn-unused-imports #-}+module Crypto.Proto.HomomPRF (protoInfo, fileDescriptorProto) where+import Prelude ((+), (/))+import qualified Prelude as Prelude'+import qualified Data.Typeable as Prelude'+import qualified GHC.Generics as Prelude'+import qualified Data.Data as Prelude'+import qualified Text.ProtocolBuffers.Header as P'+import Text.DescriptorProtos.FileDescriptorProto (FileDescriptorProto)+import Text.ProtocolBuffers.Reflections (ProtoInfo)+import qualified Text.ProtocolBuffers.WireMessage as P' (wireGet,getFromBS)++protoInfo :: ProtoInfo+protoInfo+ = Prelude'.read+ "ProtoInfo {protoMod = ProtoName {protobufName = FIName \".HomomPRF\", haskellPrefix = [MName \"Crypto\",MName \"Proto\"], parentModule = [], baseName = MName \"HomomPRF\"}, protoFilePath = [\"Crypto\",\"Proto\",\"HomomPRF.hs\"], protoSource = \"HomomPRF.proto\", extensionKeys = fromList [], messages = [DescriptorInfo {descName = ProtoName {protobufName = FIName \".HomomPRF.LinearFuncChain\", haskellPrefix = [MName \"Crypto\",MName \"Proto\"], parentModule = [MName \"HomomPRF\"], baseName = MName \"LinearFuncChain\"}, descFilePath = [\"Crypto\",\"Proto\",\"HomomPRF\",\"LinearFuncChain.hs\"], isGroup = False, fields = fromList [FieldInfo {fieldName = ProtoFName {protobufName' = FIName \".HomomPRF.LinearFuncChain.funcs\", haskellPrefix' = [MName \"Crypto\",MName \"Proto\"], parentModule' = [MName \"HomomPRF\",MName \"LinearFuncChain\"], baseName' = FName \"funcs\", baseNamePrefix' = \"\"}, fieldNumber = FieldId {getFieldId = 1}, wireTag = WireTag {getWireTag = 10}, packedTag = Nothing, wireTagLength = 1, isPacked = False, isRequired = False, canRepeat = True, mightPack = False, typeCode = FieldType {getFieldType = 11}, typeName = Just (ProtoName {protobufName = FIName \".Lol.LinearRq\", haskellPrefix = [MName \"Crypto\",MName \"Proto\"], parentModule = [MName \"Lol\"], baseName = MName \"LinearRq\"}), hsRawDefault = Nothing, hsDefault = Nothing}], descOneofs = fromList [], keys = fromList [], extRanges = [], knownKeys = fromList [], storeUnknown = False, lazyFields = False, makeLenses = False},DescriptorInfo {descName = ProtoName {protobufName = FIName \".HomomPRF.TunnelInfoChain\", haskellPrefix = [MName \"Crypto\",MName \"Proto\"], parentModule = [MName \"HomomPRF\"], baseName = MName \"TunnelInfoChain\"}, descFilePath = [\"Crypto\",\"Proto\",\"HomomPRF\",\"TunnelInfoChain.hs\"], isGroup = False, fields = fromList [FieldInfo {fieldName = ProtoFName {protobufName' = FIName \".HomomPRF.TunnelInfoChain.hints\", haskellPrefix' = [MName \"Crypto\",MName \"Proto\"], parentModule' = [MName \"HomomPRF\",MName \"TunnelInfoChain\"], baseName' = FName \"hints\", baseNamePrefix' = \"\"}, fieldNumber = FieldId {getFieldId = 1}, wireTag = WireTag {getWireTag = 10}, packedTag = Nothing, wireTagLength = 1, isPacked = False, isRequired = False, canRepeat = True, mightPack = False, typeCode = FieldType {getFieldType = 11}, typeName = Just (ProtoName {protobufName = FIName \".SHE.TunnelInfo\", haskellPrefix = [MName \"Crypto\",MName \"Proto\"], parentModule = [MName \"SHE\"], baseName = MName \"TunnelInfo\"}), hsRawDefault = Nothing, hsDefault = Nothing}], descOneofs = fromList [], keys = fromList [], extRanges = [], knownKeys = fromList [], storeUnknown = False, lazyFields = False, makeLenses = False},DescriptorInfo {descName = ProtoName {protobufName = FIName \".HomomPRF.RoundHintChain\", haskellPrefix = [MName \"Crypto\",MName \"Proto\"], parentModule = [MName \"HomomPRF\"], baseName = MName \"RoundHintChain\"}, descFilePath = [\"Crypto\",\"Proto\",\"HomomPRF\",\"RoundHintChain.hs\"], isGroup = False, fields = fromList [FieldInfo {fieldName = ProtoFName {protobufName' = FIName \".HomomPRF.RoundHintChain.hints\", haskellPrefix' = [MName \"Crypto\",MName \"Proto\"], parentModule' = [MName \"HomomPRF\",MName \"RoundHintChain\"], baseName' = FName \"hints\", baseNamePrefix' = \"\"}, fieldNumber = FieldId {getFieldId = 1}, wireTag = WireTag {getWireTag = 10}, packedTag = Nothing, wireTagLength = 1, isPacked = False, isRequired = False, canRepeat = True, mightPack = False, typeCode = FieldType {getFieldType = 11}, typeName = Just (ProtoName {protobufName = FIName \".SHE.KSHint\", haskellPrefix = [MName \"Crypto\",MName \"Proto\"], parentModule = [MName \"SHE\"], baseName = MName \"KSHint\"}), hsRawDefault = Nothing, hsDefault = Nothing}], descOneofs = fromList [], keys = fromList [], extRanges = [], knownKeys = fromList [], storeUnknown = False, lazyFields = False, makeLenses = False}], enums = [], oneofs = [], knownKeyMap = fromList []}"++fileDescriptorProto :: FileDescriptorProto+fileDescriptorProto+ = P'.getFromBS (P'.wireGet 11)+ (P'.pack+ "\184\SOH\n\SO\&HomomPRF.proto\SUB\tLol.proto\SUB\tSHE.proto\"/\n\SILinearFuncChain\DC2\FS\n\ENQfuncs\CAN\SOH \ETX(\v2\r.Lol.LinearRq\"1\n\SITunnelInfoChain\DC2\RS\n\ENQhints\CAN\SOH \ETX(\v2\SI.SHE.TunnelInfo\",\n\SORoundHintChain\DC2\SUB\n\ENQhints\CAN\SOH \ETX(\v2\v.SHE.KSHint")
+ Crypto/Proto/HomomPRF/LinearFuncChain.hs view
@@ -0,0 +1,79 @@+{-# LANGUAGE BangPatterns, DeriveDataTypeable, DeriveGeneric, FlexibleInstances, MultiParamTypeClasses #-}+{-# OPTIONS_GHC -fno-warn-unused-imports #-}+module Crypto.Proto.HomomPRF.LinearFuncChain (LinearFuncChain(..)) where+import Prelude ((+), (/))+import qualified Prelude as Prelude'+import qualified Data.Typeable as Prelude'+import qualified GHC.Generics as Prelude'+import qualified Data.Data as Prelude'+import qualified Text.ProtocolBuffers.Header as P'+import qualified Crypto.Proto.Lol.LinearRq as Lol (LinearRq)++data LinearFuncChain = LinearFuncChain{funcs :: !(P'.Seq Lol.LinearRq)}+ deriving (Prelude'.Show, Prelude'.Eq, Prelude'.Ord, Prelude'.Typeable, Prelude'.Data, Prelude'.Generic)++instance P'.Mergeable LinearFuncChain where+ mergeAppend (LinearFuncChain x'1) (LinearFuncChain y'1) = LinearFuncChain (P'.mergeAppend x'1 y'1)++instance P'.Default LinearFuncChain where+ defaultValue = LinearFuncChain P'.defaultValue++instance P'.Wire LinearFuncChain where+ wireSize ft' self'@(LinearFuncChain x'1)+ = case ft' of+ 10 -> calc'Size+ 11 -> P'.prependMessageSize calc'Size+ _ -> P'.wireSizeErr ft' self'+ where+ calc'Size = (P'.wireSizeRep 1 11 x'1)+ wirePut ft' self'@(LinearFuncChain x'1)+ = case ft' of+ 10 -> put'Fields+ 11 -> do+ P'.putSize (P'.wireSize 10 self')+ put'Fields+ _ -> P'.wirePutErr ft' self'+ where+ put'Fields+ = do+ P'.wirePutRep 10 11 x'1+ wireGet ft'+ = case ft' of+ 10 -> P'.getBareMessageWith update'Self+ 11 -> P'.getMessageWith update'Self+ _ -> P'.wireGetErr ft'+ where+ update'Self wire'Tag old'Self+ = case wire'Tag of+ 10 -> Prelude'.fmap (\ !new'Field -> old'Self{funcs = P'.append (funcs old'Self) new'Field}) (P'.wireGet 11)+ _ -> let (field'Number, wire'Type) = P'.splitWireTag wire'Tag in P'.unknown field'Number wire'Type old'Self++instance P'.MessageAPI msg' (msg' -> LinearFuncChain) LinearFuncChain where+ getVal m' f' = f' m'++instance P'.GPB LinearFuncChain++instance P'.ReflectDescriptor LinearFuncChain where+ getMessageInfo _ = P'.GetMessageInfo (P'.fromDistinctAscList []) (P'.fromDistinctAscList [10])+ reflectDescriptorInfo _+ = Prelude'.read+ "DescriptorInfo {descName = ProtoName {protobufName = FIName \".HomomPRF.LinearFuncChain\", haskellPrefix = [MName \"Crypto\",MName \"Proto\"], parentModule = [MName \"HomomPRF\"], baseName = MName \"LinearFuncChain\"}, descFilePath = [\"Crypto\",\"Proto\",\"HomomPRF\",\"LinearFuncChain.hs\"], isGroup = False, fields = fromList [FieldInfo {fieldName = ProtoFName {protobufName' = FIName \".HomomPRF.LinearFuncChain.funcs\", haskellPrefix' = [MName \"Crypto\",MName \"Proto\"], parentModule' = [MName \"HomomPRF\",MName \"LinearFuncChain\"], baseName' = FName \"funcs\", baseNamePrefix' = \"\"}, fieldNumber = FieldId {getFieldId = 1}, wireTag = WireTag {getWireTag = 10}, packedTag = Nothing, wireTagLength = 1, isPacked = False, isRequired = False, canRepeat = True, mightPack = False, typeCode = FieldType {getFieldType = 11}, typeName = Just (ProtoName {protobufName = FIName \".Lol.LinearRq\", haskellPrefix = [MName \"Crypto\",MName \"Proto\"], parentModule = [MName \"Lol\"], baseName = MName \"LinearRq\"}), hsRawDefault = Nothing, hsDefault = Nothing}], descOneofs = fromList [], keys = fromList [], extRanges = [], knownKeys = fromList [], storeUnknown = False, lazyFields = False, makeLenses = False}"++instance P'.TextType LinearFuncChain where+ tellT = P'.tellSubMessage+ getT = P'.getSubMessage++instance P'.TextMsg LinearFuncChain where+ textPut msg+ = do+ P'.tellT "funcs" (funcs msg)+ textGet+ = do+ mods <- P'.sepEndBy (P'.choice [parse'funcs]) P'.spaces+ Prelude'.return (Prelude'.foldl (\ v f -> f v) P'.defaultValue mods)+ where+ parse'funcs+ = P'.try+ (do+ v <- P'.getT "funcs"+ Prelude'.return (\ o -> o{funcs = P'.append (funcs o) v}))
+ Crypto/Proto/HomomPRF/RoundHintChain.hs view
@@ -0,0 +1,79 @@+{-# LANGUAGE BangPatterns, DeriveDataTypeable, DeriveGeneric, FlexibleInstances, MultiParamTypeClasses #-}+{-# OPTIONS_GHC -fno-warn-unused-imports #-}+module Crypto.Proto.HomomPRF.RoundHintChain (RoundHintChain(..)) where+import Prelude ((+), (/))+import qualified Prelude as Prelude'+import qualified Data.Typeable as Prelude'+import qualified GHC.Generics as Prelude'+import qualified Data.Data as Prelude'+import qualified Text.ProtocolBuffers.Header as P'+import qualified Crypto.Proto.SHE.KSHint as SHE (KSHint)++data RoundHintChain = RoundHintChain{hints :: !(P'.Seq SHE.KSHint)}+ deriving (Prelude'.Show, Prelude'.Eq, Prelude'.Ord, Prelude'.Typeable, Prelude'.Data, Prelude'.Generic)++instance P'.Mergeable RoundHintChain where+ mergeAppend (RoundHintChain x'1) (RoundHintChain y'1) = RoundHintChain (P'.mergeAppend x'1 y'1)++instance P'.Default RoundHintChain where+ defaultValue = RoundHintChain P'.defaultValue++instance P'.Wire RoundHintChain where+ wireSize ft' self'@(RoundHintChain x'1)+ = case ft' of+ 10 -> calc'Size+ 11 -> P'.prependMessageSize calc'Size+ _ -> P'.wireSizeErr ft' self'+ where+ calc'Size = (P'.wireSizeRep 1 11 x'1)+ wirePut ft' self'@(RoundHintChain x'1)+ = case ft' of+ 10 -> put'Fields+ 11 -> do+ P'.putSize (P'.wireSize 10 self')+ put'Fields+ _ -> P'.wirePutErr ft' self'+ where+ put'Fields+ = do+ P'.wirePutRep 10 11 x'1+ wireGet ft'+ = case ft' of+ 10 -> P'.getBareMessageWith update'Self+ 11 -> P'.getMessageWith update'Self+ _ -> P'.wireGetErr ft'+ where+ update'Self wire'Tag old'Self+ = case wire'Tag of+ 10 -> Prelude'.fmap (\ !new'Field -> old'Self{hints = P'.append (hints old'Self) new'Field}) (P'.wireGet 11)+ _ -> let (field'Number, wire'Type) = P'.splitWireTag wire'Tag in P'.unknown field'Number wire'Type old'Self++instance P'.MessageAPI msg' (msg' -> RoundHintChain) RoundHintChain where+ getVal m' f' = f' m'++instance P'.GPB RoundHintChain++instance P'.ReflectDescriptor RoundHintChain where+ getMessageInfo _ = P'.GetMessageInfo (P'.fromDistinctAscList []) (P'.fromDistinctAscList [10])+ reflectDescriptorInfo _+ = Prelude'.read+ "DescriptorInfo {descName = ProtoName {protobufName = FIName \".HomomPRF.RoundHintChain\", haskellPrefix = [MName \"Crypto\",MName \"Proto\"], parentModule = [MName \"HomomPRF\"], baseName = MName \"RoundHintChain\"}, descFilePath = [\"Crypto\",\"Proto\",\"HomomPRF\",\"RoundHintChain.hs\"], isGroup = False, fields = fromList [FieldInfo {fieldName = ProtoFName {protobufName' = FIName \".HomomPRF.RoundHintChain.hints\", haskellPrefix' = [MName \"Crypto\",MName \"Proto\"], parentModule' = [MName \"HomomPRF\",MName \"RoundHintChain\"], baseName' = FName \"hints\", baseNamePrefix' = \"\"}, fieldNumber = FieldId {getFieldId = 1}, wireTag = WireTag {getWireTag = 10}, packedTag = Nothing, wireTagLength = 1, isPacked = False, isRequired = False, canRepeat = True, mightPack = False, typeCode = FieldType {getFieldType = 11}, typeName = Just (ProtoName {protobufName = FIName \".SHE.KSHint\", haskellPrefix = [MName \"Crypto\",MName \"Proto\"], parentModule = [MName \"SHE\"], baseName = MName \"KSHint\"}), hsRawDefault = Nothing, hsDefault = Nothing}], descOneofs = fromList [], keys = fromList [], extRanges = [], knownKeys = fromList [], storeUnknown = False, lazyFields = False, makeLenses = False}"++instance P'.TextType RoundHintChain where+ tellT = P'.tellSubMessage+ getT = P'.getSubMessage++instance P'.TextMsg RoundHintChain where+ textPut msg+ = do+ P'.tellT "hints" (hints msg)+ textGet+ = do+ mods <- P'.sepEndBy (P'.choice [parse'hints]) P'.spaces+ Prelude'.return (Prelude'.foldl (\ v f -> f v) P'.defaultValue mods)+ where+ parse'hints+ = P'.try+ (do+ v <- P'.getT "hints"+ Prelude'.return (\ o -> o{hints = P'.append (hints o) v}))
+ Crypto/Proto/HomomPRF/TunnelInfoChain.hs view
@@ -0,0 +1,79 @@+{-# LANGUAGE BangPatterns, DeriveDataTypeable, DeriveGeneric, FlexibleInstances, MultiParamTypeClasses #-}+{-# OPTIONS_GHC -fno-warn-unused-imports #-}+module Crypto.Proto.HomomPRF.TunnelInfoChain (TunnelInfoChain(..)) where+import Prelude ((+), (/))+import qualified Prelude as Prelude'+import qualified Data.Typeable as Prelude'+import qualified GHC.Generics as Prelude'+import qualified Data.Data as Prelude'+import qualified Text.ProtocolBuffers.Header as P'+import qualified Crypto.Proto.SHE.TunnelInfo as SHE (TunnelInfo)++data TunnelInfoChain = TunnelInfoChain{hints :: !(P'.Seq SHE.TunnelInfo)}+ deriving (Prelude'.Show, Prelude'.Eq, Prelude'.Ord, Prelude'.Typeable, Prelude'.Data, Prelude'.Generic)++instance P'.Mergeable TunnelInfoChain where+ mergeAppend (TunnelInfoChain x'1) (TunnelInfoChain y'1) = TunnelInfoChain (P'.mergeAppend x'1 y'1)++instance P'.Default TunnelInfoChain where+ defaultValue = TunnelInfoChain P'.defaultValue++instance P'.Wire TunnelInfoChain where+ wireSize ft' self'@(TunnelInfoChain x'1)+ = case ft' of+ 10 -> calc'Size+ 11 -> P'.prependMessageSize calc'Size+ _ -> P'.wireSizeErr ft' self'+ where+ calc'Size = (P'.wireSizeRep 1 11 x'1)+ wirePut ft' self'@(TunnelInfoChain x'1)+ = case ft' of+ 10 -> put'Fields+ 11 -> do+ P'.putSize (P'.wireSize 10 self')+ put'Fields+ _ -> P'.wirePutErr ft' self'+ where+ put'Fields+ = do+ P'.wirePutRep 10 11 x'1+ wireGet ft'+ = case ft' of+ 10 -> P'.getBareMessageWith update'Self+ 11 -> P'.getMessageWith update'Self+ _ -> P'.wireGetErr ft'+ where+ update'Self wire'Tag old'Self+ = case wire'Tag of+ 10 -> Prelude'.fmap (\ !new'Field -> old'Self{hints = P'.append (hints old'Self) new'Field}) (P'.wireGet 11)+ _ -> let (field'Number, wire'Type) = P'.splitWireTag wire'Tag in P'.unknown field'Number wire'Type old'Self++instance P'.MessageAPI msg' (msg' -> TunnelInfoChain) TunnelInfoChain where+ getVal m' f' = f' m'++instance P'.GPB TunnelInfoChain++instance P'.ReflectDescriptor TunnelInfoChain where+ getMessageInfo _ = P'.GetMessageInfo (P'.fromDistinctAscList []) (P'.fromDistinctAscList [10])+ reflectDescriptorInfo _+ = Prelude'.read+ "DescriptorInfo {descName = ProtoName {protobufName = FIName \".HomomPRF.TunnelInfoChain\", haskellPrefix = [MName \"Crypto\",MName \"Proto\"], parentModule = [MName \"HomomPRF\"], baseName = MName \"TunnelInfoChain\"}, descFilePath = [\"Crypto\",\"Proto\",\"HomomPRF\",\"TunnelInfoChain.hs\"], isGroup = False, fields = fromList [FieldInfo {fieldName = ProtoFName {protobufName' = FIName \".HomomPRF.TunnelInfoChain.hints\", haskellPrefix' = [MName \"Crypto\",MName \"Proto\"], parentModule' = [MName \"HomomPRF\",MName \"TunnelInfoChain\"], baseName' = FName \"hints\", baseNamePrefix' = \"\"}, fieldNumber = FieldId {getFieldId = 1}, wireTag = WireTag {getWireTag = 10}, packedTag = Nothing, wireTagLength = 1, isPacked = False, isRequired = False, canRepeat = True, mightPack = False, typeCode = FieldType {getFieldType = 11}, typeName = Just (ProtoName {protobufName = FIName \".SHE.TunnelInfo\", haskellPrefix = [MName \"Crypto\",MName \"Proto\"], parentModule = [MName \"SHE\"], baseName = MName \"TunnelInfo\"}), hsRawDefault = Nothing, hsDefault = Nothing}], descOneofs = fromList [], keys = fromList [], extRanges = [], knownKeys = fromList [], storeUnknown = False, lazyFields = False, makeLenses = False}"++instance P'.TextType TunnelInfoChain where+ tellT = P'.tellSubMessage+ getT = P'.getSubMessage++instance P'.TextMsg TunnelInfoChain where+ textPut msg+ = do+ P'.tellT "hints" (hints msg)+ textGet+ = do+ mods <- P'.sepEndBy (P'.choice [parse'hints]) P'.spaces+ Prelude'.return (Prelude'.foldl (\ v f -> f v) P'.defaultValue mods)+ where+ parse'hints+ = P'.try+ (do+ v <- P'.getT "hints"+ Prelude'.return (\ o -> o{hints = P'.append (hints o) v}))
+ Crypto/Proto/SHE.hs view
@@ -0,0 +1,23 @@+{-# LANGUAGE BangPatterns, DeriveDataTypeable, DeriveGeneric, FlexibleInstances, MultiParamTypeClasses #-}+{-# OPTIONS_GHC -fno-warn-unused-imports #-}+module Crypto.Proto.SHE (protoInfo, fileDescriptorProto) where+import Prelude ((+), (/))+import qualified Prelude as Prelude'+import qualified Data.Typeable as Prelude'+import qualified GHC.Generics as Prelude'+import qualified Data.Data as Prelude'+import qualified Text.ProtocolBuffers.Header as P'+import Text.DescriptorProtos.FileDescriptorProto (FileDescriptorProto)+import Text.ProtocolBuffers.Reflections (ProtoInfo)+import qualified Text.ProtocolBuffers.WireMessage as P' (wireGet,getFromBS)++protoInfo :: ProtoInfo+protoInfo+ = Prelude'.read+ "ProtoInfo {protoMod = ProtoName {protobufName = FIName \".SHE\", haskellPrefix = [MName \"Crypto\",MName \"Proto\"], parentModule = [], baseName = MName \"SHE\"}, protoFilePath = [\"Crypto\",\"Proto\",\"SHE.hs\"], protoSource = \"SHE.proto\", extensionKeys = fromList [], messages = [DescriptorInfo {descName = ProtoName {protobufName = FIName \".SHE.SecretKey\", haskellPrefix = [MName \"Crypto\",MName \"Proto\"], parentModule = [MName \"SHE\"], baseName = MName \"SecretKey\"}, descFilePath = [\"Crypto\",\"Proto\",\"SHE\",\"SecretKey.hs\"], isGroup = False, fields = fromList [FieldInfo {fieldName = ProtoFName {protobufName' = FIName \".SHE.SecretKey.sk\", haskellPrefix' = [MName \"Crypto\",MName \"Proto\"], parentModule' = [MName \"SHE\",MName \"SecretKey\"], baseName' = FName \"sk\", baseNamePrefix' = \"\"}, fieldNumber = FieldId {getFieldId = 1}, wireTag = WireTag {getWireTag = 10}, packedTag = Nothing, wireTagLength = 1, isPacked = False, isRequired = True, canRepeat = False, mightPack = False, typeCode = FieldType {getFieldType = 11}, typeName = Just (ProtoName {protobufName = FIName \".Lol.R\", haskellPrefix = [MName \"Crypto\",MName \"Proto\"], parentModule = [MName \"Lol\"], baseName = MName \"R\"}), hsRawDefault = Nothing, hsDefault = Nothing},FieldInfo {fieldName = ProtoFName {protobufName' = FIName \".SHE.SecretKey.v\", haskellPrefix' = [MName \"Crypto\",MName \"Proto\"], parentModule' = [MName \"SHE\",MName \"SecretKey\"], baseName' = FName \"v\", baseNamePrefix' = \"\"}, fieldNumber = FieldId {getFieldId = 2}, wireTag = WireTag {getWireTag = 17}, packedTag = Nothing, wireTagLength = 1, isPacked = False, isRequired = True, canRepeat = False, mightPack = False, typeCode = FieldType {getFieldType = 1}, typeName = Nothing, hsRawDefault = Nothing, hsDefault = Nothing}], descOneofs = fromList [], keys = fromList [], extRanges = [], knownKeys = fromList [], storeUnknown = False, lazyFields = False, makeLenses = False},DescriptorInfo {descName = ProtoName {protobufName = FIName \".SHE.RqPolynomial\", haskellPrefix = [MName \"Crypto\",MName \"Proto\"], parentModule = [MName \"SHE\"], baseName = MName \"RqPolynomial\"}, descFilePath = [\"Crypto\",\"Proto\",\"SHE\",\"RqPolynomial.hs\"], isGroup = False, fields = fromList [FieldInfo {fieldName = ProtoFName {protobufName' = FIName \".SHE.RqPolynomial.coeffs\", haskellPrefix' = [MName \"Crypto\",MName \"Proto\"], parentModule' = [MName \"SHE\",MName \"RqPolynomial\"], baseName' = FName \"coeffs\", baseNamePrefix' = \"\"}, fieldNumber = FieldId {getFieldId = 1}, wireTag = WireTag {getWireTag = 10}, packedTag = Nothing, wireTagLength = 1, isPacked = False, isRequired = False, canRepeat = True, mightPack = False, typeCode = FieldType {getFieldType = 11}, typeName = Just (ProtoName {protobufName = FIName \".Lol.RqProduct\", haskellPrefix = [MName \"Crypto\",MName \"Proto\"], parentModule = [MName \"Lol\"], baseName = MName \"RqProduct\"}), hsRawDefault = Nothing, hsDefault = Nothing}], descOneofs = fromList [], keys = fromList [], extRanges = [], knownKeys = fromList [], storeUnknown = False, lazyFields = False, makeLenses = False},DescriptorInfo {descName = ProtoName {protobufName = FIName \".SHE.KSHint\", haskellPrefix = [MName \"Crypto\",MName \"Proto\"], parentModule = [MName \"SHE\"], baseName = MName \"KSHint\"}, descFilePath = [\"Crypto\",\"Proto\",\"SHE\",\"KSHint.hs\"], isGroup = False, fields = fromList [FieldInfo {fieldName = ProtoFName {protobufName' = FIName \".SHE.KSHint.hint\", haskellPrefix' = [MName \"Crypto\",MName \"Proto\"], parentModule' = [MName \"SHE\",MName \"KSHint\"], baseName' = FName \"hint\", baseNamePrefix' = \"\"}, fieldNumber = FieldId {getFieldId = 1}, wireTag = WireTag {getWireTag = 10}, packedTag = Nothing, wireTagLength = 1, isPacked = False, isRequired = False, canRepeat = True, mightPack = False, typeCode = FieldType {getFieldType = 11}, typeName = Just (ProtoName {protobufName = FIName \".SHE.RqPolynomial\", haskellPrefix = [MName \"Crypto\",MName \"Proto\"], parentModule = [MName \"SHE\"], baseName = MName \"RqPolynomial\"}), hsRawDefault = Nothing, hsDefault = Nothing},FieldInfo {fieldName = ProtoFName {protobufName' = FIName \".SHE.KSHint.gad\", haskellPrefix' = [MName \"Crypto\",MName \"Proto\"], parentModule' = [MName \"SHE\",MName \"KSHint\"], baseName' = FName \"gad\", baseNamePrefix' = \"\"}, fieldNumber = FieldId {getFieldId = 2}, wireTag = WireTag {getWireTag = 18}, packedTag = Nothing, wireTagLength = 1, isPacked = False, isRequired = True, canRepeat = False, mightPack = False, typeCode = FieldType {getFieldType = 11}, typeName = Just (ProtoName {protobufName = FIName \".Lol.TypeRep\", haskellPrefix = [MName \"Crypto\",MName \"Proto\"], parentModule = [MName \"Lol\"], baseName = MName \"TypeRep\"}), hsRawDefault = Nothing, hsDefault = Nothing}], descOneofs = fromList [], keys = fromList [], extRanges = [], knownKeys = fromList [], storeUnknown = False, lazyFields = False, makeLenses = False},DescriptorInfo {descName = ProtoName {protobufName = FIName \".SHE.TunnelInfo\", haskellPrefix = [MName \"Crypto\",MName \"Proto\"], parentModule = [MName \"SHE\"], baseName = MName \"TunnelInfo\"}, descFilePath = [\"Crypto\",\"Proto\",\"SHE\",\"TunnelInfo.hs\"], isGroup = False, fields = fromList [FieldInfo {fieldName = ProtoFName {protobufName' = FIName \".SHE.TunnelInfo.func\", haskellPrefix' = [MName \"Crypto\",MName \"Proto\"], parentModule' = [MName \"SHE\",MName \"TunnelInfo\"], baseName' = FName \"func\", baseNamePrefix' = \"\"}, fieldNumber = FieldId {getFieldId = 1}, wireTag = WireTag {getWireTag = 10}, packedTag = Nothing, wireTagLength = 1, isPacked = False, isRequired = True, canRepeat = False, mightPack = False, typeCode = FieldType {getFieldType = 11}, typeName = Just (ProtoName {protobufName = FIName \".Lol.LinearRq\", haskellPrefix = [MName \"Crypto\",MName \"Proto\"], parentModule = [MName \"Lol\"], baseName = MName \"LinearRq\"}), hsRawDefault = Nothing, hsDefault = Nothing},FieldInfo {fieldName = ProtoFName {protobufName' = FIName \".SHE.TunnelInfo.hint\", haskellPrefix' = [MName \"Crypto\",MName \"Proto\"], parentModule' = [MName \"SHE\",MName \"TunnelInfo\"], baseName' = FName \"hint\", baseNamePrefix' = \"\"}, fieldNumber = FieldId {getFieldId = 2}, wireTag = WireTag {getWireTag = 18}, packedTag = Nothing, wireTagLength = 1, isPacked = False, isRequired = False, canRepeat = True, mightPack = False, typeCode = FieldType {getFieldType = 11}, typeName = Just (ProtoName {protobufName = FIName \".SHE.KSHint\", haskellPrefix = [MName \"Crypto\",MName \"Proto\"], parentModule = [MName \"SHE\"], baseName = MName \"KSHint\"}), hsRawDefault = Nothing, hsDefault = Nothing},FieldInfo {fieldName = ProtoFName {protobufName' = FIName \".SHE.TunnelInfo.e\", haskellPrefix' = [MName \"Crypto\",MName \"Proto\"], parentModule' = [MName \"SHE\",MName \"TunnelInfo\"], baseName' = FName \"e\", baseNamePrefix' = \"\"}, fieldNumber = FieldId {getFieldId = 3}, wireTag = WireTag {getWireTag = 24}, packedTag = Nothing, wireTagLength = 1, isPacked = False, isRequired = True, canRepeat = False, mightPack = False, typeCode = FieldType {getFieldType = 13}, typeName = Nothing, hsRawDefault = Nothing, hsDefault = Nothing},FieldInfo {fieldName = ProtoFName {protobufName' = FIName \".SHE.TunnelInfo.r\", haskellPrefix' = [MName \"Crypto\",MName \"Proto\"], parentModule' = [MName \"SHE\",MName \"TunnelInfo\"], baseName' = FName \"r\", baseNamePrefix' = \"\"}, fieldNumber = FieldId {getFieldId = 4}, wireTag = WireTag {getWireTag = 32}, packedTag = Nothing, wireTagLength = 1, isPacked = False, isRequired = True, canRepeat = False, mightPack = False, typeCode = FieldType {getFieldType = 13}, typeName = Nothing, hsRawDefault = Nothing, hsDefault = Nothing},FieldInfo {fieldName = ProtoFName {protobufName' = FIName \".SHE.TunnelInfo.s\", haskellPrefix' = [MName \"Crypto\",MName \"Proto\"], parentModule' = [MName \"SHE\",MName \"TunnelInfo\"], baseName' = FName \"s\", baseNamePrefix' = \"\"}, fieldNumber = FieldId {getFieldId = 5}, wireTag = WireTag {getWireTag = 40}, packedTag = Nothing, wireTagLength = 1, isPacked = False, isRequired = True, canRepeat = False, mightPack = False, typeCode = FieldType {getFieldType = 13}, typeName = Nothing, hsRawDefault = Nothing, hsDefault = Nothing},FieldInfo {fieldName = ProtoFName {protobufName' = FIName \".SHE.TunnelInfo.p\", haskellPrefix' = [MName \"Crypto\",MName \"Proto\"], parentModule' = [MName \"SHE\",MName \"TunnelInfo\"], baseName' = FName \"p\", baseNamePrefix' = \"\"}, fieldNumber = FieldId {getFieldId = 6}, wireTag = WireTag {getWireTag = 48}, packedTag = Nothing, wireTagLength = 1, isPacked = False, isRequired = True, canRepeat = False, mightPack = False, typeCode = FieldType {getFieldType = 4}, typeName = Nothing, hsRawDefault = Nothing, hsDefault = Nothing}], descOneofs = fromList [], keys = fromList [], extRanges = [], knownKeys = fromList [], storeUnknown = False, lazyFields = False, makeLenses = False}], enums = [], oneofs = [], knownKeyMap = fromList []}"++fileDescriptorProto :: FileDescriptorProto+fileDescriptorProto+ = P'.getFromBS (P'.wireGet 11)+ (P'.pack+ "\170\STX\n\tSHE.proto\SUB\tLol.proto\"*\n\tSecretKey\DC2\DC2\n\STXsk\CAN\SOH \STX(\v2\ACK.Lol.R\DC2\t\n\SOHv\CAN\STX \STX(\SOH\".\n\fRqPolynomial\DC2\RS\n\ACKcoeffs\CAN\SOH \ETX(\v2\SO.Lol.RqProduct\"D\n\ACKKSHint\DC2\US\n\EOThint\CAN\SOH \ETX(\v2\DC1.SHE.RqPolynomial\DC2\EM\n\ETXgad\CAN\STX \STX(\v2\f.Lol.TypeRep\"p\n\nTunnelInfo\DC2\ESC\n\EOTfunc\CAN\SOH \STX(\v2\r.Lol.LinearRq\DC2\EM\n\EOThint\CAN\STX \ETX(\v2\v.SHE.KSHint\DC2\t\n\SOHe\CAN\ETX \STX(\r\DC2\t\n\SOHr\CAN\EOT \STX(\r\DC2\t\n\SOHs\CAN\ENQ \STX(\r\DC2\t\n\SOHp\CAN\ACK \STX(\EOT")
+ Crypto/Proto/SHE/KSHint.hs view
@@ -0,0 +1,88 @@+{-# LANGUAGE BangPatterns, DeriveDataTypeable, DeriveGeneric, FlexibleInstances, MultiParamTypeClasses #-}+{-# OPTIONS_GHC -fno-warn-unused-imports #-}+module Crypto.Proto.SHE.KSHint (KSHint(..)) where+import Prelude ((+), (/))+import qualified Prelude as Prelude'+import qualified Data.Typeable as Prelude'+import qualified GHC.Generics as Prelude'+import qualified Data.Data as Prelude'+import qualified Text.ProtocolBuffers.Header as P'+import qualified Crypto.Proto.Lol.TypeRep as Lol (TypeRep)+import qualified Crypto.Proto.SHE.RqPolynomial as SHE (RqPolynomial)++data KSHint = KSHint{hint :: !(P'.Seq SHE.RqPolynomial), gad :: !(Lol.TypeRep)}+ deriving (Prelude'.Show, Prelude'.Eq, Prelude'.Ord, Prelude'.Typeable, Prelude'.Data, Prelude'.Generic)++instance P'.Mergeable KSHint where+ mergeAppend (KSHint x'1 x'2) (KSHint y'1 y'2) = KSHint (P'.mergeAppend x'1 y'1) (P'.mergeAppend x'2 y'2)++instance P'.Default KSHint where+ defaultValue = KSHint P'.defaultValue P'.defaultValue++instance P'.Wire KSHint where+ wireSize ft' self'@(KSHint x'1 x'2)+ = case ft' of+ 10 -> calc'Size+ 11 -> P'.prependMessageSize calc'Size+ _ -> P'.wireSizeErr ft' self'+ where+ calc'Size = (P'.wireSizeRep 1 11 x'1 + P'.wireSizeReq 1 11 x'2)+ wirePut ft' self'@(KSHint x'1 x'2)+ = case ft' of+ 10 -> put'Fields+ 11 -> do+ P'.putSize (P'.wireSize 10 self')+ put'Fields+ _ -> P'.wirePutErr ft' self'+ where+ put'Fields+ = do+ P'.wirePutRep 10 11 x'1+ P'.wirePutReq 18 11 x'2+ wireGet ft'+ = case ft' of+ 10 -> P'.getBareMessageWith update'Self+ 11 -> P'.getMessageWith update'Self+ _ -> P'.wireGetErr ft'+ where+ update'Self wire'Tag old'Self+ = case wire'Tag of+ 10 -> Prelude'.fmap (\ !new'Field -> old'Self{hint = P'.append (hint old'Self) new'Field}) (P'.wireGet 11)+ 18 -> Prelude'.fmap (\ !new'Field -> old'Self{gad = P'.mergeAppend (gad old'Self) (new'Field)}) (P'.wireGet 11)+ _ -> let (field'Number, wire'Type) = P'.splitWireTag wire'Tag in P'.unknown field'Number wire'Type old'Self++instance P'.MessageAPI msg' (msg' -> KSHint) KSHint where+ getVal m' f' = f' m'++instance P'.GPB KSHint++instance P'.ReflectDescriptor KSHint where+ getMessageInfo _ = P'.GetMessageInfo (P'.fromDistinctAscList [18]) (P'.fromDistinctAscList [10, 18])+ reflectDescriptorInfo _+ = Prelude'.read+ "DescriptorInfo {descName = ProtoName {protobufName = FIName \".SHE.KSHint\", haskellPrefix = [MName \"Crypto\",MName \"Proto\"], parentModule = [MName \"SHE\"], baseName = MName \"KSHint\"}, descFilePath = [\"Crypto\",\"Proto\",\"SHE\",\"KSHint.hs\"], isGroup = False, fields = fromList [FieldInfo {fieldName = ProtoFName {protobufName' = FIName \".SHE.KSHint.hint\", haskellPrefix' = [MName \"Crypto\",MName \"Proto\"], parentModule' = [MName \"SHE\",MName \"KSHint\"], baseName' = FName \"hint\", baseNamePrefix' = \"\"}, fieldNumber = FieldId {getFieldId = 1}, wireTag = WireTag {getWireTag = 10}, packedTag = Nothing, wireTagLength = 1, isPacked = False, isRequired = False, canRepeat = True, mightPack = False, typeCode = FieldType {getFieldType = 11}, typeName = Just (ProtoName {protobufName = FIName \".SHE.RqPolynomial\", haskellPrefix = [MName \"Crypto\",MName \"Proto\"], parentModule = [MName \"SHE\"], baseName = MName \"RqPolynomial\"}), hsRawDefault = Nothing, hsDefault = Nothing},FieldInfo {fieldName = ProtoFName {protobufName' = FIName \".SHE.KSHint.gad\", haskellPrefix' = [MName \"Crypto\",MName \"Proto\"], parentModule' = [MName \"SHE\",MName \"KSHint\"], baseName' = FName \"gad\", baseNamePrefix' = \"\"}, fieldNumber = FieldId {getFieldId = 2}, wireTag = WireTag {getWireTag = 18}, packedTag = Nothing, wireTagLength = 1, isPacked = False, isRequired = True, canRepeat = False, mightPack = False, typeCode = FieldType {getFieldType = 11}, typeName = Just (ProtoName {protobufName = FIName \".Lol.TypeRep\", haskellPrefix = [MName \"Crypto\",MName \"Proto\"], parentModule = [MName \"Lol\"], baseName = MName \"TypeRep\"}), hsRawDefault = Nothing, hsDefault = Nothing}], descOneofs = fromList [], keys = fromList [], extRanges = [], knownKeys = fromList [], storeUnknown = False, lazyFields = False, makeLenses = False}"++instance P'.TextType KSHint where+ tellT = P'.tellSubMessage+ getT = P'.getSubMessage++instance P'.TextMsg KSHint where+ textPut msg+ = do+ P'.tellT "hint" (hint msg)+ P'.tellT "gad" (gad msg)+ textGet+ = do+ mods <- P'.sepEndBy (P'.choice [parse'hint, parse'gad]) P'.spaces+ Prelude'.return (Prelude'.foldl (\ v f -> f v) P'.defaultValue mods)+ where+ parse'hint+ = P'.try+ (do+ v <- P'.getT "hint"+ Prelude'.return (\ o -> o{hint = P'.append (hint o) v}))+ parse'gad+ = P'.try+ (do+ v <- P'.getT "gad"+ Prelude'.return (\ o -> o{gad = v}))
+ Crypto/Proto/SHE/RqPolynomial.hs view
@@ -0,0 +1,79 @@+{-# LANGUAGE BangPatterns, DeriveDataTypeable, DeriveGeneric, FlexibleInstances, MultiParamTypeClasses #-}+{-# OPTIONS_GHC -fno-warn-unused-imports #-}+module Crypto.Proto.SHE.RqPolynomial (RqPolynomial(..)) where+import Prelude ((+), (/))+import qualified Prelude as Prelude'+import qualified Data.Typeable as Prelude'+import qualified GHC.Generics as Prelude'+import qualified Data.Data as Prelude'+import qualified Text.ProtocolBuffers.Header as P'+import qualified Crypto.Proto.Lol.RqProduct as Lol (RqProduct)++data RqPolynomial = RqPolynomial{coeffs :: !(P'.Seq Lol.RqProduct)}+ deriving (Prelude'.Show, Prelude'.Eq, Prelude'.Ord, Prelude'.Typeable, Prelude'.Data, Prelude'.Generic)++instance P'.Mergeable RqPolynomial where+ mergeAppend (RqPolynomial x'1) (RqPolynomial y'1) = RqPolynomial (P'.mergeAppend x'1 y'1)++instance P'.Default RqPolynomial where+ defaultValue = RqPolynomial P'.defaultValue++instance P'.Wire RqPolynomial where+ wireSize ft' self'@(RqPolynomial x'1)+ = case ft' of+ 10 -> calc'Size+ 11 -> P'.prependMessageSize calc'Size+ _ -> P'.wireSizeErr ft' self'+ where+ calc'Size = (P'.wireSizeRep 1 11 x'1)+ wirePut ft' self'@(RqPolynomial x'1)+ = case ft' of+ 10 -> put'Fields+ 11 -> do+ P'.putSize (P'.wireSize 10 self')+ put'Fields+ _ -> P'.wirePutErr ft' self'+ where+ put'Fields+ = do+ P'.wirePutRep 10 11 x'1+ wireGet ft'+ = case ft' of+ 10 -> P'.getBareMessageWith update'Self+ 11 -> P'.getMessageWith update'Self+ _ -> P'.wireGetErr ft'+ where+ update'Self wire'Tag old'Self+ = case wire'Tag of+ 10 -> Prelude'.fmap (\ !new'Field -> old'Self{coeffs = P'.append (coeffs old'Self) new'Field}) (P'.wireGet 11)+ _ -> let (field'Number, wire'Type) = P'.splitWireTag wire'Tag in P'.unknown field'Number wire'Type old'Self++instance P'.MessageAPI msg' (msg' -> RqPolynomial) RqPolynomial where+ getVal m' f' = f' m'++instance P'.GPB RqPolynomial++instance P'.ReflectDescriptor RqPolynomial where+ getMessageInfo _ = P'.GetMessageInfo (P'.fromDistinctAscList []) (P'.fromDistinctAscList [10])+ reflectDescriptorInfo _+ = Prelude'.read+ "DescriptorInfo {descName = ProtoName {protobufName = FIName \".SHE.RqPolynomial\", haskellPrefix = [MName \"Crypto\",MName \"Proto\"], parentModule = [MName \"SHE\"], baseName = MName \"RqPolynomial\"}, descFilePath = [\"Crypto\",\"Proto\",\"SHE\",\"RqPolynomial.hs\"], isGroup = False, fields = fromList [FieldInfo {fieldName = ProtoFName {protobufName' = FIName \".SHE.RqPolynomial.coeffs\", haskellPrefix' = [MName \"Crypto\",MName \"Proto\"], parentModule' = [MName \"SHE\",MName \"RqPolynomial\"], baseName' = FName \"coeffs\", baseNamePrefix' = \"\"}, fieldNumber = FieldId {getFieldId = 1}, wireTag = WireTag {getWireTag = 10}, packedTag = Nothing, wireTagLength = 1, isPacked = False, isRequired = False, canRepeat = True, mightPack = False, typeCode = FieldType {getFieldType = 11}, typeName = Just (ProtoName {protobufName = FIName \".Lol.RqProduct\", haskellPrefix = [MName \"Crypto\",MName \"Proto\"], parentModule = [MName \"Lol\"], baseName = MName \"RqProduct\"}), hsRawDefault = Nothing, hsDefault = Nothing}], descOneofs = fromList [], keys = fromList [], extRanges = [], knownKeys = fromList [], storeUnknown = False, lazyFields = False, makeLenses = False}"++instance P'.TextType RqPolynomial where+ tellT = P'.tellSubMessage+ getT = P'.getSubMessage++instance P'.TextMsg RqPolynomial where+ textPut msg+ = do+ P'.tellT "coeffs" (coeffs msg)+ textGet+ = do+ mods <- P'.sepEndBy (P'.choice [parse'coeffs]) P'.spaces+ Prelude'.return (Prelude'.foldl (\ v f -> f v) P'.defaultValue mods)+ where+ parse'coeffs+ = P'.try+ (do+ v <- P'.getT "coeffs"+ Prelude'.return (\ o -> o{coeffs = P'.append (coeffs o) v}))
+ Crypto/Proto/SHE/SecretKey.hs view
@@ -0,0 +1,87 @@+{-# LANGUAGE BangPatterns, DeriveDataTypeable, DeriveGeneric, FlexibleInstances, MultiParamTypeClasses #-}+{-# OPTIONS_GHC -fno-warn-unused-imports #-}+module Crypto.Proto.SHE.SecretKey (SecretKey(..)) where+import Prelude ((+), (/))+import qualified Prelude as Prelude'+import qualified Data.Typeable as Prelude'+import qualified GHC.Generics as Prelude'+import qualified Data.Data as Prelude'+import qualified Text.ProtocolBuffers.Header as P'+import qualified Crypto.Proto.Lol.R as Lol (R)++data SecretKey = SecretKey{sk :: !(Lol.R), v :: !(P'.Double)}+ deriving (Prelude'.Show, Prelude'.Eq, Prelude'.Ord, Prelude'.Typeable, Prelude'.Data, Prelude'.Generic)++instance P'.Mergeable SecretKey where+ mergeAppend (SecretKey x'1 x'2) (SecretKey y'1 y'2) = SecretKey (P'.mergeAppend x'1 y'1) (P'.mergeAppend x'2 y'2)++instance P'.Default SecretKey where+ defaultValue = SecretKey P'.defaultValue P'.defaultValue++instance P'.Wire SecretKey where+ wireSize ft' self'@(SecretKey x'1 x'2)+ = case ft' of+ 10 -> calc'Size+ 11 -> P'.prependMessageSize calc'Size+ _ -> P'.wireSizeErr ft' self'+ where+ calc'Size = (P'.wireSizeReq 1 11 x'1 + P'.wireSizeReq 1 1 x'2)+ wirePut ft' self'@(SecretKey x'1 x'2)+ = case ft' of+ 10 -> put'Fields+ 11 -> do+ P'.putSize (P'.wireSize 10 self')+ put'Fields+ _ -> P'.wirePutErr ft' self'+ where+ put'Fields+ = do+ P'.wirePutReq 10 11 x'1+ P'.wirePutReq 17 1 x'2+ wireGet ft'+ = case ft' of+ 10 -> P'.getBareMessageWith update'Self+ 11 -> P'.getMessageWith update'Self+ _ -> P'.wireGetErr ft'+ where+ update'Self wire'Tag old'Self+ = case wire'Tag of+ 10 -> Prelude'.fmap (\ !new'Field -> old'Self{sk = P'.mergeAppend (sk old'Self) (new'Field)}) (P'.wireGet 11)+ 17 -> Prelude'.fmap (\ !new'Field -> old'Self{v = new'Field}) (P'.wireGet 1)+ _ -> let (field'Number, wire'Type) = P'.splitWireTag wire'Tag in P'.unknown field'Number wire'Type old'Self++instance P'.MessageAPI msg' (msg' -> SecretKey) SecretKey where+ getVal m' f' = f' m'++instance P'.GPB SecretKey++instance P'.ReflectDescriptor SecretKey where+ getMessageInfo _ = P'.GetMessageInfo (P'.fromDistinctAscList [10, 17]) (P'.fromDistinctAscList [10, 17])+ reflectDescriptorInfo _+ = Prelude'.read+ "DescriptorInfo {descName = ProtoName {protobufName = FIName \".SHE.SecretKey\", haskellPrefix = [MName \"Crypto\",MName \"Proto\"], parentModule = [MName \"SHE\"], baseName = MName \"SecretKey\"}, descFilePath = [\"Crypto\",\"Proto\",\"SHE\",\"SecretKey.hs\"], isGroup = False, fields = fromList [FieldInfo {fieldName = ProtoFName {protobufName' = FIName \".SHE.SecretKey.sk\", haskellPrefix' = [MName \"Crypto\",MName \"Proto\"], parentModule' = [MName \"SHE\",MName \"SecretKey\"], baseName' = FName \"sk\", baseNamePrefix' = \"\"}, fieldNumber = FieldId {getFieldId = 1}, wireTag = WireTag {getWireTag = 10}, packedTag = Nothing, wireTagLength = 1, isPacked = False, isRequired = True, canRepeat = False, mightPack = False, typeCode = FieldType {getFieldType = 11}, typeName = Just (ProtoName {protobufName = FIName \".Lol.R\", haskellPrefix = [MName \"Crypto\",MName \"Proto\"], parentModule = [MName \"Lol\"], baseName = MName \"R\"}), hsRawDefault = Nothing, hsDefault = Nothing},FieldInfo {fieldName = ProtoFName {protobufName' = FIName \".SHE.SecretKey.v\", haskellPrefix' = [MName \"Crypto\",MName \"Proto\"], parentModule' = [MName \"SHE\",MName \"SecretKey\"], baseName' = FName \"v\", baseNamePrefix' = \"\"}, fieldNumber = FieldId {getFieldId = 2}, wireTag = WireTag {getWireTag = 17}, packedTag = Nothing, wireTagLength = 1, isPacked = False, isRequired = True, canRepeat = False, mightPack = False, typeCode = FieldType {getFieldType = 1}, typeName = Nothing, hsRawDefault = Nothing, hsDefault = Nothing}], descOneofs = fromList [], keys = fromList [], extRanges = [], knownKeys = fromList [], storeUnknown = False, lazyFields = False, makeLenses = False}"++instance P'.TextType SecretKey where+ tellT = P'.tellSubMessage+ getT = P'.getSubMessage++instance P'.TextMsg SecretKey where+ textPut msg+ = do+ P'.tellT "sk" (sk msg)+ P'.tellT "v" (v msg)+ textGet+ = do+ mods <- P'.sepEndBy (P'.choice [parse'sk, parse'v]) P'.spaces+ Prelude'.return (Prelude'.foldl (\ v f -> f v) P'.defaultValue mods)+ where+ parse'sk+ = P'.try+ (do+ v <- P'.getT "sk"+ Prelude'.return (\ o -> o{sk = v}))+ parse'v+ = P'.try+ (do+ v <- P'.getT "v"+ Prelude'.return (\ o -> o{v = v}))
+ Crypto/Proto/SHE/TunnelInfo.hs view
@@ -0,0 +1,128 @@+{-# LANGUAGE BangPatterns, DeriveDataTypeable, DeriveGeneric, FlexibleInstances, MultiParamTypeClasses #-}+{-# OPTIONS_GHC -fno-warn-unused-imports #-}+module Crypto.Proto.SHE.TunnelInfo (TunnelInfo(..)) where+import Prelude ((+), (/))+import qualified Prelude as Prelude'+import qualified Data.Typeable as Prelude'+import qualified GHC.Generics as Prelude'+import qualified Data.Data as Prelude'+import qualified Text.ProtocolBuffers.Header as P'+import qualified Crypto.Proto.Lol.LinearRq as Lol (LinearRq)+import qualified Crypto.Proto.SHE.KSHint as SHE (KSHint)++data TunnelInfo = TunnelInfo{func :: !(Lol.LinearRq), hint :: !(P'.Seq SHE.KSHint), e :: !(P'.Word32), r :: !(P'.Word32),+ s :: !(P'.Word32), p :: !(P'.Word64)}+ deriving (Prelude'.Show, Prelude'.Eq, Prelude'.Ord, Prelude'.Typeable, Prelude'.Data, Prelude'.Generic)++instance P'.Mergeable TunnelInfo where+ mergeAppend (TunnelInfo x'1 x'2 x'3 x'4 x'5 x'6) (TunnelInfo y'1 y'2 y'3 y'4 y'5 y'6)+ = TunnelInfo (P'.mergeAppend x'1 y'1) (P'.mergeAppend x'2 y'2) (P'.mergeAppend x'3 y'3) (P'.mergeAppend x'4 y'4)+ (P'.mergeAppend x'5 y'5)+ (P'.mergeAppend x'6 y'6)++instance P'.Default TunnelInfo where+ defaultValue = TunnelInfo P'.defaultValue P'.defaultValue P'.defaultValue P'.defaultValue P'.defaultValue P'.defaultValue++instance P'.Wire TunnelInfo where+ wireSize ft' self'@(TunnelInfo x'1 x'2 x'3 x'4 x'5 x'6)+ = case ft' of+ 10 -> calc'Size+ 11 -> P'.prependMessageSize calc'Size+ _ -> P'.wireSizeErr ft' self'+ where+ calc'Size+ = (P'.wireSizeReq 1 11 x'1 + P'.wireSizeRep 1 11 x'2 + P'.wireSizeReq 1 13 x'3 + P'.wireSizeReq 1 13 x'4 ++ P'.wireSizeReq 1 13 x'5+ + P'.wireSizeReq 1 4 x'6)+ wirePut ft' self'@(TunnelInfo x'1 x'2 x'3 x'4 x'5 x'6)+ = case ft' of+ 10 -> put'Fields+ 11 -> do+ P'.putSize (P'.wireSize 10 self')+ put'Fields+ _ -> P'.wirePutErr ft' self'+ where+ put'Fields+ = do+ P'.wirePutReq 10 11 x'1+ P'.wirePutRep 18 11 x'2+ P'.wirePutReq 24 13 x'3+ P'.wirePutReq 32 13 x'4+ P'.wirePutReq 40 13 x'5+ P'.wirePutReq 48 4 x'6+ wireGet ft'+ = case ft' of+ 10 -> P'.getBareMessageWith update'Self+ 11 -> P'.getMessageWith update'Self+ _ -> P'.wireGetErr ft'+ where+ update'Self wire'Tag old'Self+ = case wire'Tag of+ 10 -> Prelude'.fmap (\ !new'Field -> old'Self{func = P'.mergeAppend (func old'Self) (new'Field)}) (P'.wireGet 11)+ 18 -> Prelude'.fmap (\ !new'Field -> old'Self{hint = P'.append (hint old'Self) new'Field}) (P'.wireGet 11)+ 24 -> Prelude'.fmap (\ !new'Field -> old'Self{e = new'Field}) (P'.wireGet 13)+ 32 -> Prelude'.fmap (\ !new'Field -> old'Self{r = new'Field}) (P'.wireGet 13)+ 40 -> Prelude'.fmap (\ !new'Field -> old'Self{s = new'Field}) (P'.wireGet 13)+ 48 -> Prelude'.fmap (\ !new'Field -> old'Self{p = new'Field}) (P'.wireGet 4)+ _ -> let (field'Number, wire'Type) = P'.splitWireTag wire'Tag in P'.unknown field'Number wire'Type old'Self++instance P'.MessageAPI msg' (msg' -> TunnelInfo) TunnelInfo where+ getVal m' f' = f' m'++instance P'.GPB TunnelInfo++instance P'.ReflectDescriptor TunnelInfo where+ getMessageInfo _+ = P'.GetMessageInfo (P'.fromDistinctAscList [10, 24, 32, 40, 48]) (P'.fromDistinctAscList [10, 18, 24, 32, 40, 48])+ reflectDescriptorInfo _+ = Prelude'.read+ "DescriptorInfo {descName = ProtoName {protobufName = FIName \".SHE.TunnelInfo\", haskellPrefix = [MName \"Crypto\",MName \"Proto\"], parentModule = [MName \"SHE\"], baseName = MName \"TunnelInfo\"}, descFilePath = [\"Crypto\",\"Proto\",\"SHE\",\"TunnelInfo.hs\"], isGroup = False, fields = fromList [FieldInfo {fieldName = ProtoFName {protobufName' = FIName \".SHE.TunnelInfo.func\", haskellPrefix' = [MName \"Crypto\",MName \"Proto\"], parentModule' = [MName \"SHE\",MName \"TunnelInfo\"], baseName' = FName \"func\", baseNamePrefix' = \"\"}, fieldNumber = FieldId {getFieldId = 1}, wireTag = WireTag {getWireTag = 10}, packedTag = Nothing, wireTagLength = 1, isPacked = False, isRequired = True, canRepeat = False, mightPack = False, typeCode = FieldType {getFieldType = 11}, typeName = Just (ProtoName {protobufName = FIName \".Lol.LinearRq\", haskellPrefix = [MName \"Crypto\",MName \"Proto\"], parentModule = [MName \"Lol\"], baseName = MName \"LinearRq\"}), hsRawDefault = Nothing, hsDefault = Nothing},FieldInfo {fieldName = ProtoFName {protobufName' = FIName \".SHE.TunnelInfo.hint\", haskellPrefix' = [MName \"Crypto\",MName \"Proto\"], parentModule' = [MName \"SHE\",MName \"TunnelInfo\"], baseName' = FName \"hint\", baseNamePrefix' = \"\"}, fieldNumber = FieldId {getFieldId = 2}, wireTag = WireTag {getWireTag = 18}, packedTag = Nothing, wireTagLength = 1, isPacked = False, isRequired = False, canRepeat = True, mightPack = False, typeCode = FieldType {getFieldType = 11}, typeName = Just (ProtoName {protobufName = FIName \".SHE.KSHint\", haskellPrefix = [MName \"Crypto\",MName \"Proto\"], parentModule = [MName \"SHE\"], baseName = MName \"KSHint\"}), hsRawDefault = Nothing, hsDefault = Nothing},FieldInfo {fieldName = ProtoFName {protobufName' = FIName \".SHE.TunnelInfo.e\", haskellPrefix' = [MName \"Crypto\",MName \"Proto\"], parentModule' = [MName \"SHE\",MName \"TunnelInfo\"], baseName' = FName \"e\", baseNamePrefix' = \"\"}, fieldNumber = FieldId {getFieldId = 3}, wireTag = WireTag {getWireTag = 24}, packedTag = Nothing, wireTagLength = 1, isPacked = False, isRequired = True, canRepeat = False, mightPack = False, typeCode = FieldType {getFieldType = 13}, typeName = Nothing, hsRawDefault = Nothing, hsDefault = Nothing},FieldInfo {fieldName = ProtoFName {protobufName' = FIName \".SHE.TunnelInfo.r\", haskellPrefix' = [MName \"Crypto\",MName \"Proto\"], parentModule' = [MName \"SHE\",MName \"TunnelInfo\"], baseName' = FName \"r\", baseNamePrefix' = \"\"}, fieldNumber = FieldId {getFieldId = 4}, wireTag = WireTag {getWireTag = 32}, packedTag = Nothing, wireTagLength = 1, isPacked = False, isRequired = True, canRepeat = False, mightPack = False, typeCode = FieldType {getFieldType = 13}, typeName = Nothing, hsRawDefault = Nothing, hsDefault = Nothing},FieldInfo {fieldName = ProtoFName {protobufName' = FIName \".SHE.TunnelInfo.s\", haskellPrefix' = [MName \"Crypto\",MName \"Proto\"], parentModule' = [MName \"SHE\",MName \"TunnelInfo\"], baseName' = FName \"s\", baseNamePrefix' = \"\"}, fieldNumber = FieldId {getFieldId = 5}, wireTag = WireTag {getWireTag = 40}, packedTag = Nothing, wireTagLength = 1, isPacked = False, isRequired = True, canRepeat = False, mightPack = False, typeCode = FieldType {getFieldType = 13}, typeName = Nothing, hsRawDefault = Nothing, hsDefault = Nothing},FieldInfo {fieldName = ProtoFName {protobufName' = FIName \".SHE.TunnelInfo.p\", haskellPrefix' = [MName \"Crypto\",MName \"Proto\"], parentModule' = [MName \"SHE\",MName \"TunnelInfo\"], baseName' = FName \"p\", baseNamePrefix' = \"\"}, fieldNumber = FieldId {getFieldId = 6}, wireTag = WireTag {getWireTag = 48}, packedTag = Nothing, wireTagLength = 1, isPacked = False, isRequired = True, canRepeat = False, mightPack = False, typeCode = FieldType {getFieldType = 4}, typeName = Nothing, hsRawDefault = Nothing, hsDefault = Nothing}], descOneofs = fromList [], keys = fromList [], extRanges = [], knownKeys = fromList [], storeUnknown = False, lazyFields = False, makeLenses = False}"++instance P'.TextType TunnelInfo where+ tellT = P'.tellSubMessage+ getT = P'.getSubMessage++instance P'.TextMsg TunnelInfo where+ textPut msg+ = do+ P'.tellT "func" (func msg)+ P'.tellT "hint" (hint msg)+ P'.tellT "e" (e msg)+ P'.tellT "r" (r msg)+ P'.tellT "s" (s msg)+ P'.tellT "p" (p msg)+ textGet+ = do+ mods <- P'.sepEndBy (P'.choice [parse'func, parse'hint, parse'e, parse'r, parse's, parse'p]) P'.spaces+ Prelude'.return (Prelude'.foldl (\ v f -> f v) P'.defaultValue mods)+ where+ parse'func+ = P'.try+ (do+ v <- P'.getT "func"+ Prelude'.return (\ o -> o{func = v}))+ parse'hint+ = P'.try+ (do+ v <- P'.getT "hint"+ Prelude'.return (\ o -> o{hint = P'.append (hint o) v}))+ parse'e+ = P'.try+ (do+ v <- P'.getT "e"+ Prelude'.return (\ o -> o{e = v}))+ parse'r+ = P'.try+ (do+ v <- P'.getT "r"+ Prelude'.return (\ o -> o{r = v}))+ parse's+ = P'.try+ (do+ v <- P'.getT "s"+ Prelude'.return (\ o -> o{s = v}))+ parse'p+ = P'.try+ (do+ v <- P'.getT "p"+ Prelude'.return (\ o -> o{p = v}))
+ HomomPRF.proto view
@@ -0,0 +1,26 @@+// proto messages for precomputation step of homomorphic PRF+// evaluation and testing++// These messages are just repeated messages from SHE.proto, used when multiple+// operations (on different types) are done in sequence. This avoids having+// to load messages for each step of a computation, which could be error prone+// since the messages are type-specific.++import "Lol.proto";+import "SHE.proto";++// run this:++// hprotoc -I ../lol -a Lol.proto=Crypto.Proto -a SHE.proto=Crypto.Proto -p Crypto.Proto HomomPRF.proto++message LinearFuncChain {+ repeated LinearRq funcs = 1;+}++message TunnelInfoChain {+ repeated TunnelInfo hints = 1;+}++message RoundHintChain {+ repeated KSHint hints = 1;+}
README view
@@ -3,3 +3,15 @@ * SymmSHE.hs gives an implementation of a symmetric-key, somewhat-homomorphic encryption scheme that is essentially equivalent to the one from the toolkit paper [LPR'13].++* KeyHomomorphicPRF.hs gives an implementation of the+ key-homomorphic pseudo-random function from Banerjee+ and Peikert in Crypto 2014 ([BP14]).++* HomomPRF provides an interface for the homomorphic evaluation of the [BP14]+ PRF.++Note that an example using each application can be found in the 'examples'+directory. Tests and benchmarks for SHE and KeyHomomorphicPRF are provided in+the 'tests' and 'benchmarks' directories. Tests and benchmarks for HomomPRF are+included in the example for HomomPRF.
+ SHE.proto view
@@ -0,0 +1,33 @@+// proto messages for key switch hints and secret keys from SymmSHE++import "Lol.proto";++// run this:++// hprotoc -I ../lol -a Lol.proto=Crypto.Proto -p Crypto.Proto SHE.proto++message SecretKey {+ required R sk = 1; // ring element+ required double v = 2; // scaled variance+}++// internally used in KSHint+message RqPolynomial {+ repeated RqProduct coeffs = 1; // constant coefficient first, then linear, etc.+}++// linear or quadratic key switch hint+message KSHint {+ repeated RqPolynomial hint = 1;+ required TypeRep gad = 2; // gadget used for key switching+}++// information for a single ring switch+message TunnelInfo {+ required LinearRq func = 1; // linear function to apply+ repeated KSHint hint = 2;+ required uint32 e = 3; // index of greatest common subring of r and s+ required uint32 r = 4; // input ring index+ required uint32 s = 5; // output ring index+ required uint64 p = 6; // plaintext modulus+}
+ benchmarks/BenchAppsMain.hs view
@@ -0,0 +1,125 @@+{-|+Module : BenchAppsMain+Description : Main driver for lol-apps benchmarks.+Copyright : (c) Eric Crockett, 2011-2017+ Chris Peikert, 2011-2017+License : GPL-2+Maintainer : ecrockett0@email.com+Stability : experimental+Portability : POSIX++Main driver for lol-apps benchmarks.+-}++{-# LANGUAGE DataKinds #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE PartialTypeSignatures #-}+{-# LANGUAGE PolyKinds #-}+{-# LANGUAGE RebindableSyntax #-}+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE TypeFamilies #-}+{-# LANGUAGE TypeOperators #-}++{-# OPTIONS_GHC -fno-warn-partial-type-signatures #-}++module BenchAppsMain where++import Control.Applicative+import Control.Monad.Random++import Crypto.Lol+import Crypto.Lol.Applications.KeyHomomorphicPRF+import Crypto.Lol.Applications.SymmSHE hiding (CT)+import Crypto.Lol.Benchmarks+import Crypto.Lol.Cyclotomic.Tensor.CPP+import Crypto.Lol.Utils.PrettyPrint.Table+import Crypto.Lol.Types++import KHPRFBenches+import SHEBenches+import Crypto.Random.DRBG++infixr 9 **+data a ** b++type family Zq (a :: k) :: * where+ Zq (a ** b) = (Zq a, Zq b)+ Zq q = (ZqBasic q Int64)++benchNames :: [String]+benchNames = [+ "encrypt",+ "decrypt",+ "*",+ "addPublic",+ "mulPublic",+ "rescaleCT",+ "keySwitch",+ "tunnel",+ "balanced-startup"]++main :: IO ()+main = do+ let o = (defaultOpts Nothing){benches=[]}+ pct = Proxy::Proxy CT+ bs <- sequence $+ sheBenches' pct (Proxy::Proxy TrivGad) (Proxy::Proxy HashDRBG) +++ [khprfBenches pct (Proxy::Proxy (BaseBGad 2))]+ mapM_ (prettyBenches o) bs++sheBenches' :: _ => Proxy t -> Proxy gad -> Proxy gen -> [rnd Benchmark]+sheBenches' pt pgad pgen = [+ benchGroup "SHE" $ ($ pt) <$>+ [sheBenches (Proxy::Proxy '(F16, F1024, Zq 8, Zq 1017857)) pgen,+ sheBenches (Proxy::Proxy '(F16, F2048, Zq 16, Zq 1017857)) pgen],+ benchGroup "Dec" $ ($ pt) <$>+ [decBenches (Proxy::Proxy '(F16, F1024, Zq 8, Zq 1017857)),+ decBenches (Proxy::Proxy '(F16, F2048, Zq 16, Zq 1017857))],+ benchGroup "Rescale" $ ($ pt) <$>+ [rescaleBenches (Proxy::Proxy '(F32, F2048, Zq 16, Zq 1017857, Zq (1017857 ** 1032193))) pgad,+ rescaleBenches (Proxy::Proxy '(F32, F64*F9*F25, Zq 16, Zq 1008001, Zq (1008001 ** 1065601))) pgad],+ benchGroup "Tunnel" $ ($ pt) <$>+ [tunnelBenches {- H0 -> H1 -} (Proxy::Proxy '(F128,+ F128 * F7 * F13,+ F64 * F7, F64 * F7 * F13,+ Zq PP32,+ Zq 3144961)) pgad,+ tunnelBenches {- H1 -> H2 -} (Proxy::Proxy '(F64 * F7,+ F64 * F7 * F13,+ F32 * F7 * F13,+ F32 * F7 * F13,+ Zq PP32,+ Zq 3144961)) pgad,+ tunnelBenches {- H2 -> H3 -} (Proxy::Proxy '(F32 * F7 * F13,+ F32 * F7 * F13,+ F8 * F5 * F7 * F13,+ F8 * F5 * F7 *F13,+ Zq PP32,+ Zq 3144961)) pgad,+ tunnelBenches {- H3 -> H4 -} (Proxy::Proxy '(F8 * F5 * F7 * F13,+ F8 * F5 * F7 *F13,+ F4 * F3 * F5 * F7 * F13,+ F4 * F3 * F5 * F7 * F13,+ Zq PP32,+ Zq 3144961)) pgad,+ tunnelBenches {- H4 -> H5 -} (Proxy::Proxy '(F4 * F3 * F5 * F7 * F13,+ F4 * F3 * F5 * F7 *F13,+ F9 * F5 * F7 * F13,+ F9 * F5 * F7 * F13,+ Zq PP32,+ Zq 3144961)) pgad]]++khprfBenches :: forall t gad rnd . (_) => Proxy t -> Proxy gad -> rnd Benchmark+khprfBenches pt _ = benchGroup "KHPRF Table"+ [benchGroup "left/KHPRF" $ benches' leftSpineTree,+ benchGroup "balanced/KHPRF" $ benches' balancedTree,+ benchGroup "right/KHPRF" $ benches' rightSpineTree]+ where+ benches' = khPRFBenches 5 pt (Proxy::Proxy F128) (Proxy::Proxy '(Zq 8, Zq 2, gad))++-- EAC: is there a simple way to parameterize the variance?+-- generates a secret key with scaled variance 1.0+instance (GenSKCtx t m' z Double) => Random (SK (Cyc t m' z)) where+ random = runRand $ genSK (1 :: Double)+ randomR = error "randomR not defined for SK"
+ benchmarks/KHPRFBenches.hs view
@@ -0,0 +1,74 @@+{-|+Module : KHPRFBenches+Description : Benchmarks for KeyHomomorphicPRF.+Copyright : (c) Eric Crockett, 2011-2017+ Chris Peikert, 2011-2017+License : GPL-2+Maintainer : ecrockett0@email.com+Stability : experimental+Portability : POSIX++Benchmarks for KeyHomomorphicPRF.+-}++{-# LANGUAGE DataKinds #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE MultiParamTypeClasses #-}+{-# LANGUAGE NoImplicitPrelude #-}+{-# LANGUAGE PartialTypeSignatures #-}+{-# LANGUAGE PolyKinds #-}+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE TypeFamilies #-}++{-# OPTIONS_GHC -fno-warn-partial-type-signatures #-}++module KHPRFBenches (khPRFBenches) where++import Control.Applicative+import Control.Monad.Random hiding (fromList)+import Control.Monad.State hiding (state)++import Crypto.Lol+import Crypto.Lol.Applications.KeyHomomorphicPRF+import Crypto.Lol.Benchmarks++import MathObj.Matrix hiding (zipWith)++khPRFBenches :: forall rnd t m zq zp gad . (MonadRandom rnd, _)+ => Int -> Proxy t -> Proxy m -> Proxy '(zq,zp,gad) -> (Int -> FullBinTree) -> [rnd Benchmark]+khPRFBenches n _ _ plwe t =+ let pcyc = Proxy::Proxy '(t,m,zq,zp,gad)+ in [+ genBenchArgs "ring-startup" (benchRingPRF n t [0]) pcyc,+ genBenchArgs "ring-amortized" (benchRingPRF n t (grayCode n)) pcyc,+ genBenchArgs "lwe-startup" (benchLatticePRF n 3 t [0]) plwe,+ genBenchArgs "lwe-amortized" (benchLatticePRF n 3 t (grayCode n)) plwe+ ]++-- benchmarks time to run the PRF on each input, including the time+-- it takes to initialize the state with input 0.+benchRingPRF :: forall t m zq (zp :: *) (gad :: *) . (_)+ => Int -> (Int -> FullBinTree) -> [Int] -> Cyc t m zq -> Bench '(t,m,zq,zp,gad)+benchRingPRF size t xs s = benchM $ do+ let gadLen = length $ untag (gadget :: Tagged gad [Cyc t m zq])+ a0 <- fromList 1 gadLen <$> take gadLen <$> getRandoms+ a1 <- fromList 1 gadLen <$> take gadLen <$> getRandoms+ let family = makeFamily a0 a1 (t size) :: PRFFamily gad (Cyc t m zq) (Cyc t m zp)+ return $ bench+ (let st = prfState family Nothing -- initialize with input 0+ in (flip evalState st . mapM (ringPRFM s))) xs++-- benchmarks time to run the PRF on each input, including the time+-- it takes to initialize the state with input 0.+benchLatticePRF :: forall (zp :: *) (zq :: *) (gad :: *) . (_)+ => Int -> Int -> (Int -> FullBinTree) -> [Int] -> Bench '(zq,zp,gad)+benchLatticePRF size n t xs = benchM $ do+ let gadLen = length $ untag (gadget :: Tagged gad [zq])+ a0 :: Matrix zq <- fromList n (n*gadLen) <$> take (gadLen*n*n) <$> getRandoms+ a1 :: Matrix zq <- fromList n (n*gadLen) <$> take (gadLen*n*n) <$> getRandoms+ s :: Matrix zq <- fromList 1 n <$> take n <$> getRandoms+ let family = makeFamily a0 a1 (t size) :: PRFFamily gad zq zp+ return $ bench+ (let state = prfState family Nothing -- initialize with input 0+ in (flip evalState state . mapM (latticePRFM s))) xs
− benchmarks/Main.hs
@@ -1,9 +0,0 @@--import SHEBenches--import Criterion.Main--main :: IO ()-main = defaultMain =<< sequence [- sheBenches- ]
benchmarks/SHEBenches.hs view
@@ -1,136 +1,151 @@-{-# LANGUAGE DataKinds, FlexibleContexts,- NoImplicitPrelude, PolyKinds, RebindableSyntax,- ScopedTypeVariables, TypeFamilies,- TypeOperators #-}+{-|+Module : SHEBenches+Description : Benchmarks for SymmSHE.+Copyright : (c) Eric Crockett, 2011-2017+ Chris Peikert, 2011-2017+License : GPL-2+Maintainer : ecrockett0@email.com+Stability : experimental+Portability : POSIX -module SHEBenches (sheBenches) where+Benchmarks for SymmSHE.+-} -import Apply.SHE-import Benchmarks hiding (hideArgs)-import GenArgs-import GenArgs.SHE-import Utils+{-# LANGUAGE DataKinds #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE PartialTypeSignatures #-}+{-# LANGUAGE PolyKinds #-}+{-# LANGUAGE RebindableSyntax #-}+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE TypeFamilies #-}+{-# LANGUAGE TypeOperators #-} +{-# OPTIONS_GHC -fno-warn-partial-type-signatures #-}++module SHEBenches (sheBenches, decBenches, rescaleBenches, tunnelBenches) where++import Crypto.Lol.Benchmarks+ import Control.Applicative import Control.Monad.Random import Control.Monad.State+import Crypto.Lol.Utils.ShowType import Crypto.Random.DRBG import Crypto.Lol import Crypto.Lol.Applications.SymmSHE-import Crypto.Lol.Types hiding (CT)-import qualified Crypto.Lol.Types as CT+import Crypto.Lol.Types+import Crypto.Lol.Types.ZPP -import qualified Criterion as C+addGen5 :: Proxy gen -> Proxy '(t,m,m',zp,zq) -> Proxy '(t,m,m',zp,zq,gen)+addGen5 _ _ = Proxy -hideArgs :: forall a rnd bnch .- (GenArgs (StateT (Maybe (SKOf a)) rnd) bnch, Monad rnd, ShowType a,- ResultOf bnch ~ Bench a)- => bnch -> Proxy a -> rnd Benchmark-hideArgs f p = (C.bench (showType p) . unbench) <$>- (evalStateT (genArgs f) (Nothing :: Maybe (SKOf a)))+addGen6 :: Proxy gad -> Proxy '(t,m,m',zp,zq,zq') -> Proxy '(t,m,m',zp,zq,zq',gad)+addGen6 _ _ = Proxy -sheBenches :: (MonadRandom m) => m Benchmark-sheBenches = benchGroup "SHE" [- benchGroup "encrypt" $ applyEnc encParams $ hideArgs bench_enc,- benchGroup "decrypt" $ applyDec decParams $ hideArgs bench_dec,- benchGroup "*" $ applyCTFunc ctParams $ hideArgs bench_mul,- benchGroup "addPublic" $ applyCTFunc ctParams $ hideArgs bench_addPublic,- benchGroup "mulPublic" $ applyCTFunc ctParams $ hideArgs bench_mulPublic,- benchGroup "dec" $ applyDec decParams $ hideArgs bench_dec,- benchGroup "rescaleCT" $ applyRescale rescaleParams $ hideArgs bench_rescaleCT,- benchGroup "keySwitch" $ applyKSQ ksqParams $ hideArgs bench_keySwQ,- benchGroup "tunnel" $ applyTunn tunnelParams $ hideArgs bench_tunnel- ]+sheBenches :: forall t m m' zp zq gen rnd . (MonadRandom rnd, _)+ => Proxy '(m,m',zp,zq) -> Proxy gen -> Proxy t -> rnd Benchmark+sheBenches _ pgen _ =+ let ptmr = Proxy :: Proxy '(t,m,m',zp,zq)+ in benchGroup (showType ptmr ++ "/SymmSHE") $ ($ ptmr) <$> [+ genBenchArgs "encrypt" bench_enc . addGen5 pgen,+ genBenchArgs "*" bench_mul,+ genBenchArgs "addPublic" bench_addPublic,+ genBenchArgs "mulPublic" bench_mulPublic+ ] -bench_enc :: forall t m m' z zp zq gen . (EncryptCtx t m m' z zp zq, CryptoRandomGen gen, z ~ LiftOf zp, NFElt zp, NFElt zq)+-- zq must be Liftable+decBenches :: forall t m m' zp zq rnd . (MonadRandom rnd, _)+ => Proxy '(m,m',zp,zq) -> Proxy t -> rnd Benchmark+decBenches _ _ =+ let ptmr = Proxy::Proxy '(t,m,m',zp,zq)+ in benchGroup (showType ptmr ++ "/SymmSHE") [genBenchArgs "decrypt" bench_dec ptmr]++-- must be able to round from zq' to zq+rescaleBenches :: forall t m m' zp zq zq' gad rnd . (MonadRandom rnd, _)+ => Proxy '(m,m',zp,zq,zq') -> Proxy gad -> Proxy t -> rnd Benchmark+rescaleBenches _ pgad _ =+ let ptmr = Proxy :: Proxy '(t,m,m',zp,zq,zq')+ in benchGroup (showType ptmr ++ "/SymmSHE") $ ($ ptmr) <$> [+ genBenchArgs "rescaleCT" bench_rescaleCT,+ genBenchArgs "keySwitchQuadCirc" bench_keySwQ . addGen6 pgad]++tunnelBenches :: forall t r r' s s' zp zq gad rnd . (MonadRandom rnd, _)+ => Proxy '(r,r',s,s',zp,zq) -> Proxy gad -> Proxy t -> rnd Benchmark+tunnelBenches _ _ _ =+ let ptmr = Proxy :: Proxy '(t,r,r',s,s',zp,zq,gad)+ in benchGroup (showType ptmr ++ "/SymmSHE") [genBenchArgs "tunnel" bench_tunnel ptmr]+++bench_enc :: forall t m m' z zp (zq :: *) (gen :: *) . (z ~ LiftOf zp, _) => SK (Cyc t m' z) -> PT (Cyc t m zp) -> Bench '(t,m,m',zp,zq,gen) bench_enc sk pt = benchIO $ do gen <- newGenIO return $ evalRand (encrypt sk pt :: Rand (CryptoRand gen) (CT m zp (Cyc t m' zq))) gen -bench_mul :: (Ring (CT m zp (Cyc t m' zq)), NFData (CT m zp (Cyc t m' zq)))- => CT m zp (Cyc t m' zq) -> CT m zp (Cyc t m' zq) -> Bench '(t,m,m',zp,zq)-bench_mul a = bench (*a)--bench_addPublic :: (AddPublicCtx t m m' zp zq, NFElt zp, NFElt zq) => Cyc t m zp -> CT m zp (Cyc t m' zq) -> Bench '(t,m,m',zp,zq)-bench_addPublic a ct = bench (addPublic a) ct--bench_mulPublic :: (MulPublicCtx t m m' zp zq, NFElt zp, NFElt zq) => Cyc t m zp -> CT m zp (Cyc t m' zq) -> Bench '(t,m,m',zp,zq)-bench_mulPublic a ct = bench (mulPublic a) ct- -- requires zq to be Liftable-bench_dec :: (DecryptCtx t m m' z zp zq, NFElt zp)- => SK (Cyc t m' z) -> CT m zp (Cyc t m' zq) -> Bench '(t,m,m',zp,zq)-bench_dec sk ct = bench (decrypt sk) ct--bench_rescaleCT :: forall t m m' zp zq zq' .- (RescaleCyc (Cyc t) zq' zq, ToSDCtx t m' zp zq', NFData (CT m zp (Cyc t m' zq)))- => CT m zp (Cyc t m' zq') -> Bench '(t,m,m',zp,zq,zq')-bench_rescaleCT = bench (rescaleLinearCT :: CT m zp (Cyc t m' zq') -> CT m zp (Cyc t m' zq))--bench_keySwQ :: (Ring (CT m zp (Cyc t m' zq)), NFData (CT m zp (Cyc t m' zq)))- => KSHint m zp t m' zq gad zq' -> CT m zp (Cyc t m' zq) -> Bench '(t,m,m',zp,zq,zq',gad)-bench_keySwQ (KeySwitch kswq) x = bench kswq $ x*x--bench_tunnel :: (NFData (CT s zp (Cyc t s' zq)))- => Tunnel t r r' s s' zp zq gad -> CT r zp (Cyc t r' zq) -> Bench '(t,r,r',s,s',zp,zq,gad)-bench_tunnel (Tunnel f) x = bench f x--type Gens = '[HashDRBG]-type Gadgets = '[TrivGad, BaseBGad 2]-type Tensors = '[CT.CT,RT]-type MM'PQCombos =- '[ '(F4, F128, Zq 64, Zq 257),- '(F4, F128, Zq 64, Zq (257 ** 641)),- '(F12, F32 * F9, Zq 64, Zq 577),- '(F12, F32 * F9, Zq 64, Zq (577 ** 1153)),- '(F12, F32 * F9, Zq 64, Zq (577 ** 1153 ** 2017)),- '(F12, F32 * F9, Zq 64, Zq (577 ** 1153 ** 2017 ** 2593)),- '(F12, F32 * F9, Zq 64, Zq (577 ** 1153 ** 2017 ** 2593 ** 3169)),- '(F12, F32 * F9, Zq 64, Zq (577 ** 1153 ** 2017 ** 2593 ** 3169 ** 3457)),- '(F12, F32 * F9, Zq 64, Zq (577 ** 1153 ** 2017 ** 2593 ** 3169 ** 3457 ** 6337)),- '(F12, F32 * F9, Zq 64, Zq (577 ** 1153 ** 2017 ** 2593 ** 3169 ** 3457 ** 6337 ** 7489)),- '(F12, F32 * F9 * F25, Zq 64, Zq 14401),- '(F12, F32 * F9 * F25, Zq 64, Zq (14401 ** 21601))- ]--type CTParams = ( '(,) <$> Tensors) <*> MM'PQCombos-ctParams :: Proxy CTParams-ctParams = Proxy--type DecParams = ( '(,) <$> Tensors) <*> (Nub (Filter Liftable MM'PQCombos))-decParams :: Proxy DecParams-decParams = Proxy+bench_dec :: forall t m m' z zp zq . (z ~ LiftOf zp, _)+ => PT (Cyc t m zp) -> SK (Cyc t m' z) -> Bench '(t,m,m',zp,zq)+bench_dec pt sk = benchM $ do+ ct :: CT m zp (Cyc t m' zq) <- encrypt sk pt+ return $ bench (decrypt sk) ct -type RescaleParams = ( '(,) <$> Tensors) <*> (Map AddZq (Filter NonLiftable MM'PQCombos))-rescaleParams :: Proxy RescaleParams-rescaleParams = Proxy+bench_mul :: forall t m m' z zp zq . (z ~ LiftOf zp, LiftOf zp ~ ModRep zp, _)+ => PT (Cyc t m zp) -> PT (Cyc t m zp) -> SK (Cyc t m' z) -> (Bench '(t,m,m',zp,zq))+bench_mul pta ptb sk = benchM $ do+ a :: CT m zp (Cyc t m' zq) <- encrypt sk pta+ b <- encrypt sk ptb+ return $ bench (*a) b -type KSQParams = ( '(,) <$> Gadgets) <*> RescaleParams-ksqParams :: Proxy KSQParams-ksqParams = Proxy+bench_addPublic :: forall t m m' z zp zq . (z ~ LiftOf zq, _)+ => Cyc t m zp -> PT (Cyc t m zp) -> SK (Cyc t m' z) -> Bench '(t,m,m',zp,zq)+bench_addPublic a pt sk = benchM $ do+ ct :: CT m zp (Cyc t m' zq) <- encrypt sk pt+ return $ bench (addPublic a) ct -type EncParams = ( '(,) <$> Gens) <*> CTParams-encParams :: Proxy EncParams-encParams = Proxy+bench_mulPublic :: forall t m m' z zp zq . (z ~ LiftOf zq, _)+ => Cyc t m zp -> PT (Cyc t m zp) -> SK (Cyc t m' z) -> Bench '(t,m,m',zp,zq)+bench_mulPublic a pt sk = benchM $ do+ ct :: CT m zp (Cyc t m' zq) <- encrypt sk pt+ return $ bench (mulPublic a) ct --- 3144961,5241601,7338241,9959041,10483201,11531521,12579841,15200641,18869761,19393921-type TunnParams =- ( '(,) <$> Gadgets) <*>- (( '(,) <$> Tensors) <*>- (( '(,) <$> TunnRings) <*> TunnMods))-tunnelParams :: Proxy TunnParams-tunnelParams = Proxy+bench_rescaleCT :: forall t m m' z zp (zq :: *) (zq' :: *) . (z ~ LiftOf zq, _)+ => PT (Cyc t m zp) -> SK (Cyc t m' z) -> Bench '(t,m,m',zp,zq,zq')+bench_rescaleCT pt sk = benchM $ do+ ct <- encrypt sk pt+ return $ bench (rescaleLinearCT :: CT m zp (Cyc t m' zq') -> CT m zp (Cyc t m' zq)) ct -type TunnRings = '[- {- H0 -> H1 -} '(F128, F128 * F7 * F13, F64 * F7, F64 * F7 * F13),- {- H1 -> H2 -} '(F64 * F7, F64 * F7 * F13, F32 * F7 * F13, F32 * F7 * F13),- {- H2 -> H3 -} '(F32 * F7 * F13, F32 * F7 * F13, F8 * F5 * F7 * F13, F8 * F5 * F7 *F13),- {- H3 -> H4 -} '(F8 * F5 * F7 * F13, F8 * F5 * F7 *F13, F4 * F3 * F5 * F7 * F13, F4 * F3 * F5 * F7 * F13),- {- H4 -> H5 -} '(F4 * F3 * F5 * F7 * F13, F4 * F3 * F5 * F7 *F13, F9 * F5 * F7 * F13, F9 * F5 * F7 * F13)- ]+bench_keySwQ :: forall t m m' z zp zq (zq' :: *) (gad :: *) . (z ~ LiftOf zp, _)+ => PT (Cyc t m zp) -> SK (Cyc t m' z) -> Bench '(t,m,m',zp,zq,zq',gad)+bench_keySwQ pt sk = benchM $ do+ x :: CT m zp (Cyc t m' zq) <- encrypt sk pt+ ksqHint :: KSQuadCircHint gad (Cyc t m' zq') <- ksQuadCircHint sk+ let y = x*x+ return $ bench (keySwitchQuadCirc ksqHint) y -type TunnMods = '[- '(Zq PP32, Zq 3144961)- ]+-- possible bug: If I enable -XPartialTypeSigs and add a ",_" to the constraint list below, GHC+-- can't figure out that `e `Divides` s`, even when it's explicitly listed!+bench_tunnel :: forall t e e' r r' s s' z zp zq gad .+ (z ~ LiftOf zp,+ GenTunnelInfoCtx t e r s e' r' s' z zp zq gad,+ TunnelCtx t r s e' r' s' zp zq gad,+ e ~ FGCD r s,+ ZPP zp, Mod zp,+ z ~ ModRep zp,+ r `Divides` r',+ Fact e,+ NFData zp,+ CElt t (ZpOf zp))+ => PT (Cyc t r zp) -> SK (Cyc t r' z) -> SK (Cyc t s' z) -> Bench '(t,r,r',s,s',zp,zq,gad)+bench_tunnel pt skin skout = benchM $ do+ x <- encrypt skin pt+ let crts :: [Cyc t s zp] = proxy crtSet (Proxy::Proxy e) \\ gcdDivides (Proxy::Proxy r) (Proxy::Proxy s)+ r = proxy totientFact (Proxy::Proxy r)+ e = proxy totientFact (Proxy::Proxy e)+ dim = r `div` e+ -- only take as many crts as we need+ -- otherwise linearDec fails+ linf :: Linear t zp e r s = linearDec (take dim crts) \\ gcdDivides (Proxy::Proxy r) (Proxy::Proxy s)+ hints :: TunnelInfo gad t e r s e' r' s' zp zq <- tunnelInfo linf skout skin+ return $ bench (tunnelCT hints :: CT r zp (Cyc t r' zq) -> CT s zp (Cyc t s' zq)) x
+ examples/HomomPRFMain.hs view
@@ -0,0 +1,185 @@+{-|+Module : HomomPRFMain+Description : Example, test, and macro-benchmark for homomorphic evaluation of a PRF.+Copyright : (c) Eric Crockett, 2011-2017+ Chris Peikert, 2011-2017+License : GPL-2+Maintainer : ecrockett0@email.com+Stability : experimental+Portability : POSIX++Example, test, and macro-benchmark for homomorphic evaluation of a PRF.+-}++{-# LANGUAGE DataKinds #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE PartialTypeSignatures #-}+{-# LANGUAGE PolyKinds #-}+{-# LANGUAGE RebindableSyntax #-}+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE TypeFamilies #-}+{-# LANGUAGE TypeOperators #-}++{-# OPTIONS_GHC -fno-warn-partial-type-signatures #-}++module HomomPRFMain where++import Control.DeepSeq+import Control.Monad.Except+import Control.Monad.Random+import Control.Monad.Reader+import Control.Monad.State++import Crypto.Lol hiding (lift)+import Crypto.Lol.Applications.HomomPRF+import Crypto.Lol.Applications.KeyHomomorphicPRF+import Crypto.Lol.Applications.SymmSHE+import Crypto.Lol.Cyclotomic.Tensor.CPP as CPP+import Crypto.Lol.Types.Proto+import Crypto.Lol.Types.Random+import Crypto.Random.DRBG++import Data.Promotion.Prelude+import Data.Time.Clock+import Data.Typeable+import MathObj.Matrix (columns)+import System.FilePath ((</>), pathSeparator)+import System.IO+import Text.Printf++import HomomPRFParams++type T = CPP.CT+type Z = Int64++protoDir :: Int -> String -> String+protoDir p = (((pathSeparator : "home") </> "eric" </> "Desktop" </> "Lol" </> ("p" ++ show p ++ "-")) ++)++lfuncPath, thintPath, rhintPath, tskPath, rskPath :: Int -> String+thintPath p = protoDir p "tunnel.hint"+rhintPath p = protoDir p "round.hint"+lfuncPath p = protoDir p "tunnelfuncs.lfuns"+-- | The key used as the input to tunneling; also used for encryption+tskPath p = protoDir p "encKey.secret"+-- | The output key of tunneling, used for rounding; also for decryption+rskPath p = protoDir p "decKey.secret"++-- R' - ... - S'+-- | - | - |+-- R - ... - S+-- PRF evaluation usually goes from R' to R. Homomorphic evaluation+-- goes from R' to S, via S'. To test, we run the computation in the clear+-- from R' to R, then tunnel in the clear to S.+main :: IO ()+main = do+ putStrLn $ "Starting homomorphic PRF evaluation with tensor " ++ show (typeRep (Proxy::Proxy T))+ hints' <- runExceptT readHints+ (lfuns, hints :: EvalHints T RngList Z ZP ZQ ZQSeq KSGad, encKey, decKey) <- case hints' of+ (Right a) -> do+ putStrLn "Using precomputed hints."+ return a+ (Left st) -> do+ putStrLn $ "Could not read precomputed hints: " ++ st+ gen :: CryptoRand HashDRBG <- liftIO newGenIO -- uses system entropy+ (lfuns, hints, encKey, decKey) <- time "Generating hints..." $ flip evalRand gen $ do+ let v = 1.0 :: Double+ encKey <- genSK v+ (tHints, decKey) <- tunnelInfoChain encKey+ let lfuns = ptTunnelFuncs+ rHints <- roundHints decKey+ let hints = Hints tHints rHints+ return (lfuns, hints, encKey, decKey)+ writeHints lfuns hints encKey decKey+ return (lfuns, hints, encKey, decKey)+ gen :: CryptoRand HashDRBG <- liftIO newGenIO -- uses system entropy+ (family, s, ct) <- time "Generating random inputs..." $ flip evalRand gen $ do+ family :: PRFFamily PRFGad _ _ <- randomFamily 10 -- works on 10-bit input+ s <- getRandom+ ct <- encrypt encKey s+ return (family, s, ct)+ st <- time "Initializing PRF state..." $ prfState family Nothing --initialize with input 0+ encprf <- time "Evaluating PRF..." $ flip runReader hints $ flip evalStateT st $ homomPRFM ct 0+ hprf <- time "Decrypting PRF output..." $ decrypt decKey encprf++ -- test+ clearPRF <- time "In-the-clear PRF..." $ head $ head $ columns $ ringPRF s 0 st -- homomPRF only computes first elt+ clearPRF' <- time "In-the-clear tunnel..." $ ptTunnel lfuns clearPRF+ if clearPRF' == hprf+ then putStrLn "PASS: Homomorphic output matches in-the-clear."+ else putStrLn "TEST FAILED"++readHints :: forall mon t rngs z e zp zq zqs gad r' s' .+ (MonadIO mon, MonadError String mon, Mod zp, UnPP (CharOf zp) ~ '(Prime2, e),+ ProtoReadable (TunnelFuncs t (PTRings rngs) (TwoOf zp)),+ ProtoReadable (TunnelInfoChain gad t rngs zp (ZqUp zq zqs)),+ ProtoReadable (RoundHints t (Fst (Last rngs)) (Snd (Last rngs)) z e zp (ZqDown zq zqs) zqs gad),+ ProtoReadable (SK (Cyc t r' z)), ProtoReadable (SK (Cyc t s' z)))+ => mon (TunnelFuncs t (PTRings rngs) (TwoOf zp),+ EvalHints t rngs z zp zq zqs gad,+ SK (Cyc t r' z), SK (Cyc t s' z))+readHints = do+ let p = fromIntegral $ proxy modulus (Proxy::Proxy zp)+ lfuns <- parseProtoFile $ lfuncPath p+ tHints <- parseProtoFile $ thintPath p+ rHints <- parseProtoFile $ rhintPath p+ tsk <- parseProtoFile $ tskPath p+ rsk <- parseProtoFile $ rskPath p+ return (lfuns, Hints tHints rHints, tsk, rsk)+{-+readOrGenHints :: (MonadIO mon, MonadRandom mon, Head RngList ~ '(r,r'), Last RngList ~ '(s,s'))+ => mon (EvalHints T RngList Z ZP ZQ ZQSeq KSGad, SK (Cyc T r' Z), SK (Cyc T s' Z))+readOrGenHints = do+ res <- runExceptT readHints+ case res of+ (Left st) -> do+ liftIO $ putStrLn $ "Could not read precomputed data. Error was: " ++ st+ (hints, sk, skout) <- do++ liftIO $ putStrLn "Writing hints to disk..."+ writeHints hints sk skout+ return (hints, sk, skout)+ (Right a) -> do+ liftIO $ putStrLn "Precomputed hints found."+ return a+-}+writeHints :: forall mon t rngs z e zp zq zqs gad r' s' .+ (MonadIO mon, Mod zp, UnPP (CharOf zp) ~ '(Prime2, e),+ ProtoReadable (TunnelFuncs t (PTRings rngs) (TwoOf zp)),+ ProtoReadable (TunnelInfoChain gad t rngs zp (ZqUp zq zqs)),+ ProtoReadable (RoundHints t (Fst (Last rngs)) (Snd (Last rngs)) z e zp (ZqDown zq zqs) zqs gad),+ ProtoReadable (SK (Cyc t r' z)), ProtoReadable (SK (Cyc t s' z)))+ => TunnelFuncs t (PTRings rngs) (TwoOf zp)+ -> EvalHints t rngs z zp zq zqs gad+ -> SK (Cyc t r' z)+ -> SK (Cyc t s' z)+ -> mon ()+writeHints lfuns (Hints tHints rHints) encKey decKey = do+ let p = fromIntegral $ proxy modulus (Proxy::Proxy zp)+ writeProtoFile (lfuncPath p) lfuns+ writeProtoFile (thintPath p) tHints+ writeProtoFile (rhintPath p) rHints+ writeProtoFile (tskPath p) encKey+ writeProtoFile (rskPath p) decKey++-- timing functionality+time :: (NFData a) => String -> a -> IO a+time s m = do+ putStr' s+ wallStart <- getCurrentTime+ m `deepseq` printTimes wallStart 1+ return m++-- flushes the print buffer+putStr' :: String -> IO ()+putStr' str = do+ putStr str+ hFlush stdout++printTimes :: UTCTime -> Int -> IO ()+printTimes wallStart iters = do+ wallEnd <- getCurrentTime+ let wallTime = realToFrac $ diffUTCTime wallEnd wallStart :: Double+ printf "Wall time: %0.3fs" wallTime+ if iters == 1+ then putStr "\n\n"+ else printf "\tAverage wall time: %0.3fs\n\n" $ wallTime / fromIntegral iters
+ examples/HomomPRFParams.hs view
@@ -0,0 +1,55 @@+{-|+Module : HomomPRFParams+Description : Parameters for homomorphic PRF.+Copyright : (c) Eric Crockett, 2011-2017+ Chris Peikert, 2011-2017+License : GPL-2+Maintainer : ecrockett0@email.com+Stability : experimental+Portability : POSIX++Parameters for homomorphic PRF.+-}++{-# LANGUAGE DataKinds #-}+{-# LANGUAGE PolyKinds #-}+{-# LANGUAGE TypeOperators #-}++module HomomPRFParams (RngList, Zq, ZQSeq, ZP, ZQ, KSGad, PRFGad) where++import Crypto.Lol+import Crypto.Lol.Types++type H0 = F128+type H1 = F64 * F7+type H2 = F32 * F7 * F13+type H3 = F8 * F5 * F7 * F13+type H4 = F4 * F3 * F5 * F7 * F13+type H5 = F9 * F5 * F7 * F13+type H0' = H0 * F7 * F13+type H1' = H1 * F13+type H2' = H2+type H3' = H3+type H4' = H4+type H5' = H5+type RngList = '[ '(H0,H0'), '(H1,H1'), '(H2,H2'), '(H3,H3'), '(H4,H4'), '(H5,H5') ]++type Zq (q :: k) = ZqBasic q Int64+-- three 24-bit moduli, enough to handle rounding for p=32 (depth-4 circuit at ~17 bits per mul)+type ZQ1 = Zq 18869761+type ZQ2 = (Zq 19393921, ZQ1)+type ZQ3 = (Zq 19918081, ZQ2)+type ZQ4 = (Zq 25159681, ZQ3)+-- a 31-bit modulus, for rounding off after the last four hops+type ZQ5 = (Zq 2149056001, ZQ4)+-- for rounding off after the first hop+type ZQ6 = (Zq 3144961, ZQ5)+type ZQ7 = (Zq 7338241, ZQ6)+type ZQSeq = '[ZQ7, ZQ6, ZQ5, ZQ4, ZQ3, ZQ2, ZQ1]++type ZP = Zq PP8+type ZQ = ZQ4 -- if p=2^k, choose ZQ[k+1]++-- these need not be the same+type KSGad = BaseBGad 2+type PRFGad = BaseBGad 2
+ examples/KHPRFMain.hs view
@@ -0,0 +1,67 @@+{-|+Module : KHPRFMain+Description : Example using KeyHomomorphicPRF.+Copyright : (c) Eric Crockett, 2011-2017+ Chris Peikert, 2011-2017+License : GPL-2+Maintainer : ecrockett0@email.com+Stability : experimental+Portability : POSIX++Example using KeyHomomorphicPRF.+-}++{-# LANGUAGE DataKinds #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE NoImplicitPrelude #-}+{-# LANGUAGE PartialTypeSignatures #-}+{-# LANGUAGE PolyKinds #-}+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE TypeFamilies #-}++module KHPRFMain where++import Control.Applicative+import Control.DeepSeq+import Control.Monad.Random hiding (fromList)+import Control.Monad.State hiding (state)++import Crypto.Lol+import Crypto.Lol.Applications.KeyHomomorphicPRF+import Crypto.Lol.Cyclotomic.Tensor.CPP+import Crypto.Lol.Types++import MathObj.Matrix hiding (zipWith)++type Zq q = ZqBasic q Int64+type Cyclo m q = Cyc CT m (Zq q)+type Gad = BaseBGad 2+type M = F128++type Cyclo' q = Cyclo M q++main :: IO ()+main = do+ family :: PRFFamily Gad (Cyclo' 257) (Cyclo M 32) <- randomFamily 10 -- works on 10-bit input+ s <- getRandom -- prf seed+ let state = prfState family Nothing -- initialize with input 0+ prf = ringPRFM s+ xs = grayCode 3+ res = map rows $ flip evalState state $ mapM prf xs+ res `deepseq` print "done"++main2 :: IO ()+main2 = do+ let n = 3 -- 3 rows/matrix+ k = 10 -- 10 bit input+ t = balancedTree k+ gadLen = 9+ a0 <- fromList n (n*gadLen) <$> take (gadLen*n*n) <$> getRandoms+ a1 <- fromList n (n*gadLen) <$> take (gadLen*n*n) <$> getRandoms+ let family = makeFamily a0 a1 t :: PRFFamily Gad (Zq 257) (Zq 32)+ s <- fromList 1 n <$> take n <$> getRandoms+ let state = prfState family Nothing -- initialize with input 0+ prf x = latticePRFM s x+ xs = grayCode 3+ res = map rows $ flip evalState state $ mapM prf xs+ print res
+ examples/SHEMain.hs view
@@ -0,0 +1,95 @@+{-|+Module : SHEMain+Description : Example using SymmSHE.+Copyright : (c) Eric Crockett, 2011-2017+ Chris Peikert, 2011-2017+License : GPL-2+Maintainer : ecrockett0@email.com+Stability : experimental+Portability : POSIX++Example using SymmSHE.+-}++{-# LANGUAGE DataKinds #-}+{-# LANGUAGE PolyKinds #-}+{-# LANGUAGE RebindableSyntax #-}+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE TemplateHaskell #-}++module SHEMain where++import Crypto.Lol hiding ((^))+import Crypto.Lol.Applications.SymmSHE -- exports *ciphertext* 'CT'+import Crypto.Lol.Types+import qualified Crypto.Lol.Cyclotomic.Tensor.CPP as C -- the *tensor* 'CT'++import Algebra.Ring ((^))++import Control.Monad.Random (getRandom)++-- PTIndex must divide CTIndex+type PTIndex = F128++-- Crypto.Lol includes Factored types F1..F512+-- for cyclotomic indices outside this range,+-- we provide a TH wrapper.+-- TH to constuct the cyclotomic index 11648+type CTIndex = $(fType $ 2^7 * 7 * 13)++-- To use crtSet (for example, when ring switching), the plaintext+-- modulus must be a PrimePower (ZPP constraint). Crypto.Lol exports+-- (via Crypto.Lol.Factored) PP2,PP4,...,PP128, as well as some prime+-- powers for 3,5,7, and 11. Alternately, an arbitrary prime power+-- p^e can be constructed with the Template Haskell splice $(ppType+-- (p,e)). For applications that don't use crtSet, the PT modulus can+-- be a TypeLit.+type PTZq = ZqBasic PP8 Int64++-- uses GHC.TypeLits as modulus, and Int64 as underyling+-- representation (needed to use with CT backend). The modulus+-- doesn't have to be "good", but "good" moduli are faster.+type Zq q = ZqBasic q Int64 -- uses PolyKinds+type CTZq1 = Zq 536937857+type CTZq2 = (CTZq1, Zq 536972801)+type CTZq3 = (CTZq2, Zq 537054337)++-- Tensor backend, either Repa (RT) or C (CT)+type T = C.CT -- can also use RT++type KSGad = TrivGad -- can also use (BaseBGad 2), for example++type PTRing = Cyc T PTIndex PTZq+type CTRing1 = CT PTIndex PTZq (Cyc T CTIndex CTZq1)+type CTRing2 = CT PTIndex PTZq (Cyc T CTIndex CTZq2)+type SKRing = Cyc T CTIndex (LiftOf PTZq)++main :: IO ()+main = do+ plaintext <- getRandom+ sk :: SK SKRing <- genSK (1 :: Double)+ -- encrypt with a single modulus+ ciphertext :: CTRing1 <- encrypt sk plaintext++ let ct1 = 2*ciphertext+ pt1 = decrypt sk ct1+ print $ "Test1: " ++ (show $ 2*plaintext == pt1)++ hint :: KSQuadCircHint KSGad (Cyc T CTIndex CTZq2) <- ksQuadCircHint sk+ let ct2 = keySwitchQuadCirc hint $ ciphertext*ciphertext+ pt2 = decrypt sk ct2+ -- note: this requires a *LARGE* CT modulus to succeed+ print $ "Test2: " ++ (show $ plaintext*plaintext == pt2)++ -- so we support using *several* small moduli:+ hint' :: KSQuadCircHint KSGad (Cyc T CTIndex CTZq3) <- ksQuadCircHint sk+ ciphertext' :: CTRing2 <- encrypt sk plaintext+ let ct3 = keySwitchQuadCirc hint' $ ciphertext' * ciphertext'+ -- the CT modulus of ct3 is a ring product, which can't be lifted to a fixed size repr+ -- so use decryptUnrestricted instead+ pt3 = decryptUnrestricted sk ct3+ ct3' = rescaleLinearCT ct3 :: CTRing1+ -- after rescaling, ct3' has a single modulus, so we can use normal decrypt+ pt3' = decrypt sk ct3'+ print $ "Test3: " ++ (show $ (plaintext*plaintext == pt3) && (pt3' == pt3))+
− examples/SymmSHE/SimpleSHE.hs
@@ -1,81 +0,0 @@-{-# LANGUAGE DataKinds #-}-{-# LANGUAGE NoImplicitPrelude #-}-{-# LANGUAGE PolyKinds #-}-{-# LANGUAGE RebindableSyntax #-}-{-# LANGUAGE ScopedTypeVariables #-}-{-# LANGUAGE TemplateHaskell #-}--import Crypto.Lol hiding ((^))-import Crypto.Lol.Applications.SymmSHE -- exports *ciphertext* 'CT'-import Crypto.Lol.Types hiding (CT)-import qualified Crypto.Lol.Types as C -- the *tensor* 'CT'--import Algebra.Ring ((^))--import Control.Monad.Random (getRandom)---- PTIndex must divide CTIndex-type PTIndex = F128---- Crypto.Lol includes Factored types F1..F512--- for cyclotomic indices outside this range,--- we provide a TH wrapper.--- TH to constuct the cyclotomic index 11648-type CTIndex = $(fType $ 2^7 * 7 * 13)---- To use crtSet (for example, when ring switching), the plaintext--- modulus must be a PrimePower (ZPP constraint). Crypto.Lol exports--- (via Crypto.Lol.Factored) PP2,PP4,...,PP128, as well as some prime--- powers for 3,5,7, and 11. Alternately, an arbitrary prime power--- p^e can be constructed with the Template Haskell splice $(ppType--- (p,e)). For applications that don't use crtSet, the PT modulus can--- be a TypeLit.-type PTZq = ZqBasic PP8 Int64---- uses GHC.TypeLits as modulus, and Int64 as underyling--- representation (needed to use with CT backend). The modulus--- doesn't have to be "good", but "good" moduli are faster.-type Zq q = ZqBasic q Int64 -- uses PolyKinds-type CTZq1 = Zq 536937857-type CTZq2 = (CTZq1, Zq 536972801)-type CTZq3 = (CTZq2, Zq 537054337)---- Tensor backend, either Repa (RT) or C (CT)-type T = C.CT -- can also use RT--type KSGad = TrivGad -- can also use (BaseBGad 2), for example--type PTRing = Cyc T PTIndex PTZq-type CTRing1 = CT PTIndex PTZq (Cyc T CTIndex CTZq1)-type CTRing2 = CT PTIndex PTZq (Cyc T CTIndex CTZq2)-type SKRing = Cyc T CTIndex (LiftOf PTZq)--main :: IO ()-main = do- plaintext <- getRandom- sk :: SK SKRing <- genSK (1 :: Double)- -- encrypt with a single modulus- ciphertext :: CTRing1 <- encrypt sk plaintext-- let ct1 = 2*ciphertext- pt1 = decrypt sk ct1- print $ "Test1: " ++ (show $ 2*plaintext == pt1)-- kswq <- proxyT (keySwitchQuadCirc sk) (Proxy::Proxy (KSGad, CTZq2))- let ct2 = kswq $ ciphertext*ciphertext- pt2 = decrypt sk ct2- -- note: this requires a *LARGE* CT modulus to succeed- print $ "Test2: " ++ (show $ plaintext*plaintext == pt2)-- -- so we support using *several* small moduli:- kswq' <- proxyT (keySwitchQuadCirc sk) (Proxy::Proxy (KSGad, CTZq3))- ciphertext' :: CTRing2 <- encrypt sk plaintext- let ct3 = kswq' $ ciphertext' * ciphertext'- -- the CT modulus of ct3 is a ring product, which can't be lifted to a fixed size repr- -- so use decryptUnrestricted instead- pt3 = decryptUnrestricted sk ct3- ct3' = rescaleLinearCT ct3 :: CTRing1- -- after rescaling, ct3' has a single modulus, so we can use normal decrypt- pt3' = decrypt sk ct3'- print $ "Test3: " ++ (show $ (plaintext*plaintext == pt3) && (pt3' == pt3))-
lol-apps.cabal view
@@ -5,7 +5,7 @@ -- PVP summary: +-+------- breaking API changes -- | | +----- non-breaking API additions -- | | | +--- code changes with no API change-version: 0.1.1.0+version: 0.2.0.0 synopsis: Lattice-based cryptographic applications using Lol. homepage: https://github.com/cpeikert/Lol Bug-Reports: https://github.com/cpeikert/Lol/issues@@ -17,21 +17,11 @@ category: Crypto stability: experimental build-type: Simple-extra-source-files: README, CHANGES.md,- benchmarks/SHEBenches.hs,- tests/SHETests.hs,- utils/Apply.hs,- utils/Apply/SHE.hs- utils/Benchmarks.hs,- utils/GenArgs.hs,- utils/GenArgs/SHE.hs- utils/Tests.hs,- utils/TestTypes.hs,- utils/Utils.hs+extra-source-files: README, CHANGES.md, SHE.proto, HomomPRF.proto cabal-version: >= 1.10 description: This library contains example cryptographic applications built using- <https://hackage.haskell.org/package/lol Λ ○ λ> (Lol),+ <https://hackage.haskell.org/package/lol Λ ∘ λ> (Lol), a general-purpose library for ring-based lattice cryptography. source-repository head@@ -61,46 +51,71 @@ ghc-options: -fno-liberate-case -funfolding-use-threshold1000 -funfolding-keeness-factor1000 exposed-modules:+ Crypto.Lol.Applications.HomomPRF+ Crypto.Lol.Applications.KeyHomomorphicPRF Crypto.Lol.Applications.SymmSHE+ Crypto.Proto.HomomPRF+ Crypto.Proto.HomomPRF.LinearFuncChain+ Crypto.Proto.HomomPRF.RoundHintChain+ Crypto.Proto.HomomPRF.TunnelInfoChain+ Crypto.Proto.SHE+ Crypto.Proto.SHE.KSHint+ Crypto.Proto.SHE.RqPolynomial+ Crypto.Proto.SHE.SecretKey+ Crypto.Proto.SHE.TunnelInfo build-depends:- base>=4.8 && <5,- deepseq >= 1.4.1.1 && <1.5,- lol >= 0.3 && < 0.5,- MonadRandom >= 0.2 && < 0.5,- numeric-prelude >= 0.4.2 && < 0.5+ base >= 4.9 && < 5,+ containers,+ deepseq >= 1.4.1.1,+ lol >= 0.6.0.0,+ MonadRandom >= 0.2,+ mtl,+ numeric-prelude >= 0.4.2,+ protocol-buffers,+ protocol-buffers-descriptor,+ singletons,+ split test-suite test-apps type: exitcode-stdio-1.0- hs-source-dirs: tests,utils+ hs-source-dirs: tests, examples default-language: Haskell2010- main-is: Main.hs+ main-is: TestAppsMain.hs+ ghc-options: -main-is TestAppsMain+ other-modules: KHPRFTests, SHETests - ghc-options: -threaded -rtsopts+ ghc-options: -threaded -rtsopts build-depends: arithmoi,- base,+ base >= 4.9 && < 5, constraints, deepseq, DRBG,- lol,+ lol >= 0.6.0.0, lol-apps,+ lol-cpp,+ lol-repa,+ lol-tests, MonadRandom, mtl,- QuickCheck >= 2.8 && < 2.9,+ numeric-prelude,+ QuickCheck >= 2.8, random, repa, singletons,- test-framework >= 0.8 && < 0.9,- test-framework-quickcheck2 >= 0.3 && < 0.4,+ test-framework >= 0.8,+ test-framework-quickcheck2 >= 0.3, vector Benchmark bench-apps type: exitcode-stdio-1.0- hs-source-dirs: benchmarks,utils+ hs-source-dirs: benchmarks, examples default-language: Haskell2010- main-is: Main.hs+ main-is: BenchAppsMain.hs+ ghc-options: -main-is BenchAppsMain+ other-modules: KHPRFBenches, SHEBenches -- if flag(llvm) -- ghc-options: -fllvm -optlo-O3@@ -110,30 +125,80 @@ build-depends: arithmoi,- base,+ base >= 4.9 && < 5,+ containers, criterion, deepseq, DRBG,- lol,+ lol >= 0.6.0.0, lol-apps,+ lol-benches,+ lol-cpp,+ lol-repa, MonadRandom, mtl,+ numeric-prelude, singletons, transformers, vector, repa -executable simpleSHE- hs-source-dirs: examples/SymmSHE, utils+executable homomprf+ hs-source-dirs: examples default-language: Haskell2010- main-is: SimpleSHE.hs+ main-is: HomomPRFMain.hs+ ghc-options: -main-is HomomPRFMain+ other-modules: HomomPRFParams ghc-options: -threaded -rtsopts build-depends: arithmoi,- base,- lol,+ base >= 4.9 && < 5,+ deepseq,+ DRBG,+ filepath,+ lol >= 0.6.0.0, lol-apps,+ lol-cpp,+ MonadRandom,+ mtl,+ numeric-prelude,+ singletons,+ time++executable khprf+ hs-source-dirs: examples+ default-language: Haskell2010+ main-is: KHPRFMain.hs+ ghc-options: -main-is KHPRFMain++ ghc-options: -threaded -rtsopts++ build-depends:+ arithmoi,+ base >= 4.9 && < 5,+ deepseq,+ lol >= 0.6.0.0,+ lol-apps,+ lol-cpp,+ MonadRandom,+ mtl,+ numeric-prelude++executable symmshe+ hs-source-dirs: examples+ default-language: Haskell2010+ main-is: SHEMain.hs+ ghc-options: -main-is SHEMain++ ghc-options: -threaded -rtsopts++ build-depends:+ arithmoi,+ base >= 4.9 && < 5,+ lol >= 0.6.0.0,+ lol-apps,+ lol-cpp, MonadRandom, numeric-prelude
+ tests/KHPRFTests.hs view
@@ -0,0 +1,63 @@+{-|+Module : KHPRFTests+Description : Tests for KeyHomomorphicPRF.+Copyright : (c) Eric Crockett, 2011-2017+ Chris Peikert, 2011-2017+License : GPL-2+Maintainer : ecrockett0@email.com+Stability : experimental+Portability : POSIX++Tests for KeyHomomorphicPRF.+-}++{-# LANGUAGE DataKinds #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE NoImplicitPrelude #-}+{-# LANGUAGE PartialTypeSignatures #-}+{-# LANGUAGE ScopedTypeVariables #-}++{-# OPTIONS_GHC -fno-warn-partial-type-signatures #-}++module KHPRFTests (khprfTests) where++import Control.Applicative+import Control.Monad.Random++import Crypto.Lol+import Crypto.Lol.Applications.KeyHomomorphicPRF+import Crypto.Lol.Cyclotomic.UCyc+import Crypto.Lol.Tests+import Crypto.Lol.Utils.ShowType++import MathObj.Matrix++import qualified Test.Framework as TF++khprfTests :: forall t m zp zq gad . (_)+ => Proxy '(m,zp,zq,gad) -> Proxy t -> TF.Test+khprfTests _ _ =+ let ptmr = Proxy::Proxy '(t,m,zp,zq,gad)+ in testGroup (showType ptmr) $ ($ ptmr) <$> [+ genTestArgs "PRF_3bits" (prop_keyHomom 3),+ genTestArgs "PRF_5bits" (prop_keyHomom 5)]++-- +/-1 in every coefficient of the rounding basis+prop_keyHomom :: forall t m zp zq gad . (Fact m, CElt t zq, CElt t zp, _)+ => Int -> Test '(t,m,zp,zq,gad)+prop_keyHomom size = testIO $ do+ family :: PRFFamily gad (Cyc t m zq) (Cyc t m zp) <- randomFamily size+ s1 <- getRandom+ s2 <- getRandom+ x <- ((`mod` (2^size)) . abs) <$> getRandom+ let s3 = s1+s2+ state = prfState family Nothing+ prf1 = ringPRF s1 x state+ prf2 = ringPRF s2 x state+ prf3 = ringPRF s3 x state+ prf3' = prf1+prf2 :: Matrix (Cyc t m zp)+ a = uncycPow <$> prf3+ b = uncycPow <$> prf3'+ c = concat $ rows $ a - b+ c' = map (maximum . fmapPow abs . lift) c+ return $ maximum c' <= 1
− tests/Main.hs
@@ -1,10 +0,0 @@--import SHETests--import Test.Framework--main :: IO ()-main = do- flip defaultMainWithArgs ["--threads=1","--maximum-generated-tests=100"]- [ testGroup "SHE Tests" sheTests- ]
tests/SHETests.hs view
@@ -1,312 +1,270 @@-{-# LANGUAGE DataKinds, FlexibleContexts,- NoImplicitPrelude, PolyKinds, RebindableSyntax,- ScopedTypeVariables, TypeFamilies, TypeOperators #-}+{-|+Module : SHETests+Description : Tests for SymmSHE.+Copyright : (c) Eric Crockett, 2011-2017+ Chris Peikert, 2011-2017+License : GPL-2+Maintainer : ecrockett0@email.com+Stability : experimental+Portability : POSIX -module SHETests (sheTests) where+Tests for SymmSHE.+-} -import Apply.SHE-import GenArgs-import GenArgs.SHE-import Tests hiding (hideArgs)-import Utils+{-# LANGUAGE DataKinds #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE PartialTypeSignatures #-}+{-# LANGUAGE PolyKinds #-}+{-# LANGUAGE RebindableSyntax #-}+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE TypeFamilies #-}+{-# LANGUAGE TypeOperators #-} +{-# OPTIONS_GHC -fno-warn-partial-type-signatures #-}++module SHETests (sheTests, decTest, modSwPTTest, ksTests, twemTests, tunnelTests) where+ import Control.Applicative import Control.Monad import Control.Monad.Random-import Control.Monad.State import Crypto.Lol import Crypto.Lol.Applications.SymmSHE-import qualified Crypto.Lol.Cyclotomic.Tensor.CTensor as CT-import qualified Crypto.Lol.Cyclotomic.Tensor.RepaTensor as RT+import Crypto.Lol.Tests+import Crypto.Lol.Utils.ShowType import qualified Test.Framework as TF-import Test.Framework.Providers.QuickCheck2 -v :: Double-v = 1+sheTests :: forall t m m' zp zq . (_)+ => Proxy '(m,m',zp,zq) -> Proxy t -> TF.Test+sheTests _ _ =+ let ptmr = Proxy::Proxy '(t,m,m',zp,zq)+ in testGroup (showType ptmr) $ ($ ptmr) <$> [+ genTestArgs "DecU . Enc" prop_encDecU,+ genTestArgs "AddPub" prop_addPub,+ genTestArgs "MulScal" prop_mulScal,+ genTestArgs "MulPub" prop_mulPub,+ genTestArgs "ScalarPub" prop_addScalar,+ genTestArgs "CTAdd" prop_ctadd,+ genTestArgs "CTAdd2" prop_ctadd2,+ genTestArgs "CTMul" prop_ctmul,+ genTestArgs "CT zero" prop_ctzero,+ genTestArgs "CT one" prop_ctone] -hideArgs :: forall a rnd bnch.- (GenArgs (StateT (Maybe (SKOf a)) rnd) bnch, MonadRandom rnd,- ShowType a, ResultOf bnch ~ Test a)- => bnch -> Proxy a -> rnd TF.Test-hideArgs f p = do- res <- evalStateT (genArgs f) (Nothing :: Maybe (SKOf a))- case res of- Test b -> return $ testProperty (showType p) b- TestM b -> testProperty (showType p) <$> b+-- zq must be liftable+decTest :: forall t m m' zp zq . (_)+ => Proxy '(m,m',zp,zq) -> Proxy t -> TF.Test+decTest _ _ =+ let ptmr = Proxy::Proxy '(t,m,m',zp,zq)+ in testGroup (showType ptmr)+ [genTestArgs "Dec . Enc" prop_encDec ptmr] -sheTests :: [TF.Test]-sheTests =- [testGroupM "Dec . Enc" $ applyDec decParams $ hideArgs prop_encDec,- testGroupM "DecU . Enc" $ applyCTFunc ctParams $ hideArgs prop_encDecU,- testGroupM "AddPub" $ applyCTFunc ctParams $ hideArgs prop_addPub,- testGroupM "MulPub" $ applyCTFunc ctParams $ hideArgs prop_mulPub,- testGroupM "ScalarPub" $ applyCTFunc ctParams $ hideArgs prop_addScalar,- testGroupM "CTAdd" $ applyCTFunc ctParams $ hideArgs prop_ctadd,- testGroupM "CTMul" $ applyCTFunc ctParams $ hideArgs prop_ctmul,- testGroupM "CT zero" $ applyCTFunc ctParams $ hideArgs prop_ctzero,- testGroupM "CT one" $ applyCTFunc ctParams $ hideArgs prop_ctone,- testGroupM "ModSwitch PT" modSwPTTests,- testGroupM "Tunnel" tunnelTests,- testGroupM "Twace" $ applyCTTwEm twoIdxParams $ hideArgs prop_cttwace,- testGroupM "Embed" $ applyCTTwEm twoIdxParams $ hideArgs prop_ctembed,- testGroupM "KSLin" $ applyKSQ ksqParams $ hideArgs prop_ksLin,- testGroupM "keySwitch" $ applyKSQ ksqParams $ hideArgs prop_ksQuad- ]+modSwPTTest :: forall t m m' zp zp' zq . (_)+ => Proxy '(m,m',zp,zp',zq) -> Proxy t -> TF.Test+modSwPTTest _ _ =+ let ptmr = Proxy::Proxy '(t,m,m',zp,zp',zq)+ in testGroup (showType ptmr)+ [genTestArgs "ModSwitch PT" prop_modSwPT ptmr] -type CTCombos = '[- '(F7, F7, Zq 2,Zq (19393921 ** 18869761)),- '(F7, F21,Zq 2,Zq (19393921 ** 18869761)),- '(F2, F8, Zq 2,Zq 536871001),- '(F1, F8, Zq 2,Zq 536871001),- '(F4, F12,Zq 2,Zq 2148249601),- '(F4, F8, Zq 3,Zq 2148249601),- '(F7, F7, Zq 4,Zq (19393921 ** 18869761)),- '(F7, F21,Zq 4,Zq (19393921 ** 18869761)),- '(F1, F4, Zq 4,Zq 18869761),- '(F4, F4, Zq 4,Zq 18869761),- '(F14,F14,Zq 4,Zq 18869761),- '(F28,F28,Zq 4,Zq 18869761),- '(F28,F28,Zq 4,Zq 80221),- '(F1, F8, Zq 4,Zq 536871001),- '(F2, F8, Zq 4,Zq 536871001),- '(F4, F12,Zq 8,Zq 2148249601)- ]+ksTests :: forall t m m' zp zq zq' gad . (_)+ => Proxy '(m,m',zp,zq,zq') -> Proxy gad -> Proxy t -> TF.Test+ksTests _ _ _ =+ let ptmr = Proxy::Proxy '(t,m,m',zp,zq,zq',gad)+ in testGroup (showType ptmr) $ ($ ptmr) <$> [+ genTestArgs "KSLin" prop_ksLin,+ genTestArgs "KSQuad" prop_ksQuad] -type Gadgets = '[TrivGad, BaseBGad 2]-type Tensors = '[CT.CT,RT.RT]-type MM'PQCombos =- '[ '(F1, F7, Zq 2, Zq (19393921 ** 18869761)),- '(F2, F4, Zq 8, Zq (2148854401 ** 2148249601)),- '(F4, F12, Zq 2, Zq (2148854401 ** 2148249601)),- '(F8, F64, Zq 2, Zq (2148854401 ** 2148249601)),- '(F3, F27, Zq 2, Zq (2148854401 ** 2148249601)),- '(F2, F4, Zq 8, Zq (2148854401 ** 2148249601 ** 2150668801)),- '(F4, F12, Zq 2, Zq (2148854401 ** 2148249601 ** 2150668801)),- '(F8, F64, Zq 2, Zq (2148854401 ** 2148249601 ** 2150668801)),- '(F3, F27, Zq 2, Zq (2148854401 ** 2148249601 ** 2150668801))]+twemTests :: forall t r r' s s' zp zq . (_)+ => Proxy '(r,r',s,s',zp,zq) -> Proxy t -> TF.Test+twemTests _ _ =+ let ptmr = Proxy::Proxy '(t,r,r',s,s',zp,zq)+ in testGroup (showType ptmr) [+ genTestArgs "Embed" prop_ctembed ptmr,+ genTestArgs "Twace" prop_cttwace ptmr] +tunnelTests :: forall t r r' s s' zp zq gad . (_)+ => Proxy '(r,r',s,s',zp,zq) -> Proxy gad -> Proxy t -> TF.Test+tunnelTests _ _ _ =+ let ptmr = Proxy::Proxy '(t,r,r',s,s',zp,zq,gad)+ in testGroup (showType ptmr)+ [genTestArgs "Tunnel" prop_ringTunnel ptmr] -type CTParams = ( '(,) <$> Tensors) <*> CTCombos-ctParams :: Proxy CTParams-ctParams = Proxy -type DecParams = ( '(,) <$> Tensors) <*> (Nub (Filter Liftable CTCombos))-decParams :: Proxy DecParams-decParams = Proxy -type Zq'Params = ( '(,) <$> Tensors) <*> (Map AddZq (Filter NonLiftable MM'PQCombos))-type KSQParams = ( '(,) <$> Gadgets) <*> Zq'Params-ksqParams :: Proxy KSQParams-ksqParams = Proxy -type TwoIdxParams = ( '(,) <$> Tensors) <*> '[ '(F1, F7, F3, F21, Zq 2, Zq 18869761)]-twoIdxParams :: Proxy TwoIdxParams-twoIdxParams = Proxy -prop_ksLin :: (DecryptUCtx t m m' z zp zq, Eq (Cyc t m zp))- => KSLinear t m m' z zp zq zq' gad- -> PTCT m zp (Cyc t m' zq)- -> Test '(t,m,m',zp,zq,zq',gad)-prop_ksLin (KSL kswlin skout) (PTCT x' x) =- let y = kswlin x- y' = decryptUnrestricted skout y- in test $ x' == y'+prop_encDecU :: forall t m m' z zp zq . (z ~ LiftOf zp, _)+ => PT (Cyc t m zp) -> SK (Cyc t m' z) -> Test '(t,m,m',zp,zq)+prop_encDecU x sk = testIO $ do+ y :: CT m zp (Cyc t m' zq) <- encrypt sk x+ let x' = decryptUnrestricted sk $ y+ return $ x == x' -prop_ksQuad :: (Ring (CT m zp (Cyc t m' zq)),- DecryptUCtx t m m' z zp zq,- Eq (Cyc t m zp))- => SK (Cyc t m' z)- -> KSHint m zp t m' zq gad zq'- -> PTCT m zp (Cyc t m' zq)- -> PTCT m zp (Cyc t m' zq)- -> Test '(t,m,m',zp,zq,zq',gad)-prop_ksQuad sk (KeySwitch kswq) (PTCT y1 x1) (PTCT y2 x2) =- let x' = kswq $ x1*x2- y = y1*y2- x = decryptUnrestricted sk x'- in test $ y == x+prop_addPub :: forall t m m' z zp zq . (z ~ LiftOf zp, _)+ => Cyc t m zp+ -> PT (Cyc t m zp)+ -> SK (Cyc t m' z)+ -> Test '(t,m,m',zp,zq)+prop_addPub a pt sk = testIO $ do+ ct :: CT m zp (Cyc t m' zq) <- encrypt sk pt+ let ct' = addPublic a ct+ pt' = decryptUnrestricted sk ct'+ return $ pt' == (a+pt) -prop_addPub :: forall t m m' z zp zq .- (DecryptUCtx t m m' z zp zq,- AddPublicCtx t m m' zp zq,- Eq (Cyc t m zp))- => SK (Cyc t m' z)- -> Cyc t m zp- -> PTCT m zp (Cyc t m' zq)+prop_mulScal :: forall t m m' z zp zq . (z ~ LiftOf zp, _)+ => zp+ -> PT (Cyc t m zp)+ -> SK (Cyc t m' z) -> Test '(t,m,m',zp,zq)-prop_addPub sk x (PTCT y' y) =- let xy = addPublic x y- xy' = decryptUnrestricted sk xy- in test $ xy' == (x+y')+prop_mulScal a pt sk = testIO $ do+ ct :: CT m zp (Cyc t m' zq) <- encrypt sk pt+ let ct' = mulScalar a ct+ pt' = decryptUnrestricted sk ct'+ return $ pt' == ((scalarCyc a) * pt) -prop_mulPub :: (DecryptUCtx t m m' z zp zq,- MulPublicCtx t m m' zp zq,- Eq (Cyc t m zp))- => SK (Cyc t m' z)- -> Cyc t m zp- -> PTCT m zp (Cyc t m' zq)+prop_mulPub :: forall t m m' z zp zq . (z ~ LiftOf zp, _)+ => Cyc t m zp+ -> PT (Cyc t m zp)+ -> SK (Cyc t m' z) -> Test '(t,m,m',zp,zq)-prop_mulPub sk x (PTCT y' y) =- let xy = mulPublic x y- xy' = decryptUnrestricted sk xy- in test $ xy' == (x*y')+prop_mulPub a pt sk = testIO $ do+ ct :: CT m zp (Cyc t m' zq) <- encrypt sk pt+ let ct' = mulPublic a ct+ pt' = decryptUnrestricted sk ct'+ return $ pt' == (a*pt) -prop_addScalar :: (DecryptUCtx t m m' z zp zq,- AddScalarCtx t m' zp zq,- Eq (Cyc t m zp))- => SK (Cyc t m' z) -> zp -> PTCT m zp (Cyc t m' zq) -> Test '(t,m,m',zp,zq)-prop_addScalar sk c (PTCT x' x) =- let cx = addScalar c x- cx' = decryptUnrestricted sk cx- in test $ cx' == ((scalarCyc c)+x')+prop_addScalar :: forall t m m' z zp zq . (z ~ LiftOf zp, _)+ => zp -> PT (Cyc t m zp) -> SK (Cyc t m' z) -> Test '(t,m,m',zp,zq)+prop_addScalar c pt sk = testIO $ do+ ct :: CT m zp (Cyc t m' zq) <- encrypt sk pt+ let ct' = addScalar c ct+ pt' = decryptUnrestricted sk ct'+ return $ pt' == ((scalarCyc c)+pt) -prop_ctadd :: (DecryptUCtx t m m' z zp zq,- Additive (CT m zp (Cyc t m' zq)),- Eq (Cyc t m zp))- => SK (Cyc t m' z)- -> PTCT m zp (Cyc t m' zq)- -> PTCT m zp (Cyc t m' zq)+prop_ctadd :: forall t m m' z zp zq . (z ~ LiftOf zp, _)+ => PT (Cyc t m zp)+ -> PT (Cyc t m zp)+ -> SK (Cyc t m' z) -> Test '(t,m,m',zp,zq)-prop_ctadd sk (PTCT x1' x1) (PTCT x2' x2) =- let y = x1+x2- y' = decryptUnrestricted sk y- in test $ x1'+x2' == y'+prop_ctadd pt1 pt2 sk = testIO $ do+ ct1 :: CT m zp (Cyc t m' zq) <- encrypt sk pt1+ ct2 :: CT m zp (Cyc t m' zq) <- encrypt sk pt2+ let ct' = ct1 + ct2+ pt' = decryptUnrestricted sk ct'+ return $ pt1+pt2 == pt' -prop_ctmul :: (DecryptUCtx t m m' z zp zq,- Ring (CT m zp (Cyc t m' zq)),- Eq (Cyc t m zp))- => SK (Cyc t m' z)- -> PTCT m zp (Cyc t m' zq)- -> PTCT m zp (Cyc t m' zq)+-- tests adding with different scale values+prop_ctadd2 :: forall t m m' z zp zq . (z ~ LiftOf zp, _)+ => PT (Cyc t m zp)+ -> PT (Cyc t m zp)+ -> SK (Cyc t m' z) -> Test '(t,m,m',zp,zq)-prop_ctmul sk (PTCT x1' x1) (PTCT x2' x2) =- let y = x1*x2- y' = decryptUnrestricted sk y- in test $ x1'*x2' == y'+prop_ctadd2 pt1 pt2 sk = testIO $ do+ ct1 :: CT m zp (Cyc t m' zq) <- encrypt sk pt1+ ct2 :: CT m zp (Cyc t m' zq) <- encrypt sk pt2+ -- no-op to induce unequal scale values+ let ct' = ct1 + (modSwitchPT ct2)+ pt' = decryptUnrestricted sk ct'+ return $ pt1+pt2 == pt' -prop_ctzero :: forall t m m' z zp zq .- (DecryptUCtx t m m' z zp zq,- Additive (CT m zp (Cyc t m' zq)),- Eq (Cyc t m zp))+prop_ctmul :: forall t m m' z zp zq . (z ~ LiftOf zp, _)+ => PT (Cyc t m zp)+ -> PT (Cyc t m zp)+ -> SK (Cyc t m' z)+ -> Test '(t,m,m',zp,zq)+prop_ctmul pt1 pt2 sk = testIO $ do+ ct1 :: CT m zp (Cyc t m' zq) <- encrypt sk pt1+ ct2 :: CT m zp (Cyc t m' zq) <- encrypt sk pt2+ let ct' = ct1 * ct2+ pt' = decryptUnrestricted sk ct'+ return $ pt1*pt2 == pt'++prop_ctzero :: forall t m m' z zp (zq :: *) . (z ~ LiftOf zp, Fact m, _) => SK (Cyc t m' z) -> Test '(t,m,m',zp,zq) prop_ctzero sk = let z = decryptUnrestricted sk (zero :: CT m zp (Cyc t m' zq)) in test $ zero == z -prop_ctone :: forall t m m' z zp zq .- (DecryptUCtx t m m' z zp zq,- Ring (CT m zp (Cyc t m' zq)),- Eq (Cyc t m zp))+prop_ctone :: forall t m m' z zp (zq :: *) . (z ~ LiftOf zp, Fact m, _) => SK (Cyc t m' z) -> Test '(t,m,m',zp,zq) prop_ctone sk =- let z = decryptUnrestricted sk (one :: CT m zp (Cyc t m' zq))+ let z = decryptUnrestricted sk (one :: CT m zp (Cyc t m' zq)) :: Cyc t m zp in test $ one == z -prop_ctembed :: forall t r r' s s' z zp zq .- (DecryptUCtx t r r' z zp zq,- DecryptUCtx t s s' z zp zq,- r `Divides` s,- r' `Divides` s',- Eq (Cyc t s zp))- => SK (Cyc t r' z) -> PTCT r zp (Cyc t r' zq) -> Test '(t,r,r',s,s',zp,zq)-prop_ctembed sk (PTCT x' x) =- let y = embedCT x :: CT s zp (Cyc t s' zq)- y' = decryptUnrestricted (embedSK sk) y- in test $ (embed x' :: Cyc t s zp) == y'---- CT must be encrypted with key from small ring-prop_cttwace :: forall t r r' s s' z zp zq .- (Eq zp,- EncryptCtx t s s' z zp zq,- DecryptUCtx t r r' z zp zq,- r `Divides` s,- r' `Divides` s',- r ~ (FGCD r' s))- => SK (Cyc t r' z) -> Cyc t s zp -> Test '(t,r,r',s,s',zp,zq)-prop_cttwace sk x = testIO $ do- y :: CT s zp (Cyc t s' zq) <- encrypt (embedSK sk) x- let y' = twaceCT y :: CT r zp (Cyc t r' zq)- x' = decryptUnrestricted sk y'- return $ (twace x :: Cyc t r zp) == x'--prop_encDecU :: forall t m m' z zp zq .- (EncryptCtx t m m' z zp zq,- DecryptUCtx t m m' z zp zq,- Eq (Cyc t m zp))- => SK (Cyc t m' z) -> Cyc t m zp -> Test '(t,m,m',zp,zq)-prop_encDecU sk x = testIO $ do- y :: CT m zp (Cyc t m' zq) <- encrypt sk x- let x' = decryptUnrestricted sk $ y- return $ x == x'--prop_encDec :: forall t m m' z zp zq .- (EncryptCtx t m m' z zp zq,- DecryptCtx t m m' z zp zq,- Eq (Cyc t m zp))+prop_encDec :: forall t m m' z zp zq . (z ~ LiftOf zp, _) => SK (Cyc t m' z) -> Cyc t m zp -> Test '(t,m,m',zp,zq) prop_encDec sk x = testIO $ do y :: CT m zp (Cyc t m' zq) <- encrypt sk x let x' = decrypt sk $ y return $ x == x' -helper :: (Proxy '(t,b) -> a) -> Proxy t -> Proxy b -> a-helper f _ _ = f Proxy---- one-off tests, no hideArgsper-prop_modSwPT :: forall t m m' z zp zp' zq .- (Eq zp, Eq zp',- DecryptUCtx t m m' z zp zq,- DecryptUCtx t m m' z zp' zq,- ModSwitchPTCtx t m' zp zp' zq,- RescaleCyc (Cyc t) zp zp',- Mod zp, Mod zp',- ModRep zp ~ ModRep zp')- => SK (Cyc t m' z) -> CT m zp (Cyc t m' zq) -> Test '(t, '(m,m',zp',zp,zq))-prop_modSwPT sk y =+prop_modSwPT :: forall t m m' z zp (zp' :: *) (zq :: *) . (z ~ LiftOf zp, _)+ => PT (Cyc t m zp) -> SK (Cyc t m' z) -> Test '(t,m,m',zp,zp',zq)+prop_modSwPT pt sk = testIO $ do+ y :: CT m zp (Cyc t m' zq) <- encrypt sk pt let p = proxy modulus (Proxy::Proxy zp) p' = proxy modulus (Proxy::Proxy zp') z = (fromIntegral $ p `div` p')*y x = decryptUnrestricted sk z y' = modSwitchPT z :: CT m zp' (Cyc t m' zq) x'' = decryptUnrestricted sk y'- in test $ x'' == rescaleCyc Dec x+ return $ x'' == rescaleCyc Dec x -modSwPTTests :: [IO TF.Test]-modSwPTTests = (modSwPTTests' (Proxy::Proxy CT.CT)) ++ (modSwPTTests' (Proxy::Proxy RT.RT))- where modSwPTTests' p =- [helper (hideArgs prop_modSwPT) p (Proxy::Proxy '(F7,F21,Zq 4,Zq 8,Zq 18869761)),- helper (hideArgs prop_modSwPT) p (Proxy::Proxy '(F7,F42,Zq 2,Zq 4,Zq (18869761 ** 19393921)))]+prop_ksLin :: forall t m m' z zp (zq :: *) (zq' :: *) (gad :: *) . (z ~ LiftOf zp, _)+ => PT (Cyc t m zp) -> SK (Cyc t m' z) -> SK (Cyc t m' z) -> Test '(t,m,m',zp,zq,zq',gad)+prop_ksLin pt skin skout = testIO $ do+ ct <- encrypt skin pt+ kslHint :: KSLinearHint gad (Cyc t m' zq') <- ksLinearHint skout skin+ let ct' = keySwitchLinear kslHint ct :: CT m zp (Cyc t m' zq)+ pt' = decryptUnrestricted skout ct'+ return $ pt == pt' -tunnelTests :: [IO TF.Test]-tunnelTests = (tunnelTests' (Proxy::Proxy CT.CT)) ++ (tunnelTests' (Proxy::Proxy RT.RT))- where tunnelTests' p =- [helper (hideArgs prop_ringTunnel) p- (Proxy::Proxy '(F8,F40,F20,F60,Zq 4,Zq (18869761 ** 19393921),TrivGad))]+prop_ksQuad :: forall t m m' z zp zq (zq' :: *) (gad :: *) . (z ~ LiftOf zp, _)+ => PT (Cyc t m zp) -> PT (Cyc t m zp) -> SK (Cyc t m' z) -> Test '(t,m,m',zp,zq,zq',gad)+prop_ksQuad pt1 pt2 sk = testIO $ do+ ct1 :: CT m zp (Cyc t m' zq) <- encrypt sk pt1+ ct2 <- encrypt sk pt2+ ksqHint :: KSQuadCircHint gad (Cyc t m' zq') <- ksQuadCircHint sk+ let ct' = keySwitchQuadCirc ksqHint $ ct1*ct2+ ptProd = pt1*pt2+ pt' = decryptUnrestricted sk ct'+ return $ ptProd == pt' +prop_ctembed :: forall t r r' s s' z zp (zq :: *) . (z ~ LiftOf zp, Fact s', Fact s, _)+ => PT (Cyc t r zp) -> SK (Cyc t r' z) -> Test '(t,r,r',s,s',zp,zq)+prop_ctembed pt sk =testIO $ do+ ct :: CT r zp (Cyc t r' zq) <- encrypt sk pt+ let ct' = embedCT ct :: CT s zp (Cyc t s' zq)+ pt' = decryptUnrestricted (embedSK sk) ct'+ return $ embed pt == pt'++-- CT must be encrypted with key from small ring+prop_cttwace :: forall t r r' s s' z zp (zq :: *) . (z ~ LiftOf zp, Fact r, _)+ => PT (Cyc t s zp) -> SK (Cyc t r' z) -> Test '(t,r,r',s,s',zp,zq)+prop_cttwace pt sk = testIO $ do+ ct :: CT s zp (Cyc t s' zq) <- encrypt (embedSK sk) pt+ let ct' = twaceCT ct :: CT r zp (Cyc t r' zq)+ pt' = decryptUnrestricted sk ct'+ return $ twace pt == pt'+ prop_ringTunnel :: forall t e r s e' r' s' z zp zq gad .- (TunnelCtx t e r s e' r' s' z zp zq gad,+ (GenTunnelInfoCtx t e r s e' r' s' z zp zq gad,+ TunnelCtx t r s e' r' s' zp zq gad, EncryptCtx t r r' z zp zq,- GenSKCtx t r' z Double,- GenSKCtx t s' z Double, DecryptUCtx t s s' z zp zq, Random zp, Eq zp, e ~ FGCD r s, Fact e)- => Cyc t r zp -> Test '(t,'(r,r',s,s',zp,zq,gad))-prop_ringTunnel x = testIO $ do+ => PT (Cyc t r zp) -> SK (Cyc t r' z) -> SK (Cyc t s' z) -> Test '(t,r,r',s,s',zp,zq,gad)+prop_ringTunnel x skin skout = testIO $ do let totr = proxy totientFact (Proxy::Proxy r) tote = proxy totientFact (Proxy::Proxy e) basisSize = totr `div` tote -- choose a random linear function of the appropriate size bs :: [Cyc t s zp] <- replicateM basisSize getRandom- let f = (linearDec bs) \\ (gcdDivides (Proxy::Proxy r) (Proxy::Proxy s)) :: Linear t zp e r s+ let f = linearDec bs \\ (gcdDivides (Proxy::Proxy r) (Proxy::Proxy s)) :: Linear t zp e r s expected = evalLin f x \\ (gcdDivides (Proxy::Proxy r) (Proxy::Proxy s))- skin :: SK (Cyc t r' (LiftOf zp)) <- genSK v- skout :: SK (Cyc t s' (LiftOf zp)) <- genSK v y :: CT r zp (Cyc t r' zq) <- encrypt skin x- tunn <- proxyT (tunnelCT f skout skin) (Proxy::Proxy gad)- let y' = tunn y :: CT s zp (Cyc t s' zq)+ hints :: TunnelInfo gad t e r s e' r' s' zp zq <- tunnelInfo f skout skin+ let y' = tunnelCT hints y :: CT s zp (Cyc t s' zq) actual = decryptUnrestricted skout y' :: Cyc t s zp return $ expected == actual-
+ tests/TestAppsMain.hs view
@@ -0,0 +1,115 @@+{-|+Module : TestAppsMain+Description : Main driver for lol-apps tests.+Copyright : (c) Eric Crockett, 2011-2017+ Chris Peikert, 2011-2017+License : GPL-2+Maintainer : ecrockett0@email.com+Stability : experimental+Portability : POSIX++Main driver for lol-apps tests.+-}++{-# LANGUAGE DataKinds #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE PartialTypeSignatures #-}+{-# LANGUAGE PolyKinds #-}+{-# LANGUAGE TypeFamilies #-}+{-# LANGUAGE TypeOperators #-}++{-# OPTIONS_GHC -fno-warn-partial-type-signatures #-}++module TestAppsMain where++import Control.Monad.Random++import Crypto.Lol (Cyc)+import Crypto.Lol.Applications.SymmSHE hiding (CT)+import Crypto.Lol.Cyclotomic.Tensor.CPP+import Crypto.Lol.Cyclotomic.Tensor.Repa+import Crypto.Lol.Factored+import Crypto.Lol.Gadget+import Crypto.Lol.Types++import Data.Int+import Data.Proxy++import KHPRFTests+import SHETests+import Test.Framework++infixr 9 **+data a ** b++type family Zq (a :: k) :: * where+ Zq (a ** b) = (Zq a, Zq b)+ Zq q = (ZqBasic q Int64)++main :: IO ()+main = do+ flip defaultMainWithArgs ["--threads=1","--maximum-generated-tests=100"] $ concat+ [defaultTests (Proxy::Proxy CT) (Proxy::Proxy TrivGad),+ defaultTests (Proxy::Proxy RT) (Proxy::Proxy TrivGad)]++defaultTests :: _ => Proxy t -> Proxy gad -> [Test]+defaultTests pt pgad =+ [testGroup "SHE" $ ($ pt) <$> [+ sheTests (Proxy::Proxy '(F7, F7, Zq 2,Zq (19393921 ** 18869761))),+ sheTests (Proxy::Proxy '(F7, F21,Zq 2,Zq (19393921 ** 18869761))),+ sheTests (Proxy::Proxy '(F2, F8, Zq 2,Zq 536871001)),+ sheTests (Proxy::Proxy '(F1, F8, Zq 2,Zq 536871001)),+ sheTests (Proxy::Proxy '(F4, F12,Zq 2,Zq 2148249601)),+ sheTests (Proxy::Proxy '(F4, F8, Zq 3,Zq 2148249601)),+ sheTests (Proxy::Proxy '(F7, F7, Zq 4,Zq (19393921 ** 18869761))),+ sheTests (Proxy::Proxy '(F7, F21,Zq 4,Zq (19393921 ** 18869761))),+ sheTests (Proxy::Proxy '(F1, F4, Zq 4,Zq 18869761)),+ sheTests (Proxy::Proxy '(F4, F4, Zq 4,Zq 18869761)),+ sheTests (Proxy::Proxy '(F14,F14,Zq 4,Zq 18869761)),+ sheTests (Proxy::Proxy '(F28,F28,Zq 4,Zq 18869761)),+ sheTests (Proxy::Proxy '(F28,F28,Zq 4,Zq 80221)),+ sheTests (Proxy::Proxy '(F1, F8, Zq 4,Zq 536871001)),+ sheTests (Proxy::Proxy '(F2, F8, Zq 4,Zq 536871001)),+ sheTests (Proxy::Proxy '(F4, F12,Zq 8,Zq 2148249601)),++ decTest (Proxy::Proxy '(F2, F8, Zq 2,Zq 536871001)),+ decTest (Proxy::Proxy '(F1, F8, Zq 2,Zq 536871001)),+ decTest (Proxy::Proxy '(F4, F12,Zq 2,Zq 2148249601)),+ decTest (Proxy::Proxy '(F4, F8, Zq 3,Zq 2148249601)),+ decTest (Proxy::Proxy '(F1, F4, Zq 4,Zq 18869761)),+ decTest (Proxy::Proxy '(F4, F4, Zq 4,Zq 18869761)),+ decTest (Proxy::Proxy '(F14,F14,Zq 4,Zq 18869761)),+ decTest (Proxy::Proxy '(F28,F28,Zq 4,Zq 18869761)),+ decTest (Proxy::Proxy '(F28,F28,Zq 4,Zq 80221)),+ decTest (Proxy::Proxy '(F1, F8, Zq 4,Zq 536871001)),+ decTest (Proxy::Proxy '(F2, F8, Zq 4,Zq 536871001)),+ decTest (Proxy::Proxy '(F4, F12,Zq 8,Zq 2148249601)),++ modSwPTTest (Proxy::Proxy '(F7,F21,Zq 4,Zq 8,Zq 18869761)),+ modSwPTTest (Proxy::Proxy '(F7,F42,Zq 2,Zq 4,Zq (18869761 ** 19393921))),++ ksTests (Proxy::Proxy '(F1, F7, Zq 2, Zq 19393921, Zq (19393921 ** 18869761))) pgad,+ ksTests (Proxy::Proxy '(F2, F4, Zq 8, Zq 2148854401, Zq (2148854401 ** 2148249601))) pgad,+ ksTests (Proxy::Proxy '(F4, F12, Zq 2, Zq 2148854401, Zq (2148854401 ** 2148249601))) pgad,+ ksTests (Proxy::Proxy '(F8, F64, Zq 2, Zq 2148854401, Zq (2148854401 ** 2148249601))) pgad,+ ksTests (Proxy::Proxy '(F3, F27, Zq 2, Zq 2148854401, Zq (2148854401 ** 2148249601))) pgad,+ ksTests (Proxy::Proxy '(F2, F4, Zq 8, Zq 2148854401, Zq (2148854401 ** 2148249601 ** 2150668801))) pgad,+ ksTests (Proxy::Proxy '(F4, F12, Zq 2, Zq 2148854401, Zq (2148854401 ** 2148249601 ** 2150668801))) pgad,+ ksTests (Proxy::Proxy '(F8, F64, Zq 2, Zq 2148854401, Zq (2148854401 ** 2148249601 ** 2150668801))) pgad,+ ksTests (Proxy::Proxy '(F3, F27, Zq 2, Zq 2148854401, Zq (2148854401 ** 2148249601 ** 2150668801))) pgad,++ twemTests (Proxy::Proxy '(F1, F7, F3, F21, Zq 2, Zq 18869761)),++ tunnelTests (Proxy::Proxy '(F8,F40,F20,F60,Zq 4,Zq (18869761 ** 19393921))) pgad],+ testGroup "KHPRF" $ ($ pt) <$> [+ khprfTests (Proxy::Proxy '(F32, Zq 2, Zq 8, BaseBGad 2)),+ khprfTests (Proxy::Proxy '(F32, Zq 2, Zq 8, TrivGad)),+ khprfTests (Proxy::Proxy '(F32, Zq 32, Zq 257, BaseBGad 2))]+ ]++-- EAC: is there a simple way to parameterize the variance?+-- generates a secret key with scaled variance 1.0+instance (GenSKCtx t m' z Double) => Random (SK (Cyc t m' z)) where+ random = runRand $ genSK (1 :: Double)+ randomR = error "randomR not defined for SK"
− utils/Apply.hs
@@ -1,17 +0,0 @@-{-# LANGUAGE DataKinds, FlexibleInstances, MultiParamTypeClasses, PolyKinds,- TypeFamilies, TypeOperators #-}---- applies functions to proxy arguments-module Apply where---- not associated due to the generic instance below:--- any definition of ArgsCtx would conflict with specific instances-data family ArgsCtx ctx--class (params :: [k]) `Satisfy` (ctx :: *) where- run :: proxy params- -> (ArgsCtx ctx -> rnd res)- -> [rnd res]--instance '[] `Satisfy` ctx where- run _ _ = []
− utils/Apply/SHE.hs
@@ -1,235 +0,0 @@-{-# LANGUAGE ConstraintKinds #-}-{-# LANGUAGE DataKinds #-}-{-# LANGUAGE FlexibleContexts #-}-{-# LANGUAGE FlexibleInstances #-}-{-# LANGUAGE GADTs #-}-{-# LANGUAGE MultiParamTypeClasses #-}-{-# LANGUAGE NoImplicitPrelude #-}-{-# LANGUAGE PolyKinds #-}-{-# LANGUAGE RankNTypes #-}-{-# LANGUAGE RebindableSyntax #-}-{-# LANGUAGE ScopedTypeVariables #-}-{-# LANGUAGE TypeFamilies #-}-{-# LANGUAGE TypeOperators #-}-{-# LANGUAGE UndecidableInstances #-}--module Apply.SHE-(AddZq-,Liftable-,NonLiftable-,RoundDown-,applyKSQ-,applyRescale-,applyDec-,applyCTFunc-,applyEnc-,applyTunn-,applyCTTwEm-) where--import Apply-import GenArgs-import Utils--import Control.DeepSeq-import Control.Monad.Random-import Control.Monad.State--import Crypto.Lol-import Crypto.Lol.Applications.SymmSHE-import Crypto.Lol.Types.ZPP--import Crypto.Random.DRBG--import Data.Promotion.Prelude.Eq-import Data.Singletons-import Data.Singletons.TypeRepStar ()--data AddZq :: TyFun (Factored, Factored, *, *) (Factored, Factored, *, *, *) -> *-type instance Apply AddZq '(m,m',zp,zq) = '(m,m',zp,RoundDown zq,zq)--data Liftable :: TyFun (Factored, Factored, *, *) Bool -> *-type instance Apply Liftable '(m,m',zp,zq) = Int64 :== (LiftOf zq)--data NonLiftable :: TyFun (Factored, Factored, *, *) Bool -> *-type instance Apply NonLiftable '(m,m',zp,zq) = Integer :== (LiftOf zq)--type family RoundDown zq where- RoundDown (a,(b,c)) = (b,c)- RoundDown ((a,b),c) = (a,b)- RoundDown (a,b) = a--data DecCtxD-type DecCtx t m m' zp zq =- (Random zp, NFElt zp,- EncryptCtx t m m' (LiftOf zp) zp zq,- -- ^ these provide the context to generate the parameters- DecryptCtx t m m' (LiftOf zp) zp zq, Eq zp,- ShowType '(t,m,m',zp,zq))-data instance ArgsCtx DecCtxD where- DecD :: (DecCtx t m m' zp zq) => Proxy '(t,m,m',zp,zq) -> ArgsCtx DecCtxD-instance (params `Satisfy` DecCtxD, DecCtx t m m' zp zq)- => ( '(t, '(m,m',zp,zq)) ': params) `Satisfy` DecCtxD where- run _ f = f (DecD (Proxy::Proxy '(t,m,m',zp,zq))) : run (Proxy::Proxy params) f--applyDec :: (params `Satisfy` DecCtxD) =>- Proxy params ->- (forall t m m' zp zq . (DecCtx t m m' zp zq)- => Proxy '(t,m,m',zp,zq) -> rnd res)- -> [rnd res]-applyDec params g = run params $ \(DecD p) -> g p--data TunnCtxD--- union of compatible constraints in benchmarks-type TunnCtx t r r' e e' s s' zp zq gad =- (NFData (CT s zp (Cyc t s' zq)),- ShowType '(t,r,r',s,s',zp,zq,gad),- EncryptCtx t r r' (LiftOf zp) zp zq,- EncryptCtx t s s' (LiftOf zp) zp zq,- TunnelCtx t e r s e' r' s' (LiftOf zp) zp zq gad,- e ~ FGCD r s,- ZPP zp, Random zp,- Fact e,- CElt t (ZpOf zp))-data instance ArgsCtx TunnCtxD where- TunnD :: (TunnCtx t r r' e e' s s' zp zq gad)- => Proxy '(t,r,r',s,s',zp,zq,gad) -> ArgsCtx TunnCtxD-instance (params `Satisfy` TunnCtxD, TunnCtx t r r' e e' s s' zp zq gad)- => ( '(gad, '(t, '( '(r,r',s,s'), '(zp,zq)))) ': params) `Satisfy` TunnCtxD where- run _ f = f (TunnD (Proxy::Proxy '(t,r,r',s,s',zp,zq,gad))) : run (Proxy::Proxy params) f--applyTunn :: (params `Satisfy` TunnCtxD) =>- Proxy params ->- (forall t r r' e e' s s' zp zq gad . (TunnCtx t r r' e e' s s' zp zq gad)- => Proxy '(t,r,r',s,s',zp,zq,gad) -> rnd res)- -> [rnd res]-applyTunn params g = run params $ \(TunnD p) -> g p--data CTEmCtxD--- union of compatible constraints in benchmarks-type CTEmCtx t r r' s s' zp zq =- (Random zp, Eq zp, -- CJP: added b/c CElt doesn't have them- DecryptUCtx t r r' (LiftOf zp) zp zq,- DecryptUCtx t s s' (LiftOf zp) zp zq,- ShowType '(t,r,r',s,s',zp,zq),- EncryptCtx t r r' (LiftOf zp) zp zq,- r `Divides` s,- r' `Divides` s',- s `Divides` s',- r ~ (FGCD r' s))-data instance ArgsCtx CTEmCtxD where- TwEmD :: (CTEmCtx t r r' s s' zp zq)- => Proxy '(t,r,r',s,s',zp,zq) -> ArgsCtx CTEmCtxD-instance (params `Satisfy` CTEmCtxD, CTEmCtx t r r' s s' zp zq)- => ( '(t, '(r,r',s,s',zp,zq)) ': params) `Satisfy` CTEmCtxD where- run _ f = f (TwEmD (Proxy::Proxy '(t,r,r',s,s',zp,zq))) : run (Proxy::Proxy params) f--applyCTTwEm :: (params `Satisfy` CTEmCtxD) =>- Proxy params ->- (forall t r r' s s' zp zq . (CTEmCtx t r r' s s' zp zq)- => Proxy '(t,r,r',s,s',zp,zq) -> rnd res)- -> [rnd res]-applyCTTwEm params g = run params $ \(TwEmD p) -> g p---- allowed args: CT, KSHint, SK--- context for (*), (==), decryptUnrestricted-data KSQCtxD--- it'd be nice to make this associated to `Satsify`,--- but we have to use a *ton* of kind signatures if we do-type KSQCtx gad t m m' zp zq zq' =- (Random zp, Eq zp, -- CJP: added b/c CElt doesn't have them- EncryptCtx t m m' (LiftOf zp) zp zq,- DecryptUCtx t m m' (LiftOf zp) zp zq,- KeySwitchCtx gad t m' zp zq zq',- KSHintCtx gad t m' (LiftOf zp) zq',- -- ^ these provide the context to generate the parameters- Ring (CT m zp (Cyc t m' zq)),- -- Eq (Cyc t m zp),- Fact m, Fact m', CElt t zp, m `Divides` m',- Reduce (LiftOf zp) zq, Lift' zq, CElt t (LiftOf zp), ToSDCtx t m' zp zq, Reduce (LiftOf zq) zp,- -- ^ these provide the context for tests- NFData (CT m zp (Cyc t m' zq)),- ShowType '(t,m,m',zp,zq,zq',gad))- -- ^ these provide the context for benchmarks-data instance ArgsCtx KSQCtxD where- KSQD :: (KSQCtx gad t m m' zp zq zq')- => Proxy '(t,m,m',zp,zq,zq',gad) -> ArgsCtx KSQCtxD-instance (params `Satisfy` KSQCtxD, KSQCtx gad t m m' zp zq zq')- => ( '(gad , '(t, '(m, m', zp, zq, zq'))) ': params) `Satisfy` KSQCtxD where- run _ f = f (KSQD (Proxy::Proxy '(t,m,m',zp,zq,zq',gad))) : run (Proxy::Proxy params) f--applyKSQ :: (params `Satisfy` KSQCtxD) =>- Proxy params ->- (forall t m m' zp zq zq' gad . (KSQCtx gad t m m' zp zq zq')- => Proxy '(t,m,m',zp,zq,zq',gad) -> rnd res)- -> [rnd res]-applyKSQ params g = run params $ \(KSQD p) -> g p--data RescaleCtxD-type RescaleCtx t m m' zp zq zq' =- (Random zp,- EncryptCtx t m m' (LiftOf zp) zp zq',- ShowType '(t,m,m',zp,zq,zq'),- RescaleCyc (Cyc t) zq' zq,- NFData (CT m zp (Cyc t m' zq)),- ToSDCtx t m' zp zq')-data instance ArgsCtx RescaleCtxD where- RD :: (RescaleCtx t m m' zp zq zq')- => Proxy '(t,m,m',zp,zq,zq') -> ArgsCtx RescaleCtxD-instance (params `Satisfy` RescaleCtxD, RescaleCtx t m m' zp zq zq')- => ( '(t, '(m,m',zp,zq,zq')) ': params) `Satisfy` RescaleCtxD where- run _ f = f (RD (Proxy::Proxy '(t,m,m',zp,zq,zq'))) : run (Proxy::Proxy params) f--applyRescale :: (params `Satisfy` RescaleCtxD) =>- Proxy params ->- (forall t m m' zp zq zq' . (RescaleCtx t m m' zp zq zq')- => Proxy '(t,m,m',zp,zq,zq') -> rnd res)- -> [rnd res]-applyRescale params g = run params $ \(RD p) -> g p--data CTCtxD--- union of compatible constraints in benchmarks-type CTCtx t m m' zp zq =- (Random zp, Eq zp, NFElt zp, NFElt zq, -- CJP: CElt doesn't have these- EncryptCtx t m m' (LiftOf zp) zp zq,- Ring (CT m zp (Cyc t m' zq)),- AddPublicCtx t m m' zp zq,- DecryptUCtx t m m' (LiftOf zp) zp zq,- MulPublicCtx t m m' zp zq,- ShowType '(t,m,m',zp,zq))-data instance ArgsCtx CTCtxD where- CTD :: (CTCtx t m m' zp zq)- => Proxy '(t,m,m',zp,zq) -> ArgsCtx CTCtxD-instance (params `Satisfy` CTCtxD, CTCtx t m m' zp zq)- => ( '(t, '(m,m',zp,zq)) ': params) `Satisfy` CTCtxD where- run _ f = f (CTD (Proxy::Proxy '(t,m,m',zp,zq))) : run (Proxy::Proxy params) f--applyCTFunc :: (params `Satisfy` CTCtxD, MonadRandom rnd) =>- Proxy params- -> (forall t m m' zp zq . (CTCtx t m m' zp zq, Generatable (StateT (Maybe (SK (Cyc t m' (LiftOf zp)))) rnd) zp)- => Proxy '(t,m,m',zp,zq) -> rnd res)- -> [rnd res]-applyCTFunc params g = run params $ \(CTD p) -> g p--data EncCtxD-type EncCtx t m m' zp zq gen =- (Random zp, NFElt zp, NFElt zq,- EncryptCtx t m m' (LiftOf zp) zp zq,- Ring (CT m zp (Cyc t m' zq)),- AddPublicCtx t m m' zp zq,- MulPublicCtx t m m' zp zq,- ShowType '(t,m,m',zp,zq,gen),- CryptoRandomGen gen)-data instance ArgsCtx EncCtxD where- EncD :: (EncCtx t m m' zp zq gen)- => Proxy '(t,m,m',zp,zq,gen) -> ArgsCtx EncCtxD-instance (params `Satisfy` EncCtxD, EncCtx t m m' zp zq gen)- => ( '(gen, '(t, '(m,m',zp,zq))) ': params) `Satisfy` EncCtxD where- run _ f = f (EncD (Proxy::Proxy '(t,m,m',zp,zq,gen))) : run (Proxy::Proxy params) f--applyEnc :: (params `Satisfy` EncCtxD) =>- Proxy params- -> (forall t m m' zp zq gen . (EncCtx t m m' zp zq gen)- => Proxy '(t,m,m',zp,zq,gen) -> rnd res)- -> [rnd res]-applyEnc params g = run params $ \(EncD p) -> g p
− utils/Benchmarks.hs
@@ -1,44 +0,0 @@-{-# LANGUAGE FlexibleContexts, FlexibleInstances, MultiParamTypeClasses,- PolyKinds, RankNTypes, ScopedTypeVariables, TypeFamilies #-}--module Benchmarks-(Benchmarks.bench-,benchIO-,benchGroup-,hideArgs-,Bench(..)-,Benchmark-,NFData) where--import GenArgs-import Utils--import Control.DeepSeq-import Criterion as C--import Data.Proxy---- wrapper for Criterion's `nf`-bench :: NFData b => (a -> b) -> a -> Bench params-bench f = Bench . nf f---- wrapper for Criterion's `nfIO`-benchIO :: NFData b => IO b -> Bench params-benchIO = Bench . nfIO---- wrapper for Criterion's-benchGroup :: (Monad rnd) => String -> [rnd Benchmark] -> rnd Benchmark-benchGroup str = (bgroup str <$>) . sequence---- normalizes any function resulting in a Benchmark to--- one that takes a proxy for its arguments-hideArgs :: (GenArgs rnd bnch, Monad rnd, ShowType a,- ResultOf bnch ~ Bench a)- => bnch -> Proxy a -> rnd Benchmark-hideArgs f p = (C.bench (showType p) . unbench) <$> genArgs f--newtype Bench params = Bench {unbench :: Benchmarkable}--instance (Monad rnd) => GenArgs rnd (Bench params) where- type ResultOf (Bench params) = Bench params- genArgs = return
− utils/GenArgs.hs
@@ -1,31 +0,0 @@-{-# LANGUAGE FlexibleInstances, MultiParamTypeClasses, TypeFamilies #-}---- generates arguments to functions-module GenArgs where--import Control.Monad.Random-import Data.Proxy---- bnch represents a function whose arguments can be generated,--- resulting in a "NFValue"-class GenArgs rnd bnch where- type ResultOf bnch- genArgs :: bnch -> rnd (ResultOf bnch)--instance (Generatable rnd a, GenArgs rnd b,- Monad rnd, ResultOf b ~ ResultOf (a -> b))- => GenArgs rnd (a -> b) where- type ResultOf (a -> b) = ResultOf b- genArgs f = do- x <- genArg- genArgs $ f x---- a parameter that can be generated using a particular monad-class Generatable rnd arg where- genArg :: rnd arg--instance {-# Overlappable #-} (Random a, MonadRandom rnd) => Generatable rnd a where- genArg = getRandom--instance (Monad rnd) => Generatable rnd (Proxy a) where- genArg = return Proxy
− utils/GenArgs/SHE.hs
@@ -1,110 +0,0 @@-{-# LANGUAGE DataKinds, FlexibleContexts, FlexibleInstances, GADTs,- MultiParamTypeClasses, NoImplicitPrelude, PolyKinds,- RebindableSyntax, ScopedTypeVariables, TypeFamilies,- UndecidableInstances #-}--module GenArgs.SHE where--import GenArgs--import Control.Applicative-import Control.Monad.Random-import Control.Monad.State--import Crypto.Lol-import Crypto.Lol.Applications.SymmSHE-import Crypto.Lol.Types.ZPP----extract an SK type from a tuple of params-type family SKOf (a :: k) :: * where- SKOf '(t,m,m',zp,zq) = SK (Cyc t m' (LiftOf zp))- SKOf '(t,m,m',zp,zq,zq') = SK (Cyc t m' (LiftOf zp))- SKOf '(t,m,m',zp,zq,zq',gad) = SK (Cyc t m' (LiftOf zp))- SKOf '(t,r,r',s,s',zp,zq) = SK (Cyc t r' (LiftOf zp))- SKOf '(t,r,r',s,s',zp,zq,gad) = SK (Cyc t r' (LiftOf zp))- SKOf '(t,'(m,m',zp,zp',zq)) = SK (Cyc t m' (LiftOf zp))---- generates a secrete key with svar=1, using non-cryptographic randomness-instance (GenSKCtx t m z Double,- MonadRandom rnd,- MonadState (Maybe (SK (Cyc t m z))) rnd)- => Generatable rnd (SK (Cyc t m z)) where- genArg = do- msk <- get- case msk of- Just sk -> return sk- Nothing -> do- sk <- genSK (1 :: Double)- put $ Just sk- return sk--instance (Generatable rnd (PTCT m zp (Cyc t m' zq)), Monad rnd)- => Generatable rnd (CT m zp (Cyc t m' zq)) where- genArg = do- (PTCT _ ct) :: PTCT m zp (Cyc t m' zq) <- genArg- return ct---- use this data type in functions that need a circular key switch hint-newtype KSHint m zp t m' zq gad zq' = KeySwitch (CT m zp (Cyc t m' zq) -> CT m zp (Cyc t m' zq))-instance (Generatable rnd (SK (Cyc t m' z)),- z ~ LiftOf zp,- KeySwitchCtx gad t m' zp zq zq',- KSHintCtx gad t m' z zq',- MonadRandom rnd)- => Generatable rnd (KSHint m zp t m' zq gad zq') where- genArg = do- sk :: SK (Cyc t m' z) <- genArg- KeySwitch <$> proxyT (keySwitchQuadCirc sk) (Proxy::Proxy (gad,zq'))--newtype Tunnel t r r' s s' zp zq gad = Tunnel (CT r zp (Cyc t r' zq) -> CT s zp (Cyc t s' zq))-instance (Generatable rnd (SK (Cyc t r' z)),- z ~ LiftOf zp,- TunnelCtx t e r s e' r' s' z zp zq gad,- e ~ FGCD r s,- ZPP zp,- Fact e,- CElt t (ZpOf zp),- MonadRandom rnd,- Generatable (StateT (Maybe (SK (Cyc t s' z))) rnd) (SK (Cyc t s' z)))- => Generatable rnd (Tunnel t r r' s s' zp zq gad) where- genArg = do- skin :: SK (Cyc t r' z) <- genArg- -- EAC: bit of a hack for now- skout <- evalStateT genArg (Nothing :: Maybe (SK (Cyc t s' z)))- let crts :: [Cyc t s zp] = proxy crtSet (Proxy::Proxy e)\\ gcdDivides (Proxy::Proxy r) (Proxy::Proxy s)- r = proxy totientFact (Proxy::Proxy r)- e = proxy totientFact (Proxy::Proxy e)- dim = r `div` e- -- only take as many crts as we need- -- otherwise linearDec fails- linf :: Linear t zp e r s = linearDec (take dim crts) \\ gcdDivides (Proxy::Proxy r) (Proxy::Proxy s)- Tunnel <$> proxyT (tunnelCT linf skout skin) (Proxy::Proxy gad)--data KSLinear t m m' z zp zq (zq' :: *) (gad :: *) = KSL (CT m zp (Cyc t m' zq) -> CT m zp (Cyc t m' zq)) (SK (Cyc t m' z))-instance (KeySwitchCtx gad t m' zp zq zq',- KSHintCtx gad t m' z zq',- MonadRandom rnd,- Generatable rnd (SK (Cyc t m' z)), -- for skin- Generatable (StateT (Maybe (SK (Cyc t m' z))) rnd) (SK (Cyc t m' z))) -- for skout- => Generatable rnd (KSLinear t m m' z zp zq zq' gad) where- genArg = do- skin <- genArg- -- generate an independent key- skout <- evalStateT genArg (Nothing :: Maybe (SK (Cyc t m' z)))- ksl <- proxyT (keySwitchLinear skout skin) (Proxy::Proxy (gad,zq'))- return $ KSL ksl skout--data PTCT m zp rq where- PTCT :: Cyc t m zp -> CT m zp (Cyc t m' zq) -> PTCT m zp (Cyc t m' zq)-instance (EncryptCtx t m m' z zp zq,- z ~ LiftOf zp,- MonadRandom rnd,- Generatable rnd (SK (Cyc t m' z)),- Generatable rnd (Cyc t m zp),- rq ~ Cyc t m' zq)- => Generatable rnd (PTCT m zp rq) where- genArg = do- sk :: SK (Cyc t m' z) <- genArg- pt <- genArg- ct <- encrypt sk pt- return $ PTCT pt ct
− utils/TestTypes.hs
@@ -1,38 +0,0 @@-{-# LANGUAGE ConstraintKinds, DataKinds, FlexibleContexts,- FlexibleInstances, MultiParamTypeClasses,- NoImplicitPrelude, PolyKinds, RankNTypes, RebindableSyntax,- ScopedTypeVariables, TypeFamilies, TypeOperators #-}--module TestTypes-(SmoothQ1, SmoothQ2, SmoothQ3-,SmoothZQ1, SmoothZQ2, SmoothZQ3-,Zq-,ZQ1,ZQ2,ZQ3) where--import Control.Monad.Random--import Crypto.Lol--import Utils--import Test.QuickCheck.Monadic--instance (MonadRandom m) => MonadRandom (PropertyM m) where- getRandom = run getRandom- getRandoms = run getRandoms- getRandomR r = run $ getRandomR r- getRandomRs r = run $ getRandomRs r---- three 24-bit moduli, enough to handle rounding for p=32 (depth-4 circuit at ~17 bits per mul)-type ZQ1 = Zq 18869761-type ZQ2 = Zq (19393921 ** 18869761)-type ZQ3 = Zq (19918081 ** 19393921 ** 18869761)---- the next three moduli are "good" for any index dividing 128*27*25*7-type SmoothQ1 = 2148249601-type SmoothQ2 = 2148854401-type SmoothQ3 = 2150668801--type SmoothZQ1 = Zq 2148249601-type SmoothZQ2 = Zq (2148854401 ** 2148249601)-type SmoothZQ3 = Zq (2148854401 ** 2148249601 ** 2150668801)
− utils/Tests.hs
@@ -1,47 +0,0 @@-{-# LANGUAGE FlexibleContexts, FlexibleInstances, GADTs, MultiParamTypeClasses,- PolyKinds, RankNTypes, ScopedTypeVariables, TypeFamilies #-}-module Tests-(test-,testIO-,TF.testGroup-,testGroupM-,hideArgs-,Test(..)) where--import GenArgs-import Utils--import Control.Monad.Random--import Data.Proxy--import qualified Test.Framework as TF-import Test.Framework.Providers.QuickCheck2--test :: Bool -> Test params-test = Test--testIO :: (forall m . MonadRandom m => m Bool) -> Test params-testIO = TestM--testGroupM :: String -> [IO TF.Test] -> TF.Test-testGroupM str = TF.buildTest . (TF.testGroup str <$>) . sequence---- normalizes any function resulting in a Benchmark to--- one that takes a proxy for its arguments-hideArgs :: (GenArgs rnd bnch, MonadRandom rnd, ShowType a,- ResultOf bnch ~ Test a)- => bnch -> Proxy a -> rnd TF.Test-hideArgs f p = do- res <- genArgs f- case res of- Test b -> return $ testProperty (showType p) b- TestM b -> testProperty (showType p) <$> b--data Test params where- Test :: Bool -> Test params- TestM :: (forall m . MonadRandom m => m Bool) -> Test params--instance (MonadRandom rnd) => GenArgs rnd (Test params) where- type ResultOf (Test params) = Test params- genArgs = return
− utils/Utils.hs
@@ -1,127 +0,0 @@-{-# LANGUAGE ConstraintKinds, DataKinds, FlexibleContexts, FlexibleInstances,- GADTs, KindSignatures, MultiParamTypeClasses, PolyKinds,- RankNTypes, ScopedTypeVariables, TypeFamilies, TypeOperators,- UndecidableInstances #-}--module Utils-(Zq-,type (**)-,type (<$>)-,type (<*>)--,module Data.Promotion.Prelude.List-,goodQs-,showType-,ShowType) where--import Crypto.Lol (Int64,Fact,valueFact,Mod(..), Proxy(..), proxy, TrivGad, BaseBGad)-import Crypto.Lol.Reflects-import Crypto.Lol.Cyclotomic.Tensor.RepaTensor-import Crypto.Lol.Cyclotomic.Tensor.CTensor-import Crypto.Lol.Types.ZqBasic-import Crypto.Random.DRBG--import Data.Promotion.Prelude.List--import Math.NumberTheory.Primes.Testing (isPrime)---- an infinite list of primes greater than the input and congruent to--- 1 mod m-goodQs :: (Integral i) => i -> i -> [i]-goodQs m lower = checkVal (lower + ((m-lower) `mod` m) + 1)- where checkVal v = if (isPrime (fromIntegral v :: Integer))- then v : checkVal (v+m)- else checkVal (v+m)--infixr 9 **-data a ** b--type family Zq (a :: k) :: * where- Zq (a ** b) = (Zq a, Zq b)- Zq q = (ZqBasic q Int64)---type family (f :: (k1 -> k2)) <$> (xs :: [k1]) where- f <$> '[] = '[]- f <$> (x ': xs) = (f x) ': (f <$> xs)--type family (fs :: [k1 -> k2]) <*> (xs :: [k1]) where- fs <*> xs = Go fs xs xs--type family Go (fs :: [k1 -> k2]) (xs :: [k1]) (ys :: [k1]) where- Go '[] xs ys = '[]- Go (f ': fs) '[] ys = Go fs ys ys- Go (f ': fs) (x ': xs) ys = (f x) ': (Go (f ': fs) xs ys)---------- a wrapper type for printing test/benchmark names-data ArgType (a :: k) = AT---- allows automatic printing of test parameters-type ShowType a = Show (ArgType a)--showType :: forall a . (Show (ArgType a)) => Proxy a -> String-showType _ = show (AT :: ArgType a)--instance Show (ArgType HashDRBG) where- show _ = "HashDRBG"--instance (Fact m) => Show (ArgType m) where- show _ = "F" ++ show (proxy valueFact (Proxy::Proxy m))--instance (Mod (ZqBasic q i), Show i) => Show (ArgType (ZqBasic q i)) where- show _ = "Q" ++ show (proxy modulus (Proxy::Proxy (ZqBasic q i)))--instance Show (ArgType RT) where- show _ = "RT"--instance Show (ArgType CT) where- show _ = "CT"--instance Show (ArgType Int64) where- show _ = "Int64"--instance Show (ArgType TrivGad) where- show _ = "TrivGad"--instance (Reflects b Integer) => Show (ArgType (BaseBGad (b :: k))) where- show _ = "Base" ++ show (proxy value (Proxy::Proxy b) :: Integer) ++ "Gad"---- for RNS-style moduli-instance (Show (ArgType a), Show (ArgType b)) => Show (ArgType (a,b)) where- show _ = show (AT :: ArgType a) ++ "*" ++ show (AT :: ArgType b)---- we use tuples rather than lists because types in a list must have the same kind,--- but tuples permit different kinds-instance (Show (ArgType a), Show (ArgType b))- => Show (ArgType '(a,b)) where- show _ = show (AT :: ArgType a) ++ " " ++ show (AT :: ArgType b)--instance (Show (ArgType a), Show (ArgType '(b,c)))- => Show (ArgType '(a,b,c)) where- show _ = show (AT :: ArgType a) ++ " " ++ show (AT :: ArgType '(b,c))--instance (Show (ArgType a), Show (ArgType '(b,c,d)))- => Show (ArgType '(a,b,c,d)) where- show _ = show (AT :: ArgType a) ++ " " ++ show (AT :: ArgType '(b,c,d))--instance (Show (ArgType a), Show (ArgType '(b,c,d,e)))- => Show (ArgType '(a,b,c,d,e)) where- show _ = show (AT :: ArgType a) ++ " " ++ show (AT :: ArgType '(b,c,d,e))--instance (Show (ArgType a), Show (ArgType '(b,c,d,e,f)))- => Show (ArgType '(a,b,c,d,e,f)) where- show _ = show (AT :: ArgType a) ++ " " ++ show (AT :: ArgType '(b,c,d,e,f))--instance (Show (ArgType a), Show (ArgType '(b,c,d,e,f,g)))- => Show (ArgType '(a,b,c,d,e,f,g)) where- show _ = show (AT :: ArgType a) ++ " " ++ show (AT :: ArgType '(b,c,d,e,f,g))--instance (Show (ArgType a), Show (ArgType '(b,c,d,e,f,g,h)))- => Show (ArgType '(a,b,c,d,e,f,g,h)) where- show _ = show (AT :: ArgType a) ++ " " ++ show (AT :: ArgType '(b,c,d,e,f,g,h))