frostrb 0.4.0 → 0.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 6ec10bec048f4bbf00419a36f27e901afb7ca0b12ae20140d827e1e2eaba107e
4
- data.tar.gz: 13bce5e0d48b971619c698224e0051162b57b0e08dcc9dabad7eef8a770ecda5
3
+ metadata.gz: 971ebd8ce7d6cf7faae3a152a2ac1ab89af43ba8317276b1a9595610c543b5b5
4
+ data.tar.gz: 03b261ac549b8745c35ef35b61a9b5c63534d4043e2b287a58d680c79e510318
5
5
  SHA512:
6
- metadata.gz: 21d11540bbb90c3f3e0e4e96b17204140b40ee52b783da59d12de0898e64d11ed7a4feefc937fd08dff87c001592c14eed39f4d06757211198581047045aa98f
7
- data.tar.gz: ca60c7fd06432c8c8d6b72fd2a5fb77b42e6184f892af8496c1d540d4215c36ca074fef9c5b495ea8bbcd1e675649a166d41a07b8ab64257f520490ae4ffd869
6
+ metadata.gz: 96d05d23ca3dec9b7d187a4a6ffdda6c78e193d7bf9f56699e0abbb85926d3763a61ceb7b05952fcd16ad748f15a7ad1712c03719ba0ac75ae11613d80cda895
7
+ data.tar.gz: 8f7a5926c9c755704f8cc13260956c08d4a2ba1f46ed8e20e8ec8786cfc7fe70fad27250d03ce83e64168b99a100f4eaec42c96025e02d1ed1d665be88d998d2
data/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # FROST for Ruby [![Build Status](https://github.com/azuchi/frostrb/actions/workflows/main.yml/badge.svg?branch=master)](https://github.com/azuchi/frostrb/actions/workflows/main.yml)
2
2
 
3
- This library is ruby implementations of ['Two-Round Threshold Schnorr Signatures with FROST'](https://datatracker.ietf.org/doc/draft-irtf-cfrg-frost/).
3
+ This library is a ruby implementation of ['Two-Round Threshold Schnorr Signatures with FROST'](https://datatracker.ietf.org/doc/draft-irtf-cfrg-frost/).
4
4
 
5
5
  Note: This library has not been security audited and tested widely, so should not be used in production.
6
6
 
@@ -37,20 +37,18 @@ require 'frost'
37
37
  # Setup context.
38
38
  ctx = FROST::Context.new(ECDSA::Group::Secp256k1, FROST::Type::RFC9591)
39
39
 
40
- # Dealer generate secret.
41
- secret = FROST::SigningKey.generate(ctx)
42
- group_pubkey = secret.to_point
40
+ max_signers = 3
41
+ min_signers = 2
43
42
 
44
- # Generate polynomial(f(x) = ax + b)
45
- polynomial = secret.gen_poly(1)
43
+ # Setup dealer.
44
+ dealer = FROST::Dealer.new(ctx, max_signers, min_signers)
45
+ group_pubkey = dealer.group_public_key
46
46
 
47
47
  # Calculate secret shares.
48
- share1 = polynomial.gen_share(1)
49
- share2 = polynomial.gen_share(2)
50
- share3 = polynomial.gen_share(3)
48
+ share1, _, share3 = dealer.gen_shares
51
49
 
52
50
  # Round 1: Generate nonce and commitment
53
- ## each party generate hiding and binding nonce.
51
+ ## each party generates hiding and binding nonce.
54
52
  hiding_nonce1 = FROST::Nonce.gen_from_secret(share1)
55
53
  binding_nonce1 = FROST::Nonce.gen_from_secret(share1)
56
54
  hiding_nonce3 = FROST::Nonce.gen_from_secret(share3)
@@ -79,7 +77,7 @@ FROST.verify(sig, group_pubkey, msg)
79
77
 
80
78
  ### Bitcoin support
81
79
 
82
- When using Bitcoin(taproot), the context type must be `FROST::Type::Taproot` instead of `FROST::Type::RFC9591`.
80
+ When using Bitcoin(taproot), the context type must be `FROST::Type::TAPROOT` instead of `FROST::Type::RFC9591`.
83
81
 
84
82
  ```ruby
85
83
  ctx = FROST::Context.new(ECDSA::Group::Secp256k1, FROST::Type::TAPROOT)
@@ -106,13 +104,13 @@ round1_outputs = {}
106
104
  round1_outputs[i] = secret_package.public_package
107
105
  end
108
106
 
109
- # Each participant send their commitments and proof to other participants.
107
+ # Each participant sends their commitments and proof to other participants.
110
108
  received_package = {}
111
109
  1.upto(max_signer) do |i|
112
110
  received_package[i] = round1_outputs.select {|k, _| k != i}.values
113
111
  end
114
112
 
115
- # Each participant verify knowledge of proof in received package.
113
+ # Each participant verifies knowledge of proof in a received package.
116
114
  received_package.each do |id, packages|
117
115
  secret_package = secret_packages[id]
118
116
  packages.each do |package|
@@ -121,7 +119,7 @@ received_package.each do |id, packages|
121
119
  end
122
120
 
123
121
  # Round 2:
124
- # Each participant generate share for other participants and send it.
122
+ # Each participant generates a share for other participants and send it.
125
123
  received_shares = {}
126
124
  1.upto(max_signer) do |i|
127
125
  secret_package = secret_packages[i] # own secret
@@ -140,7 +138,7 @@ end
140
138
  end
141
139
  end
142
140
 
143
- # Each participant computes signing share.
141
+ # Each participant computes a signing share.
144
142
  signing_shares = {}
145
143
  1.upto(max_signer) do |i|
146
144
  shares = received_shares[i].map{|_, share| share}
@@ -159,11 +157,14 @@ Using `FROST::Repairable` module, you can repair existing (or new) participant's
159
157
 
160
158
  ```ruby
161
159
  ctx = FROST::Context.new(ECDSA::Group::Secp256k1, FROST::Type::RFC9591)
162
- dealer = FROST::SigningKey.generate(ctx)
160
+ max_signers = 5
161
+ min_signers = 3
163
162
 
164
- # Dealer generate shares.
165
- polynomial = dealer.gen_poly(min_signers - 1)
166
- shares = 1.upto(max_signers).map {|identifier| polynomial.gen_share(identifier) }
163
+ # Setup daler
164
+ dealer = FROST::SigningKey.generate(ctx, max_signers, min_signers)
165
+
166
+ # Dealer generates shares.
167
+ shares = dealer.gen_shares
167
168
 
168
169
  # Signer 2 will lose their share
169
170
  # Signers (helpers) 1, 4 and 5 will help signer 2 (participant) to recover their share
@@ -0,0 +1,50 @@
1
+ module FROST
2
+ # Dealer
3
+ class Dealer
4
+ attr_reader :ctx
5
+ attr_reader :max_signers
6
+ attr_reader :min_signers
7
+ attr_reader :polynomial
8
+
9
+ # Create a new dealer.
10
+ # @param [FROST::Context] ctx FROST context.
11
+ # @param [Integer] max_signers Maximum number of signers.
12
+ # @return [FROST::Dealer]
13
+ # @raise [ArgumentError]
14
+ def initialize(ctx, max_signers, min_signers)
15
+ raise ArgumentError, "context must be FROST::Context." unless ctx.is_a?(FROST::Context)
16
+ raise ArgumentError, "min_signers must be Integer." unless min_signers.is_a?(Integer)
17
+ raise ArgumentError, "min_signers must be greater than 1." if min_signers < 2
18
+ raise ArgumentError, "max_signers must be Integer." unless max_signers.is_a?(Integer)
19
+ raise ArgumentError, "max_signers must be greater than or equal to min_signers." if max_signers < min_signers
20
+ @ctx = ctx
21
+ @min_signers = min_signers
22
+ @max_signers = max_signers
23
+ key = SigningKey.generate(ctx)
24
+ @polynomial = key.gen_poly(min_signers - 1)
25
+ end
26
+
27
+ # Generate shares.
28
+ # @return [Array] Array of shares(FROST::SecretShare).
29
+ # @raise [ArgumentError]
30
+ def gen_shares(identifiers = nil)
31
+ raise ArgumentError, "identifiers must be Array." if identifiers && !identifiers.is_a?(Array)
32
+ identifiers = if identifiers
33
+ identifiers.each do |id|
34
+ raise ArgumentError, "identifier must be Integer." unless id.is_a?(Integer)
35
+ raise ArgumentError, "identifier must be greater than 0." if id < 1
36
+ end
37
+ identifiers
38
+ else
39
+ (1..max_signers).to_a
40
+ end
41
+ identifiers.map{ |i| polynomial.gen_share(i) }
42
+ end
43
+
44
+ # Get a group public key.
45
+ # @return [ECDSA::Point]
46
+ def group_public_key
47
+ polynomial.verification_point
48
+ end
49
+ end
50
+ end
data/lib/frost/version.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module FROST
4
- VERSION = "0.4.0"
4
+ VERSION = "0.5.0"
5
5
  end
data/lib/frost.rb CHANGED
@@ -17,6 +17,7 @@ module FROST
17
17
  autoload :SecretShare, "frost/secret_share"
18
18
  autoload :Polynomial, "frost/polynomial"
19
19
  autoload :SigningKey, "frost/signing_key"
20
+ autoload :Dealer, "frost/dealer"
20
21
  autoload :DKG, "frost/dkg"
21
22
  autoload :Repairable, "frost/repairable"
22
23
 
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: frostrb
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.0
4
+ version: 0.5.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - azuchi
8
8
  bindir: exe
9
9
  cert_chain: []
10
- date: 2025-05-15 00:00:00.000000000 Z
10
+ date: 2025-05-17 00:00:00.000000000 Z
11
11
  dependencies:
12
12
  - !ruby/object:Gem::Dependency
13
13
  name: ecdsa_ext
@@ -59,6 +59,7 @@ files:
59
59
  - lib/frost.rb
60
60
  - lib/frost/commitments.rb
61
61
  - lib/frost/context.rb
62
+ - lib/frost/dealer.rb
62
63
  - lib/frost/dkg.rb
63
64
  - lib/frost/dkg/public_package.rb
64
65
  - lib/frost/dkg/secret_package.rb