// Verifies that the 'message' is included in the signature and that it // is correct. // Message is your own hash, and reply contains the inclusion proof + signature // on the aggregated message func VerifySignature(suite abstract.Suite, reply *StampSignature, public abstract.Point, message []byte) bool { // Check if aggregate public key is correct if !public.Equal(reply.AggPublic) { dbg.Lvl1("Aggregate-public-key check: FAILED (maybe you have an outdated config file of the tree)") return false } // First check if the challenge is ok if err := VerifyChallenge(suite, reply); err != nil { dbg.Lvl1("Challenge-check: FAILED (", err, ")") return false } dbg.Lvl2("Challenge-check: OK") // Incorporate the timestamp in the message since the verification process // is done by reconstructing the challenge var b bytes.Buffer if err := binary.Write(&b, binary.LittleEndian, reply.Timestamp); err != nil { dbg.Lvl1("Error marshaling the timestamp for signature verification") return false } msg := append(b.Bytes(), []byte(reply.MerkleRoot)...) if err := VerifySchnorr(suite, msg, public, reply.Challenge, reply.Response); err != nil { dbg.Lvl1("Signature-check: FAILED (", err, ")") return false } dbg.Lvl2("Signature-check: OK") // finally check the proof if !proof.CheckProof(suite.Hash, reply.MerkleRoot, hashid.HashId(message), reply.Prf) { dbg.Lvl2("Inclusion-check: FAILED") return false } dbg.Lvl2("Inclusion-check: OK") return true }
// NewDataFilter returns a new data filter initialized with the rights values // taken out from the run config. If absent, will take defaults values. // Keys expected are: // discard_measurementname = perc => will take the lower and upper percentile = // perc // discard_measurementname = lower,upper => will take different percentiles func NewDataFilter(config map[string]string) DataFilter { df := DataFilter{ percentiles: make(map[string]float64), } reg, err := regexp.Compile("filter_(\\w+)") if err != nil { dbg.Lvl1("DataFilter: Error compiling regexp:", err) return df } // analyse the each entry for k, v := range config { if measure := reg.FindString(k); measure == "" { continue } else { // this value must be filtered by how many ? perc, err := strconv.ParseFloat(v, 64) if err != nil { dbg.Lvl1("DataFilter: Cannot parse value for filter measure:", measure) continue } measure = strings.Replace(measure, "filter_", "", -1) df.percentiles[measure] = perc } } dbg.Lvl3("Filtering:", df.percentiles) return df }
func RunServer(flags *app.Flags, conf *app.ConfigColl) { hostname := flags.Hostname if hostname == conf.Hosts[0] { dbg.Lvlf3("Tree is %+v", conf.Tree) } dbg.Lvl3(hostname, "Starting to run") app.RunFlags.StartedUp(len(conf.Hosts)) peer := conode.NewPeer(hostname, conf.ConfigConode) if app.RunFlags.AmRoot { for { setupRound := sign.NewRoundSetup(peer.Node) peer.StartAnnouncementWithWait(setupRound, 5*time.Second) counted := <-setupRound.Counted dbg.Lvl1("Number of peers counted:", counted) if counted == len(conf.Hosts) { dbg.Lvl1("All hosts replied") break } time.Sleep(time.Second) } } RegisterRoundMeasure(peer.Node.LastRound()) peer.LoopRounds(RoundMeasureType, conf.Rounds) dbg.Lvlf3("Done - flags are %+v", app.RunFlags) monitor.End() }
// scaleServers will take the right percentage of server to contact to stamp // request. If percentage is 0, only contact the leader (if the client is on the // same physical machine than the leader/root). func scaleServers(flags *app.Flags, conf *app.ConfigColl, servers []string) []string { if len(servers) == 0 || conf.StampRatio > 1 { dbg.Lvl1("Client wont change the servers percentage ") return servers } if conf.StampRatio == -1 { // take only the root if we are a "root client" also if flags.AmRoot { dbg.Lvl1("Client will only contact root") return []string{servers[0]} } else { // others client dont do nothing dbg.Lvl3("Client wont contact anyone") return []string{} } } // else take the right perc i := int(math.Ceil(conf.StampRatio * float64(len(servers)))) fn := dbg.Lvl3 if flags.AmRoot { fn = dbg.Lvl1 } fn("Client will contact", i, "/", len(servers), "servers") return servers[0:i] }
func ExampleLongFunctions() { dbg.Lvl1("Before") thisIsAVeryLongFunctionNameThatWillOverflow() dbg.Lvl1("After") // Output: // 1: ( dbg_test.ExampleLongFunctions: 0) - Before // 1: (dbg_test.thisIsAVeryLongFunctionNameThatWillOverflow: 0) - Overflow // 1: ( dbg_test.ExampleLongFunctions: 0) - After }
// verifyHost will anaylze the systempacket information and verify the signature // It will return a ACK properly initialized with the right codes in it. func verifyHost(pubKeyFile string) (net.Conn, Ack) { // get the right public key pub, host, err := cliutils.ReadPubKey(suite, pubKeyFile) if err != nil { dbg.Fatal("Could not read the public key from the file:", err) } dbg.Lvl1("Public key file read") // Then get a connection conn, err := net.Dial("tcp", host) if err != nil { dbg.Fatal("Error when getting the connection to the host:", err) } dbg.Lvl1("Verifier connected to the host. Validation in progress...") // Get the system packet message var sys SystemPacket if err = suite.Read(conn, &sys); err != nil { dbg.Fatal("Error when reading the system packet message from host:", err) } // Get the signature length first var length int if err := suite.Read(conn, &length); err != nil { dbg.Fatal("Could not read length of the signature ...") } // Get the signature sig := make([]byte, length) if err := suite.Read(conn, &sig); err != nil { dbg.Fatal("Error reading the signature:", err) } // First, encode the sys packet var b bytes.Buffer if err := suite.Write(&b, sys); err != nil { dbg.Fatal("Error when encoding the syspacket to be verified:", err) } X := make([]abstract.Point, 1) X[0] = pub // Verify signature var ack Ack ack.Type = TYPE_SYS ack.Code = SYS_EXIT if _, err := anon.Verify(suite, b.Bytes(), anon.Set(X), nil, sig); err != nil { // Wrong signature ack.Code = SYS_WRONG_SIG dbg.Lvl1("WARNING: signature provided is wrong.") } else { // verfiy SystemPacket itself ack.Code = SYS_OK dbg.Lvl1("Host's signature verified and system seems healty. OK") } return conn, ack }
func wait_for_blocks() { server := "localhost:2011" suite = app.GetSuite("25519") dbg.Lvl2("Connecting to", server) conn := coconet.NewTCPConn(server) err := conn.Connect() if err != nil { dbg.Fatal("Error when getting the connection to the host:", err) } dbg.Lvl1("Connected to ", server) for i := 0; i < 1000; i++ { time.Sleep(1 * time.Second) msg := &BitCoSi.BitCoSiMessage{ Type: BitCoSi.BlockRequestType, ReqNo: 0, } err = conn.PutData(msg) if err != nil { dbg.Fatal("Couldn't send hash-message to server: ", err) } dbg.Lvl1("Sent signature request") // Wait for the signed message tsm := new(BitCoSi.BitCoSiMessage) tsm.Brep = &BitCoSi.BlockReply{} tsm.Brep.SuiteStr = suite.String() err = conn.GetData(tsm) if err != nil { dbg.Fatal("Error while receiving signature:", err) } //dbg.Lvlf1("Got signature response %+v", tsm.Brep) T := new(BitCoSi.TrBlock) T.Block = tsm.Brep.Block T.Print() dbg.Lvlf1("Response %v ", tsm.Brep.Response) } // Asking to close the connection err = conn.PutData(&BitCoSi.BitCoSiMessage{ ReqNo: 1, Type: BitCoSi.BitCoSiClose, }) conn.Close() }
// The core of the file: read any input from the connection and outputs it into // the server connection func proxyConnection(conn net.Conn, done chan bool) { dec := json.NewDecoder(conn) nerr := 0 for { m := Measure{} // Receive data if err := dec.Decode(&m); err != nil { if err == io.EOF { break } dbg.Lvl1("Error receiving data from", conn.RemoteAddr().String(), ":", err) nerr += 1 if nerr > 1 { dbg.Lvl1("Too many errors from", conn.RemoteAddr().String(), ": Abort connection") break } } dbg.Lvl3("Proxy received", m) // Implement our own ready-count, so it doesn't have to go through the // main monitor which might be far away. switch m.Name { case "ready": atomic.AddInt64(&readyCount, 1) case "ready_count": m.Ready = int(readyCount) err := json.NewEncoder(conn).Encode(m) if err != nil { dbg.Lvl2("Couldn't send ready-result back to client") break } default: // Proxy data - add who is sending, as we only have one channel // to the server m.Sender = conn.RemoteAddr().String() if err := serverEnc.Encode(m); err != nil { dbg.Lvl2("Error proxying data :", err) break } if m.Name == "end" { // the end dbg.Lvl2("Proxy detected end of measurement. Closing connection.") break } } } conn.Close() done <- true }
func (d *Localhost) Start(args ...string) error { os.Chdir(d.RunDir) dbg.Lvl4("Localhost: chdir into", d.RunDir) ex := d.RunDir + "/" + d.App dbg.Lvl4("Localhost: in Start() => hosts", d.Hosts) d.running = true dbg.Lvl1("Starting", len(d.Hosts), "applications of", ex) for index, host := range d.Hosts { dbg.Lvl3("Starting", index, "=", host) amroot := fmt.Sprintf("-amroot=%s", strconv.FormatBool(index == 0)) cmdArgs := []string{"-hostname", host, "-mode", "server", "-logger", "localhost:" + monitor.SinkPort, amroot} cmdArgs = append(args, cmdArgs...) dbg.Lvl3("CmdArgs are", cmdArgs) cmd := exec.Command(ex, cmdArgs...) cmd.Stdout = os.Stdout cmd.Stderr = os.Stderr go func(i int, h string) { dbg.Lvl3("Localhost: will start host", host) d.wg_run.Add(1) err := cmd.Run() if err != nil { dbg.Lvl3("Error running localhost", h, ":", err) } d.wg_run.Done() dbg.Lvl3("host (index", i, ")", h, "done") }(index, host) } return nil }
// Reads in the platform that we want to use and prepares for the tests func main() { flag.Parse() deployP = platform.NewPlatform(platform_dst) if deployP == nil { dbg.Fatal("Platform not recognized.", platform_dst) } dbg.Lvl1("Deploying to", platform_dst) simulations := flag.Args() if len(simulations) == 0 { dbg.Fatal("Please give a simulation to run") } for _, simulation := range simulations { runconfigs := platform.ReadRunFile(deployP, simulation) if len(runconfigs) == 0 { dbg.Fatal("No tests found in", simulation) } deployP.Configure() if clean { deployP.Deploy(runconfigs[0]) deployP.Cleanup() } else { logname := strings.Replace(filepath.Base(simulation), ".toml", "", 1) RunTests(logname, runconfigs) } } }
// readHostFile will read the host file // HOSTNAME PUBLICKEY // for each line. and returns the whole set and any errror if any are found. func readHostFile(file string) ([]string, []string, error) { // open it up hostFile, err := os.Open(file) if err != nil { return nil, nil, err } // Then read it up hosts := make([]string, 0) pubs := make([]string, 0) scanner := bufio.NewScanner(hostFile) ln := 0 for scanner.Scan() { line := scanner.Text() ln += 1 spl := strings.Split(line, " ") if len(spl) != 2 { return nil, nil, errors.New(fmt.Sprintf("Hostfile misformatted at line %s", ln)) } // add it HOSTS -> PUBLIC KEY h, err := cliutils.VerifyPort(spl[0], conode.DefaultPort) if err != nil { dbg.Fatal("Error reading address in host file:", spl[0], err) } hosts = append(hosts, h) pubs = append(pubs, spl[1]) } dbg.Lvl1("Read the hosts files:", ln, "entries") return hosts, pubs, nil }
// Scanner for a file contatining singatures func SigScanner(filename string) ([]string, error) { var blocks []string head := "-----BEGIN PGP SIGNATURE-----" dbg.Lvl3("Reading file", filename) file, err := os.Open(filename) defer file.Close() if err != nil { dbg.Lvl1("Couldn't open file", file, err) return nil, err } scanner := bufio.NewScanner(file) var block []string for scanner.Scan() { text := scanner.Text() dbg.Lvl3("Decoding", text) // end of the first part if text == head { dbg.Lvl3("Found header") if len(block) > 0 { blocks = append(blocks, strings.Join(block, "\n")) block = make([]string, 0) } } block = append(block, text) } blocks = append(blocks, strings.Join(block, "\n")) return blocks, nil }
// This file handles the creation a of cothority tree. // Basically, it takes a list of files generated by the "key" command by each // hosts and turn that into a full tree with the hostname and public key in each // node. // BuildTree takes a file formatted like this : // host pubKey // host2 pubKey // ... ... // For the moment it takes a branching factor on how to make the tree // and the name of the file where to write the config // It writes the tree + any other configs to output using toml format // with the app/config_conode.go struct func Build(hostFile string, bf int, configFile string) { // First, read the list of host and public keys hosts, pubs, err := readHostFile(hostFile) if err != nil { dbg.Fatal("Error reading the host file:", err) } // Then construct the tree tree := constructTree(hosts, pubs, bf) // then constrcut the aggregated public key K0 k0 := aggregateKeys(pubs) var b bytes.Buffer err = cliutils.WritePub64(suite, &b, k0) if err != nil { dbg.Fatal("Could not aggregate public keys in base64") } // Then write the config conf := app.ConfigConode{ Suite: suiteStr, Tree: tree, Hosts: hosts, AggPubKey: b.String(), } app.WriteTomlConfig(conf, configFile) dbg.Lvl1("Written config file with tree to", configFile) }
// Helper functions that will return the suite used during the process from a string name func GetSuite(suite string) abstract.Suite { s, ok := suites.All()[suite] if !ok { dbg.Lvl1("Suites available:", suites.All()) dbg.Fatal("Didn't find suite", suite) } return s }
func verify(metadata *CommitEntry, beSigned string) { defer wg.Done() var err error metadata.decision, err = ApprovalCheck(metadata.policy, metadata.signatures, beSigned) if err != nil { dbg.Lvl1("Problem with verifying approval of developers") } }
func (round *RoundMeasure) Response(in []*sign.SigningMessage, out *sign.SigningMessage) error { err := round.RoundCosi.Response(in, out) if round.IsRoot { round.measure.Measure() dbg.Lvl1("Round", round.RoundNbr-round.firstRound+1, "finished - took", round.measure.WallTime) } return err }
// Send message to client given by name func (round *RoundStamperListener) PutToClient(name string, data coconet.BinaryMarshaler) { err := round.Clients[name].PutData(data) if err == coconet.ErrClosed { round.Clients[name].Close() return } if err != nil && err != coconet.ErrNotEstablished { dbg.Lvl1("%p error putting to client: %v", round, err) } }
// Scanner for a file containing commit id func CommitScanner(filename string) (string, error) { dbg.Lvl3("Reading file", filename) file, err := os.Open(filename) defer file.Close() if err != nil { dbg.Lvl1("Couldn't open file", file, err) return "", err } comid := make([]byte, 40) _, err = file.Read(comid) if err != nil { dbg.Lvl1("Couldn't read from file", filename, err) return "", err } return string(comid), err }
// SImply adds all the public keys we give to it func aggregateKeys(pubs []string) abstract.Point { k0 := suite.Point().Null() for i, ki := range pubs { // convert from string to public key kip, _ := cliutils.ReadPub64(suite, strings.NewReader(ki)) k0 = k0.Add(k0, kip) dbg.Lvl2("Public key n#", i, ":", kip) } dbg.Lvl1("Aggregated public key:", k0) return k0 }
// Takes a 'file' to hash and being stamped at the 'server'. The output of the // signing will be written to 'file'.sig func StampFile(file, server string) { // Create the hash of the file and send it over the net myHash := hashFile(file) stamper, err := conode.NewStamp("config.toml") if err != nil { dbg.Fatal("Couldn't setup stamper:", err) } tsm, err := stamper.GetStamp(myHash, server) if err != nil { dbg.Fatal("Stamper didn't succeed:", err) } if err := tsm.Srep.Save(file + sigExtension); err != nil { dbg.Fatal("Could not write signature file:", err) } dbg.Lvl1("Signature file", file+".sig", "written.") dbg.Lvl1("Stamp OK - signature file", file+".sig", "written.") }
func main() { conf := &app.ConfigColl{} app.ReadConfig(conf) // we must know who we are if app.RunFlags.Hostname == "" { dbg.Fatal("Hostname empty: Abort") } // Do some common setup if app.RunFlags.Mode == "client" { app.RunFlags.Hostname = app.RunFlags.Name } hostname := app.RunFlags.Hostname if hostname == conf.Hosts[0] { dbg.Lvlf3("Tree is %+v", conf.Tree) } dbg.Lvl3(hostname, "Starting to run") app.RunFlags.StartedUp(len(conf.Hosts)) peer := conode.NewPeer(hostname, conf.ConfigConode) if app.RunFlags.AmRoot { for { time.Sleep(time.Second) setupRound := sign.NewRoundSetup(peer.Node) peer.StartAnnouncementWithWait(setupRound, 5*time.Second) counted := <-setupRound.Counted dbg.Lvl1("Number of peers counted:", counted) if counted == len(conf.Hosts) { dbg.Lvl1("All hosts replied") break } } } RegisterRoundMeasure(peer.Node.LastRound()) peer.LoopRounds(RoundMeasureType, conf.Rounds) dbg.Lvlf3("Done - flags are %+v", app.RunFlags) monitor.End() }
func ExampleLLvl() { dbg.Lvl1("Lvl output") dbg.LLvl1("LLvl output") dbg.Lvlf1("Lvlf output") dbg.LLvlf1("LLvlf output") // Output: // 1: ( dbg_test.ExampleLLvl: 0) - Lvl output // -1: ( dbg_test.ExampleLLvl: 0) - LLvl output // 1: ( dbg_test.ExampleLLvl: 0) - Lvlf output // -1: ( dbg_test.ExampleLLvl: 0) - LLvlf output }
// Closes the channel func (peer *Peer) Close() { if peer.Closed { dbg.Lvl1("Peer", peer.Name(), "Already closed!") return } else { peer.Closed = true } peer.CloseChan <- true peer.Node.Close() StampListenersClose() dbg.Lvlf3("Closing of peer: %s finished", peer.Name()) }
func ExampleLevel2() { dbg.DebugVisible = 2 dbg.Lvl1("Level1") dbg.Lvl2("Level2") dbg.Lvl3("Level3") dbg.Lvl4("Level4") dbg.Lvl5("Level5") // Output: // 1: ( dbg_test.ExampleLevel2: 0) - Level1 // 2: ( dbg_test.ExampleLevel2: 0) - Level2 }
// ForceExit connects to the stamp-port of the conode and asks him to exit func ForceExit(address string) { add, err := cliutils.VerifyPort(address, conode.DefaultPort+1) if err != nil { dbg.Fatal("Couldn't convert", address, "to a IP:PORT") } conn := coconet.NewTCPConn(add) err = conn.Connect() if err != nil { dbg.Fatal("Error when getting the connection to the host:", err) } dbg.Lvl1("Connected to", add) msg := &conode.TimeStampMessage{ Type: conode.StampExit, } dbg.Lvl1("Asking to exit") err = conn.PutData(msg) if err != nil { dbg.Fatal("Couldn't send exit-message to server:", err) } }
func main() { Current := new(Node) Magic := [4]byte{0xF9, 0xBE, 0xB4, 0xD9} Current.IP = net.IPv4(0, 1, 2, 3) Current.PublicKey = "my_cool_key" Current.Last_Block = "0" Parser, _ := BitCoSi.NewParser("/home/lefteris/hi/blocks", Magic) server := "localhost:2011" // suite = app.GetSuite("25519") dbg.Lvl2("Connecting to", server) conn := coconet.NewTCPConn(server) err := conn.Connect() if err != nil { dbg.Fatal("Error when getting the connection to the host:", err) } dbg.Lvl1("Connected to ", server) go wait_for_blocks() for i := 0; i < 10; i++ { Current.transaction_pool = Parser.Parse(i, 10+i) for len(Current.transaction_pool) > 0 { msg := &BitCoSi.BitCoSiMessage{ Type: BitCoSi.TransactionAnnouncmentType, ReqNo: 0, Treq: &BitCoSi.TransactionAnnouncment{Val: Current.transaction_pool[0]}} err = conn.PutData(msg) Current.transaction_pool = Current.transaction_pool[1:] if err != nil { dbg.Fatal("Couldn't send hash-message to server: ", err) } time.Sleep(10 * time.Millisecond) } } wait_for_Key_blocks() time.Sleep(900000 * time.Millisecond) // Asking to close the connection err = conn.PutData(&BitCoSi.BitCoSiMessage{ ReqNo: 1, Type: BitCoSi.BitCoSiClose, }) conn.Close() dbg.Lvl2("Connection closed with server") }
func (round *RoundException) Response(in []*SigningMessage, out *SigningMessage) error { if round.Name == ExceptionForceFailure { dbg.Lvl1("Forcing failure in response") round.RaiseException() } // initialize exception handling nullPoint := round.Cosi.Suite.Point().Null() children := round.Cosi.Children for _, sm := range in { from := sm.From switch sm.Type { default: // default == no response from child dbg.Lvl4(round.Name, "Empty response from child", from, sm.Type) if children[from] != nil { round.Cosi.ExceptionList = append(round.Cosi.ExceptionList, children[from].PubKey()) // remove public keys and point commits from subtree of failed child round.Cosi.ExceptionX_hat.Add(round.Cosi.ExceptionX_hat, round.Cosi.ChildX_hat[from]) round.Cosi.ExceptionV_hat.Add(round.Cosi.ExceptionV_hat, round.Cosi.ChildV_hat[from]) } continue case Response: // disregard response from children who did not commit _, ok := round.Cosi.ChildV_hat[from] if ok == true && round.Cosi.ChildV_hat[from].Equal(nullPoint) { dbg.Lvl4(round.Name, ": no response from", from, sm.Type) continue } dbg.Lvl4(round.Name, "accepts response from", from, sm.Type) round.Cosi.ExceptionV_hat.Add(round.Cosi.ExceptionV_hat, sm.Rm.ExceptionV_hat) round.Cosi.ExceptionX_hat.Add(round.Cosi.ExceptionX_hat, sm.Rm.ExceptionX_hat) round.Cosi.ExceptionList = append(round.Cosi.ExceptionList, sm.Rm.ExceptionList...) } } round.Cosi.X_hat.Sub(round.Cosi.X_hat, round.Cosi.ExceptionX_hat) err := round.RoundCosi.Response(in, out) if err != nil { return err } out.Rm.ExceptionList = round.Cosi.ExceptionList out.Rm.ExceptionV_hat = round.Cosi.ExceptionV_hat out.Rm.ExceptionX_hat = round.Cosi.ExceptionX_hat return nil }
// Verifies whether the Schnorr signature is correct func TestVerifySchnorr(t *testing.T) { setupTestSig() var b bytes.Buffer if err := binary.Write(&b, binary.LittleEndian, reply.Timestamp); err != nil { dbg.Lvl1("Error marshaling the timestamp for signature verification") } msg := append(b.Bytes(), []byte(reply.MerkleRoot)...) err := conode.VerifySchnorr(suite, msg, X0, reply.Challenge, reply.Response) if err != nil { dbg.Fatal("Schnorr verification failed") } else { dbg.Lvl2("Schnorr OK") } }
func ApprovalCheck(PolicyFile, SignaturesFile, Id string) (bool, error) { var ( commit SignedCommit // Commit corresponding to be verified developers openpgp.EntityList // List of all developers whose public keys are in the policy file approvers map[string]*openpgp.Entity // Map of developers who provided a valid signature. Indexed by public key id (openpgp.PrimaryKey.KeyIdString) err error ) commit.Policy.Threshold, commit.Policy.DevPubKeys, commit.Policy.CothKey, err = PolicyScanner(PolicyFile) checkFileError(err, PolicyFile) commit.Signatures, err = SigScanner(SignaturesFile) checkFileError(err, SignaturesFile) commit.CommitID = Id // commit.CommitID, err = CommitScanner(CommitIdFile) // checkFileError(err, CommitIdFile) // commit.Approval = false approvers = make(map[string]*openpgp.Entity) // Creating openpgp entitylist from list of public keys developers = make(openpgp.EntityList, 0) for _, pubkey := range commit.Policy.DevPubKeys { keybuf, err := openpgp.ReadArmoredKeyRing(strings.NewReader(pubkey)) if err != nil { dbg.Error("Could not decode armored public key", err) } for _, entity := range keybuf { developers = append(developers, entity) } } // Verifying every signature in the list and counting valid ones for _, signature := range commit.Signatures { result, err := openpgp.CheckArmoredDetachedSignature(developers, bytes.NewBufferString(commit.CommitID), strings.NewReader(signature)) if err != nil { dbg.Lvl1("The signature is invalid or cannot be verified due to", err) } else { if approvers[result.PrimaryKey.KeyIdString()] == nil { // We need to check that this is a unique signature approvers[result.PrimaryKey.KeyIdString()] = result dbg.Lvl3("Approver: %+v", result.Identities) } } } dbg.Lvl3("Is release approved? ", len(approvers) >= commit.Policy.Threshold) // commit.Approval = (len(approvers) >= commit.Policy.Threshold) return len(approvers) >= commit.Policy.Threshold, err // return commit, err }
// 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)) }