rsa 0.1.0 → 0.1.1

Sign up to get free protection for your applications and to get access to all the features.
data/README CHANGED
@@ -17,10 +17,31 @@ Features
17
17
  * Compatible with Ruby 1.9.1+ and JRuby 1.5.0+.
18
18
  * Compatible with older Ruby versions with the help of the [Backports][] gem.
19
19
 
20
+ Examples
21
+ --------
22
+
23
+ require 'rsa'
24
+
25
+ ### Generating a new RSA key pair
26
+
27
+ key_pair = RSA::KeyPair.generate(128)
28
+
29
+ ### Encrypting a plaintext message
30
+
31
+ ciphertext = key_pair.encrypt("Hello, world!")
32
+
33
+ ### Decrypting a ciphertext message
34
+
35
+ plaintext = key_pair.decrypt(ciphertext)
36
+
20
37
  Documentation
21
38
  -------------
22
39
 
23
- * <http://rsa.rubyforge.org/>
40
+ <http://rsa.rubyforge.org/>
41
+
42
+ * {RSA::KeyPair}
43
+ * {RSA::Key}
44
+ * {RSA::PKCS1}
24
45
 
25
46
  Dependencies
26
47
  ------------
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.1.0
1
+ 0.1.1
@@ -91,65 +91,140 @@ module RSA
91
91
  # Encrypts the given `plaintext` using the public key from this key
92
92
  # pair.
93
93
  #
94
- # @param [Integer, String, IO] plaintext
94
+ # @overload encrypt(plaintext, options = {})
95
+ # @param [Integer] plaintext
96
+ # @param [Hash{Symbol => Object}] options
97
+ # @return [Integer]
98
+ #
99
+ # @overload encrypt(plaintext, options = {})
100
+ # @param [String, IO, StringIO] plaintext
101
+ # @param [Hash{Symbol => Object}] options
102
+ # @return [String]
103
+ #
104
+ # @param [Object] plaintext
95
105
  # @param [Hash{Symbol => Object}] options
96
106
  # @option options [Symbol, #to_sym] :padding (nil)
97
- # @return [Integer]
98
107
  def encrypt(plaintext, options = {})
99
- PKCS1.rsaep(public_key, convert_to_integer(plaintext))
108
+ case plaintext
109
+ when Integer then encrypt_integer(plaintext, options)
110
+ when String then PKCS1.i2osp(encrypt_integer(PKCS1.os2ip(plaintext), options))
111
+ when StringIO, IO then PKCS1.i2osp(encrypt_integer(PKCS1.os2ip(plaintext.read), options))
112
+ else raise ArgumentError, plaintext.inspect # FIXME
113
+ end
100
114
  end
101
115
 
102
116
  ##
103
117
  # Decrypts the given `ciphertext` using the private key from this key
104
118
  # pair.
105
119
  #
106
- # @param [Integer, String, IO] ciphertext
120
+ # @overload decrypt(ciphertext, options = {})
121
+ # @param [Integer] ciphertext
122
+ # @param [Hash{Symbol => Object}] options
123
+ # @return [Integer]
124
+ #
125
+ # @overload decrypt(ciphertext, options = {})
126
+ # @param [String, IO, StringIO] ciphertext
127
+ # @param [Hash{Symbol => Object}] options
128
+ # @return [String]
129
+ #
130
+ # @param [Object] ciphertext
107
131
  # @param [Hash{Symbol => Object}] options
108
132
  # @option options [Symbol, #to_sym] :padding (nil)
109
- # @return [Integer]
110
133
  def decrypt(ciphertext, options = {})
111
- PKCS1.rsadp(private_key, convert_to_integer(ciphertext))
134
+ case ciphertext
135
+ when Integer then decrypt_integer(ciphertext, options)
136
+ when String then PKCS1.i2osp(decrypt_integer(PKCS1.os2ip(ciphertext), options))
137
+ when StringIO, IO then PKCS1.i2osp(decrypt_integer(PKCS1.os2ip(ciphertext.read), options))
138
+ else raise ArgumentError, ciphertext.inspect # FIXME
139
+ end
112
140
  end
113
141
 
114
142
  ##
115
143
  # Signs the given `plaintext` using the private key from this key pair.
116
144
  #
117
- # @param [Integer, String, IO] plaintext
145
+ # @overload sign(plaintext, options = {})
146
+ # @param [Integer] plaintext
147
+ # @param [Hash{Symbol => Object}] options
148
+ # @return [Integer]
149
+ #
150
+ # @overload sign(plaintext, options = {})
151
+ # @param [String, IO, StringIO] plaintext
152
+ # @param [Hash{Symbol => Object}] options
153
+ # @return [String]
154
+ #
155
+ # @param [Object] plaintext
118
156
  # @param [Hash{Symbol => Object}] options
119
157
  # @option options [Symbol, #to_sym] :padding (nil)
120
- # @return [Integer]
121
158
  def sign(plaintext, options = {})
122
- PKCS1.rsasp1(private_key, convert_to_integer(plaintext))
159
+ case plaintext
160
+ when Integer then sign_integer(plaintext, options)
161
+ when String then PKCS1.i2osp(sign_integer(PKCS1.os2ip(plaintext), options))
162
+ when StringIO, IO then PKCS1.i2osp(sign_integer(PKCS1.os2ip(plaintext.read), options))
163
+ else raise ArgumentError, plaintext.inspect # FIXME
164
+ end
123
165
  end
124
166
 
125
167
  ##
126
168
  # Verifies the given `signature` using the public key from this key
127
169
  # pair.
128
170
  #
129
- # @param [Integer, String, IO] signature
130
- # @param [Integer, String, IO] plaintext
171
+ # @overload verify(signature, plaintext, options = {})
172
+ # @param [Integer] signature
173
+ # @param [Integer] plaintext
174
+ # @param [Hash{Symbol => Object}] options
175
+ # @return [Boolean]
176
+ #
177
+ # @overload verify(signature, plaintext, options = {})
178
+ # @param [String, IO, StringIO] signature
179
+ # @param [String, IO, StringIO] plaintext
180
+ # @param [Hash{Symbol => Object}] options
181
+ # @return [Boolean]
182
+ #
183
+ # @param [Object] signature
184
+ # @param [Object] plaintext
131
185
  # @param [Hash{Symbol => Object}] options
132
186
  # @option options [Symbol, #to_sym] :padding (nil)
133
187
  # @return [Boolean]
134
188
  def verify(signature, plaintext, options = {})
135
- PKCS1.rsavp1(public_key, convert_to_integer(signature)).eql?(convert_to_integer(plaintext))
189
+ signature = case signature
190
+ when Integer then signature
191
+ when String then PKCS1.os2ip(signature)
192
+ when StringIO, IO then PKCS1.os2ip(signature.read)
193
+ else raise ArgumentError, signature.inspect # FIXME
194
+ end
195
+ plaintext = case plaintext
196
+ when Integer then plaintext
197
+ when String then PKCS1.os2ip(plaintext)
198
+ when StringIO, IO then PKCS1.os2ip(plaintext.read)
199
+ else raise ArgumentError, plaintext.inspect # FIXME
200
+ end
201
+ verify_integer(signature, plaintext, options)
136
202
  end
137
203
 
138
204
  protected
139
205
 
140
206
  ##
141
- # Converts the given `input` to an integer suitable for use with RSA
142
- # primitives.
143
- #
144
- # @param [Integer, String, IO] input
145
- # @return [Integer]
146
- def convert_to_integer(input)
147
- case input
148
- when Integer then input
149
- when String then PKCS1.os2ip(input)
150
- when IO, StringIO then PKCS1.os2ip(input.read)
151
- else raise ArgumentError, input.inspect # FIXME
152
- end
207
+ # @private
208
+ def encrypt_integer(plaintext, options = {})
209
+ PKCS1.rsaep(public_key, plaintext)
210
+ end
211
+
212
+ ##
213
+ # @private
214
+ def decrypt_integer(ciphertext, options = {})
215
+ PKCS1.rsadp(private_key, ciphertext)
216
+ end
217
+
218
+ ##
219
+ # @private
220
+ def sign_integer(plaintext, options = {})
221
+ PKCS1.rsasp1(private_key, plaintext)
222
+ end
223
+
224
+ ##
225
+ # @private
226
+ def verify_integer(signature, plaintext, options = {})
227
+ PKCS1.rsavp1(public_key, signature).eql?(plaintext)
153
228
  end
154
229
  end # class KeyPair
155
230
  end # module RSA
@@ -30,8 +30,8 @@ module RSA
30
30
  # This is equivalent to `base**exponent % modulus` but much faster for
31
31
  # large exponents.
32
32
  #
33
- # This is presently a semi-naive implementation. Don't rely on it for
34
- # very large exponents.
33
+ # The running time of the used algorithm, the right-to-left binary
34
+ # method, is O(log _exponent_).
35
35
  #
36
36
  # @example
37
37
  # RSA::Math.modpow(5, 3, 13) #=> 8
@@ -43,9 +43,13 @@ module RSA
43
43
  # @return [Integer]
44
44
  # @see http://en.wikipedia.org/wiki/Modular_exponentiation
45
45
  def self.modpow(base, exponent, modulus)
46
- 1.upto(exponent).inject(1) do |c, e|
47
- (c * base) % modulus
46
+ result = 1
47
+ while exponent > 0
48
+ result = (base * result) % modulus unless (exponent & 1).zero?
49
+ base = (base * base) % modulus
50
+ exponent >>= 1
48
51
  end
52
+ result
49
53
  end
50
54
 
51
55
  ##
@@ -2,7 +2,7 @@ module RSA
2
2
  module VERSION
3
3
  MAJOR = 0
4
4
  MINOR = 1
5
- TINY = 0
5
+ TINY = 1
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
- - 0
9
- version: 0.1.0
8
+ - 1
9
+ version: 0.1.1
10
10
  platform: ruby
11
11
  authors:
12
12
  - Arto Bendiken