secret_sharing 0.0.3 → 0.0.4

Sign up to get free protection for your applications and to get access to all the features.
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: []