Verifiable Computing
In haskell
\(\color{#EC5f67}{\text{PRIVATE}} \)
\(\color{#6699CC}{\text{Public}} \)
Motivation
Efficiently verify the correctness of computations without executing them
Example
ALICE has query \( \color{#6699CC}u \)
BOB HAS private \( \color{#EC5f67} w \)
Alice wants to know
Desired
ALICE wants computation correctness
Bob wants his secrets, \(\color{#EC5f67}{\text{secret}} \)
Example
USES
Pre Image
Prove you have a pre image to a hash function
Account Balance
Prove your account has enough monies for a transaction
Membership
Prove you are part of a group without revealing your identity
Sealed BID auction
Prove who won, without revealing any of the bids
GENERAL Approach
Put Computation in right
"FORM"
evaluate "FORM" WITH PRIVATE INPUTS
YieldING A PROof
THAT EACH part WAS executing according TO THE PRESHARED "form"
Mathematical
Wizardry
THAT FALLS OUT OF ALGEbraic
GEOMetry
BACKGROUND
pt 1
PARTIAL HOMOmophic ENCRyption
Performing a limited set of operations on CIPHER TEXT
HOMOmophic ENCRyption
GROUP HOMOMORPHISM
For some cryptographic schemes this also works for encrypted values
HOMOmophic ENCRyption
Floor AREA of my shed?
Width: 7m
LENGTH: 3m
ENTER THE CLOUD
Width: \( \color{#EC5F67}7\)m
Shed FLOOR AREA SOLver™
PRIVACY
LENgTH: \( \color{#EC5F67}3\)m
RSA to the rescue
GO CLOUD GO
Shed FLOOR SIZE SOLver™
BACKGROUND
pt 2
Pairing Crypto
A relation between 2 group elements that gives an output, that has this algebraic relation to the inputs
Text
REAL WORLD PROCESS
Verifier generates circuit representation and shares
Prover evaluates the constraints
for the function homomorphically and obtains the output and witness
Verifier verifies using pairing on the homomorphic output to verify the witness
SIMPLE
circuit
COmpiler
TASK
Prove you evaluated $$ m^2 + 36 - n $$
correctly with $$ m = 2, n = 3 $$
type Name = Text
data BinOp
= BMul
| BAdd
| BSub
data Expr
= Var Name
| Lit Rational
| BinOp BinOp Expr Expr
Code
instance Num Expr where
(*) = BinOp BMul
(+) = BinOp BAdd
(-) = BinOp BSub
fromInteger = Lit . fromInteger
abs = notImplemented
signum = notImplemented
task1 = (Var "m") * (Var "m") + 36 - (Var "n")
Code Cont.
STEp 1: FLATTEN
Convert \(m^2 + 36 - n \) so it only contains commands in the form
OUR EXAMPLE Flattened
FORMS
Constraints
data Gate
= GAdd
| GSub
| GMul deriving (Show)
data Constraint
= CSet Name (Either Name Rational)
| CBinOp {
gate :: Gate
, output :: Name
, input1 :: Name
, input2 :: Name
} deriving (Show)
data ConstraintSystem
= ConstraintSystem {
supply :: Int
, cs :: [Constraint]
} deriving (Show)
type Builder a = State ConstraintSystem a
runBuilder :: Builder a -> ConstraintSystem
runBuilder m = execState m initCS
where
initCS = ConstraintSystem { supply = 0, cs = []}
names :: [Text]
names = [1 ..] >>= flip replicateM ['a' .. 'z'] >>= return . toS
fresh :: Builder Name
fresh = do
v <- gets supply
modify $ \s -> s { supply = v + 1 }
pure $ names `unsafeIndex` v
emit :: Constraint -> Builder ()
emit c = modify (\s -> s { cs = c : cs s })
compile :: Name -> Expr -> Builder ()
compile output expr = case expr of
Var nm ->
emit $ CSet output (Left nm)
Lit v ->
emit $ CSet output (Right v)
BinOp op e1 e2 -> do
input1 <- compile' e1
input2 <- compile' e2
let gop = case op of
BMul -> GMul
BAdd -> GAdd
BSub -> GSub
emit $ CBinOp gop output input1 input2
compile' :: Expr -> Builder Name
compile' (Var nm) = return nm
compile' e = do
output <- fresh
compile output e
return output
> constraints task1
b = m * m
c = 36
a = b + c
result = a - n
And with the help of some pretty instances
STEp 2: TO r1Cs
We can represent each one of our constraints
as a set of 3 polynomials
We are going to construct a clever polynomial that only is 0 on correct inputs
STEp 2: TO r1Cs
Each constraint can be represented as a relation between vectors.
R1CS
data R1C
= R1C {
v :: [Rational]
, w :: [Rational]
, y :: [Rational]
} deriving (Show)
newtype R1CS = R1CS [R1C] deriving (Show)
uses :: Name -> [Rational]
uses var = fmap (bool 0 1 . (==var)) vars
toR1C :: Constraint -> R1C
toR1C c = case c of
CBinOp GMul output input1 input2 -> R1C {
v = uses input1
, w = uses input2
, y = uses output
}
STEp 2: TO r1Cs
(cont.)
uses :: Name -> [Rational]
uses var = fmap (bool 0 1 . (==var)) vars
toR1C :: Constraint -> R1C
toR1C c = case c of
CBinOp GMul output input1 input2 -> R1C {
v = uses input1
, w = uses input2
, y = uses output
}
+ CSet output (Right value) -> R1C {
+ v = zipWith (+)
+ (uses output)
+ (fmap (bool 0 (-value) . (=="one")) vars)
+ , w = [1]
+ , y = [0]
+ }
STEp 2: TO r1Cs
(cont.)
uses :: Name -> [Rational]
uses var = fmap (bool 0 1 . (==var)) vars
toR1C :: Constraint -> R1C
toR1C c = case c of
CBinOp GMul output input1 input2 -> R1C {
v = uses input1
, w = uses input2
, y = uses output
}
CSet output (Right value) -> R1C {
v = zipWith (+)
(uses output)
(fmap (bool 0 (-value) . (=="one")) vars)
, w = [1]
, y = [0]
}
+ CBinOp GAdd output input1 input2 -> R1C {
+ v = zipWith (+) (uses input1) (uses input2)
+ , w = [1]
+ , y = uses output
+ }
STEp 2: TO r1Cs
(cont.)
...
CSet output (Right value) -> R1C {
v = zipWith (+)
(uses output)
(fmap (bool 0 (-value) . (=="one")) vars)
, w = [1]
, y = [0]
}
CBinOp GAdd output input1 input2 -> R1C {
v = zipWith (+) (uses input1) (uses input2)
, w = [1]
, y = uses output
}
+ CBinOp GSub output input1 input2 -> R1C {
+ v = zipWith (+)
+ (uses input1)
+ (fmap (bool 0 (-1) . (==input2)) vars)
+ , w = [1]
+ , y = uses output
+ }
> r1cs $ constraints task1
b = m * m
==================
v = [0,1,0,0,0,0,0]
w = [0,1,0,0,0,0,0]
y = [0,0,0,0,0,1,0]
c = 36
==================
v = [-36,0,0,0,0,0,1]
w = [1]
y = [0]
a = b + c
==================
v = [0,0,0,0,0,1,1]
w = [1]
y = [0,0,0,0,1,0,0]
result = a - n
==================
v = [0,0,-1,0,1,0,0]
w = [1]
y = [0,0,0,1,0,0,0]
STEp 3: WITNESS ME
The witness is the assignment to all variables.
Execute the flattened commands and set the values as you go
Initial state ( with our inputs )
Step 3.1
Step 3.2
Step 3.3
Step 3.4
satisfy :: [Rational] -> R1C -> Bool
satisfy s (R1C v w y) = (sv * sw) - sy == 0
where
sv = dot s v
sw = dot s w
sy = dot s y
dot a b = sum (zipWith (*) a b)
> fmap (satisfy witness) (r1cs $ constraints task1)
[True,True,True,True]
Checking each gate INDIVIDUALLY?
No way jose
STEp 4: SUCCINCT
Lagrange interpolation
Given a set of points, give me a polynomial that passes through all of those points.
Thanks to this we can check
the witness in a single step
Boolean operations
...
data BinOp
= BMul
| BAdd
| BSub
+ | BAnd
+ | BOr
+ | BXor
...
Arithemitization
compile output expr = case expr of
...
BinOp op e1 e2 -> do
input1 <- compile' e1
input2 <- compile' e2
binOp op output input1 input2
binOp :: BinOp -> Name -> Name -> Name -> Builder ()
binOp BAnd out input1 input2 = binOp BMul out input1 input2
binOp BOr out input1 input2 = do
tmp1 <- fresh
tmp2 <- fresh
binOp BMul tmp1 input1 input2
binOp BAdd tmp2 input1 input2
binOp BSub out tmp2 tmp1
binOp BXor out input1 input2 = do
tmp1 <- fresh
binOp BSub tmp1 input1 input2
binOp BMul out tmp1 tmp1
binOp op output input1 input2 = emit $ CBinOp gate output input1 input2
where
gate =
case op of
BMul -> GMul
BAdd -> GAdd
BSub -> GSub
IMportant
WHAT we just did was a big simplification
IN the real world
All our arithmetic operations would be not be done with regular numbers.
IN the real world
Instead it'd be
elliptic curve elements
over a
finite field with a prime modulus.
Elliptic curve ELEMENT
A \( (x, y) \) coordinate on a curve that looks like
... OVer a finite Field
Instead of being a real curve, you have a set of discrete points.
( Barreto-Naehrig Curve: BN128 )
The final verification step, relates the circuit output, the witness, and the circuit description, checked without having access the the private inputs.
It's computationally infeasible to construct a forged proof
questions
Verifiable Computing
By ..
Verifiable Computing
- 2,749