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 ...@@ -2,12 +2,13 @@ package main
import ( import (
"crycomp/internal/blood" "crycomp/internal/blood"
"crycomp/internal/crypto/elgamal"
"crycomp/internal/crypto/group"
"crycomp/internal/crypto/oblivious"
"crypto/rand" "crypto/rand"
"fmt" "fmt"
"math/big" "math/big"
"strconv" "strconv"
"golang.org/x/crypto/openpgp/elgamal"
) )
type Encryption struct { type Encryption struct {
...@@ -31,35 +32,60 @@ func NewParty(x int, keyChan chan []*elgamal.PublicKey, encChan chan []*Encrypti ...@@ -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() { func (p *Party) Listen() {
_, ok := <-p.keyChan // Wait for Alice to send public keys.
keys, ok := <-p.keyChan
if !ok { if !ok {
panic("key channel closed unexpectedly") panic("key channel closed unexpectedly")
} }
var encs []*Encryption // encrypt Bob's column using the public keys.
for i, key := range(<-p.keyChan) { encs := make([]*Encryption, 8)
for i, key := range keys {
var res []byte var res []byte
res = strconv.AppendBool(res, blood.Table[i][p.x]) res = strconv.AppendBool(res, blood.Table[i][p.x])
c1, c2, _ := elgamal.Encrypt(rand.Reader, key, res) 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 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) keys := make([]*elgamal.PublicKey, 8)
//TODO: insert actual publickey on index x // Generate a private key for Elgamal
var pKey elgamal.PrivateKey params := group.Default()
//TODO: Generate 7 fake public keys 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 p.keyChan <- keys
encs := <-p.encChan encs := <-p.encChan
data, _ := elgamal.Decrypt(&pKey,encs[p.x].C1, encs[p.x].C2) //Result as byte slice // Decrypt
result, _ := strconv.ParseBool(string(data)) data, err := elgamal.Decrypt(priv, encs[p.x].C1, encs[p.x].C2) //Result as byte slice
return result if err != nil {
return false, err
}
result, err := strconv.ParseBool(string(data))
return result, err
} }
type Protocol struct { type Protocol struct {
...@@ -69,19 +95,21 @@ type Protocol struct { ...@@ -69,19 +95,21 @@ type Protocol struct {
func NewProtocol(x, y int) *Protocol { func NewProtocol(x, y int) *Protocol {
keyChan := make(chan []*elgamal.PublicKey) keyChan := make(chan []*elgamal.PublicKey)
encChan := make(chan []*Encryption) encChan := make(chan []*Encryption)
rec := NewParty(x, keyChan,encChan) rec := NewParty(x, keyChan, encChan)
sen := NewParty(y,keyChan,encChan) sen := NewParty(y, keyChan, encChan)
return &Protocol{ return &Protocol{
Receiver: rec, Receiver: rec,
Sender: sen, Sender: sen,
} }
} }
// RunProtocol runs the protocol between receiving blood type x and donor blood // RunProtocol runs the protocol between receiving blood type x and donor blood
// type y. // type y.
func RunProtocol(x, y int) bool { func RunProtocol(x, y int) (bool, error) {
p := NewProtocol(x, y) p := NewProtocol(x, y)
// We let Bob listen until Alice sends.
// This kinda simulates talking over a network.
go func() { go func() {
p.Sender.Listen() p.Sender.Listen()
}() }()
...@@ -90,9 +118,10 @@ func RunProtocol(x, y int) bool { ...@@ -90,9 +118,10 @@ func RunProtocol(x, y int) bool {
func main() { func main() {
bloodA, bloodB := blood.Type_ABn, blood.Type_ABp bloodA, bloodB := blood.Type_ABn, blood.Type_ABp
z := RunProtocol(bloodA, bloodB) z, err := RunProtocol(bloodA, bloodB)
if err != nil {
if z == blood.Table[bloodA][bloodB] { fmt.Println("Protocol failed with error:", err)
} else if z == blood.Table[bloodA][bloodB] {
fmt.Println("Protocol succeded") fmt.Println("Protocol succeded")
} else { } else {
fmt.Printf("Protocol failed, output was %t, but should be %t", z, blood.Table[bloodA][bloodB]) 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) { ...@@ -28,7 +28,10 @@ func TestProtocol(t *testing.T) {
for y := 0; y < n; y++ { for y := 0; y < n; y++ {
testName := fmt.Sprintf("(x=%s,y=%s)", blood.Names[x], blood.Names[y]) testName := fmt.Sprintf("(x=%s,y=%s)", blood.Names[x], blood.Names[y])
t.Run(testName, func(t *testing.T) { 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) t.Fatalf("Failed blood compatibility test for index [%d,%d]. Expected %t, got %t", x, y, !z, z)
} }
}) })
......
package elgamal package elgamal
import ( import (
"crycomp/internal/blood/crypto/group" "crycomp/internal/crypto/group"
"crycomp/internal/crypto/util"
"crypto/rand" "crypto/rand"
"errors" "errors"
"io" "io"
...@@ -19,9 +20,13 @@ type PrivateKey struct { ...@@ -19,9 +20,13 @@ type PrivateKey struct {
X *big.Int X *big.Int
} }
// GenerateKey returns an Elgamal private key by choosing an element x in Zq // GenerateKey returns an Elgamal private key with corresponding public key.
// and then computing h = g^x mod p in Gq for the public key. The private key // The security depends un the underlying group. Therefore we assume that p
// is (G, x) and public key is (G, h). // 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) { func GenerateKey(random io.Reader, params *group.Params) (priv *PrivateKey, err error) {
x, err := rand.Int(random, params.Q) x, err := rand.Int(random, params.Q)
if err != nil { if err != nil {
...@@ -42,7 +47,8 @@ func GenerateKey(random io.Reader, params *group.Params) (priv *PrivateKey, err ...@@ -42,7 +47,8 @@ func GenerateKey(random io.Reader, params *group.Params) (priv *PrivateKey, err
return // return priv and 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) { func Encrypt(random io.Reader, pub *PublicKey, msg []byte) (c1, c2 *big.Int, err error) {
m := new(big.Int).SetBytes(msg) m := new(big.Int).SetBytes(msg)
if m.Cmp(pub.Q) != -1 { if m.Cmp(pub.Q) != -1 {
...@@ -50,8 +56,7 @@ func Encrypt(random io.Reader, pub *PublicKey, msg []byte) (c1, c2 *big.Int, err ...@@ -50,8 +56,7 @@ func Encrypt(random io.Reader, pub *PublicKey, msg []byte) (c1, c2 *big.Int, err
} }
m = encodeMessage(pub, m) m = encodeMessage(pub, m)
// TODO m must not b zero r, err := util.RandInt(random, pub.Q)
r, err := randInt(random, pub.Q)
if err != nil { if err != nil {
return return
} }
...@@ -64,6 +69,7 @@ func Encrypt(random io.Reader, pub *PublicKey, msg []byte) (c1, c2 *big.Int, err ...@@ -64,6 +69,7 @@ func Encrypt(random io.Reader, pub *PublicKey, msg []byte) (c1, c2 *big.Int, err
return return
} }
// Decrypt an Elgamal ciphertext using an Elgamal private key.
func Decrypt(priv *PrivateKey, c1, c2 *big.Int) (msg []byte, err error) { func Decrypt(priv *PrivateKey, c1, c2 *big.Int) (msg []byte, err error) {
s := new(big.Int).Exp(c1, priv.X, priv.P) s := new(big.Int).Exp(c1, priv.X, priv.P)
if s.ModInverse(s, priv.P) == nil { if s.ModInverse(s, priv.P) == nil {
...@@ -79,6 +85,8 @@ func Decrypt(priv *PrivateKey, c1, c2 *big.Int) (msg []byte, err error) { ...@@ -79,6 +85,8 @@ func Decrypt(priv *PrivateKey, c1, c2 *big.Int) (msg []byte, err error) {
return 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) { func encodeMessage(pub *PublicKey, x *big.Int) (m *big.Int) {
m = new(big.Int).Add(x, one) m = new(big.Int).Add(x, one)
exp := new(big.Int).Set(pub.Q) exp := new(big.Int).Set(pub.Q)
...@@ -91,6 +99,8 @@ func encodeMessage(pub *PublicKey, x *big.Int) (m *big.Int) { ...@@ -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) { func decodeMessage(priv *PrivateKey, x *big.Int) (m *big.Int) {
m = new(big.Int) m = new(big.Int)
if x.Cmp(priv.Q) != 1 { if x.Cmp(priv.Q) != 1 {
...@@ -102,16 +112,3 @@ func decodeMessage(priv *PrivateKey, x *big.Int) (m *big.Int) { ...@@ -102,16 +112,3 @@ func decodeMessage(priv *PrivateKey, x *big.Int) (m *big.Int) {
return m.Sub(m, one) 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 ...@@ -2,7 +2,7 @@ package elgamal
import ( import (
"bytes" "bytes"
"crycomp/internal/blood/crypto/group" "crycomp/internal/crypto/group"
"crypto/rand" "crypto/rand"
"fmt" "fmt"
"math/big" "math/big"
......
package oblivious package oblivious
import ( import (
"crycomp/internal/blood/crypto/elgamal" "crycomp/internal/crypto/elgamal"
"crycomp/internal/blood/crypto/group" "crycomp/internal/crypto/group"
"crypto/rand" "crycomp/internal/crypto/util"
"io" "io"
"math/big" "math/big"
) )
var one = big.NewInt(1)
var two = big.NewInt(2) 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) { func OGenElgamel(random io.Reader, params *group.Params) (pub *elgamal.PublicKey, err error) {
tmp := new(big.Int).Sub(params.P, one) s, err := util.RandInt(random, params.P)
// sample
r, err := rand.Int(random, tmp)
if err != nil { if err != nil {
return return
} }
s := r.Add(r, one)
pub = &elgamal.PublicKey{ pub = &elgamal.PublicKey{
P: params.P, P: params.P,
Q: params.Q, Q: params.Q,
G: params.G, G: params.G,
H: s.Exp(r, two, params.P), H: s.Exp(s, two, params.P),
} }
return 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