Class: FROST::Polynomial
- Inherits:
-
Object
- Object
- FROST::Polynomial
- Defined in:
- lib/frost/polynomial.rb
Overview
Polynomial class.
Instance Attribute Summary collapse
-
#coefficients ⇒ Object
readonly
Returns the value of attribute coefficients.
-
#group ⇒ Object
readonly
Returns the value of attribute group.
Class Method Summary collapse
-
.derive_interpolating_value(x_coordinates, xi, group, x: nil) ⇒ Integer
Generates the lagrange coefficient for the i’th participant.
-
.from_secret(secret, degree, group) ⇒ FROST::Polynomial
Generate random polynomial using secret as constant term.
Instance Method Summary collapse
-
#gen_commitments ⇒ Array
Generate coefficient commitments.
-
#gen_proof_of_knowledge(identifier) ⇒ FROST::Signature
Generate proof of knowledge for secret.
-
#gen_share(identifier) ⇒ FROST::SecretShare
Generate secret share.
-
#initialize(coefficients, group) ⇒ Polynomial
constructor
Generate polynomial.
-
#secret ⇒ Integer
Get secret value in this polynomial.
-
#verification_point ⇒ ECDSA::Point
Get point to correspond to secret in this polynomial.
Constructor Details
#initialize(coefficients, group) ⇒ Polynomial
Generate polynomial. The first is the constant term, followed by the coefficients in descending order of order.
12 13 14 15 16 17 18 19 |
# File 'lib/frost/polynomial.rb', line 12 def initialize(coefficients, group) raise ArgumentError, "coefficients must be an Array." unless coefficients.is_a?(Array) raise ArgumentError, "group must be ECDSA::Group." unless group.is_a?(ECDSA::Group) raise ArgumentError, "Two or more coefficients are required." if coefficients.length < 2 @coefficients = coefficients @group = group end |
Instance Attribute Details
#coefficients ⇒ Object (readonly)
Returns the value of attribute coefficients.
5 6 7 |
# File 'lib/frost/polynomial.rb', line 5 def coefficients @coefficients end |
#group ⇒ Object (readonly)
Returns the value of attribute group.
6 7 8 |
# File 'lib/frost/polynomial.rb', line 6 def group @group end |
Class Method Details
.derive_interpolating_value(x_coordinates, xi, group, x: nil) ⇒ Integer
Generates the lagrange coefficient for the i’th participant. The Lagrange polynomial for a set of points (xj, yj) for 0 <= j <= k is ∑_i=0^k yi.ℓi(x), where ℓi(x) is the Lagrange basis polynomial: ℓi(x) = ∏_j≠i (x - xj) / (xi - xj). This computes ℓj(x) for the set of points ‘xs` and for the j corresponding to the given xj.
87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 |
# File 'lib/frost/polynomial.rb', line 87 def self.derive_interpolating_value(x_coordinates, xi, group, x: nil) raise ArgumentError, "xi is not included in x_coordinates." unless x_coordinates.include?(xi) raise ArgumentError, "Duplicate values in x_coordinates." if (x_coordinates.length - x_coordinates.uniq.length) > 0 raise ArgumentError, "group must be ECDSA::Group." unless group.is_a?(ECDSA::Group) raise ArgumentError, "x must be Integer." if x && !x.is_a?(Integer) field = ECDSA::PrimeField.new(group.order) numerator = 1 denominator = 1 x_coordinates.each do |xj| next if xi == xj if x numerator *= (x - xj) denominator *= (xi - xj) else numerator *= xj denominator *= (xj - xi) end end field.mod(numerator * field.inverse(denominator)) end |
.from_secret(secret, degree, group) ⇒ FROST::Polynomial
Generate random polynomial using secret as constant term.
25 26 27 28 29 30 31 32 |
# File 'lib/frost/polynomial.rb', line 25 def self.from_secret(secret, degree, group) secret = secret.scalar if secret.is_a?(FROST::SigningKey) raise ArgumentError, "secret must be Integer." unless secret.is_a?(Integer) raise ArgumentError, "degree must be Integer." unless degree.is_a?(Integer) raise ArgumentError, "degree must be greater than or equal to 1." if degree < 1 coeffs = degree.times.map {SecureRandom.random_number(group.order - 1)} Polynomial.new(coeffs.prepend(secret), group) end |
Instance Method Details
#gen_commitments ⇒ Array
Generate coefficient commitments
54 55 56 |
# File 'lib/frost/polynomial.rb', line 54 def gen_commitments coefficients.map{|c| group.generator * c } end |
#gen_proof_of_knowledge(identifier) ⇒ FROST::Signature
Generate proof of knowledge for secret.
61 62 63 |
# File 'lib/frost/polynomial.rb', line 61 def gen_proof_of_knowledge(identifier) FROST::DKG.gen_proof_of_knowledge(identifier, self) end |
#gen_share(identifier) ⇒ FROST::SecretShare
Generate secret share.
37 38 39 40 41 42 43 44 45 46 47 48 49 50 |
# File 'lib/frost/polynomial.rb', line 37 def gen_share(identifier) raise ArgumentError, "identifiers must be Integer." unless identifier.is_a?(Integer) return SecretShare.new(identifier, 0, group) if coefficients.empty? return SecretShare.new(identifier, coefficients.last, group) if identifier == 0 # Calculate using Horner's method. last = coefficients.last (coefficients.length - 2).step(0, -1) do |i| tmp = last * identifier last = (tmp + coefficients[i]) % group.order end SecretShare.new(identifier, last, group) end |
#secret ⇒ Integer
Get secret value in this polynomial.
67 68 69 |
# File 'lib/frost/polynomial.rb', line 67 def secret coefficients.first end |
#verification_point ⇒ ECDSA::Point
Get point to correspond to secret in this polynomial.
73 74 75 |
# File 'lib/frost/polynomial.rb', line 73 def verification_point group.generator * secret end |