rsa 0.1.2 → 0.1.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (5) hide show
  1. data/VERSION +1 -1
  2. data/lib/rsa.rb +2 -1
  3. data/lib/rsa/math.rb +102 -23
  4. data/lib/rsa/version.rb +1 -1
  5. metadata +3 -3
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.1.2
1
+ 0.1.3
data/lib/rsa.rb CHANGED
@@ -1,4 +1,5 @@
1
- require 'stringio' unless defined?(StringIO)
1
+ require 'bigdecimal' unless defined?(BigDecimal)
2
+ require 'stringio' unless defined?(StringIO)
2
3
 
3
4
  if RUBY_VERSION < '1.9.1'
4
5
  # @see http://rubygems.org/gems/backports
@@ -6,6 +6,62 @@ module RSA
6
6
 
7
7
  class ArithmeticError < ArgumentError; end
8
8
 
9
+ ##
10
+ # Yields an infinite pseudo-prime number sequence.
11
+ #
12
+ # This is a pseudo-prime generator that simply yields the initial values
13
+ # 2 and 3, followed by all positive integers that are not divisible by 2
14
+ # or 3.
15
+ #
16
+ # It works identically to `Prime::Generator23`, the Ruby 1.9 standard
17
+ # library's default pseudo-prime generator implementation.
18
+ #
19
+ # @example
20
+ # RSA::Math.primes.take(5) #=> [2, 3, 5, 7, 11]
21
+ #
22
+ # @yield [p] each pseudo-prime number
23
+ # @yieldparam [Integer] p a pseudo-prime number
24
+ # @return [Enumerator] yielding pseudo-primes
25
+ # @see http://ruby-doc.org/core-1.9/classes/Prime.html
26
+ def self.primes(&block)
27
+ if block_given?
28
+ yield 2; yield 3; yield 5
29
+ prime, step = 5, 4
30
+ loop { yield prime += (step = 6 - step) }
31
+ end
32
+ enum_for(:primes)
33
+ end
34
+
35
+ ##
36
+ # Yields the prime factorization of the nonzero integer `n`.
37
+ #
38
+ # @example
39
+ # RSA::Math.factorize(12).to_a #=> [[2, 2], [3, 1]]
40
+ #
41
+ # @param [Integer] n a nonzero integer
42
+ # @yield [p, e] each prime factor
43
+ # @yieldparam [Integer] p the prime factor base
44
+ # @yieldparam [Integer] e the prime factor exponent
45
+ # @return [Enumerator]
46
+ # @raise [ZeroDivisionError] if `n` is zero
47
+ # @see http://ruby-doc.org/core-1.9/classes/Prime.html
48
+ def self.factorize(n, &block)
49
+ raise ZeroDivisionError if n.zero?
50
+ if block_given?
51
+ n = n.abs if n < 0
52
+ primes.find do |p|
53
+ e = 0
54
+ while (q, r = n.divmod(p); r.zero?)
55
+ n, e = q, e + 1
56
+ end
57
+ yield p, e unless e.zero?
58
+ n <= p
59
+ end
60
+ yield n, 1 if n > 1
61
+ end
62
+ enum_for(:factorize, n)
63
+ end
64
+
9
65
  ##
10
66
  # Performs a primality test on the integer `n`, returning `true` if it
11
67
  # is a prime.
@@ -13,16 +69,19 @@ module RSA
13
69
  # @example
14
70
  # 1.upto(10).select { |n| RSA::Math.prime?(n) } #=> [2, 3, 5, 7]
15
71
  #
16
- # @param [Integer] n
72
+ # @param [Integer] n an integer
17
73
  # @return [Boolean] `true` if `n` is a prime number, `false` otherwise
18
74
  # @see http://en.wikipedia.org/wiki/Primality_test
19
75
  # @see http://ruby-doc.org/core-1.9/classes/Prime.html
20
76
  def self.prime?(n)
21
- if n.respond_to?(:prime?)
22
- n.prime?
23
- else
24
- require 'prime' unless defined?(Prime) # Ruby 1.9+ only
25
- Prime.prime?(n)
77
+ case
78
+ when n < 0 then prime?(n.abs)
79
+ when n < 2 then false
80
+ else primes do |p|
81
+ q, r = n.divmod(p)
82
+ return true if q < p
83
+ return false if r.zero?
84
+ end
26
85
  end
27
86
  end
28
87
 
@@ -130,10 +189,10 @@ module RSA
130
189
  # RSA::Math.modpow(5, 3, 13) #=> 8
131
190
  # RSA::Math.modpow(4, 13, 497) #=> 445
132
191
  #
133
- # @param [Integer] base
134
- # @param [Integer] exponent
135
- # @param [Integer] modulus
136
- # @return [Integer]
192
+ # @param [Integer] base the base
193
+ # @param [Integer] exponent the exponent
194
+ # @param [Integer] modulus the modulus
195
+ # @return [Integer] the result
137
196
  # @see http://en.wikipedia.org/wiki/Modular_exponentiation
138
197
  def self.modpow(base, exponent, modulus)
139
198
  result = 1
@@ -145,28 +204,38 @@ module RSA
145
204
  result
146
205
  end
147
206
 
207
+ ONE = BigDecimal('1')
208
+
148
209
  ##
149
210
  # Returns the Euler totient for the positive integer `n`.
150
211
  #
151
- # This is presently a very naive implementation. Don't rely on it for
152
- # anything but very small values of `n`.
153
- #
154
212
  # @example
155
213
  # (1..5).map { |n| RSA::Math.phi(n) } #=> [1, 1, 2, 2, 4]
156
214
  #
157
- # @param [Integer] n
158
- # @return [Integer]
215
+ # @param [Integer] n a positive integer, or zero
216
+ # @return [Integer] the Euler totient of `n`
217
+ # @raise [ArgumentError] if `n` < 0
159
218
  # @see http://en.wikipedia.org/wiki/Euler's_totient_function
160
219
  # @see http://mathworld.wolfram.com/TotientFunction.html
161
220
  def self.phi(n)
162
- 1 + (2...n).count { |i| coprime?(n, i) }
221
+ case
222
+ when n < 0 then raise ArgumentError, "expected a positive integer, but got #{n}"
223
+ when n < 2 then 1 # by convention
224
+ when prime?(n) then n - 1
225
+ else factorize(n).inject(n) { |product, (p, e)| product * (ONE - (ONE / BigDecimal(p.to_s))) }.round.to_i
226
+ end
163
227
  end
164
228
 
165
229
  ##
166
230
  # Returns the binary logarithm of `n`.
167
231
  #
168
- # @param [Integer] n
169
- # @return [Float]
232
+ # @example
233
+ # RSA::Math.log2(16) #=> 4.0
234
+ # RSA::Math.log2(1024) #=> 10.0
235
+ #
236
+ # @param [Integer] n a positive integer
237
+ # @return [Float] the logarithm
238
+ # @raise [Errno::EDOM] if `n` < 1
170
239
  # @see http://en.wikipedia.org/wiki/Binary_logarithm
171
240
  def self.log2(n)
172
241
  ::Math.log2(n)
@@ -175,8 +244,13 @@ module RSA
175
244
  ##
176
245
  # Returns the base-256 logarithm of `n`.
177
246
  #
178
- # @param [Integer] n
179
- # @return [Float]
247
+ # @example
248
+ # RSA::Math.log256(16) #=> 0.5
249
+ # RSA::Math.log256(1024) #=> 1.25
250
+ #
251
+ # @param [Integer] n a positive integer
252
+ # @return [Float] the logarithm
253
+ # @raise [Errno::EDOM] if `n` < 1
180
254
  # @see http://en.wikipedia.org/wiki/Logarithm
181
255
  def self.log256(n)
182
256
  ::Math.log(n, 256)
@@ -186,9 +260,14 @@ module RSA
186
260
  # Returns the natural logarithm of `n`. If the optional argument `b` is
187
261
  # given, it will be used as the base of the logarithm.
188
262
  #
189
- # @param [Integer] n
190
- # @param [Integer] b
191
- # @return [Float]
263
+ # @example
264
+ # RSA::Math.log(16, 2) #=> 4.0
265
+ # RSA::Math.log(16, 256) #=> 0.5
266
+ #
267
+ # @param [Integer] n a positive integer
268
+ # @param [Integer] b a positive integer >= 2, or `nil`
269
+ # @return [Float] the logarithm
270
+ # @raise [Errno::EDOM] if `n` < 1, or if `b` < 2
192
271
  # @see http://en.wikipedia.org/wiki/Natural_logarithm
193
272
  def self.log(n, b = nil)
194
273
  b ? ::Math.log(n, b) : ::Math.log(n)
@@ -2,7 +2,7 @@ module RSA
2
2
  module VERSION
3
3
  MAJOR = 0
4
4
  MINOR = 1
5
- TINY = 2
5
+ TINY = 3
6
6
  EXTRA = nil
7
7
 
8
8
  STRING = [MAJOR, MINOR, TINY, EXTRA].compact.join('.')
metadata CHANGED
@@ -5,8 +5,8 @@ version: !ruby/object:Gem::Version
5
5
  segments:
6
6
  - 0
7
7
  - 1
8
- - 2
9
- version: 0.1.2
8
+ - 3
9
+ version: 0.1.3
10
10
  platform: ruby
11
11
  authors:
12
12
  - Arto Bendiken
@@ -14,7 +14,7 @@ autorequire:
14
14
  bindir: bin
15
15
  cert_chain: []
16
16
 
17
- date: 2010-09-07 00:00:00 +02:00
17
+ date: 2010-09-10 00:00:00 +02:00
18
18
  default_executable:
19
19
  dependencies:
20
20
  - !ruby/object:Gem::Dependency