lol-apps-0.1.0.0: utils/GenArgs/SHE.hs
{-# 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 hiding (CT)
import Crypto.Lol.Applications.SymmSHE
import Crypto.Lol.Cyclotomic.Linear
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