Skip to content

Commit 71c8040

Browse files
committed
pkey/rsa: port RSA#{private,public}_{encrypt,decrypt} to the EVP API
Implement these methods using the new OpenSSL::PKey::PKey#{encrypt,sign} family. The definitions are now in lib/openssl/pkey.rb. Also, recommend using those generic methods in the documentation.
1 parent 641bafa commit 71c8040

File tree

2 files changed

+106
-141
lines changed

2 files changed

+106
-141
lines changed

ext/openssl/ossl_pkey_rsa.c

-141
Original file line numberDiff line numberDiff line change
@@ -229,138 +229,6 @@ ossl_rsa_to_der(VALUE self)
229229
return ossl_pkey_export_spki(self, 1);
230230
}
231231

232-
/*
233-
* call-seq:
234-
* rsa.public_encrypt(string) => String
235-
* rsa.public_encrypt(string, padding) => String
236-
*
237-
* Encrypt _string_ with the public key. _padding_ defaults to PKCS1_PADDING.
238-
* The encrypted string output can be decrypted using #private_decrypt.
239-
*/
240-
static VALUE
241-
ossl_rsa_public_encrypt(int argc, VALUE *argv, VALUE self)
242-
{
243-
RSA *rsa;
244-
const BIGNUM *rsa_n;
245-
int buf_len, pad;
246-
VALUE str, buffer, padding;
247-
248-
GetRSA(self, rsa);
249-
RSA_get0_key(rsa, &rsa_n, NULL, NULL);
250-
if (!rsa_n)
251-
ossl_raise(eRSAError, "incomplete RSA");
252-
rb_scan_args(argc, argv, "11", &buffer, &padding);
253-
pad = (argc == 1) ? RSA_PKCS1_PADDING : NUM2INT(padding);
254-
StringValue(buffer);
255-
str = rb_str_new(0, RSA_size(rsa));
256-
buf_len = RSA_public_encrypt(RSTRING_LENINT(buffer), (unsigned char *)RSTRING_PTR(buffer),
257-
(unsigned char *)RSTRING_PTR(str), rsa, pad);
258-
if (buf_len < 0) ossl_raise(eRSAError, NULL);
259-
rb_str_set_len(str, buf_len);
260-
261-
return str;
262-
}
263-
264-
/*
265-
* call-seq:
266-
* rsa.public_decrypt(string) => String
267-
* rsa.public_decrypt(string, padding) => String
268-
*
269-
* Decrypt _string_, which has been encrypted with the private key, with the
270-
* public key. _padding_ defaults to PKCS1_PADDING.
271-
*/
272-
static VALUE
273-
ossl_rsa_public_decrypt(int argc, VALUE *argv, VALUE self)
274-
{
275-
RSA *rsa;
276-
const BIGNUM *rsa_n;
277-
int buf_len, pad;
278-
VALUE str, buffer, padding;
279-
280-
GetRSA(self, rsa);
281-
RSA_get0_key(rsa, &rsa_n, NULL, NULL);
282-
if (!rsa_n)
283-
ossl_raise(eRSAError, "incomplete RSA");
284-
rb_scan_args(argc, argv, "11", &buffer, &padding);
285-
pad = (argc == 1) ? RSA_PKCS1_PADDING : NUM2INT(padding);
286-
StringValue(buffer);
287-
str = rb_str_new(0, RSA_size(rsa));
288-
buf_len = RSA_public_decrypt(RSTRING_LENINT(buffer), (unsigned char *)RSTRING_PTR(buffer),
289-
(unsigned char *)RSTRING_PTR(str), rsa, pad);
290-
if (buf_len < 0) ossl_raise(eRSAError, NULL);
291-
rb_str_set_len(str, buf_len);
292-
293-
return str;
294-
}
295-
296-
/*
297-
* call-seq:
298-
* rsa.private_encrypt(string) => String
299-
* rsa.private_encrypt(string, padding) => String
300-
*
301-
* Encrypt _string_ with the private key. _padding_ defaults to PKCS1_PADDING.
302-
* The encrypted string output can be decrypted using #public_decrypt.
303-
*/
304-
static VALUE
305-
ossl_rsa_private_encrypt(int argc, VALUE *argv, VALUE self)
306-
{
307-
RSA *rsa;
308-
const BIGNUM *rsa_n;
309-
int buf_len, pad;
310-
VALUE str, buffer, padding;
311-
312-
GetRSA(self, rsa);
313-
RSA_get0_key(rsa, &rsa_n, NULL, NULL);
314-
if (!rsa_n)
315-
ossl_raise(eRSAError, "incomplete RSA");
316-
if (!RSA_PRIVATE(self, rsa))
317-
ossl_raise(eRSAError, "private key needed.");
318-
rb_scan_args(argc, argv, "11", &buffer, &padding);
319-
pad = (argc == 1) ? RSA_PKCS1_PADDING : NUM2INT(padding);
320-
StringValue(buffer);
321-
str = rb_str_new(0, RSA_size(rsa));
322-
buf_len = RSA_private_encrypt(RSTRING_LENINT(buffer), (unsigned char *)RSTRING_PTR(buffer),
323-
(unsigned char *)RSTRING_PTR(str), rsa, pad);
324-
if (buf_len < 0) ossl_raise(eRSAError, NULL);
325-
rb_str_set_len(str, buf_len);
326-
327-
return str;
328-
}
329-
330-
/*
331-
* call-seq:
332-
* rsa.private_decrypt(string) => String
333-
* rsa.private_decrypt(string, padding) => String
334-
*
335-
* Decrypt _string_, which has been encrypted with the public key, with the
336-
* private key. _padding_ defaults to PKCS1_PADDING.
337-
*/
338-
static VALUE
339-
ossl_rsa_private_decrypt(int argc, VALUE *argv, VALUE self)
340-
{
341-
RSA *rsa;
342-
const BIGNUM *rsa_n;
343-
int buf_len, pad;
344-
VALUE str, buffer, padding;
345-
346-
GetRSA(self, rsa);
347-
RSA_get0_key(rsa, &rsa_n, NULL, NULL);
348-
if (!rsa_n)
349-
ossl_raise(eRSAError, "incomplete RSA");
350-
if (!RSA_PRIVATE(self, rsa))
351-
ossl_raise(eRSAError, "private key needed.");
352-
rb_scan_args(argc, argv, "11", &buffer, &padding);
353-
pad = (argc == 1) ? RSA_PKCS1_PADDING : NUM2INT(padding);
354-
StringValue(buffer);
355-
str = rb_str_new(0, RSA_size(rsa));
356-
buf_len = RSA_private_decrypt(RSTRING_LENINT(buffer), (unsigned char *)RSTRING_PTR(buffer),
357-
(unsigned char *)RSTRING_PTR(str), rsa, pad);
358-
if (buf_len < 0) ossl_raise(eRSAError, NULL);
359-
rb_str_set_len(str, buf_len);
360-
361-
return str;
362-
}
363-
364232
/*
365233
* call-seq:
366234
* rsa.sign_pss(digest, data, salt_length:, mgf1_hash:) -> String
@@ -657,10 +525,6 @@ Init_ossl_rsa(void)
657525
rb_define_alias(cRSA, "to_pem", "export");
658526
rb_define_alias(cRSA, "to_s", "export");
659527
rb_define_method(cRSA, "to_der", ossl_rsa_to_der, 0);
660-
rb_define_method(cRSA, "public_encrypt", ossl_rsa_public_encrypt, -1);
661-
rb_define_method(cRSA, "public_decrypt", ossl_rsa_public_decrypt, -1);
662-
rb_define_method(cRSA, "private_encrypt", ossl_rsa_private_encrypt, -1);
663-
rb_define_method(cRSA, "private_decrypt", ossl_rsa_private_decrypt, -1);
664528
rb_define_method(cRSA, "sign_pss", ossl_rsa_sign_pss, -1);
665529
rb_define_method(cRSA, "verify_pss", ossl_rsa_verify_pss, -1);
666530

@@ -678,11 +542,6 @@ Init_ossl_rsa(void)
678542

679543
rb_define_method(cRSA, "params", ossl_rsa_get_params, 0);
680544

681-
DefRSAConst(PKCS1_PADDING);
682-
DefRSAConst(SSLV23_PADDING);
683-
DefRSAConst(NO_PADDING);
684-
DefRSAConst(PKCS1_OAEP_PADDING);
685-
686545
/*
687546
* TODO: Test it
688547
rb_define_method(cRSA, "blinding_on!", ossl_rsa_blinding_on, 0);

lib/openssl/pkey.rb

+106
Original file line numberDiff line numberDiff line change
@@ -243,5 +243,111 @@ def new(*args, &blk) # :nodoc:
243243
end
244244
end
245245
end
246+
247+
# :call-seq:
248+
# rsa.private_encrypt(string) -> String
249+
# rsa.private_encrypt(string, padding) -> String
250+
#
251+
# Encrypt +string+ with the private key. +padding+ defaults to
252+
# PKCS1_PADDING. The encrypted string output can be decrypted using
253+
# #public_decrypt.
254+
#
255+
# <b>Deprecated in version 3.0</b>.
256+
# Consider using PKey::PKey#sign_raw and PKey::PKey#verify_raw, and
257+
# PKey::PKey#verify_recover instead.
258+
def private_encrypt(string, padding = PKCS1_PADDING)
259+
n or raise OpenSSL::PKey::RSAError, "incomplete RSA"
260+
private? or raise OpenSSL::PKey::RSAError, "private key needed."
261+
begin
262+
sign_raw(nil, string, {
263+
"rsa_padding_mode" => translate_padding_mode(padding),
264+
})
265+
rescue OpenSSL::PKey::PKeyError
266+
raise OpenSSL::PKey::RSAError, $!.message
267+
end
268+
end
269+
270+
# :call-seq:
271+
# rsa.public_decrypt(string) -> String
272+
# rsa.public_decrypt(string, padding) -> String
273+
#
274+
# Decrypt +string+, which has been encrypted with the private key, with the
275+
# public key. +padding+ defaults to PKCS1_PADDING.
276+
#
277+
# <b>Deprecated in version 3.0</b>.
278+
# Consider using PKey::PKey#sign_raw and PKey::PKey#verify_raw, and
279+
# PKey::PKey#verify_recover instead.
280+
def public_decrypt(string, padding = PKCS1_PADDING)
281+
n or raise OpenSSL::PKey::RSAError, "incomplete RSA"
282+
begin
283+
verify_recover(nil, string, {
284+
"rsa_padding_mode" => translate_padding_mode(padding),
285+
})
286+
rescue OpenSSL::PKey::PKeyError
287+
raise OpenSSL::PKey::RSAError, $!.message
288+
end
289+
end
290+
291+
# :call-seq:
292+
# rsa.public_encrypt(string) -> String
293+
# rsa.public_encrypt(string, padding) -> String
294+
#
295+
# Encrypt +string+ with the public key. +padding+ defaults to
296+
# PKCS1_PADDING. The encrypted string output can be decrypted using
297+
# #private_decrypt.
298+
#
299+
# <b>Deprecated in version 3.0</b>.
300+
# Consider using PKey::PKey#encrypt and PKey::PKey#decrypt instead.
301+
def public_encrypt(data, padding = PKCS1_PADDING)
302+
n or raise OpenSSL::PKey::RSAError, "incomplete RSA"
303+
begin
304+
encrypt(data, {
305+
"rsa_padding_mode" => translate_padding_mode(padding),
306+
})
307+
rescue OpenSSL::PKey::PKeyError
308+
raise OpenSSL::PKey::RSAError, $!.message
309+
end
310+
end
311+
312+
# :call-seq:
313+
# rsa.private_decrypt(string) -> String
314+
# rsa.private_decrypt(string, padding) -> String
315+
#
316+
# Decrypt +string+, which has been encrypted with the public key, with the
317+
# private key. +padding+ defaults to PKCS1_PADDING.
318+
#
319+
# <b>Deprecated in version 3.0</b>.
320+
# Consider using PKey::PKey#encrypt and PKey::PKey#decrypt instead.
321+
def private_decrypt(data, padding = PKCS1_PADDING)
322+
n or raise OpenSSL::PKey::RSAError, "incomplete RSA"
323+
private? or raise OpenSSL::PKey::RSAError, "private key needed."
324+
begin
325+
decrypt(data, {
326+
"rsa_padding_mode" => translate_padding_mode(padding),
327+
})
328+
rescue OpenSSL::PKey::PKeyError
329+
raise OpenSSL::PKey::RSAError, $!.message
330+
end
331+
end
332+
333+
PKCS1_PADDING = 1
334+
SSLV23_PADDING = 2
335+
NO_PADDING = 3
336+
PKCS1_OAEP_PADDING = 4
337+
338+
private def translate_padding_mode(num)
339+
case num
340+
when PKCS1_PADDING
341+
"pkcs1"
342+
when SSLV23_PADDING
343+
"sslv23"
344+
when NO_PADDING
345+
"none"
346+
when PKCS1_OAEP_PADDING
347+
"oaep"
348+
else
349+
raise OpenSSL::PKey::PKeyError, "unsupported padding mode"
350+
end
351+
end
246352
end
247353
end

0 commit comments

Comments
 (0)