secret_sharing 0.0.3 → 0.0.4

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,15 +1,15 @@
1
1
  ---
2
2
  !binary "U0hBMQ==":
3
3
  metadata.gz: !binary |-
4
- MTU5NTYxM2RmYzRmOTdlMzVlYzczNTg1ODc2NDBmYTcwOGNiNWY2Yg==
4
+ ZGRmOTk3Y2EyYTJhY2FiODk2YWYwODNlNWZlMzI5ZTJlY2M0MDk3Yg==
5
5
  data.tar.gz: !binary |-
6
- NjA3MGFiOGNiYzlhOGQ0MWIxYjNkM2VlNDVkMGZiYmQ2MzgyZTgzZA==
6
+ ZTVkODUxZjRkMGUzZWYyMzRkYzFiNTYyNWU2OWUyMzJjYzhkNjU3OA==
7
7
  SHA512:
8
8
  metadata.gz: !binary |-
9
- NGM2YjkzZDQyMGYyNGU5NzhhMGUxZjAxMTVmZTg4MGJjNTRkNTI1NGJmYzkw
10
- NzAwN2Y4NGQ3MmJkZWNlN2NiNjhkM2FkYTExZDFlNTNjMDM4MDYyNDdjNWNi
11
- MmYyOGUwNTU1ZDE0MTAzZmU4NzUzZGViMmM2OTRiYTUxN2M4NTQ=
9
+ MjY5OTQ3ZTU4NjA1MzhkMmY0MzkwM2U0NTVkYmJjOTg3MDMyZjIyNmUwZWUw
10
+ OGRmZDAzZWFjYzBiMDlkNzdhZmMyMjU5N2Y5MzNmOTA3ZTc2YTY3Zjg4ZDFk
11
+ NDRhYmZmZTc4NjFkY2FlOGRlZmQ1ZmZhZjdjOGI5MmRjYWE5NGM=
12
12
  data.tar.gz: !binary |-
13
- NzRmYjIwMzk2MWJmYTUxY2YxMjIzYzUyOWMwMDVhZGIwZGI5NTIxOTlhNDdl
14
- OWNjYzczNzJkMmJhOTBjYzk2Yjc3ZWVmMmFmNjI4ZmI3ZWZhM2M0Y2RiNjIz
15
- MDBkYTU0NGE3NGU3MTg1MmQyYmE4ZmE5MmZmMzI1MjQzNjI3ZWQ=
13
+ Y2YwZjQ1YjVjMGJlOGU2YzVlZTA4NTJhZWEzMDFiYjRlNzU0NGQ1M2ViNjZj
14
+ NTQ0MTc4NjNmYjI1NWIyNTkwOWYzYmE2ZjBkOGRhMDQ3MTdjZTk2Zjk0YmY4
15
+ NTEyYzg1NzU2NDhkN2YwMTE2ZGQ0ZjE5MzY2Y2U1NjQ1ZTQ0MTQ=
data/Gemfile CHANGED
@@ -1,8 +1,13 @@
1
1
  source 'https://rubygems.org'
2
+ gemspec
2
3
 
3
- gem 'rake', group: [:development, :test]
4
- gem 'rspec', group: [:development, :test]
5
- gem 'yard', group: :development
6
- gem 'rubocop', require: false, group: :development
7
- gem 'simplecov', require: false, group: [:development, :test]
8
- gem 'coveralls', require: false, group: [:development, :test]
4
+ group :development, :test do
5
+ gem 'rake'
6
+ gem 'rspec'
7
+ gem 'mutant'
8
+ gem 'mutant-rspec'
9
+ gem 'yard'
10
+ gem 'rubocop', require: false
11
+ gem 'simplecov', require: false
12
+ gem 'coveralls', require: false
13
+ end
data/README.md CHANGED
@@ -4,7 +4,7 @@
4
4
  [![Code Climate](https://codeclimate.com/github/duse-io/secret_sharing_ruby/badges/gpa.svg)](https://codeclimate.com/github/duse-io/secret_sharing_ruby)
5
5
  [![Inline docs](http://inch-ci.org/github/duse-io/secret_sharing_ruby.svg?branch=master)](http://inch-ci.org/github/duse-io/secret_sharing_ruby)
6
6
 
7
- # SecretSharing
7
+ # secret_sharing
8
8
 
9
9
  > **Warning:** This implementation has not been tested in production nor has it
10
10
  > been examined by a security audit. All uses are your own responsibility.
@@ -25,32 +25,46 @@ Or install it yourself as:
25
25
 
26
26
  $ gem install secret_sharing
27
27
 
28
- ## Usage
28
+ ## Implementation details
29
29
 
30
- require 'secret_sharing'
31
- shares = SecretSharing.split_secret('secret', 2, 3) # => [...]
32
- length = shares.length # => 3
33
- secret = SecretSharing.recover_secret(shares[0..1]) # => 'my secret'
30
+ This implementation of shamir's secret sharing has initially been developed to
31
+ be used in [duse](https://duse.io/), however, it is designed to be used in any
32
+ other context just as well.
33
+
34
+ The representation of a share is simply `x-hex(y)`. We chose this
35
+ representation, mainly to make it easier for this library to become compatible
36
+ with other implementations, if we choose to.
34
37
 
35
- This implementation can also handle non-ascii characters, however, the charset
36
- will be visible in the calculated shares. Thus splitting ascii only strings is
37
- "more" secure. (but always remember, shamir's secret sharing alone is not
38
- secure)
38
+ For better approximation and equal length of the resulting shares, a zero
39
+ padding has been added. For example, if there are ten or more shares, then all
40
+ single digit shares have a prepending zero.
39
41
 
40
- ## Compatible libraries
42
+ * `01-574060c9`
43
+ * `02-1fe7479f`
44
+ * ...
45
+ * `10-651e7e4b`
41
46
 
42
- Since this implementation is special in some ways most [Shamir’s Secret
43
- Sharing](http://de.wikipedia.org/wiki/Shamir%E2%80%99s_Secret_Sharing)
44
- libraries are not compatible. The only library that is compatible as of now is
45
- [duse-io/secret-sharing-dart](https://github.com/duse-io/secret-sharing-dart).
47
+ Also, when generating a random polynomial, we make sure the coefficients are
48
+ random, but never zero. If we would allow the coefficients to be zero, it could
49
+ result in a lower threshold than intended. For example, if the threshold is
50
+ three, then the degree of the polynomial would be two so in the form of
51
+ `f(x)=a0 + a1*x + a2*x^2`. If `a2` would be zero than the polynomial would be
52
+ of dergree one, which would result in a real threshold of two rather than
53
+ three.
46
54
 
47
- We do have [integration
48
- tests](https://github.com/duse-io/lib-integration-tests) that make sure the
49
- libraries work with each other.
55
+ ## Usage
56
+
57
+ require 'secret_sharing'
58
+ shares = SecretSharing.split_secret('my secret', 2, 3)
59
+ # => ["1-437b3d6cce8e7b77adb75", "2-86f673fa74e31127903f6", "3-ca71aa881b37a6d772c77"]
60
+ length = shares.length
61
+ # => 3
62
+ secret = SecretSharing.recover_secret(shares[0..1])
63
+ # => 'my secret'
50
64
 
51
65
  ## Contributing
52
66
 
53
- 1. Fork it ( https://github.com/duse-io/secret_sharing/fork )
67
+ 1. Fork it ( https://github.com/duse-io/secret_sharing_ruby/fork )
54
68
  2. Create your feature branch (`git checkout -b my-new-feature`)
55
69
  3. Commit your changes (`git commit -am 'Add some feature'`)
56
70
  4. Push to the branch (`git push origin my-new-feature`)
@@ -30,7 +30,7 @@ module SecretSharing
30
30
  num_shares)
31
31
 
32
32
  points.map do |point|
33
- Share.new(point).to_s(Math.log10(points.length).floor + 1)
33
+ Share.new(point).to_s(Math.log10(points.length) + 1)
34
34
  end
35
35
  end
36
36
 
@@ -43,16 +43,15 @@ module SecretSharing
43
43
  (1..num_points).map do |x|
44
44
  y = intercept
45
45
  (1...@coefficients.length).each do |i|
46
- exponentiation = x**i % prime
47
- term = (@coefficients[i] * exponentiation) % prime
48
- y = (y + term) % prime
46
+ y = (y + @coefficients[i] * x ** i) % prime
49
47
  end
50
48
  Point.new(x, y)
51
49
  end
52
50
  end
53
51
 
54
52
  # Generate a random polynomial with a specific degree, defined x=0 value
55
- # and an upper limit for the coefficients of the polynomial.
53
+ # and an upper limit for the coefficients of the polynomial. All
54
+ # coefficients generated are >= 1.
56
55
  #
57
56
  # Example
58
57
  #
@@ -66,7 +65,7 @@ module SecretSharing
66
65
  fail ArgumentError, 'Degree must be a non-negative number' if degree < 0
67
66
 
68
67
  coefficients = (0...degree).reduce([intercept]) do |accumulator|
69
- accumulator << SecureRandom.random_number(upper_bound)
68
+ accumulator << SecureRandom.random_number(upper_bound - 1) + 1
70
69
  end
71
70
  new coefficients
72
71
  end
@@ -83,13 +82,11 @@ module SecretSharing
83
82
  # @param num_points [Integer] number of points to generate
84
83
  # @return [Polynomial] the generated polynomial
85
84
  def self.points_from_secret(secret_int, point_threshold, num_points)
86
- prime = SecretSharing::Prime.large_enough_prime([secret_int, num_points].max)
85
+ prime = Prime.large_enough_prime(secret_int)
87
86
  fail ArgumentError, 'Threshold must be at least 2' if point_threshold < 2
88
87
  fail ArgumentError, 'Threshold must be less than the total number of points' if point_threshold > num_points
89
88
 
90
- polynomial = SecretSharing::Polynomial.random(point_threshold - 1,
91
- secret_int,
92
- prime)
89
+ polynomial = random(point_threshold - 1, secret_int, prime)
93
90
  polynomial.points(num_points, prime)
94
91
  rescue Prime::CannotFindLargeEnoughPrime
95
92
  raise ArgumentError, 'Secret is too long'
@@ -97,8 +94,8 @@ module SecretSharing
97
94
 
98
95
  # Modular lagrange interpolation
99
96
  def self.modular_lagrange_interpolation(points)
100
- y_values = Point.transpose(points)[1]
101
- prime = SecretSharing::Prime.large_enough_prime(y_values.max)
97
+ _, y_values = Point.transpose(points)
98
+ prime = Prime.large_enough_prime(y_values.max)
102
99
  points.reduce(0) do |f_x, point|
103
100
  numerator, denominator = lagrange_fraction(points, point, prime)
104
101
  lagrange_polynomial = numerator * mod_inverse(denominator, prime)
@@ -121,7 +118,7 @@ module SecretSharing
121
118
  # inverse modulo
122
119
  def self.mod_inverse(k, prime)
123
120
  k = k % prime
124
- r = egcd(prime, k.abs)[2]
121
+ r = egcd(prime, k.abs).last
125
122
  (prime + r) % prime
126
123
  end
127
124
 
@@ -1,4 +1,4 @@
1
1
  module SecretSharing
2
2
  # gem version
3
- VERSION = '0.0.3'
3
+ VERSION = '0.0.4'
4
4
  end
@@ -9,7 +9,7 @@ Gem::Specification.new do |spec|
9
9
  spec.authors = ['flower-pot']
10
10
  spec.email = ['fbranczyk@gmail.com']
11
11
  spec.summary = 'Ruby implementation of sharmir\'s secret sharing'
12
- spec.description = 'Divide, share and reconstruct secrets.'
12
+ spec.description = 'Split and reconstruct secrets using the shamir\'s secret sharing algorithm'
13
13
  spec.homepage = 'https://github.com/duse-io/secret_sharing_ruby'
14
14
  spec.license = 'MIT'
15
15
 
@@ -59,7 +59,13 @@ RSpec.describe SecretSharing::Polynomial do
59
59
  it 'randomly generates coefficients' do
60
60
  allow(SecureRandom).to receive(:random_number).and_return(3, 5, 2)
61
61
  polynomial = SecretSharing::Polynomial.random(3, 5, 10)
62
- expect(polynomial.coefficients).to eq [5, 3, 5 ,2]
62
+ expect(polynomial.coefficients).to eq [5, 4, 6 ,3]
63
+ end
64
+
65
+ it 'ensures, that a coefficient is >= 1' do
66
+ allow(SecureRandom).to receive(:random_number).and_return(0, 0, 0)
67
+ polynomial = SecretSharing::Polynomial.random(3, 5, 10)
68
+ expect(polynomial.coefficients).to eq [5, 1, 1 ,1]
63
69
  end
64
70
 
65
71
  it 'uses the intercept as the first coefficient' do
@@ -79,11 +85,36 @@ RSpec.describe SecretSharing::Polynomial do
79
85
  expect(points.length).to eq 4
80
86
  end
81
87
 
82
- it 'requires threshold points to reconstruct' do
83
- points = SecretSharing::Polynomial.points_from_secret(234234, 2, 3)
84
- points = points[0, 2]
85
- secret = SecretSharing::Polynomial.modular_lagrange_interpolation(points)
88
+ it 'generates points according to the threshold parameter' do
89
+ points = SecretSharing::Polynomial.points_from_secret(10, 2, 4)
90
+ required_points = points[0, 2]
91
+ result = SecretSharing::Polynomial.modular_lagrange_interpolation(required_points)
92
+ expect(result).to eq 10
93
+ end
94
+
95
+ it 'allows threshold and total number of points to be equal' do
96
+ points = SecretSharing::Polynomial.points_from_secret(10, 2, 2)
97
+ result = SecretSharing::Polynomial.modular_lagrange_interpolation(points)
98
+ expect(result).to eq 10
99
+ end
100
+
101
+ it 'requires threshold points or more to reconstruct' do
102
+ points = SecretSharing::Polynomial.points_from_secret(234234, 3, 4)
103
+ required_points = points[0, 3]
104
+ secret = SecretSharing::Polynomial.modular_lagrange_interpolation(required_points)
86
105
  expect(secret).to eq 234234
106
+
107
+ required_points = points[0, 4]
108
+ secret = SecretSharing::Polynomial.modular_lagrange_interpolation(required_points)
109
+ expect(secret).to eq 234234
110
+
111
+ required_points = points[0, 2]
112
+ secret = SecretSharing::Polynomial.modular_lagrange_interpolation(required_points)
113
+ expect(secret).not_to eq 234234
114
+
115
+ required_points = points[0, 1]
116
+ secret = SecretSharing::Polynomial.modular_lagrange_interpolation(required_points)
117
+ expect(secret).not_to eq 234234
87
118
  end
88
119
 
89
120
  it 'errors when the secret is to long' do
@@ -111,4 +142,12 @@ RSpec.describe SecretSharing::Polynomial do
111
142
  )
112
143
  end
113
144
  end
145
+
146
+ describe '.egcd' do
147
+ context 'a=240 b=46' do
148
+ it 'returns a quotient of 2, s=-9 and t=47' do
149
+ expect(SecretSharing::Polynomial.egcd(240, 46)).to eq [2, -9, 47]
150
+ end
151
+ end
152
+ end
114
153
  end
@@ -37,4 +37,14 @@ RSpec.describe SecretSharing do
37
37
  expect(SecretSharing.recover_secret(shares)).to eq 'secret'
38
38
  end
39
39
  end
40
+
41
+ context 'threshold 2 out of 11 shares' do
42
+ subject(:shares) { SecretSharing.split_secret('secret', 2, 11) }
43
+
44
+ it 'adds zero padding for shares 1 to 9' do
45
+ shares[0, 9].each_with_index do |share, index|
46
+ expect(share).to start_with "0#{index+1}"
47
+ end
48
+ end
49
+ end
40
50
  end
@@ -58,4 +58,7 @@ RSpec.configure do |config|
58
58
  config.around :each do |block|
59
59
  Timeout.timeout(1, &block)
60
60
  end
61
+
62
+ config.order = :random
63
+ Kernel.srand config.seed
61
64
  end
metadata CHANGED
@@ -1,16 +1,16 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: secret_sharing
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.3
4
+ version: 0.0.4
5
5
  platform: ruby
6
6
  authors:
7
7
  - flower-pot
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-04-23 00:00:00.000000000 Z
11
+ date: 2015-04-25 00:00:00.000000000 Z
12
12
  dependencies: []
13
- description: Divide, share and reconstruct secrets.
13
+ description: Split and reconstruct secrets using the shamir's secret sharing algorithm
14
14
  email:
15
15
  - fbranczyk@gmail.com
16
16
  executables: []