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.
-
#context ⇒ Object
readonly
Returns the value of attribute context.
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(context, secret, degree) ⇒ 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.
-
#group ⇒ ECDSA::Group
Get group.
-
#initialize(context, coefficients) ⇒ 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(context, coefficients) ⇒ Polynomial
Generate polynomial. The first is the constant term, followed by the coefficients in descending order of order.
14 15 16 17 18 19 20 21 22 23 24 |
# File 'lib/frost/polynomial.rb', line 14 def initialize(context, coefficients) raise ArgumentError "context must be FROST::Context." unless context.is_a?(FROST::Context) raise ArgumentError, "coefficients must be an Array." unless coefficients.is_a?(Array) raise ArgumentError, "Two or more coefficients are required." if coefficients.length < 2 coefficients.each do |coefficient| raise ArgumentError "coefficient must be Integer." unless coefficient.is_a?(Integer) end @coefficients = coefficients @context = context 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 |
#context ⇒ Object (readonly)
Returns the value of attribute context.
6 7 8 |
# File 'lib/frost/polynomial.rb', line 6 def context @context 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.
99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 |
# File 'lib/frost/polynomial.rb', line 99 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(context, secret, degree) ⇒ FROST::Polynomial
Generate random polynomial using secret as constant term.
37 38 39 40 41 42 43 44 |
# File 'lib/frost/polynomial.rb', line 37 def self.from_secret(context, secret, degree) 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(context.group.order - 1)} Polynomial.new(context, coeffs.prepend(secret)) end |
Instance Method Details
#gen_commitments ⇒ Array
Generate coefficient commitments
66 67 68 |
# File 'lib/frost/polynomial.rb', line 66 def gen_commitments coefficients.map{|c| group.generator * c } end |
#gen_proof_of_knowledge(identifier) ⇒ FROST::Signature
Generate proof of knowledge for secret.
73 74 75 |
# File 'lib/frost/polynomial.rb', line 73 def gen_proof_of_knowledge(identifier) FROST::DKG.gen_proof_of_knowledge(identifier, self) end |
#gen_share(identifier) ⇒ FROST::SecretShare
Generate secret share.
49 50 51 52 53 54 55 56 57 58 59 60 61 62 |
# File 'lib/frost/polynomial.rb', line 49 def gen_share(identifier) raise ArgumentError, "identifiers must be Integer." unless identifier.is_a?(Integer) return SecretShare.new(context, identifier, 0) if coefficients.empty? return SecretShare.new(context, identifier, coefficients.last) 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(context, identifier, last) end |
#group ⇒ ECDSA::Group
Get group
28 29 30 |
# File 'lib/frost/polynomial.rb', line 28 def group context.group end |
#secret ⇒ Integer
Get secret value in this polynomial.
79 80 81 |
# File 'lib/frost/polynomial.rb', line 79 def secret coefficients.first end |
#verification_point ⇒ ECDSA::Point
Get point to correspond to secret in this polynomial.
85 86 87 |
# File 'lib/frost/polynomial.rb', line 85 def verification_point group.generator * secret end |