class Schnorr::MuSig::Session

Attributes

commitments[R]
id[R]
nonce[RW]
nonce_negate[RW]
num_signers[R]
secret_key[RW]
secret_nonce[RW]

Public Class Methods

new(session_id = SecureRandom.random_bytes(32), num_signers) click to toggle source
# File lib/schnorr/mu_sig/session.rb, line 13
def initialize(session_id = SecureRandom.random_bytes(32), num_signers)
  @id = session_id
  @nonce_negate = false
  @num_signers = num_signers
  @commitments = []
end

Public Instance Methods

combine_nonce(nonces) click to toggle source

Get combine nonce @param nonces (Array) an array of other signer's nonce with binary format. @return (String) combined nonce with binary format.

# File lib/schnorr/mu_sig/session.rb, line 33
def combine_nonce(nonces)
  raise ArgumentError, "Nonce is required for the number of other signers." unless num_signers == (nonces.length + 1)
  raise ArgumentError, "The number of nonce and commitment does not match." unless nonces.length == commitments.length
  # check nonce commitments
  nonces.each do | nonce|
    commitment = Digest::SHA256.digest(nonce)
    raise ArgumentError, "Nonce: #{nonce.bth} is invalid. There is no corresponding commitment." unless commitments.include?(commitment)
  end
  points = ([nonce]+ nonces).map.with_index {|n, index|ECDSA::Format::PointOctetString.decode(n, ECDSA::Group::Secp256k1)}
  r_point = points.inject(:+)
  unless ECDSA::PrimeField.jacobi(r_point.y, ECDSA::Group::Secp256k1.field.prime) == 1
    self.nonce_negate = true
    r_point = r_point.negate
  end
  ECDSA::Format::PointOctetString.encode(r_point, compression: true)
end
commitment() click to toggle source

Get self nonce commitment @return (String) commitment with binary format.

# File lib/schnorr/mu_sig/session.rb, line 26
def commitment
  Digest::SHA256.digest(nonce)
end
nonce_negate?() click to toggle source
# File lib/schnorr/mu_sig/session.rb, line 20
def nonce_negate?
  @nonce_negate
end
partial_sign(message, combined_nonce, combined_pubkey) click to toggle source

Compute partial signature. @param message (String) a message for signature with binary format. @param combined_nonce (String) combined nonce with binary format. @param combined_pubkey (String) combined public key with binary format. @return (Integer) a partial signature.

# File lib/schnorr/mu_sig/session.rb, line 55
def partial_sign(message, combined_nonce, combined_pubkey)
  field = ECDSA::PrimeField.new(ECDSA::Group::Secp256k1.order)
  point_r = ECDSA::Format::PointOctetString.decode(combined_nonce, ECDSA::Group::Secp256k1)
  point_p = ECDSA::Format::PointOctetString.decode(combined_pubkey, ECDSA::Group::Secp256k1)
  e = Schnorr.create_challenge(point_r.x, point_p, message, field, point_r.group)
  k = secret_nonce
  k = 0 - k if nonce_negate?
  field.mod(secret_key * e + k)
end