rsa 0.1.2 → 0.1.3

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.
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