rsa 0.1.1 → 0.1.2

Sign up to get free protection for your applications and to get access to all the features.
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.1.1
1
+ 0.1.2
@@ -87,6 +87,17 @@ module RSA
87
87
  end
88
88
  alias_method :n, :modulus
89
89
 
90
+ ##
91
+ # Returns a hash table representation of this key pair.
92
+ #
93
+ # @example
94
+ # key_pair.to_hash #=> {:n => ..., :d => ..., :e => ...}
95
+ #
96
+ # @return [Hash]
97
+ def to_hash
98
+ {:n => modulus, :d => private_key ? private_key.exponent : nil, :e => public_key ? public_key.exponent : nil}
99
+ end
100
+
90
101
  ##
91
102
  # Encrypts the given `plaintext` using the public key from this key
92
103
  # pair.
@@ -4,6 +4,8 @@ module RSA
4
4
  module Math
5
5
  extend ::Math
6
6
 
7
+ class ArithmeticError < ArgumentError; end
8
+
7
9
  ##
8
10
  # Performs a primality test on the integer `n`, returning `true` if it
9
11
  # is a prime.
@@ -12,7 +14,7 @@ module RSA
12
14
  # 1.upto(10).select { |n| RSA::Math.prime?(n) } #=> [2, 3, 5, 7]
13
15
  #
14
16
  # @param [Integer] n
15
- # @return [Boolean]
17
+ # @return [Boolean] `true` if `n` is a prime number, `false` otherwise
16
18
  # @see http://en.wikipedia.org/wiki/Primality_test
17
19
  # @see http://ruby-doc.org/core-1.9/classes/Prime.html
18
20
  def self.prime?(n)
@@ -24,6 +26,97 @@ module RSA
24
26
  end
25
27
  end
26
28
 
29
+ ##
30
+ # Returns `true` if the integer `a` is coprime (relatively prime) to
31
+ # integer `b`.
32
+ #
33
+ # @example
34
+ # RSA::Math.coprime?(6, 35) #=> true
35
+ # RSA::Math.coprime?(6, 27) #=> false
36
+ #
37
+ # @param [Integer] a an integer
38
+ # @param [Integer] b an integer
39
+ # @return [Boolean] `true` if `a` and `b` are coprime, `false` otherwise
40
+ # @see http://en.wikipedia.org/wiki/Coprime
41
+ # @see http://mathworld.wolfram.com/RelativelyPrime.html
42
+ def self.coprime?(a, b)
43
+ gcd(a, b).equal?(1)
44
+ end
45
+
46
+ ##
47
+ # Returns the greatest common divisor (GCD) of the two integers `a` and
48
+ # `b`. The GCD is the largest positive integer that divides both numbers
49
+ # without a remainder.
50
+ #
51
+ # @example
52
+ # RSA::Math.gcd(3, 5) #=> 1
53
+ # RSA::Math.gcd(8, 12) #=> 4
54
+ # RSA::Math.gcd(12, 60) #=> 12
55
+ # RSA::Math.gcd(90, 12) #=> 6
56
+ #
57
+ # @param [Integer] a an integer
58
+ # @param [Integer] b an integer
59
+ # @return [Integer] the greatest common divisor of `a` and `b`
60
+ # @see http://en.wikipedia.org/wiki/Greatest_common_divisor
61
+ # @see http://mathworld.wolfram.com/GreatestCommonDivisor.html
62
+ def self.gcd(a, b)
63
+ a.gcd(b)
64
+ end
65
+
66
+ ##
67
+ # Returns the Bezout coefficients of the two nonzero integers `a` and
68
+ # `b` using the extended Euclidean algorithm.
69
+ #
70
+ # @example
71
+ # RSA::Math.egcd(120, 23) #=> [-9, 47]
72
+ # RSA::Math.egcd(421, 111) #=> [-29, 110]
73
+ # RSA::Math.egcd(93, 219) #=> [33, -14]
74
+ # RSA::Math.egcd(4864, 3458) #=> [32, -45]
75
+ #
76
+ # @param [Integer] a a nonzero integer
77
+ # @param [Integer] b a nonzero integer
78
+ # @return [Array(Integer, Integer)] the Bezout coefficients `x` and `y`
79
+ # @raise [ZeroDivisionError] if `a` or `b` is zero
80
+ # @see http://en.wikipedia.org/wiki/B%C3%A9zout's_identity
81
+ # @see http://en.wikipedia.org/wiki/Extended_Euclidean_algorithm
82
+ # @see http://mathworld.wolfram.com/ExtendedGreatestCommonDivisor.html
83
+ def self.egcd(a, b)
84
+ if a.modulo(b).zero?
85
+ [0, 1]
86
+ else
87
+ x, y = egcd(b, a.modulo(b))
88
+ [y, x - y * a.div(b)]
89
+ end
90
+ end
91
+
92
+ ##
93
+ # Returns the modular multiplicative inverse of the integer `b` modulo
94
+ # `m`, where `b <= m`.
95
+ #
96
+ # The running time of the used algorithm, the extended Euclidean
97
+ # algorithm, is on the order of O(log2 _m_).
98
+ #
99
+ # @example
100
+ # RSA::Math.modinv(3, 11) #=> 4
101
+ # RSA::Math.modinv(6, 35) #=> 6
102
+ # RSA::Math.modinv(-6, 35) #=> 29
103
+ # RSA::Math.modinv(6, 36) #=> ArithmeticError
104
+ #
105
+ # @param [Integer] b
106
+ # @param [Integer] m the modulus
107
+ # @return [Integer] the modular multiplicative inverse
108
+ # @raise [ArithmeticError] if `m` <= 0, or if `b` not coprime to `m`
109
+ # @see http://en.wikipedia.org/wiki/Modular_multiplicative_inverse
110
+ # @see http://mathworld.wolfram.com/ModularInverse.html
111
+ def self.modinv(b, m)
112
+ if m > 0 && coprime?(b, m)
113
+ egcd(b, m).first.modulo(m)
114
+ else
115
+ raise ArithmeticError, "modulus #{m} is not positive" if m <= 0
116
+ raise ArithmeticError, "#{b} is not coprime to #{m}"
117
+ end
118
+ end
119
+
27
120
  ##
28
121
  # Performs modular exponentiation in a memory-efficient manner.
29
122
  #
@@ -31,7 +124,7 @@ module RSA
31
124
  # large exponents.
32
125
  #
33
126
  # The running time of the used algorithm, the right-to-left binary
34
- # method, is O(log _exponent_).
127
+ # method, is on the order of O(log _exponent_).
35
128
  #
36
129
  # @example
37
130
  # RSA::Math.modpow(5, 3, 13) #=> 8
@@ -66,7 +159,7 @@ module RSA
66
159
  # @see http://en.wikipedia.org/wiki/Euler's_totient_function
67
160
  # @see http://mathworld.wolfram.com/TotientFunction.html
68
161
  def self.phi(n)
69
- 1 + (2...n).count { |i| i.gcd(n).eql?(1) }
162
+ 1 + (2...n).count { |i| coprime?(n, i) }
70
163
  end
71
164
 
72
165
  ##
@@ -2,7 +2,7 @@ module RSA
2
2
  module VERSION
3
3
  MAJOR = 0
4
4
  MINOR = 1
5
- TINY = 1
5
+ TINY = 2
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
- - 1
9
- version: 0.1.1
8
+ - 2
9
+ version: 0.1.2
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-06 00:00:00 +02:00
17
+ date: 2010-09-07 00:00:00 +02:00
18
18
  default_executable:
19
19
  dependencies:
20
20
  - !ruby/object:Gem::Dependency