Skip to content
GitLab
Menu
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
5e570bc6
Commit
5e570bc6
authored
Sep 26, 2021
by
Anders Jensen Løvig
Browse files
Fixed folder structure
parent
03cf4408
Changes
7
Hide whitespace changes
Inline
Side-by-side
cmd/handin4/main.go
View file @
5e570bc6
...
...
@@ -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
])
...
...
cmd/handin4/main_test.go
View file @
5e570bc6
...
...
@@ -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
)
}
})
...
...
internal/
blood/
crypto/elgamal/elgamal.go
→
internal/crypto/elgamal/elgamal.go
View file @
5e570bc6
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
}
internal/
blood/
crypto/elgamal/elgamal_test.go
→
internal/crypto/elgamal/elgamal_test.go
View file @
5e570bc6
...
...
@@ -2,7 +2,7 @@ package elgamal
import
(
"bytes"
"crycomp/internal/
blood/
crypto/group"
"crycomp/internal/crypto/group"
"crypto/rand"
"fmt"
"math/big"
...
...
internal/
blood/
crypto/group/group.go
→
internal/crypto/group/group.go
View file @
5e570bc6
File moved
internal/
blood/
crypto/oblivious/oblivious.go
→
internal/crypto/oblivious/oblivious.go
View file @
5e570bc6
package
oblivious
import
(
"crycomp/internal/
blood/
crypto/elgamal"
"crycomp/internal/
blood/
crypto/group"
"cry
pto/rand
"
"crycomp/internal/crypto/elgamal"
"crycomp/internal/crypto/group"
"cry
comp/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
}
internal/crypto/util/util.go
0 → 100644
View file @
5e570bc6
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
}
Write
Preview
Supports
Markdown
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment