Commit 552f26be authored by Thomas Hoffmann's avatar Thomas Hoffmann
Browse files

Handin 5 attempt 1

parent 6f6506f6
......@@ -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() {
......
// 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
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)
}
})
}
}
}
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
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
}
}
......@@ -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 {