frostrb 0.2.0 → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 0660ec6fbd998b152bdb359276284fd64e00d89ed19e783dbd72e04cac3fad67
4
- data.tar.gz: c01bd20b7f10d10e0362d6ee4c3722c8849f748ed8899c06efd2cfcaee2dcefa
3
+ metadata.gz: e3824b64152fafddb21b2189891156852ec6a3b079274d81cbe6e0d5732ee848
4
+ data.tar.gz: 8e28eeb4c71d9b4d9636e922fd71772c86b98819c4ed2f4ea7416dc085961a7b
5
5
  SHA512:
6
- metadata.gz: 5cadf1d9b254ac672aad430dae0c27ec7f45878886bbf600cd250a8c4a405f5d89201de96b5bd145ff3fc59ae2384d227a5fe7e73c3abcf002b36a6fbd2d5098
7
- data.tar.gz: 71c14b38913bf8471436979fb8d69a99ad7ad763a79d28f1f738435999ad5b485ba7e09d5e43083bbd2edec5ade02c189076e53678c44a4512a71c86e0883a42
6
+ metadata.gz: 26b6c5dbfa59991e7ab0f6bddb11ca1dd4219cdd5c6101fb62d106fd7d982c5afb2107149332cba55db3448afce3286b4807a32415f2bcc8b63b90e00871e298
7
+ data.tar.gz: b80e53aaaff5733bf0b5f1091f2a2a7c5903fbb008551e8924aa285b61e2e8044a2f594a481f5cfca2aefe5fd72de101b6ae9e4533e7b623a6c30687052a652f
data/README.md CHANGED
@@ -80,14 +80,14 @@ DKG can be run as below.
80
80
  max_signer = 5
81
81
  min_signer = 3
82
82
 
83
- secrets = {}
83
+ secret_packages = {}
84
84
  round1_outputs = {}
85
85
  # Round 1:
86
86
  # For each participant, perform the first part of the DKG protocol.
87
87
  1.upto(max_signer) do |i|
88
- polynomial, package = FROST::DKG.generate_secret(i, min_signer, max_signer, group)
89
- secrets[i] = polynomial
90
- round1_outputs[i] = package
88
+ secret_package = FROST::DKG.generate_secret(i, min_signer, max_signer, group)
89
+ secret_packages[i] = secret_package
90
+ round1_outputs[i] = secret_package.public_package
91
91
  end
92
92
 
93
93
  # Each participant sends their commitments and proof to other participants.
@@ -98,8 +98,9 @@ end
98
98
 
99
99
  # Each participant verify knowledge of proof in received package.
100
100
  received_package.each do |id, packages|
101
+ secret_package = secret_packages[id]
101
102
  packages.each do |package|
102
- expect(FROST::DKG.verify_proof_of_knowledge(package)).to be true
103
+ expect(FROST::DKG.verify_proof_of_knowledge(secret_package, package)).to be true
103
104
  end
104
105
  end
105
106
 
@@ -107,11 +108,11 @@ end
107
108
  # Each participant generate share for other participants and send it.
108
109
  received_shares = {}
109
110
  1.upto(max_signer) do |i|
110
- polynomial = secrets[i] # own secret
111
+ secret_package = secret_packages[i] # own secret
111
112
  1.upto(max_signer) do |o|
112
113
  next if i == o
113
114
  received_shares[o] ||= []
114
- received_shares[o] << [i, polynomial.gen_share(o)]
115
+ received_shares[o] << [i, secret_package.gen_share(o)]
115
116
  end
116
117
  end
117
118
 
@@ -127,11 +128,11 @@ end
127
128
  signing_shares = {}
128
129
  1.upto(max_signer) do |i|
129
130
  shares = received_shares[i].map { |_, share| share }
130
- signing_shares[i] = FROST::DKG.compute_signing_share(secrets[i], shares)
131
+ signing_shares[i] = FROST::DKG.compute_signing_share(secret_packages[i], shares)
131
132
  end
132
133
 
133
134
  # Participant 1 compute group public key.
134
- group_pubkey = FROST::DKG.compute_group_pubkey(secrets[1], received_package[1])
135
+ group_pubkey = FROST::DKG.compute_group_pubkey(secret_packages[1], received_package[1])
135
136
 
136
137
  # The subsequent signing phase is the same as above with signing_shares as the secret.
137
138
  ```
@@ -0,0 +1,53 @@
1
+ module FROST
2
+ module DKG
3
+ # Package to hold participants' secret share.
4
+ class SecretPackage
5
+
6
+ attr_reader :identifier
7
+ attr_reader :polynomial
8
+ attr_reader :public_package
9
+ attr_reader :min_signers
10
+ attr_reader :max_signers
11
+
12
+ # Constructor.
13
+ # @param [Integer] identifier The identifier of this owner.
14
+ # @param [Integer] min_signers Minimum number of signers.
15
+ # @param [Integer] max_signers Maximum number of signers.
16
+ # @param [FROST::Polynomial] polynomial Polynomial with secret share.
17
+ def initialize(identifier, min_signers, max_signers, polynomial)
18
+ raise ArgumentError, "identifier must be Integer." unless identifier.is_a?(Integer)
19
+ raise ArgumentError, "identifier must be greater than 0." if identifier < 1
20
+ raise ArgumentError, "min_signers must be Integer." unless min_signers.is_a?(Integer)
21
+ raise ArgumentError, "max_signers must be Integer." unless max_signers.is_a?(Integer)
22
+ raise ArgumentError, "polynomial must be FROST::Polynomial." unless polynomial.is_a?(FROST::Polynomial)
23
+ raise ArgumentError, "max_signers must be greater than or equal to min_signers." if max_signers < min_signers
24
+ raise ArgumentError, "Number of coefficients of polynomial and min_signers do not match." unless min_signers == polynomial.coefficients.length
25
+
26
+ @identifier = identifier
27
+ @min_signers = min_signers
28
+ @max_signers = max_signers
29
+ @polynomial = polynomial
30
+ @public_package = Package.new(identifier, polynomial.gen_commitments, polynomial.gen_proof_of_knowledge(identifier))
31
+ end
32
+
33
+ # Generate secret share for identifier.
34
+ # @param [Integer] identifier
35
+ # @return [FROST::SecretShare] Generate share.
36
+ def gen_share(identifier)
37
+ polynomial.gen_share(identifier)
38
+ end
39
+
40
+ # Get group.
41
+ # @return [ECDSA::Group]
42
+ def group
43
+ polynomial.group
44
+ end
45
+
46
+ # Get verification point.
47
+ # @return [ECDSA::Point]
48
+ def verification_point
49
+ polynomial.verification_point
50
+ end
51
+ end
52
+ end
53
+ end
data/lib/frost/dkg.rb CHANGED
@@ -2,6 +2,7 @@ module FROST
2
2
  # Distributed Key Generation feature.
3
3
  module DKG
4
4
 
5
+ autoload :SecretPackage, "frost/dkg/secret_package"
5
6
  autoload :Package, "frost/dkg/package"
6
7
 
7
8
  module_function
@@ -10,17 +11,18 @@ module FROST
10
11
  # Participant generate key and commitments, proof of knowledge for secret.
11
12
  # @param [Integer] identifier
12
13
  # @param [ECDSA::Group] group Group of elliptic curve.
13
- # @return [Array] The triple of polynomial and public package(FROST::DKG::Package)
14
+ # @return [FROST::DKG::SecretPackage] Secret received_package for owner.
14
15
  def generate_secret(identifier, min_signers, max_signers, group)
15
16
  raise ArgumentError, "identifier must be Integer" unless identifier.is_a?(Integer)
16
17
  raise ArgumentError, "identifier must be greater than 0." if identifier < 1
17
18
  raise ArgumentError, "group must be ECDSA::Group." unless group.is_a?(ECDSA::Group)
19
+ raise ArgumentError, "min_signers must be Integer." unless min_signers.is_a?(Integer)
20
+ raise ArgumentError, "max_singers must be Integer." unless max_signers.is_a?(Integer)
18
21
  raise ArgumentError, "max_signers must be greater than or equal to min_signers." if max_signers < min_signers
19
22
 
20
23
  secret = FROST::SigningKey.generate(group)
21
- # Every participant P_i samples t random values (a_{i0}, ..., a_{i(t−1)}) ← Z_q
22
24
  polynomial = secret.gen_poly(min_signers - 1)
23
- [polynomial, Package.new(identifier, polynomial.gen_commitments, polynomial.gen_proof_of_knowledge(identifier))]
25
+ SecretPackage.new(identifier, min_signers, max_signers, polynomial)
24
26
  end
25
27
 
26
28
  # Generate proof of knowledge for secret.
@@ -43,38 +45,45 @@ module FROST
43
45
  end
44
46
 
45
47
  # Verify proof of knowledge for received commitment.
46
- # @param [FROST::DKG::Package] package Received package.
48
+ # @param [FROST::DKG::SecretPackage] secret_package Verifier's secret package.
49
+ # @param [FROST::DKG::Package] received_package Received received_package.
47
50
  # @return [Boolean]
48
- def verify_proof_of_knowledge(package)
49
- raise ArgumentError, "package must be FROST::DKG::Package." unless package.is_a?(FROST::DKG::Package)
51
+ def verify_proof_of_knowledge(secret_package, received_package)
52
+ raise ArgumentError, "secret_package must be FROST::DKG::SecretPackage." unless secret_package.is_a?(FROST::DKG::SecretPackage)
53
+ raise ArgumentError, "received_package must be FROST::DKG::Package." unless received_package.is_a?(FROST::DKG::Package)
54
+ raise FROST::Error, "Invalid number of commitments in package." unless secret_package.min_signers == received_package.commitments.length
50
55
 
51
- verification_key = package.verification_key
52
- msg = FROST.encode_identifier(package.identifier, verification_key.group) +
53
- [verification_key.to_hex + package.proof.r.to_hex].pack("H*")
56
+ verification_key = received_package.verification_key
57
+ msg = FROST.encode_identifier(received_package.identifier, verification_key.group) +
58
+ [verification_key.to_hex + received_package.proof.r.to_hex].pack("H*")
54
59
  challenge = Hash.hdkg(msg, verification_key.group)
55
- package.proof.r == verification_key.group.generator * package.proof.s + (verification_key * challenge).negate
60
+ received_package.proof.r == verification_key.group.generator * received_package.proof.s + (verification_key * challenge).negate
56
61
  end
57
62
 
58
63
  # Compute signing share using received shares from other participants
59
- # @param [FROST::Polynomial] polynomial Own polynomial contains own secret.
64
+ # @param [FROST::DKG::SecretPackage] secret_package Own secret received_package.
60
65
  # @param [Array] received_shares Array of FROST::SecretShare received by other participants.
61
66
  # @return [FROST::SecretShare] Signing share.
62
- def compute_signing_share(polynomial, received_shares)
63
- raise ArgumentError, "polynomial must be FROST::Polynomial." unless polynomial.is_a?(FROST::Polynomial)
67
+ def compute_signing_share(secret_package, received_shares)
68
+ raise ArgumentError, "polynomial must be FROST::DKG::SecretPackage." unless secret_package.is_a?(FROST::DKG::SecretPackage)
69
+ raise FROST::Error, "Invalid number of received_shares." unless secret_package.max_signers - 1 == received_shares.length
70
+
64
71
  identifier = received_shares.first.identifier
65
72
  s_id = received_shares.sum {|share| share.share}
66
- field = ECDSA::PrimeField.new(polynomial.group.order)
73
+ field = ECDSA::PrimeField.new(secret_package.group.order)
67
74
  FROST::SecretShare.new(
68
- identifier, field.mod(s_id + polynomial.gen_share(identifier).share), polynomial.group)
75
+ identifier, field.mod(s_id + secret_package.gen_share(identifier).share), secret_package.group)
69
76
  end
70
77
 
71
78
  # Compute Group public key.
72
- # @param [FROST::Polynomial] polynomial Own polynomial contains own secret.
79
+ # @param [FROST::DKG::SecretPackage] secret_package Own secret received_package.
73
80
  # @param [Array] received_packages Array of FROST::DKG::Package received by other participants.
74
81
  # @return [ECDSA::Point] Group public key.
75
- def compute_group_pubkey(polynomial, received_packages)
76
- raise ArgumentError, "polynomial must be FROST::Polynomial." unless polynomial.is_a?(FROST::Polynomial)
77
- received_packages.inject(polynomial.verification_point) {|sum, package| sum + package.commitments.first }
82
+ def compute_group_pubkey(secret_package, received_packages)
83
+ raise ArgumentError, "polynomial must be FROST::DKG::SecretPackage." unless secret_package.is_a?(FROST::DKG::SecretPackage)
84
+ raise FROST::Error, "Invalid number of received_packages." unless secret_package.max_signers - 1 == received_packages.length
85
+
86
+ received_packages.inject(secret_package.verification_point) {|sum, package| sum + package.commitments.first }
78
87
  end
79
88
  end
80
89
  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.2.0"
4
+ VERSION = "0.3.0"
5
5
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: frostrb
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.0
4
+ version: 0.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - azuchi
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2024-02-19 00:00:00.000000000 Z
11
+ date: 2024-02-22 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: ecdsa_ext
@@ -61,6 +61,7 @@ files:
61
61
  - lib/frost/commitments.rb
62
62
  - lib/frost/dkg.rb
63
63
  - lib/frost/dkg/package.rb
64
+ - lib/frost/dkg/secret_package.rb
64
65
  - lib/frost/hash.rb
65
66
  - lib/frost/nonce.rb
66
67
  - lib/frost/polynomial.rb