// 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 }
func (round *RoundStamper) Commitment(in []*sign.SigningMessage, out *sign.SigningMessage) error { // compute the local Merkle root // give up if nothing to process if len(round.StampQueue) == 0 { round.StampRoot = make([]byte, hashid.Size) round.StampProofs = make([]proof.Proof, 1) } else { // pull out to be Merkle Tree leaves round.StampLeaves = make([]hashid.HashId, 0) for _, msg := range round.StampQueue { round.StampLeaves = append(round.StampLeaves, hashid.HashId(msg)) } // create Merkle tree for this round's messages and check corectness round.StampRoot, round.StampProofs = proof.ProofTree(round.Suite.Hash, round.StampLeaves) if dbg.DebugVisible > 2 { if proof.CheckLocalProofs(round.Suite.Hash, round.StampRoot, round.StampLeaves, round.StampProofs) == true { dbg.Lvl4("Local Proofs of", round.Name, "successful for round "+ strconv.Itoa(round.RoundNbr)) } else { panic("Local Proofs" + round.Name + " unsuccessful for round " + strconv.Itoa(round.RoundNbr)) } } } out.Com.MTRoot = round.StampRoot round.RoundCosi.Commitment(in, out) return nil }
// Retrieve an object in a Merkle tree, // validating the entire path in the process. // Returns a slice of a buffer obtained from HashGet.Get(), // which might be shared and should be considered read-only. func MerkleGet(suite abstract.Suite, root []byte, path MerklePath, ctx hashid.HashGet) ([]byte, error) { // Follow pointers through intermediate levels blob := root for i := range path.Ptr { beg := path.Ptr[i] // end := beg + suite.HashLen() end := beg + 256 // change me: find hash len if end > len(blob) { return nil, errors.New("bad Merkle tree pointer offset") } id := hashid.HashId(blob[beg:end]) b, e := ctx.Get(id) // Lookup the next-level blob if e != nil { return nil, e } blob = b } // Validate and extract the actual object beg := path.Ofs end := beg + path.Len if end > len(blob) { return nil, errors.New("bad Merkle tree object offset/length") } return blob[beg:end], nil }
// Generate a Merkle proof tree for the given list of leaves, // yielding one output proof per leaf. func ProofTree(newHash func() hash.Hash, leaves []hashid.HashId) (hashid.HashId, []Proof) { if len(leaves) == 0 { return hashid.HashId(""), nil } // Determine the required tree depth nleavesArg, nleaves := len(leaves), len(leaves) depth := 0 for n := 1; n < nleaves; n <<= 1 { depth++ } // if nleaves is not a power of 2, we add 0s to fill in up to pow2 var i int for nleaves, i = (1 << uint(depth)), nleavesArg; i < nleaves; i++ { leaves = append(leaves, make([]byte, newHash().Size())) } // fmt.Println("depth=", depth, "nleaves=", nleavesArg) // Build the Merkle tree c := hashContext{newHash: newHash} tree := make([][]hashid.HashId, depth+1) tree[depth] = leaves nprev := nleaves tprev := tree[depth] for d := depth - 1; d >= 0; d-- { nnext := (nprev + 1) >> 1 // # hashes total at level i nnode := nprev >> 1 // # new nodes at level i // println("nprev", nprev, "nnext", nnext, "nnode", nnode) // fmt.Println("nprev", nprev, "nnext", nnext, "nnode", nnode) tree[d] = make([]hashid.HashId, nnext) tnext := tree[d] for i := 0; i < nnode; i++ { tnext[i] = c.hashNode(nil, tprev[i*2], tprev[i*2+1]) } // If nnode < nhash, just leave the odd one nil. nprev = nnext tprev = tnext } if nprev != 1 { panic("oops") } root := tprev[0] // Build all the individual proofs from the tree. // Some towards the end may end up being shorter than depth. proofs := make([]Proof, nleaves) for i := 0; i < nleaves; i++ { p := make([]hashid.HashId, 0, depth) // p = append(p, root) for d := depth - 1; d >= 0; d-- { h := tree[depth-d][sibling(i>>uint(d))] if h != nil { p = append(p, h) } } proofs[i] = Proof(p) } return root, proofs[:nleavesArg] }
func (s *Server) AggregateCommits(view int) []byte { //dbg.Lvl4(s.Name(), "calling AggregateCommits") s.mux.Lock() // get data from s once to avoid refetching from structure Queue := s.Queue READING := s.READING PROCESSING := s.PROCESSING // messages read will now be processed READING, PROCESSING = PROCESSING, READING s.READING, s.PROCESSING = s.PROCESSING, s.READING s.Queue[READING] = s.Queue[READING][:0] // give up if nothing to process if len(Queue[PROCESSING]) == 0 { s.mux.Unlock() s.Root = make([]byte, hashid.Size) s.Proofs = make([]proof.Proof, 1) return s.Root } // pull out to be Merkle Tree leaves s.Leaves = make([]hashid.HashId, 0) for _, msg := range Queue[PROCESSING] { s.Leaves = append(s.Leaves, hashid.HashId(msg.Tsm.Sreq.Val)) } s.mux.Unlock() // non root servers keep track of rounds here if !s.IsRoot(view) { s.rLock.Lock() lsr := s.LastRound() mr := s.maxRounds s.rLock.Unlock() // if this is our last round then close the connections if lsr >= mr && mr >= 0 { s.closeChan <- true } } // create Merkle tree for this round's messages and check corectness s.Root, s.Proofs = proof.ProofTree(s.Suite().Hash, s.Leaves) if sign.DEBUG == true { if proof.CheckLocalProofs(s.Suite().Hash, s.Root, s.Leaves, s.Proofs) == true { dbg.Lvl4("Local Proofs of", s.Name(), "successful for round "+strconv.Itoa(int(s.LastRound()))) } else { panic("Local Proofs" + s.Name() + " unsuccessful for round " + strconv.Itoa(int(s.LastRound()))) } } return s.Root }
func (sn *Node) SetBackLink(Round int) { prevRound := Round - 1 sn.Rounds[Round].BackLink = hashid.HashId(make([]byte, hashid.Size)) if prevRound >= FIRST_ROUND { // My Backlink = Hash(prevRound, sn.Rounds[prevRound].BackLink, sn.Rounds[prevRound].MTRoot) h := sn.suite.Hash() if sn.Rounds[prevRound] == nil { log.Errorln(sn.Name(), "not setting back link") return } h.Write(intToByteSlice(prevRound)) h.Write(sn.Rounds[prevRound].BackLink) h.Write(sn.Rounds[prevRound].MTRoot) sn.Rounds[Round].BackLink = h.Sum(nil) } }