// The signer connects to the leader and then waits for a message to be // signed func GoSigner(conf *app.NaiveConfig) { // Wait for leader to be ready time.Sleep(2 * time.Second) host := net.NewTcpHost(app.RunFlags.Hostname) key := cliutils.KeyPair(suite) signer := NewPeer(host, ServRole, key.Secret, key.Public) dbg.Lvl3(signer.String(), "will contact leader", conf.Hosts[0]) l := signer.Open(conf.Hosts[0]) dbg.Lvl3(signer.String(), "is connected to leader", l.PeerName()) // make the protocol for each round for round := 0; round < conf.Rounds; round++ { // Receive message m, err := l.Receive() dbg.Lvl3(signer.String(), "round", round, "received the message to be signed from the leader") if err != nil { dbg.Fatal(signer.String(), "round", round, "received error waiting msg") } if m.MsgType != net.MessageSigningType { dbg.Fatal(app.RunFlags.Hostname, "round", round, "wanted to receive a msg to sign but..", m.MsgType.String()) } msg := m.Msg.(net.MessageSigning).Msg dbg.Lvl3(signer.String(), "round", round, "received msg:", msg[:]) // Generate signature & send s := signer.Signature(msg[:]) l.Send(*s) dbg.Lvl3(signer.String(), "round", round, "sent the signature to leader") } l.Close() dbg.Lvl3(app.RunFlags.Hostname, "Finished") }
// NewPeer returns a new peer with its id and the number of peers in the schnorr signature algo // TODO verification of string addr:port func NewPeer(id int, name string, suite abstract.Suite, p poly.Threshold, isRoot bool) *Peer { if id >= p.N { log.Fatal("Error while NewPeer: gien", id, "as id whereas polyinfo.N =", p.N) } // Setup of the private / public pair key := cliutils.KeyPair(suite) // setup of the public list of key pubKeys := make([]abstract.Point, p.N) pubKeys[id] = key.Public dbg.Lvl3(name, "(id", id, ") has created its private/public key: public =>", key.Public) return &Peer{ Id: id, remote: make(map[int]RemotePeer), root: isRoot, Name: name, info: p, suite: suite, key: key, pubKeys: pubKeys, schnorr: new(poly.Schnorr), synChan: make(chan Syn), ackChan: make(chan Ack), } }
// ComputeSharedSecret will make the exchange of dealers between // the peers and will compute the sharedsecret at the end func (p *Peer) ComputeSharedSecret() *poly.SharedSecret { // Construct the dealer dealerKey := cliutils.KeyPair(p.suite) dealer := new(poly.Deal).ConstructDeal(&dealerKey, &p.key, p.info.T, p.info.R, p.pubKeys) // Construct the receiver receiver := poly.NewReceiver(p.suite, p.info, &p.key) // add already its own dealer _, err := receiver.AddDeal(p.Id, dealer) if err != nil { dbg.Fatal(p.String(), "could not add its own dealer >< ABORT") } // Send the dealer struct TO every one err = p.SendToAll(dealer) dbg.Lvl3(p.Name, "sent its dealer to every peers. (err =", err, ")") // Receive the dealer struct FROM every one // wait with a chan to get ALL dealers dealChan := make(chan *poly.Deal) for _, rp := range p.remote { go func(rp RemotePeer) { d := new(poly.Deal).UnmarshalInit(p.info.T, p.info.R, p.info.N, p.suite) err := p.suite.Read(rp.Conn, d) if err != nil { dbg.Fatal(p.Name, "received a strange dealer from", rp.String(), ":", err) } dealChan <- d }(rp) } // wait to get all dealers dbg.Lvl3(p.Name, "wait to receive every other peer's dealer...") n := 0 for { // get the dealer and add it d := <-dealChan dbg.Lvl3(p.Name, "collected one more dealer (count =", n, ")") // TODO: get the response back to the dealer _, err := receiver.AddDeal(p.Id, d) if err != nil { dbg.Fatal(p.Name, "has error when adding the dealer:", err) } n += 1 // we get enough dealers to compute the shared secret if n == p.info.T-1 { dbg.Lvl3(p.Name, "received every Dealers") break } } sh, err := receiver.ProduceSharedSecret() if err != nil { dbg.Fatal(p.Name, "could not produce shared secret. Abort. (err", err, ")") } dbg.Lvl3(p.Name, "produced shared secret !") return sh }
// KeyGeneration will generate a fresh public / private key pair // and write those down into two separate files func KeyGeneration(key, address string) { if address == "" { dbg.Fatal("You must call keygen with ipadress !") } address, err := cliutils.VerifyPort(address, conode.DefaultPort) dbg.Lvl1("Address is", address) if err != nil { dbg.Fatal(err) } // gen keypair kp := cliutils.KeyPair(suite) // Write private if err := cliutils.WritePrivKey(suite, namePriv(key), kp.Secret); err != nil { dbg.Fatal("Error writing private key file:", err) } // Write public if err := cliutils.WritePubKey(suite, namePub(key), kp.Public, address); err != nil { dbg.Fatal("Error writing public key file:", err) } dbg.Lvl1("Keypair generated and written to", namePriv(key), "/", namePub(key)) }
package network import ( "bytes" "github.com/dedis/cothority/lib/cliutils" "github.com/dedis/crypto/abstract" "github.com/dedis/crypto/config" "github.com/dedis/crypto/edwards" "reflect" "testing" ) var s abstract.Suite = edwards.NewAES128SHA256Ed25519(false) var key1 config.KeyPair = cliutils.KeyPair(s) var key2 config.KeyPair = cliutils.KeyPair(s) func TestListBasicSignatureMarshaling(t *testing.T) { Suite = s bs := BasicSignature{ Pub: key1.Public, Chall: key1.Secret, Resp: key1.Secret, } var length int = 10 sigs := make([]BasicSignature, length) for i := 0; i < length; i++ { sigs[i] = bs } lbs := ListBasicSignature{ Length: length, Sigs: sigs,
// This is the leader who waits for all connections and then sends the // message to be signed func GoLeader(conf *app.NaiveConfig) { host := net.NewTcpHost(app.RunFlags.Hostname) key := cliutils.KeyPair(suite) leader := NewPeer(host, LeadRole, key.Secret, key.Public) // Setting up the connections // notably to the monitoring process if app.RunFlags.Logger != "" { monitor.ConnectSink(app.RunFlags.Logger) } else { monitor.EnableMeasure(false) } msg := []byte("Hello World\n") // Listen for connections dbg.Lvl3(leader.String(), "making connections ...") // each conn will create its own channel to be used to handle rounds roundChans := make(chan chan chan *net.BasicSignature) // Send the message to be signed proto := func(c net.Conn) { // make the chan that will receive a new chan // for each round where to send the signature roundChan := make(chan chan *net.BasicSignature) roundChans <- roundChan n := 0 // wait for the next round for sigChan := range roundChan { dbg.Lvl3(leader.String(), "Round", n, "sending message", msg, "to signer", c.PeerName()) leader.SendMessage(msg, c) dbg.Lvl3(leader.String(), "Round", n, "receivng signature from signer", c.PeerName()) sig := leader.ReceiveBasicSignature(c) sigChan <- sig n += 1 } c.Close() dbg.Lvl3(leader.String(), "closed connection with signer", c.PeerName()) } // Connecting to the signer setup := monitor.NewMeasure("setup") go leader.Listen(app.RunFlags.Hostname, proto) dbg.Lvl3(leader.String(), "Listening for channels creation..") // listen for round chans + signatures for each round masterRoundChan := make(chan chan *net.BasicSignature) roundChanns := make([]chan chan *net.BasicSignature, 0) numberHosts := len(conf.Hosts) // Make the "setup" of channels for { ch := <-roundChans roundChanns = append(roundChanns, ch) //Received round channels from every connections- if len(roundChanns) == numberHosts-1 { // make the Fanout => master will send to all go func() { // send the new SignatureChannel to every conn for newSigChan := range masterRoundChan { for i, _ := range roundChanns { go func(j int) { roundChanns[j] <- newSigChan }(i) } } //close when finished for _, c := range roundChanns { close(c) } }() break } } setup.Measure() dbg.Lvl3(leader.String(), "got all channels ready => starting the", conf.Rounds, "rounds") // Starting to run the simulation for conf.Rounds rounds roundM := monitor.NewMeasure("round") for round := 0; round < conf.Rounds; round++ { // Measure calculation time calc := monitor.NewMeasure("calc") dbg.Lvl1("Server starting round", round+1) n := 0 faulty := 0 // launch a new round connChan := make(chan *net.BasicSignature) masterRoundChan <- connChan // Wait each signatures sigs := make([]*net.BasicSignature, 0) for n < numberHosts-1 { bs := <-connChan sigs = append(sigs, bs) n += 1 } // All sigs reeived <=> all calcs are done calc.Measure() // verify each signatures if conf.SkipChecks { dbg.Lvl3("Skipping check for round", round) } else { // Measure verificationt time verify := monitor.NewMeasure("verify") for _, sig := range sigs { if err := SchnorrVerify(suite, msg, *sig); err != nil { faulty += 1 dbg.Lvl1(leader.String(), "Round", round, "received a faulty signature!") } else { dbg.Lvl3(leader.String(), "Round", round, "received Good signature") } } verify.Measure() } roundM.Measure() dbg.Lvl3(leader.String(), "Round", round, "received", len(conf.Hosts)-1, "signatures (", faulty, "faulty sign)") } // Close down all connections close(masterRoundChan) dbg.Lvl3(leader.String(), "has done all rounds") }
func RunRoot(conf *app.NTreeConfig) { host := net.NewTcpHost(app.RunFlags.Hostname) key := cliutils.KeyPair(suite) peer := NewPeer(host, LeadRole, key.Secret, key.Public) dbg.Lvl3(peer.String(), "Up and will make connections...") // monitor if app.RunFlags.Logger == "" { monitor.EnableMeasure(false) } else { if err := monitor.ConnectSink(app.RunFlags.Logger); err != nil { dbg.Fatal(peer.String(), "could not connect to the monitor:", err) } } // msg to be sent + signed msg := []byte("Hello World") // make setup measurement setup := monitor.NewMeasure("setup") // masterRoundChan is used to tell that everyone is ready masterRoundChan := make(chan chan chan *net.ListBasicSignature) // Open connection for each children for _, c := range conf.Tree.Children { dbg.Lvl3(peer.String(), "will connect to children", c.Name) connPeer := peer.Open(c.Name) if connPeer == nil { dbg.Fatal(peer.String(), "Could not open connection to child", c.Name) } // then start Root protocol go func(conn net.Conn) { dbg.Lvl3(peer.String(), "connected to children", conn.PeerName()) roundSigChan := make(chan chan *net.ListBasicSignature) // notify we are ready to begin masterRoundChan <- roundSigChan // each rounds... for lsigChan := range roundSigChan { dbg.Lvl4(peer.String(), "starting new round with", conn.PeerName()) m := net.MessageSigning{ Length: len(msg), Msg: msg, } // send msg to children err := conn.Send(m) if err != nil { dbg.Fatal(peer.String(), "could not send message to children", conn.PeerName(), ":", err) } dbg.Lvl3(peer.String(), "sent message to children", conn.PeerName()) // Receive bundled signatures sig, err := conn.Receive() if err != nil { dbg.Fatal(peer.String(), "could not received bundled signature from", conn.PeerName(), ":", err) } if sig.MsgType != net.ListBasicSignatureType { dbg.Fatal(peer.String(), "received a wrong packet type from", conn.PeerName(), ":", sig.MsgType.String()) } // Then pass them on sigs := sig.Msg.(net.ListBasicSignature) lsigChan <- &sigs dbg.Lvl3(peer.String(), "Received list of signatures from child", conn.PeerName()) } }(connPeer) } // First collect every "ready-connections" children := make([]chan chan *net.ListBasicSignature, 0) for round := range masterRoundChan { children = append(children, round) if len(children) == len(conf.Tree.Children) { dbg.Lvl3(peer.String(), "collected each children channels") break } } close(masterRoundChan) setup.Measure() // Then for each rounds tell them to start the protocol round := monitor.NewMeasure("round") for i := 1; i <= conf.Rounds; i++ { dbg.Lvl1(peer.String(), "will start a new round", i) calc := monitor.NewMeasure("calc") // the signature channel used for this round lsigChan := make(chan *net.ListBasicSignature) // notify each connections for _, ch := range children { ch <- lsigChan } childrenSigs := make([]*net.ListBasicSignature, 0) // Wait for listsignatures coming dbg.Lvl3(peer.String(), "Waiting on signatures for round", i, "...") for sigs := range lsigChan { dbg.Lvl3(peer.String(), "will analyze one ListBasicSignature...") childrenSigs = append(childrenSigs, sigs) // we have received all bundled signatures so time it if len(childrenSigs) == len(conf.Tree.Children) { close(lsigChan) // we have finished for this round } } dbg.Lvl3(peer.String(), "Received all signatures ... ") calc.Measure() var verifyWg sync.WaitGroup var faulty uint64 = 0 var total uint64 = 0 // start timing verification verify := monitor.NewMeasure("verify") for _, sigs := range childrenSigs { // Here it launches one go routine to verify a bundle verifyWg.Add(1) go func(s *net.ListBasicSignature) { defer verifyWg.Done() if conf.SkipChecks { return } // verify each independant signatures for _, sig := range s.Sigs { if err := SchnorrVerify(suite, msg, sig); err != nil { dbg.Lvl2(peer.String(), "received incorrect signature ><", err) atomic.AddUint64(&faulty, 1) } atomic.AddUint64(&total, 1) } }(sigs) } // wait for all verifications verifyWg.Wait() // finished verifying => time it ! verify.Measure() round.Measure() dbg.Lvl3(peer.String(), "Round", i, "/", conf.Rounds, "has verified all signatures:", total-faulty, "/", total, "good signatures") } // cLosing each channels for _, ch := range children { close(ch) } dbg.Lvl2(peer.String(), "Finished all rounds successfully.") }
func RunPeer(conf *app.NTreeConfig) { host := net.NewTcpHost(app.RunFlags.Hostname) key := cliutils.KeyPair(suite) peer := NewPeer(host, ServRole, key.Secret, key.Public) dbg.Lvl3(peer.String(), "Up and will make connections...") // Chan used to communicate the message from the parent to the children // Must do a Fan out to communicate this message to all children masterMsgChan := make(chan net.MessageSigning) childrenMsgChan := make([]chan net.MessageSigning, len(conf.Tree.Children)) go func() { // init for i := range childrenMsgChan { childrenMsgChan[i] = make(chan net.MessageSigning) } // for each message for msg := range masterMsgChan { // broadcast to each channels for i, ch := range childrenMsgChan { dbg.Lvl4(peer.String(), "dispatching msg to children (", i+1, "/", len(conf.Tree.Children), ")...") ch <- msg } } // When finished, close all children channs for _, ch := range childrenMsgChan { close(ch) } }() // chan used to communicate the signature from the children to the parent // It is also used to specify the start of a new round (coming from the parent // connection) masterRoundChan := make(chan chan net.ListBasicSignature) // dispatch new round to each children childRoundChan := make([]chan chan net.ListBasicSignature, len(conf.Tree.Children)) dbg.Lvl3(peer.String(), "created children Signal Channels (length =", len(childRoundChan), ")") go func() { // init for i := range childRoundChan { childRoundChan[i] = make(chan chan net.ListBasicSignature) } // For each new round started by the parent's connection for sigChan := range masterRoundChan { // if no children, no signature will come // so close immediatly so parent connection will continue if len(conf.Tree.Children) == 0 { dbg.Lvl3(peer.String(), "Has no children so closing childRoundChan") close(sigChan) } else { // otherwise, dispatch to children for i, _ := range childRoundChan { dbg.Lvl4(peer.String(), "Dispatching signature channel to children (", i+1, "/", len(conf.Tree.Children), ")...") childRoundChan[i] <- sigChan } } } dbg.Lvl3(peer.String(), "closing the children sig channels...") for _, ch := range childRoundChan { close(ch) } }() // chan used to tell the end of the protocols done := make(chan bool) // The parent protocol proto := func(c net.Conn) { dbg.Lvl3(peer.String(), "connected with parent", c.PeerName()) // for each rounds for i := 1; i <= conf.Rounds; i++ { // Create the chan for this round sigChan := make(chan net.ListBasicSignature) // that wil be used for children to pass up their signatures masterRoundChan <- sigChan dbg.Lvl3(peer.String(), "starting round", i) // First, receive the message to be signed sig, err := c.Receive() if err != nil { dbg.Fatal(peer.String(), "error receiving message from parent", c.PeerName()) } if sig.MsgType != net.MessageSigningType { dbg.Fatal(peer.String(), "received wrong packet type from parent:", sig.MsgType.String()) } msg := sig.Msg.(net.MessageSigning) // Notify the chan so it will be broadcasted down masterMsgChan <- msg dbg.Lvl3(peer.String(), "round", i, ": received message from parent", msg.Msg) // issue our signature bs := peer.Signature(msg.Msg) // wait for children signatures sigs := make([]net.BasicSignature, 0) sigs = append(sigs, *bs) // for each ListBasicSignature n := 0 dbg.Lvl3(peer.String(), "round", i, ": waiting on signatures from children ...") for lsig := range sigChan { dbg.Lvl3(peer.String(), "round", i, ": receievd a ListSignature !") // Add each independant signature for _, sig := range lsig.Sigs { sigs = append(sigs, sig) } n += 1 //We got them all ;) if n == len(conf.Tree.Children) { close(sigChan) break } } dbg.Lvl3(peer.String(), "received", len(sigs), "signatures from children") // Then send to parent the signature lbs := net.ListBasicSignature{} lbs.Length = len(sigs) lbs.Sigs = sigs err = c.Send(lbs) if err != nil { dbg.Fatal(peer.String(), "Could not send list of signature to parents ><", err) } dbg.Lvl3(peer.String(), "round", i, ": sent the array of sigs to parent") } close(masterRoundChan) c.Close() done <- true } dbg.Lvl3(peer.String(), "listen for the parent connection...") go peer.Listen(conf.Name, proto) // Connect to the children // Relay the msg // Wait for signatures dbg.Lvl3(peer.String(), "will contact its siblings..") // To stop when every children has done all rounds // Connect to every children for i, c := range conf.Tree.Children { dbg.Lvl3(peer.String(), "is connecting to", c.Name, "(", i, ")") connPeer := peer.Open(c.Name) if connPeer == nil { dbg.Fatal(peer.String(), "Could not connect to", c.Name) } // Children protocol go func(child int, conn net.Conn) { dbg.Lvl3(peer.String(), "is connected to children", conn.PeerName(), "(", child, ")") // For each rounds new round for sigChan := range childRoundChan[child] { dbg.Lvl3(peer.String(), "starting new round with children", conn.PeerName(), "(", child, ")") // get & relay the message msg := <-childrenMsgChan[child] dbg.Lvl3(peer.String(), "will relay message to child", conn.PeerName(), "(", child, ")") err := conn.Send(msg) if err != nil { dbg.Fatal(peer.String(), "Could not relay message to children", conn.PeerName()) } dbg.Lvl4(peer.String(), "sent to the message to children", conn.PeerName()) // wait for signature bundle sig, err := conn.Receive() if err != nil { dbg.Fatal(peer.String(), "Could not receive the bundled children signature from", conn.PeerName()) } if sig.MsgType != net.ListBasicSignatureType { dbg.Fatal(peer.String(), "received an different package from", conn.PeerName(), ":", sig.MsgType.String()) } dbg.Lvl4(peer.String(), "received signature bundle from children", conn.PeerName()) lbs := sig.Msg.(net.ListBasicSignature) // send to parent sigChan <- lbs } dbg.Lvl3(peer.String(), "finished with children", conn.PeerName()) conn.Close() }(i, connPeer) } // Wait for the whole thing to be done (parent connection == master) <-done dbg.Lvl3(peer.String(), "leaving...") }