Inputs:
- identifier, identifier i of the participant, a NonZeroScalar.
- sk_i, signer secret key share, a Scalar.
- group_public_key, public key corresponding to the group signing
  key, an Element.
- nonce_i, pair of Scalar values (hiding_nonce, binding_nonce)
  generated in round one.
- msg, the message to be signed, a byte string.
- commitment_list = [(i, hiding_nonce_commitment_i,
  binding_nonce_commitment_i), ...], a list of commitments issued by
  each participant, where each element in the list indicates a
  NonZeroScalar identifier i and two commitment Element values
  (hiding_nonce_commitment_i, binding_nonce_commitment_i). This list
  MUST be sorted in ascending order by identifier.


Outputs:
- sig_share, a signature share, a Scalar.

def sign(identifier, sk_i, group_public_key,
         nonce_i, msg, commitment_list):
  # Compute the binding factor(s)
  binding_factor_list = compute_binding_factors(group_public_key,
   commitment_list, msg)
  binding_factor = binding_factor_for_participant(
      binding_factor_list, identifier)

  # Compute the group commitment
  group_commitment = compute_group_commitment(
      commitment_list, binding_factor_list)

  # Compute the interpolating value
  participant_list = participants_from_commitment_list(
      commitment_list)
  lambda_i = derive_interpolating_value(participant_list, identifier)

  # Compute the per-message challenge
  challenge = compute_challenge(
      group_commitment, group_public_key, msg)

  # Compute the signature share
  (hiding_nonce, binding_nonce) = nonce_i
  sig_share = hiding_nonce + (binding_nonce * binding_factor) +
      (lambda_i * sk_i * challenge)

  return sig_share
