Skip to content
GitLab
Projects
Groups
Snippets
/
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Menu
Open sidebar
Thomas Hoffmann
CryComp
Commits
552f26be
Commit
552f26be
authored
Oct 03, 2021
by
Thomas Hoffmann
Browse files
Handin 5 attempt 1
parent
6f6506f6
Changes
7
Hide whitespace changes
Inline
Side-by-side
cmd/handin4/main.go
View file @
552f26be
...
...
@@ -2,118 +2,29 @@ package main
import
(
"crycomp/internal/blood"
"crycomp/internal/crypto/elgamal"
"crycomp/internal/crypto/group"
"crycomp/internal/crypto/oblivious"
"crypto/rand"
"fmt"
"math/big"
"strconv"
)
type
Encryption
struct
{
C1
,
C2
*
big
.
Int
}
// Party represents one of the parties in the protocol. They contain a slice
// of all known wires and channels for communication with the other party.
type
Party
struct
{
keyChan
chan
[]
*
elgamal
.
PublicKey
encChan
chan
[]
*
Encryption
x
int
}
// NewParty returns a new party that communicates on the specified channels.
func
NewParty
(
x
int
,
keyChan
chan
[]
*
elgamal
.
PublicKey
,
encChan
chan
[]
*
Encryption
)
*
Party
{
return
&
Party
{
x
:
x
,
keyChan
:
keyChan
,
encChan
:
encChan
,
}
}
// Performs oblivious transfer from the Bob's viewpoint.
func
(
p
*
Party
)
Listen
()
{
// Wait for Alice to send public keys.
keys
,
ok
:=
<-
p
.
keyChan
if
!
ok
{
panic
(
"key channel closed unexpectedly"
)
}
// encrypt Bob's column using the public keys.
encs
:=
make
([]
*
Encryption
,
8
)
for
i
,
key
:=
range
keys
{
var
res
[]
byte
res
=
strconv
.
AppendBool
(
res
,
blood
.
Table
[
i
][
p
.
x
])
c1
,
c2
,
_
:=
elgamal
.
Encrypt
(
rand
.
Reader
,
key
,
res
)
encs
[
i
]
=
&
Encryption
{
c1
,
c2
}
}
// Send the encrypted column to Alice.
p
.
encChan
<-
encs
}
// Performs oblivious transfer from Alice's viewpoint.
func
(
p
*
Party
)
ObliviousTransfer
()
(
bool
,
error
)
{
keys
:=
make
([]
*
elgamal
.
PublicKey
,
8
)
// Generate a private key for Elgamal
params
:=
group
.
Default
()
priv
,
err
:=
elgamal
.
GenerateKey
(
rand
.
Reader
,
params
)
if
err
!=
nil
{
return
false
,
nil
}
keys
[
p
.
x
]
=
&
priv
.
PublicKey
// Generate random public keys with Ogen
for
i
:=
0
;
i
<
8
;
i
++
{
if
i
!=
p
.
x
{
keys
[
i
],
err
=
oblivious
.
OGenElgamel
(
rand
.
Reader
,
params
)
if
err
!=
nil
{
return
false
,
err
}
}
}
// Send to Bob and wait for encryptions.
p
.
keyChan
<-
keys
encs
:=
<-
p
.
encChan
// Decrypt
data
,
err
:=
elgamal
.
Decrypt
(
priv
,
encs
[
p
.
x
]
.
C1
,
encs
[
p
.
x
]
.
C2
)
//Result as byte slice
if
err
!=
nil
{
return
false
,
err
}
result
,
err
:=
strconv
.
ParseBool
(
string
(
data
))
return
result
,
err
}
type
Protocol
struct
{
Receiver
,
Sender
*
Party
}
func
NewProtocol
(
x
,
y
int
)
*
Protocol
{
keyChan
:=
make
(
chan
[]
*
elgamal
.
PublicKey
)
encChan
:=
make
(
chan
[]
*
Encryption
)
rec
:=
NewParty
(
x
,
keyChan
,
encChan
)
sen
:=
NewParty
(
y
,
keyChan
,
encChan
)
return
&
Protocol
{
Receiver
:
rec
,
Sender
:
sen
,
}
}
// RunProtocol runs the protocol between receiving blood type x and donor blood
// type y.
func
RunProtocol
(
x
,
y
int
)
(
bool
,
error
)
{
p
:=
NewProtocol
(
x
,
y
)
var
ydata
[][]
byte
for
i
:=
0
;
i
<
len
(
blood
.
Table
);
i
++
{
ydata
=
append
(
ydata
,
strconv
.
AppendBool
(
make
([]
byte
,
0
),
blood
.
Table
[
i
][
y
]))
}
p
:=
oblivious
.
NewProtocol
(
x
,
ydata
)
// We let Bob listen until Alice sends.
// This kinda simulates talking over a network.
go
func
()
{
p
.
Sender
.
Listen
()
}()
return
p
.
Receiver
.
ObliviousTransfer
()
data
,
err
:=
p
.
Receiver
.
ObliviousTransfer
(
8
)
result
,
_
:=
strconv
.
ParseBool
(
string
(
data
))
return
result
,
err
}
func
main
()
{
...
...
cmd/handin5/main.go
0 → 100644
View file @
552f26be
// 11 wires
package
main
import
(
"crycomp/internal/blood"
"crycomp/internal/crypto/oblivious"
"crycomp/internal/crypto/garbled"
"crycomp/internal/util"
"fmt"
)
////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////
type
Party
struct
{
x
[]
bool
Circuit
*
garbled
.
GCircuit
InChan
chan
[][]
byte
CircuitChan
chan
garbled
.
Table
EncInput
[][]
byte
*
oblivious
.
Party
result
bool
outChan
chan
[]
byte
}
func
NewParty
(
x
int
,
inChan
chan
[][]
byte
,
circuitChan
chan
garbled
.
Table
,
outChan
chan
[]
byte
,
party
*
oblivious
.
Party
)
(
p
*
Party
){
return
&
Party
{
x
:
util
.
Int2Bools
(
x
,
3
),
EncInput
:
make
([][]
byte
,
6
),
InChan
:
inChan
,
outChan
:
outChan
,
CircuitChan
:
circuitChan
,
Party
:
party
,
}
}
func
(
p
*
Party
)
GenerateCircuit
()
{
p
.
Circuit
=
garbled
.
NewGarbBloodCircuit
()
}
func
(
p
*
Party
)
OTSend
()
{
for
i
:=
0
;
i
<
3
;
i
++
{
p
.
Listen
(
p
.
Circuit
.
E
[
i
+
3
])
}
}
func
(
p
*
Party
)
OTReceive
()
(
res
[][]
byte
,
err
error
){
res
=
make
([][]
byte
,
3
)
var
val
int
for
i
:=
range
p
.
x
{
if
p
.
x
[
i
]
{
val
=
1
}
else
{
val
=
0
}
var
result
,
err
=
p
.
ObliviousTransfer
(
2
,
val
)
if
err
!=
nil
{
return
nil
,
err
}
res
[
i
]
=
result
}
return
res
,
nil
}
func
OTransfer
(
sender
,
receiver
*
Party
)
{
sender
.
Party
,
receiver
.
Party
=
oblivious
.
NewPartyPair
()
//sender.Listen(sender.Circuit.e)
}
// RunProtocol runs the protocol between receiving blood type x and donor blood
// type y.
// outputMode: 0: Alice learns, 1: Bob learns else both learns
func
RunProtocol
(
x
,
y
int
,
outputMode
int
)
(
bool
,
error
)
{
inCh
,
circCh
,
outCh
:=
make
(
chan
[][]
byte
),
make
(
chan
garbled
.
Table
),
make
(
chan
[]
byte
)
p1
,
p2
:=
oblivious
.
NewPartyPair
()
Alice
,
Bob
:=
NewParty
(
x
,
inCh
,
circCh
,
outCh
,
p1
),
NewParty
(
y
,
inCh
,
circCh
,
outCh
,
p2
)
go
func
(
Bob
*
Party
){
// 1. Garble
Bob
.
GenerateCircuit
()
Bob
.
CircuitChan
<-
*
Bob
.
Circuit
.
F
// 2. Encode Bobs input
Bob
.
EncInput
=
garbled
.
Enc
(
Bob
.
Circuit
.
E
[
:
3
],
Bob
.
x
)
Bob
.
InChan
<-
Bob
.
EncInput
// 3. Encode Alices input
Bob
.
OTSend
()
// 5. Output
if
outputMode
!=
1
{
// Alice learns
// Bob sends d
Bob
.
InChan
<-
Bob
.
Circuit
.
D
}
if
outputMode
!=
0
{
// Bob learns
// Alice sends Z
Bob
.
result
=
garbled
.
Decode
(
Bob
.
Circuit
.
D
,
<-
Bob
.
outChan
)
}
}(
Bob
)
go
func
(
Alice
*
Party
)
{
// 1. Garble
F
:=
<-
Alice
.
CircuitChan
Alice
.
Circuit
=
&
garbled
.
GCircuit
{
F
:
&
F
}
// 2. Encode Bobs input
Alice
.
EncInput
=
<-
Alice
.
InChan
// 3. Encode Alices input
X
,
_
:=
Alice
.
OTReceive
()
Alice
.
EncInput
=
append
(
Alice
.
EncInput
,
X
...
)
// 4. Evaluation
Z
:=
garbled
.
Eval
(
Alice
.
Circuit
.
F
,
Alice
.
EncInput
)
// 5. Output
if
outputMode
!=
1
{
// Alice learns
// Bob sends d
Alice
.
result
=
garbled
.
Decode
(
<-
Alice
.
InChan
,
Z
)
}
if
outputMode
!=
0
{
// Bob learns
// Alice sends Z
Alice
.
outChan
<-
Z
}
}(
Alice
)
if
outputMode
!=
1
{
return
Alice
.
result
,
nil
}
else
{
return
Bob
.
result
,
nil
}
}
func
main
()
{
bloodA
,
bloodB
:=
blood
.
Type_ABn
,
blood
.
Type_ABp
z
,
err
:=
RunProtocol
(
bloodA
,
bloodB
,
0
)
if
err
!=
nil
{
fmt
.
Println
(
"Protocol failed with error:"
,
err
)
}
else
if
z
==
blood
.
Table
[
bloodA
][
bloodB
]
{
fmt
.
Println
(
"Protocol succeded"
)
}
else
{
fmt
.
Printf
(
"Protocol failed, output was %t, but should be %t"
,
z
,
blood
.
Table
[
bloodA
][
bloodB
])
}
}
\ No newline at end of file
cmd/handin5/main_test.go
0 → 100644
View file @
552f26be
package
main
import
(
"crycomp/internal/blood"
"fmt"
"testing"
)
func
TestBloodTable
(
t
*
testing
.
T
)
{
// Check the dimensions of BloodTable.
if
len
(
blood
.
Table
)
!=
8
{
t
.
Fatalf
(
"Expected 8 rows, got %d"
,
len
(
blood
.
Table
))
}
for
i
:=
range
blood
.
Table
{
if
len
(
blood
.
Table
[
i
])
!=
8
{
t
.
Fatalf
(
"Expected columns in row %d, got %d"
,
i
,
len
(
blood
.
Table
))
}
}
}
func
TestProtocol
(
t
*
testing
.
T
)
{
// Runs the protocol for all combinations of recipient and donor blood types.
n
:=
len
(
blood
.
Table
)
for
x
:=
0
;
x
<
n
;
x
++
{
for
y
:=
0
;
y
<
n
;
y
++
{
testName
:=
fmt
.
Sprintf
(
"(x=%s,y=%s)"
,
blood
.
Names
[
x
],
blood
.
Names
[
y
])
t
.
Run
(
testName
,
func
(
t
*
testing
.
T
)
{
z
,
err
:=
RunProtocol
(
x
,
y
,
0
)
if
err
!=
nil
{
t
.
Errorf
(
"Protocol error: %s"
,
err
)
}
else
if
z
!=
blood
.
Table
[
x
][
y
]
{
t
.
Fatalf
(
"Failed blood compatibility test for index [%d,%d]. Expected %t, got %t"
,
x
,
y
,
!
z
,
z
)
}
})
}
}
}
internal/crypto/garbled/circuit.go
0 → 100644
View file @
552f26be
package
garbled
import
(
"crycomp/internal/util"
"crypto/rand"
"crypto"
"bytes"
m
"math/rand"
_
"crypto/sha256"
)
type
Table
struct
{
data
[]
byte
wires
,
numValues
,
numBytes
int
}
func
NewTable
(
wires
,
numValues
,
k
int
)
*
Table
{
t
:=
Table
{
data
:
make
([]
byte
,
wires
*
numValues
*
k
/
8
),
wires
:
wires
,
numValues
:
numValues
,
numBytes
:
k
/
8
,
}
return
&
t
}
func
(
t
*
Table
)
SetValue
(
data
[]
byte
,
i
,
s
int
)
{
valStart
:=
i
*
t
.
numBytes
+
s
*
t
.
numBytes
copy
(
t
.
data
[
valStart
:
valStart
+
t
.
numBytes
],
data
)
}
func
(
t
*
Table
)
GetValue
(
i
,
s
int
)
[]
byte
{
valStart
:=
i
*
t
.
numBytes
+
s
*
t
.
numBytes
return
t
.
data
[
valStart
:
valStart
+
t
.
numBytes
]
}
func
(
t
*
Table
)
SetRow
(
data
[][]
byte
,
i
int
)
{
for
j
,
val
:=
range
data
{
t
.
SetValue
(
val
,
i
,
j
)
}
}
func
(
t
*
Table
)
GetRow
(
i
int
)
[][]
byte
{
values
:=
make
([][]
byte
,
0
)
for
j
:=
0
;
j
<
t
.
numValues
;
j
++
{
values
=
append
(
values
,
t
.
GetValue
(
i
,
j
))
}
return
values
}
func
(
t
*
Table
)
GetKFirstValues
(
numInputWire
int
)
[][][]
byte
{
values
:=
make
([][][]
byte
,
0
)
for
i
:=
0
;
i
<
numInputWire
;
i
++
{
values
=
append
(
values
,
t
.
GetRow
(
i
))
}
return
values
}
func
(
t
*
Table
)
RandomizeTable
()
{
rand
.
Read
(
t
.
data
)
}
type
GCircuit
struct
{
F
*
Table
E
[][][]
byte
D
[][]
byte
}
type
Gate
struct
{
Li
,
Ri
int
i
int
truthfunc
func
(
a
,
b
int
)
int
}
func
newGate
(
Li
,
Ri
,
i
int
,
f
func
(
a
,
b
int
)
int
)
(
g
*
Gate
)
{
g
.
Li
=
Li
g
.
Ri
=
Ri
g
.
i
=
i
g
.
truthfunc
=
f
return
}
func
NewGarbBloodCircuit
()
(
circuit
*
GCircuit
)
{
numInput
:=
6
numWires
:=
11
// (1)
K
:=
NewTable
(
numWires
,
2
,
128
)
K
.
RandomizeTable
()
// (2)
C
:=
NewTable
(
numWires
-
numInput
,
4
,
256
)
for
i
:=
0
;
i
<
3
;
i
++
{
//1st layer (consisting of not's and or's )
//INput wires order: xs, xa, xb, ys, ya, yb (hopefully)
C
.
SetRow
(
GBC
(
K
,
i
,
i
+
3
,
i
+
numInput
,
ORGateWithNot
,
G
),
i
)
}
C
.
SetRow
(
GBC
(
K
,
numInput
,
numInput
+
1
,
numInput
+
3
,
ANDGate
,
G
),
4
)
C
.
SetRow
(
GBC
(
K
,
numInput
+
3
,
numInput
+
2
,
numInput
+
4
,
ANDGate
,
G
),
5
)
return
&
GCircuit
{
F
:
C
,
D
:
K
.
GetRow
(
numWires
),
E
:
K
.
GetKFirstValues
(
numInput
),
}
}
//Creates a row (C_0^i, C_1^i, C_2^i ,C_3^i) for the garbled table, where
func
GBC
(
K
*
Table
,
Li
,
Ri
,
i
int
,
c
func
(
a
,
b
int
)
int
,
g
func
(
A
,
B
[]
byte
,
i
int
)
[]
byte
)
(
CRow
[][]
byte
)
{
CRow
=
make
([][]
byte
,
0
)
CVals
:=
make
([][]
byte
,
4
)
// 4 x 256 bits
// (a)
for
a
:=
range
[]
int
{
0
,
1
}
{
for
b
:=
range
[]
int
{
0
,
1
}
{
left
:=
g
(
K
.
GetValue
(
Li
,
a
),
K
.
GetValue
(
Ri
,
b
),
i
)
right
:=
make
([]
byte
,
16
)
copy
(
right
,
K
.
GetValue
(
i
,
c
(
a
,
b
)))
right
=
append
(
right
,
make
([]
byte
,
16
)
...
)
CVals
[
a
*
2
+
b
]
=
util
.
XOR
(
left
,
right
)
}
}
// (b)
//TODO: Fix permutation
for
i
:=
range
m
.
Perm
(
4
)
{
//Generate random order
CRow
=
append
(
CRow
,
CVals
[
i
])
}
return
}
func
G
(
A
,
B
[]
byte
,
i
int
)
[]
byte
{
hash
:=
crypto
.
SHA256
.
New
()
hash
.
Write
(
A
)
hash
.
Write
(
append
(
B
,
byte
(
i
)))
return
hash
.
Sum
(
nil
)
}
func
ORGateWithNot
(
a
,
b
int
)
int
{
if
((
1
-
a
)
+
b
)
==
0
{
return
0
}
else
{
return
1
}
}
func
ANDGate
(
a
,
b
int
)
int
{
return
a
*
b
}
func
Enc
(
e
[][][]
byte
,
x
[]
bool
)
(
X
[][]
byte
){
X
=
make
([][]
byte
,
0
)
for
i
,
val
:=
range
x
{
if
val
{
X
=
append
(
X
,
e
[
i
][
1
])
}
else
{
X
=
append
(
X
,
e
[
i
][
0
])
}
}
return
}
func
Eval
(
C
*
Table
,
X
[][]
byte
)
[]
byte
{
var
K
=
X
var
res
[]
byte
for
i
:=
0
;
i
<
3
;
i
++
{
for
j
:=
0
;
j
<
4
;
j
++
{
res
=
util
.
XOR
(
G
(
K
[
i
],
K
[
i
+
3
],
i
),
C
.
GetValue
(
i
,
j
))
if
!
bytes
.
Equal
(
res
[
16
:
],
make
([]
byte
,
16
))
{
K
=
append
(
K
,
res
[
:
16
])
break
}
}
}
return
K
[
len
(
K
)
-
1
]
}
func
Decode
(
d
[][]
byte
,
Z
[]
byte
)
bool
{
if
bytes
.
Equal
(
d
[
0
],
Z
)
{
return
false
}
else
if
bytes
.
Equal
(
d
[
1
],
Z
)
{
return
true
}
//TODO: Error handling
return
false
}
\ No newline at end of file
internal/crypto/garbled/circuit_test.go
0 → 100644
View file @
552f26be
package
garbled
import
(
"testing"
"bytes"
)
func
TestGBC
(
t
*
testing
.
T
)
{
K
:=
NewTable
(
3
,
2
,
128
)
K
.
RandomizeTable
()
res
:=
GBC
(
K
,
0
,
1
,
2
,
ORGate
,
g
)
print
(
res
)
crctval
:=
append
(
K
.
GetValue
(
2
,
1
),
make
([]
byte
,
16
)
...
)
crctidx
:=
make
([]
int
,
0
)
for
i
:=
range
res
{
if
bytes
.
Equal
(
res
[
i
],
crctval
)
{
crctidx
=
append
(
crctidx
,
i
)
}
}
if
len
(
crctidx
)
!=
3
{
t
.
Error
(
"Function should return 3 true labels and 1 false label when using an OR Gate"
)
}
res
=
GBC
(
K
,
0
,
1
,
2
,
ANDGate
,
g
)
crctidx
=
make
([]
int
,
0
)
for
i
:=
range
res
{
if
bytes
.
Equal
(
res
[
i
],
crctval
)
{
crctidx
=
append
(
crctidx
,
i
)
}
}
if
len
(
crctidx
)
!=
1
{
t
.
Error
(
"Function should return 1 true labels and 3 false label when using an AND Gate"
)
}
}
func
g
(
A
,
B
[]
byte
,
i
int
)
[]
byte
{
return
make
([]
byte
,
len
(
A
)
*
2
)
}
func
ORGate
(
a
,
b
int
)
int
{
if
a
+
b
!=
0
{
return
1
}
else
{
return
0
}
}
internal/crypto/oblivious/oblivious.go
View file @
552f26be
...
...
@@ -6,6 +6,8 @@ import (
"crycomp/internal/crypto/util"
"io"
"math/big"
"crypto/rand"
"strconv"
)
var
two
=
big
.
NewInt
(
2
)
...
...
@@ -28,3 +30,211 @@ func OGenElgamel(random io.Reader, params *group.Params) (pub *elgamal.PublicKey
}
return
}
type
Encryption
struct
{
C1
,
C2
*
big
.
Int
}
// Party represents one of the parties in the protocol. They contain a slice
// of all known wires and channels for communication with the other party.
/*type Party struct {
keyChan chan []*elgamal.PublicKey
encChan chan []*Encryption
x int
}*/
type
Party
struct
{
keyChan
chan
[]
*
elgamal
.
PublicKey
encChan
chan
[]
*
Encryption
}
type
Sender
struct
{
Party
data
[][]
byte
}
type
Receiver
struct
{
Party
x
int
result
[]
byte
}
func
NewSender
(
data
[][]
byte
,
keyChan
chan
[]
*
elgamal
.
PublicKey
,
encChan
chan
[]
*
Encryption
)
(
*
Sender
)
{
return
&
Sender
{
data
:
data
,
Party
:
Party
{
keyChan
:
keyChan
,
encChan
:
encChan
},
}
}
func
NewReceiver
(
x
int
,
keyChan
chan
[]
*
elgamal
.
PublicKey
,
encChan
chan
[]
*
Encryption
)
(
*
Receiver
)
{
return
&
Receiver
{
Party
:
Party
{
keyChan
:
keyChan
,
encChan
:
encChan
},
x
:
x
,
}
}
// NewParty returns a new party that communicates on the specified channels.
func
NewParty
(
x
int
,
keyChan
chan
[]
*
elgamal
.
PublicKey
,
encChan
chan
[]
*
Encryption
)
*
Party
{
return
&
Party
{
keyChan
:
keyChan
,
encChan
:
encChan
,
}
}
// Performs oblivious transfer from the Bob's viewpoint.
func
(
p
*
Party
)
Listen
(
data
[][]
byte
)
{
// Wait for Alice to send public keys.
keys
,
ok
:=
<-
p
.
keyChan
if
!
ok
{
panic
(
"key channel closed unexpectedly"
)
}
// encrypt Bob's column using the public keys.
encs
:=
make
([]
*
Encryption
,
len
(
keys
))
for
i
,
key
:=
range
keys
{