Class: Ccrypto::Ruby::ShamirSharing

Inherits:
Object
  • Object
show all
Defined in:
lib/ccrypto/ruby/engines/secret_sharing_engine.rb

Overview

This code is borrowed from PolyPasswordHasher-Ruby project at github.com/PolyPasswordHasher/PolyPasswordHasher-Ruby

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(threshold, secretdata = nil) ⇒ ShamirSharing

Returns a new instance of ShamirSharing.



57
58
59
60
61
62
63
64
65
66
67
68
# File 'lib/ccrypto/ruby/engines/secret_sharing_engine.rb', line 57

def initialize(threshold, secretdata=nil)
  @threshold = threshold
  @secretdata = secretdata
  @_coefficients = []

  if secretdata
    secretdata.each_char do |secretbyte|
      thesecoefficients = secretbyte+OpenSSL::Random.random_bytes(@threshold-1)
      @_coefficients << thesecoefficients
    end
  end
end

Instance Attribute Details

#_coefficientsObject (readonly)

Returns the value of attribute _coefficients.



54
55
56
# File 'lib/ccrypto/ruby/engines/secret_sharing_engine.rb', line 54

def _coefficients
  @_coefficients
end

#secretdataObject (readonly)

Returns the value of attribute secretdata.



55
56
57
# File 'lib/ccrypto/ruby/engines/secret_sharing_engine.rb', line 55

def secretdata
  @secretdata
end

Instance Method Details

#compute_share(x) ⇒ Object



83
84
85
86
87
88
89
90
91
92
93
94
95
96
# File 'lib/ccrypto/ruby/engines/secret_sharing_engine.rb', line 83

def compute_share(x)
  raise "x should be integer" unless x.class == Fixnum
  raise "x must be between 1 and 255" if x <= 0 || x  >256
  raise "@_coefficient must be initialized" if @_coefficients.empty?

  sharebytes = []

  @_coefficients.each do |thiscoefficient|
    thisshare = _f(x,thiscoefficient)
    sharebytes << thisshare
  end

  return x, sharebytes
end

#is_valid_share?(share) ⇒ Boolean

Returns:

  • (Boolean)


70
71
72
73
74
75
76
77
78
79
80
81
# File 'lib/ccrypto/ruby/engines/secret_sharing_engine.rb', line 70

def is_valid_share?(share)
  raise "Share is of incorrect length: #{share.size}" if share.size !=2
  raise "Must initialize coefficient before checking is_valid_share?" unless @_coefficients
  raise "Must initialize coefficient before checking is_valid_share?" if @_coefficients.size != share[1].size

  x  = share[0]
  fx = share[1]

  correctshare = compute_share(x)

  correctshare == share
end

#recover_secretdata(shares) ⇒ Object



98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
# File 'lib/ccrypto/ruby/engines/secret_sharing_engine.rb', line 98

def recover_secretdata(shares)
  newshares = []

  shares.each do |share|
    newshares << share unless newshares.include?(share)
  end

  shares = newshares

  if @threshold > shares.size
    raise "Threshold: #{@threshold} is smaller than the number of uniquie shares: #{shares.size}"
  end

  if @secretdata
    raise "Recovoring secretdata when some is stored. Use check_share instead"
  end

  xs = []

  shares.each do |share|
    if xs.include?(share[0])
      raise "Different shares with the same first byte: #{share[0]}"
    end

    if share[1].size != shares[0][1].size
      raise "Shares have different lengths!"
    end

    xs << share[0]
  end

  mycoefficients = []
  mysecretdata = ''

  shares[0][1].size.times.each do |byte_to_use|
    fxs = []
    shares.each do |share|
      fxs << share[1][byte_to_use]
    end

    resulting_poly = _full_lagrange(xs,fxs)

    if resulting_poly[0..@threshold-1] + [0]*(shares.size - @threshold) != resulting_poly
      raise "Share do not match. Cannot decode"
    end

    mycoefficients << resulting_poly.map{|p| p.chr}.join

    mysecretdata += resulting_poly[0].chr
  end

  @_coefficients = mycoefficients
  @secretdata = mysecretdata
end