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

Merge

parents 0b5a2486 4f1f5dca
Pipeline #21807 failed with stages
in 1 minute and 3 seconds
* text eol=lf
.idea/
.vscode/
*.test
*.code-workspace
.tasks
.idea/
.vscode/
*.test
*.code-workspace
.tasks
......@@ -6,35 +6,46 @@ import (
"math/big"
"os"
"strconv"
"github.com/jessevdk/go-flags"
)
var one = big.NewInt(1)
var two = big.NewInt(2)
var opts struct {
Bits int `short:"b" long:"bit" description:"Bit length of prime p" default:"2048"`
}
func main() {
findSafePrimes(16)
findSafePrimes(32)
findSafePrimes(64)
findSafePrimes(128)
findSafePrimes(256)
findSafePrimes(512)
findSafePrimes(1024)
// findGroup()
_, err := flags.Parse(&opts)
if err != nil {
os.Exit(0)
}
findSafePrimes(opts.Bits)
}
func findSafePrimes(bits int) {
one := big.NewInt(1)
two := big.NewInt(2)
i := 1
// Find 4 safe primes
for i := 0; i < 4; i++ {
fmt.Printf("==== %d bits ====\n", bits)
kbits := bits - 1
for n := 0; n < 4; n++ {
q := new(big.Int)
p := new(big.Int)
for !p.ProbablyPrime(20) {
q, _ = rand.Prime(rand.Reader, bits-1)
fmt.Print("\rTry: ", i)
i++
q, _ = rand.Prime(rand.Reader, kbits)
p = p.Mul(q, two).Add(p, one)
}
fmt.Printf("p: %d\nq: %d\n", p, q)
fmt.Printf("\n==== %d bits ====\n", bits)
fmt.Printf("p: %d bits: %x\n", p.BitLen(), p)
fmt.Printf("q: %d bits: %x\n", q.BitLen(), q)
}
}
......
......@@ -8,7 +8,6 @@ import (
"math/big"
"os"
"strings"
"sync"
"time"
"github.com/jessevdk/go-flags"
......@@ -19,8 +18,6 @@ var opts struct {
}
var server struct {
sync.Mutex
// Server enables this authority to listen for incomming connections.
Server *network.Server
// The election being held
......@@ -32,6 +29,8 @@ var server struct {
Closed chan bool
Done chan bool
Connections map[string]*network.Conn
}
func init() {
......@@ -40,16 +39,16 @@ func init() {
os.Exit(0)
}
server.Mutex = sync.Mutex{}
server.Closed = make(chan bool, 1)
server.Done = make(chan bool, 1)
// Init configuration
// Load configuration to get election parameters and server list.
server.Config, err = network.LoadConfig()
if err != nil {
log.Fatal("ERROR: " + err.Error())
log.Fatal("fatal:", err)
}
// Find our current port and server id
portStr := fmt.Sprintf(":%d", opts.Port)
var serialNumber *big.Int = nil
for address, sn := range server.Config.Servers {
......@@ -60,140 +59,81 @@ func init() {
}
}
if serialNumber == nil {
log.Fatal("Server is not on server list")
log.Fatal("fatal: server is not on server list")
}
// Initialize server using correct certificates
server.Config.CertPath = fmt.Sprintf("config/cert/server/s%d.crt", serialNumber)
server.Config.KeyPath = fmt.Sprintf("config/cert/server/s%d.key", serialNumber)
server.Server = network.NewServer(server.Config)
// Initialize election
servers := len(server.Config.Servers)
required := (servers + 1) / 2
required := (servers / 2) + 1
config := &election.Config{
Server: server.Server,
ServerID: election.UniqueID(serialNumber.String()),
Voters: 5,
Voters: 10,
Servers: servers,
RequiredServers: required,
Deadline: time.Now().Add(10 * time.Second),
CloseCallback: closeCallback,
TallyCallback: tallyCallback,
Deadline: time.Now().Add(30 * time.Second),
ResultCallback: resultCallback,
CloseSleep: 5 * time.Second,
}
server.Election = election.NewElection(config)
// Initialize server
server.Server = network.NewServer(server.Config)
}
var clientHandlers = map[string]network.MessageHandler{
election.MsgBallot: func(conn *network.Conn, data network.MessageData) *network.Message {
var ballot election.Ballot
err := data.Unmarshal(&ballot)
if err != nil {
log.Println("ERROR: " + err.Error())
} else {
server.Election.HandleBallot(conn.SerialNumber(), &ballot)
}
return network.NewMessage(election.MsgBallotAck, nil)
},
}
var serverHandlers = map[string]network.MessageHandler{
election.MsgClosing: func(conn *network.Conn, data network.MessageData) *network.Message {
server.Election.HandleClosing(conn.SerialNumber())
return nil
},
election.MsgTally: func(conn *network.Conn, data network.MessageData) *network.Message {
var tally election.Tally
err := data.Unmarshal(&tally)
if err != nil {
log.Println("ERROR: " + err.Error())
} else {
server.Election.HandleTally("", &tally)
}
return nil
},
}
func main() {
err := server.Server.Start(opts.Port, func(connType network.ConnType) map[string]network.MessageHandler {
if connType == network.ConnTypeClient {
return clientHandlers
} else {
return serverHandlers
}
})
func startServer() {
err := server.Server.Start(opts.Port)
if err != nil {
log.Println("ERROR: " + err.Error())
log.Fatal("Failed to start server")
log.Fatal("Main: fatal:", err)
}
log.Println("==================== Collecting ====================")
err = server.Election.Start()
if err != nil {
log.Println("ERROR: " + err.Error())
log.Fatal("Failed to start election")
}
time.Sleep(1 * time.Second) // Grace period
<-server.Done // Closed
<-server.Done // Result
server.Server.Close()
}
func closeCallback() {
log.Println("DEBUG: Close callback")
func conenctServers() {
connections := 0
msgClosed := network.NewMessage(election.MsgClosing, nil)
// Connect to other servers
for address := range server.Config.Servers {
if address != server.Address {
conn, err := server.Server.Connect(address, serverHandlers)
_, err := server.Server.Connect(address)
if err != nil {
log.Println("Failed to connect to", address, err.Error())
log.Println("Main: error:", err)
continue
}
connections++
err = conn.WriteMessage(msgClosed)
if err != nil {
log.Println("ERROR: ", err.Error())
}
}
}
if connections == 0 {
log.Fatal("Failed to connect to other servers")
log.Fatal("Main: fatal: could not connect to servers")
}
}
server.Done <- true
func startElection() {
err := server.Election.Start()
if err != nil {
log.Fatal("Main: fatal:", err)
}
}
func tallyCallback() {
log.Println("DEBUG: Tally callback")
log.Println("===================== Tallying =====================")
func main() {
startServer()
time.Sleep(5 * time.Second) // Give servers time to start before connecting
conenctServers()
time.Sleep(1 * time.Second) // To let servers connect before starting election
startElection()
tally := server.Election.Tally()
server.Election.HandleTally("", tally)
<-server.Done // Result
// err := server.Client.Broadcast(network.NewMessage(election.MsgTally, tally))
// if err != nil {
// log.Println("ERROR: " + err.Error())
// }
time.Sleep(1 * time.Second) // Grace period
server.Server.Close()
}
func resultCallback(result *election.Result) {
log.Println("DEBUG: Result callback")
log.Println("====================== Result ======================")
if result == nil {
log.Printf("No votes received")
log.Printf("Main: no votes received")
} else {
percentage := (float64(result.Tally) / float64(result.Votes)) * 100
log.Printf("Final result: %d of %d (%.2f%%) voted 1\n", result.Tally, result.Votes, percentage)
log.Printf("Main: final result: %d of %d (%.2f%%) voted 1\n", result.Tally, result.Votes, percentage)
}
server.Done <- true
......
package main
import (
"bsc-shamir/crypto/common"
"bsc-shamir/election"
"bsc-shamir/network"
"bufio"
......@@ -30,8 +31,11 @@ var voter struct {
Config *network.Config
Client *network.Client
Acks map[string]bool
Done chan bool
ConnectionCount int
RecievedCount int
Acks map[string]bool
Done chan bool
}
func init() {
......@@ -43,13 +47,26 @@ func init() {
// Load config
config, err := network.LoadConfig()
if err != nil {
log.Fatal("ERROR: " + err.Error())
log.Fatal("fatal: " + err.Error())
}
config.CertPath = opts.Cert
config.KeyPath = opts.Key
// Init client
voter.RecievedCount = 0
voter.Client = network.NewClient(config)
voter.Client.OnMessage(election.MsgBallotAck, func(conn *network.Conn, data network.MessageData) {
voter.Lock()
defer voter.Unlock()
voter.Acks[conn.RemoteAddr().String()] = true
conn.Close()
voter.RecievedCount++
if voter.RecievedCount == voter.ConnectionCount {
voter.Done <- true
}
})
voter.Mutex = sync.Mutex{}
voter.Acks = make(map[string]bool)
......@@ -61,13 +78,13 @@ func main() {
vote := inputVote()
if vote != 0 && vote != 1 {
fmt.Println("Vote must be 0 or 1")
fmt.Println("error: vote must be 0 or 1")
os.Exit(0)
}
config, err := network.LoadConfig()
if err != nil {
log.Fatal("ERROR: " + err.Error())
log.Fatal("fatal: " + err.Error())
}
voter.Config = config
......@@ -79,28 +96,31 @@ func main() {
}
ballots := election.CreateBallots(t, xs, big.NewInt(vote))
params := common.DefaultParams()
for id, b := range ballots {
if !b.Verify(params) {
log.Fatal("Main: fatal: could not verify ballot for server", id)
}
}
sendBallots(ballots)
// Wait for acknowledgements or timeout
timeout := network.TimeoutAfter(10 * time.Second)
timeout := time.After(10 * time.Second)
select {
case <-voter.Done:
log.Println("All servers acknowledged")
log.Println("Main: all servers acknowledged")
case <-timeout:
for address, status := range voter.Acks {
if !status {
log.Println("Did not receive acknowledgment from ", address)
log.Println("Main: no acknowledgment from ", address)
}
}
}
err = voter.Client.Close()
if err != nil {
log.Println("ERROR: " + err.Error())
log.Println("Failed to close client")
log.Println("Main: error: ", err.Error())
}
time.Sleep(1 * time.Second) // Grace period
}
func inputVote() int64 {
......@@ -112,12 +132,12 @@ func inputVote() int64 {
reader := bufio.NewReader(os.Stdin)
text, err := reader.ReadString('\n')
if err != nil {
log.Fatal("Failed to read input")
log.Fatal("fatal: could not read input")
}
vote, err := strconv.Atoi(text[0 : len(text)-1])
if err != nil {
fmt.Println("Vote must be an integer")
fmt.Println("error: vote must be an integer")
os.Exit(0)
}
......@@ -127,46 +147,28 @@ func inputVote() int64 {
func sendBallots(ballots map[election.UniqueID]*election.Ballot) {
voter.Lock()
defer voter.Unlock()
connectionCount := 0
receivedCount := 0
i := 0
for address := range voter.Config.Servers {
conn, err := voter.Client.Connect(address,
map[string]network.MessageHandler{
election.MsgBallotAck: func(conn *network.Conn, data network.MessageData) *network.Message {
voter.Lock()
defer voter.Unlock()
voter.Acks[address] = true
conn.Close()
receivedCount++
if receivedCount == connectionCount {
voter.Done <- true
}
return nil
},
})
conn, err := voter.Client.Connect(address)
if err != nil {
log.Println("ERROR: " + err.Error())
log.Println("Main: error:", err)
continue
}
ballot := ballots[conn.SerialNumber()]
ballot := ballots[election.UniqueID(conn.SerialNumber())]
message := network.NewMessage(election.MsgBallot, ballot)
err = conn.WriteMessage(message)
if err != nil {
log.Println("ERROR: " + err.Error())
log.Println("Main: error:", err)
continue
}
voter.Acks[address] = false
connectionCount++
voter.Acks[conn.RemoteAddr().String()] = false
voter.ConnectionCount++
i++
}
if connectionCount == 0 {
log.Println("FATAL: Could not connect to servers")
os.Exit(1)
if voter.ConnectionCount == 0 {
log.Fatal("fatal: could not connect to servers")
}
}
......@@ -7,10 +7,18 @@ import (
// String constants for default primes
const (
p = "3767033279"
q = "1883516639"
// p = "3767033279"
// q = "1883516639"
g = "2"
h = "3"
// 256 bits
// p = "113725176798010050451165288258759946268131239693032262275611886693367245547103"
// q = "56862588399005025225582644129379973134065619846516131137805943346683622773551"
// 2048 bits
p = "df0df2d4d4320d6f562ddf3ef2ba7b96463e8ba2b6d965a7b377521434dea91ffc299287efc0d495e58fc33cacfc02d2ed819c83bd66b4ebf5373a001adf1b18b0a80c4df6bb372708479c3afa081ae913b99c6b74906b6d497f7752a54869d9542097b98e7373d6643cc3533197ff8160a7d79791ce3e5f53c43a89cf8f4f9fd3afd5cdc6902784daa97715ef73ba8f5d69c2f8e0e901c35917b8d081f38ae07e59df580515fdcb38a718de4c512353658f4e622ed88b7379893907e7d59df22c427f4b04fd0bfbb40e650907c25d61f0cdc7dc2f677841ee06a60ed8206e7ec46684a8716a9470aa19cb221ea1bce00f59067ce4439fd04be0c370e9f3f487"
q = "6f86f96a6a1906b7ab16ef9f795d3dcb231f45d15b6cb2d3d9bba90a1a6f548ffe14c943f7e06a4af2c7e19e567e016976c0ce41deb35a75fa9b9d000d6f8d8c58540626fb5d9b938423ce1d7d040d7489dcce35ba4835b6a4bfbba952a434ecaa104bdcc739b9eb321e61a998cbffc0b053ebcbc8e71f2fa9e21d44e7c7a7cfe9d7eae6e34813c26d54bb8af7b9dd47aeb4e17c707480e1ac8bdc6840f9c5703f2cefac028afee59c538c6f262891a9b2c7a731176c45b9bcc49c83f3eacef916213fa5827e85fdda07328483e12eb0f866e3ee17b3bc20f70353076c10373f6233425438b54a38550ce5910f50de7007ac833e7221cfe825f061b874f9fa43"
)
// Params represents common parameters used by all schemes
......@@ -24,7 +32,7 @@ type Params struct {
}
func parseNumber(number string) *big.Int {
n, success := new(big.Int).SetString(number, 10)
n, success := new(big.Int).SetString(number, 16)
if !success {
panic("Not a decimal number: " + number)
}
......
......@@ -7,8 +7,23 @@ import (
"testing"
)
func parseNumber(number string) *big.Int {
n, success := new(big.Int).SetString(number, 10)
if !success {
panic("Not a decimal number: " + number)
}
return n
}
func TestCommit(t *testing.T) {
commonParams := common.DefaultParams()
commonParams := &common.Params{
P: parseNumber("3767033279"),
Q: parseNumber("1883516639"),
Zp: zn.NewRing(parseNumber("3767033279")),
Zq: zn.NewRing(parseNumber("1883516639")),
G: parseNumber("2"),
H: parseNumber("3"),
}
params := NewParams(commonParams)
commit1 := params.Commit(big.NewInt(4), big.NewInt(5))
......@@ -42,8 +57,8 @@ func TestThresholds(test *testing.T) {
secret := big.NewInt(4567) // Does not matter
binder := params.Zq.GetRandomElement()
fails := 0
for t := 1; t <= 40; t++ {
for n := t; n <= 40; n++ {
for t := 1; t <= 10; t++ {
for n := t; n <= 10; n++ {
shares, proof := params.Create(3, createXS(5), secret, binder)
for i := 0; i < len(shares); i++ {
if !params.Verify(shares[i], proof) {
......
......@@ -4,29 +4,28 @@ import (
"bsc-shamir/crypto/pedersen"
"sync"
"github.com/google/uuid"
"github.com/gonum/stat/combin"
"github.com/google/uuid"
)
type Whitelist map[uuid.UUID]pedersen.Proof
type Judge struct {
mutex sync.Mutex
mutex sync.Mutex
Threadshold int
Points map[uuid.UUID]int
Answers map[uuid.UUID]pedersen.Proof
BallotIDs []uuid.UUID
Points map[uuid.UUID]int
Answers map[uuid.UUID]pedersen.Proof
BallotIDs []uuid.UUID
}
func NewJudge(threadshold int, box *BallotBox) *Judge {
m := len(box.ballots)
j := &Judge{
mutex: sync.Mutex{},
mutex: sync.Mutex{},
Threadshold: threadshold,
Points: make(map[uuid.UUID]int, m),
Answers: make(map[uuid.UUID]pedersen.Proof, m),
BallotIDs: []uuid.UUID{},
Points: make(map[uuid.UUID]int, m),
Answers: make(map[uuid.UUID]pedersen.Proof, m),
BallotIDs: []uuid.UUID{},
}
for _, id := range box.Filter() {
ballot := box.ballots[id]
......
......@@ -14,6 +14,7 @@ import (
"log"
"math/big"
"sync"
"time"
"crypto"
......@@ -24,10 +25,11 @@ import (
// Ballot represents a share to be submitted to a vote counter.
type Ballot struct {
ID uuid.UUID `json:"id"`
Share *pedersen.Share `json:"share"`
Commits pedersen.Proof `json:"commits"`
Proofs [2]*sigma.Proof `json:"proofs"`
ID uuid.UUID `json:"id"`
Timestamp time.Time `json:"timestamp"`
Share *pedersen.Share `json:"share"`
Commits pedersen.Proof `json:"commits"`
Proofs [2]*sigma.Proof `json:"proofs"`
}
// BallotBox collects ballots from voters
......@@ -58,13 +60,16 @@ func CreateBallots(t int, xs []*big.Int, vote *big.Int) map[UniqueID]*Ballot {
shares, commits := pedersen.NewParams(params).Create(t, xs, vote, binder)
proof := sigma.NewParams(params).Prove(vote, binder, commits[0])
timestamp := time.Now()
ballots := make(map[UniqueID]*Ballot)
for _, share := range shares {
ballots[UniqueID(share.X.String())] = &Ballot{
ID: uuid.New(),
Share: share,
Commits: commits,
Proofs: proof,
ID: uuid.New(),
Timestamp: timestamp,
Share: share,
Commits: commits,
Proofs: proof,