Example #1
0
// Pick a uint32 uniformly at random
func randUint32() uint32 {
	return random.Uint32(random.Stream)
}
Example #2
0
func (rh *RandHound) handleR1(r1 WR1) error {

	msg := &r1.R1

	idx := r1.RosterIndex
	grp := rh.ServerIdxToGroupNum[idx]
	pos := rh.ServerIdxToGroupIdx[idx]

	rh.mutex.Lock()
	defer rh.mutex.Unlock()

	// Verify R1 message signature
	if err := verifySchnorr(rh.Suite(), rh.key[grp][pos], msg); err != nil {
		return err
	}

	// Verify that server replied to the correct I1 message
	if err := verifyMessage(rh.Suite(), rh.i1s[grp], msg.HI1); err != nil {
		return err
	}

	// Record R1 message
	rh.r1s[idx] = msg

	// Prepare data for recovery of polynomial commits and verification of shares
	n := len(msg.EncShare)
	poly := make([][]byte, n)
	index := make([]int, n)
	encShare := make([]abstract.Point, n)
	encProof := make([]ProofCore, n)
	for i := 0; i < n; i++ {
		poly[i] = msg.CommitPoly
		index[i] = msg.EncShare[i].Pos
		encShare[i] = msg.EncShare[i].Val
		encProof[i] = msg.EncShare[i].Proof
	}

	// Init PVSS and recover polynomial commits
	H, _ := rh.Suite().Point().Pick(nil, rh.Suite().Cipher(rh.sid))
	pvss := NewPVSS(rh.Suite(), H, rh.threshold[grp])
	polyCommit, err := pvss.Commits(poly, index)
	if err != nil {
		return err
	}

	// Record polynomial commits
	rh.polyCommit[idx] = polyCommit

	// Return, if we already committed to secrets previously
	if len(rh.chosenSecret) > 0 {
		return nil
	}

	// Verify encrypted shares
	good, _, err := pvss.Verify(H, rh.key[grp], polyCommit, encShare, encProof)
	if err != nil {
		return err
	}

	// Record valid encrypted shares per secret/server
	for _, g := range good {
		if _, ok := rh.secret[idx]; !ok {
			rh.secret[idx] = make([]int, 0)
		}
		rh.secret[idx] = append(rh.secret[idx], msg.EncShare[g].Target)
	}

	// Check if there is at least a threshold number of reconstructable secrets
	// in each group. If yes proceed to the next phase. Note the double-usage
	// of the threshold which is used to determine if enough valid shares for a
	// single secret are available and if enough secrets for a given group are
	// available
	goodSecret := make(map[int][]int)
	for i, group := range rh.server {
		var secret []int
		for _, server := range group {
			j := server.RosterIndex
			if share, ok := rh.secret[j]; ok && rh.threshold[i] <= len(share) {
				secret = append(secret, j)
			}
		}
		if rh.threshold[i] <= len(secret) {
			goodSecret[i] = secret
		}
	}

	// Proceed, if there are enough good secrets
	if len(goodSecret) == rh.groups {

		// Reset secret for the next phase (see handleR2)
		rh.secret = make(map[int][]int)

		// Choose secrets that contribute to collective randomness
		for i := range rh.server {

			// Randomly remove some secrets so that a threshold of secrets remains
			rand := random.Bytes(rh.Suite().Hash().Size(), random.Stream)
			prng := rh.Suite().Cipher(rand)
			secret := goodSecret[i]
			for j := 0; j < len(secret)-rh.threshold[i]; j++ {
				k := int(random.Uint32(prng) % uint32(len(secret)))
				secret = append(secret[:k], secret[k+1:]...)
			}
			rh.chosenSecret[i] = secret
		}

		log.Lvlf3("Grouping: %v", rh.group)
		log.Lvlf3("ChosenSecret: %v", rh.chosenSecret)

		// Transformation of commitments from int to uint32 to avoid protobuff errors
		var chosenSecret = make([][]uint32, len(rh.chosenSecret))
		for i := range rh.chosenSecret {
			var l []uint32
			for j := range rh.chosenSecret[i] {
				l = append(l, uint32(rh.chosenSecret[i][j]))
			}
			chosenSecret[i] = l
		}

		// Prepare a message for each server of a group and send it
		for i, group := range rh.server {
			for j, server := range group {

				// Among the good secrets chosen previously collect all valid
				// shares, proofs, and polynomial commits intended for the
				// target server
				var encShare []Share
				var polyCommit []abstract.Point
				for _, k := range rh.chosenSecret[i] {
					r1 := rh.r1s[k]
					pc := rh.polyCommit[k]
					encShare = append(encShare, r1.EncShare[j])
					polyCommit = append(polyCommit, pc[j])
				}

				i2 := &I2{
					Sig:          crypto.SchnorrSig{},
					SID:          rh.sid,
					ChosenSecret: chosenSecret,
					EncShare:     encShare,
					PolyCommit:   polyCommit,
				}

				if err := signSchnorr(rh.Suite(), rh.Private(), i2); err != nil {
					return err
				}

				rh.i2s[server.RosterIndex] = i2

				if err := rh.SendTo(server, i2); err != nil {
					return err
				}
			}
		}
	}

	return nil
}