Commit 5e570bc6 authored by Anders Jensen Løvig's avatar Anders Jensen Løvig
Browse files

Fixed folder structure

parent 03cf4408
......@@ -2,12 +2,13 @@ package main
import (
"crycomp/internal/blood"
"crycomp/internal/crypto/elgamal"
"crycomp/internal/crypto/group"
"crycomp/internal/crypto/oblivious"
"crypto/rand"
"fmt"
"math/big"
"strconv"
"golang.org/x/crypto/openpgp/elgamal"
)
type Encryption struct {
......@@ -31,35 +32,60 @@ func NewParty(x int, keyChan chan []*elgamal.PublicKey, encChan chan []*Encrypti
}
}
// Performs oblivious transfer from the Bob's viewpoint.
func (p *Party) Listen() {
_, ok := <-p.keyChan
// Wait for Alice to send public keys.
keys, ok := <-p.keyChan
if !ok {
panic("key channel closed unexpectedly")
}
var encs []*Encryption
for i, key := range(<-p.keyChan) {
// 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 = append(encs, &Encryption{c1, c2})
encs[i] = &Encryption{c1, c2}
}
// Send the encrypted column to Alice.
p.encChan <- encs
}
func (p *Party) ObliviousTransfer() bool {
// Performs oblivious transfer from Alice's viewpoint.
func (p *Party) ObliviousTransfer() (bool, error) {
keys := make([]*elgamal.PublicKey, 8)
//TODO: insert actual publickey on index x
var pKey elgamal.PrivateKey
//TODO: Generate 7 fake public keys
// 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
data, _ := elgamal.Decrypt(&pKey,encs[p.x].C1, encs[p.x].C2) //Result as byte slice
result, _ := strconv.ParseBool(string(data))
return result
// 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 {
......@@ -69,19 +95,21 @@ type Protocol struct {
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)
rec := NewParty(x, keyChan, encChan)
sen := NewParty(y, keyChan, encChan)
return &Protocol{
Receiver: rec,
Sender: sen,
Sender: sen,
}
}
// RunProtocol runs the protocol between receiving blood type x and donor blood
// type y.
func RunProtocol(x, y int) bool {
func RunProtocol(x, y int) (bool, error) {
p := NewProtocol(x, y)
// We let Bob listen until Alice sends.
// This kinda simulates talking over a network.
go func() {
p.Sender.Listen()
}()
......@@ -90,9 +118,10 @@ func RunProtocol(x, y int) bool {
func main() {
bloodA, bloodB := blood.Type_ABn, blood.Type_ABp
z := RunProtocol(bloodA, bloodB)
if z == blood.Table[bloodA][bloodB] {
z, err := RunProtocol(bloodA, bloodB)
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])
......
......@@ -28,7 +28,10 @@ func TestProtocol(t *testing.T) {
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) {
if z := RunProtocol(x, y); z != blood.Table[x][y] {
z, err := RunProtocol(x, y)
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 elgamal
import (
"crycomp/internal/blood/crypto/group"
"crycomp/internal/crypto/group"
"crycomp/internal/crypto/util"
"crypto/rand"
"errors"
"io"
......@@ -19,9 +20,13 @@ type PrivateKey struct {
X *big.Int
}
// GenerateKey returns an Elgamal private key by choosing an element x in Zq
// and then computing h = g^x mod p in Gq for the public key. The private key
// is (G, x) and public key is (G, h).
// GenerateKey returns an Elgamal private key with corresponding public key.
// The security depends un the underlying group. Therefore we assume that p
// is a safeprime, such that p = 2q + 1. This gives a subgroup of order q,
// where DDH is assumed to be hard.
//
// The key is generated by choosing x in [1,q) and computing h = g^x mod p.
// Then the private key is (p, q, g, x) and the public key is (p, q, g, h)
func GenerateKey(random io.Reader, params *group.Params) (priv *PrivateKey, err error) {
x, err := rand.Int(random, params.Q)
if err != nil {
......@@ -42,7 +47,8 @@ func GenerateKey(random io.Reader, params *group.Params) (priv *PrivateKey, err
return // return priv and err
}
// Encrypt msg using textbook Elgamal
// Encrypt the message bytes using an Elgamal public key. The bytes are
// interpreted as an integer and must not be larger than q of the key.
func Encrypt(random io.Reader, pub *PublicKey, msg []byte) (c1, c2 *big.Int, err error) {
m := new(big.Int).SetBytes(msg)
if m.Cmp(pub.Q) != -1 {
......@@ -50,8 +56,7 @@ func Encrypt(random io.Reader, pub *PublicKey, msg []byte) (c1, c2 *big.Int, err
}
m = encodeMessage(pub, m)
// TODO m must not b zero
r, err := randInt(random, pub.Q)
r, err := util.RandInt(random, pub.Q)
if err != nil {
return
}
......@@ -64,6 +69,7 @@ func Encrypt(random io.Reader, pub *PublicKey, msg []byte) (c1, c2 *big.Int, err
return
}
// Decrypt an Elgamal ciphertext using an Elgamal private key.
func Decrypt(priv *PrivateKey, c1, c2 *big.Int) (msg []byte, err error) {
s := new(big.Int).Exp(c1, priv.X, priv.P)
if s.ModInverse(s, priv.P) == nil {
......@@ -79,6 +85,8 @@ func Decrypt(priv *PrivateKey, c1, c2 *big.Int) (msg []byte, err error) {
return
}
// encodeMessage encodes x as an element in the subgroup of order q of the
// public key.
func encodeMessage(pub *PublicKey, x *big.Int) (m *big.Int) {
m = new(big.Int).Add(x, one)
exp := new(big.Int).Set(pub.Q)
......@@ -91,6 +99,8 @@ func encodeMessage(pub *PublicKey, x *big.Int) (m *big.Int) {
}
}
// decodeMessage decodes an element in a subgroup of order q to the
// corresponding plaintext.
func decodeMessage(priv *PrivateKey, x *big.Int) (m *big.Int) {
m = new(big.Int)
if x.Cmp(priv.Q) != 1 {
......@@ -102,16 +112,3 @@ func decodeMessage(priv *PrivateKey, x *big.Int) (m *big.Int) {
return m.Sub(m, one)
}
func randInt(random io.Reader, q *big.Int) (r *big.Int, err error) {
tmp := new(big.Int).Set(q)
tmp.Sub(tmp, one)
r, err = rand.Int(random, tmp)
if err != nil {
return
}
r.Add(r, one)
return
}
......@@ -2,7 +2,7 @@ package elgamal
import (
"bytes"
"crycomp/internal/blood/crypto/group"
"crycomp/internal/crypto/group"
"crypto/rand"
"fmt"
"math/big"
......
package oblivious
import (
"crycomp/internal/blood/crypto/elgamal"
"crycomp/internal/blood/crypto/group"
"crypto/rand"
"crycomp/internal/crypto/elgamal"
"crycomp/internal/crypto/group"
"crycomp/internal/crypto/util"
"io"
"math/big"
)
var one = big.NewInt(1)
var two = big.NewInt(2)
// OGenElgamal returns a fake Elgamal public key for use in oblivious transfer.
// The key is generated such that distribution is identical to a key generated
// using elgamal.GenerateKey. The way the key is generated the corresponding
// private key is unknown.
func OGenElgamel(random io.Reader, params *group.Params) (pub *elgamal.PublicKey, err error) {
tmp := new(big.Int).Sub(params.P, one)
// sample
r, err := rand.Int(random, tmp)
s, err := util.RandInt(random, params.P)
if err != nil {
return
}
s := r.Add(r, one)
pub = &elgamal.PublicKey{
P: params.P,
Q: params.Q,
G: params.G,
H: s.Exp(r, two, params.P),
H: s.Exp(s, two, params.P),
}
return
}
package util
import (
"crypto/rand"
"io"
"math/big"
)
var one = big.NewInt(1)
// RandInt returns a random integer in the range [1, n).
func RandInt(random io.Reader, n *big.Int) (r *big.Int, err error) {
tmp := new(big.Int).Set(n)
tmp.Sub(tmp, one)
r, err = rand.Int(random, tmp)
if err != nil {
return
}
r.Add(r, one)
return
}
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment