Method: FROST.sign

Defined in:
lib/frost.rb

.sign(context, secret_share, group_pubkey, nonces, msg, commitment_list) ⇒ Integer

Generate signature share.

Parameters:

  • context (FROST::Context)

    FROST context.

  • secret_share (FROST::SecretShare)

    Signer secret key share.

  • group_pubkey (ECDSA::Point)

    Public key corresponding to the group signing key.

  • nonces (Array)

    Pair of nonce values (hiding_nonce, binding_nonce) for signer_i.

  • msg (String)

    The message to be signed

  • commitment_list (Array)

    A list of commitments issued by each participant.

Returns:

  • (Integer)

    A signature share.

Raises:

  • (ArgumentError)


123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
# File 'lib/frost.rb', line 123

def sign(context, secret_share, group_pubkey, nonces, msg, commitment_list)
  raise ArgumentError "context must be FROST::Context." unless context.is_a?(FROST::Context)
  raise ArgumentError, "msg must be String." unless msg.is_a?(String)
  raise ArgumentError, "group_pubkey must be ECDSA::Point." unless group_pubkey.is_a?(ECDSA::Point)
  raise ArgumentError, "group_pubkey and context groups are different." unless context.group == group_pubkey.group

  identifier = secret_share.identifier
  # Compute binding factors
  binding_factors = compute_binding_factors(context, group_pubkey, commitment_list, msg)
  binding_factor = binding_factors[identifier]

  # Compute group commitment
  group_commitment = compute_group_commitment(commitment_list, binding_factors)

  # Compute Lagrange coefficient
  identifiers = commitment_list.map(&:identifier)
  lambda_i = Polynomial.derive_interpolating_value(identifiers, identifier, context.group)

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

  # Compute the signature share
  hiding_nonce, binding_nonce = context.convert_signer_nocnes(group_commitment, nonces)
  field = ECDSA::PrimeField.new(group_pubkey.group.order)
  field.mod(hiding_nonce.value +
              field.mod(binding_nonce.value * binding_factor) + field.mod(lambda_i * secret_share.share * challenge))
end