main.go 3.16 KB
Newer Older
Anders Jensen Løvig's avatar
Anders Jensen Løvig committed
1
2
3
4
package main

import (
	"crycomp/internal/blood"
Anders Jensen Løvig's avatar
Anders Jensen Løvig committed
5
6
7
	"crycomp/internal/crypto/elgamal"
	"crycomp/internal/crypto/group"
	"crycomp/internal/crypto/oblivious"
8
	"crypto/rand"
Anders Jensen Løvig's avatar
Anders Jensen Løvig committed
9
10
	"fmt"
	"math/big"
11
	"strconv"
Anders Jensen Løvig's avatar
Anders Jensen Løvig committed
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
)

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,
	}
}

Anders Jensen Løvig's avatar
Anders Jensen Løvig committed
35
// Performs oblivious transfer from the Bob's viewpoint.
Anders Jensen Løvig's avatar
Anders Jensen Løvig committed
36
func (p *Party) Listen() {
Anders Jensen Løvig's avatar
Anders Jensen Løvig committed
37
38
	// Wait for Alice to send public keys.
	keys, ok := <-p.keyChan
Anders Jensen Løvig's avatar
Anders Jensen Løvig committed
39
40
41
	if !ok {
		panic("key channel closed unexpectedly")
	}
Anders Jensen Løvig's avatar
Anders Jensen Løvig committed
42
43
44
45

	// encrypt Bob's column using the public keys.
	encs := make([]*Encryption, 8)
	for i, key := range keys {
46
47
48
		var res []byte
		res = strconv.AppendBool(res, blood.Table[i][p.x])
		c1, c2, _ := elgamal.Encrypt(rand.Reader, key, res)
Anders Jensen Løvig's avatar
Anders Jensen Løvig committed
49
		encs[i] = &Encryption{c1, c2}
50
	}
Anders Jensen Løvig's avatar
Anders Jensen Løvig committed
51
52

	// Send the encrypted column to Alice.
Anders Jensen Løvig's avatar
Anders Jensen Løvig committed
53
54
55
	p.encChan <- encs
}

Anders Jensen Løvig's avatar
Anders Jensen Løvig committed
56
57
// Performs oblivious transfer from Alice's viewpoint.
func (p *Party) ObliviousTransfer() (bool, error) {
58
59
	keys := make([]*elgamal.PublicKey, 8)

Anders Jensen Løvig's avatar
Anders Jensen Løvig committed
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
	// 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
			}
		}
	}
77

Anders Jensen Løvig's avatar
Anders Jensen Løvig committed
78
	// Send to Bob and wait for encryptions.
79
80
81
	p.keyChan <- keys
	encs := <-p.encChan

Anders Jensen Løvig's avatar
Anders Jensen Løvig committed
82
83
84
85
86
87
88
	// 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
Anders Jensen Løvig's avatar
Anders Jensen Løvig committed
89
90
91
92
93
94
95
}

type Protocol struct {
	Receiver, Sender *Party
}

func NewProtocol(x, y int) *Protocol {
96
97
	keyChan := make(chan []*elgamal.PublicKey)
	encChan := make(chan []*Encryption)
Anders Jensen Løvig's avatar
Anders Jensen Løvig committed
98
99
	rec := NewParty(x, keyChan, encChan)
	sen := NewParty(y, keyChan, encChan)
100
101
	return &Protocol{
		Receiver: rec,
Anders Jensen Løvig's avatar
Anders Jensen Løvig committed
102
		Sender:   sen,
103
	}
Anders Jensen Løvig's avatar
Anders Jensen Løvig committed
104
105
106
107
}

// RunProtocol runs the protocol between receiving blood type x and donor blood
// type y.
Anders Jensen Løvig's avatar
Anders Jensen Løvig committed
108
func RunProtocol(x, y int) (bool, error) {
Anders Jensen Løvig's avatar
Anders Jensen Løvig committed
109
110
	p := NewProtocol(x, y)

Anders Jensen Løvig's avatar
Anders Jensen Løvig committed
111
112
	// We let Bob listen until Alice sends.
	// This kinda simulates talking over a network.
Anders Jensen Løvig's avatar
Anders Jensen Løvig committed
113
114
115
116
117
118
119
120
	go func() {
		p.Sender.Listen()
	}()
	return p.Receiver.ObliviousTransfer()
}

func main() {
	bloodA, bloodB := blood.Type_ABn, blood.Type_ABp
Anders Jensen Løvig's avatar
Anders Jensen Løvig committed
121
122
123
124
	z, err := RunProtocol(bloodA, bloodB)
	if err != nil {
		fmt.Println("Protocol failed with error:", err)
	} else if z == blood.Table[bloodA][bloodB] {
Anders Jensen Løvig's avatar
Anders Jensen Løvig committed
125
126
127
128
129
		fmt.Println("Protocol succeded")
	} else {
		fmt.Printf("Protocol failed, output was %t, but should be %t", z, blood.Table[bloodA][bloodB])
	}
}