Skip to content

Commit f653d59

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 122ecba commit f653d59

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
@@ -328,138 +328,6 @@ ossl_rsa_to_der(VALUE self)
328328
return ossl_pkey_export_spki(self, 1);
329329
}
330330

331-
/*
332-
* call-seq:
333-
* rsa.public_encrypt(string) => String
334-
* rsa.public_encrypt(string, padding) => String
335-
*
336-
* Encrypt _string_ with the public key. _padding_ defaults to PKCS1_PADDING.
337-
* The encrypted string output can be decrypted using #private_decrypt.
338-
*/
339-
static VALUE
340-
ossl_rsa_public_encrypt(int argc, VALUE *argv, VALUE self)
341-
{
342-
RSA *rsa;
343-
const BIGNUM *rsa_n;
344-
int buf_len, pad;
345-
VALUE str, buffer, padding;
346-
347-
GetRSA(self, rsa);
348-
RSA_get0_key(rsa, &rsa_n, NULL, NULL);
349-
if (!rsa_n)
350-
ossl_raise(eRSAError, "incomplete RSA");
351-
rb_scan_args(argc, argv, "11", &buffer, &padding);
352-
pad = (argc == 1) ? RSA_PKCS1_PADDING : NUM2INT(padding);
353-
StringValue(buffer);
354-
str = rb_str_new(0, RSA_size(rsa));
355-
buf_len = RSA_public_encrypt(RSTRING_LENINT(buffer), (unsigned char *)RSTRING_PTR(buffer),
356-
(unsigned char *)RSTRING_PTR(str), rsa, pad);
357-
if (buf_len < 0) ossl_raise(eRSAError, NULL);
358-
rb_str_set_len(str, buf_len);
359-
360-
return str;
361-
}
362-
363-
/*
364-
* call-seq:
365-
* rsa.public_decrypt(string) => String
366-
* rsa.public_decrypt(string, padding) => String
367-
*
368-
* Decrypt _string_, which has been encrypted with the private key, with the
369-
* public key. _padding_ defaults to PKCS1_PADDING.
370-
*/
371-
static VALUE
372-
ossl_rsa_public_decrypt(int argc, VALUE *argv, VALUE self)
373-
{
374-
RSA *rsa;
375-
const BIGNUM *rsa_n;
376-
int buf_len, pad;
377-
VALUE str, buffer, padding;
378-
379-
GetRSA(self, rsa);
380-
RSA_get0_key(rsa, &rsa_n, NULL, NULL);
381-
if (!rsa_n)
382-
ossl_raise(eRSAError, "incomplete RSA");
383-
rb_scan_args(argc, argv, "11", &buffer, &padding);
384-
pad = (argc == 1) ? RSA_PKCS1_PADDING : NUM2INT(padding);
385-
StringValue(buffer);
386-
str = rb_str_new(0, RSA_size(rsa));
387-
buf_len = RSA_public_decrypt(RSTRING_LENINT(buffer), (unsigned char *)RSTRING_PTR(buffer),
388-
(unsigned char *)RSTRING_PTR(str), rsa, pad);
389-
if (buf_len < 0) ossl_raise(eRSAError, NULL);
390-
rb_str_set_len(str, buf_len);
391-
392-
return str;
393-
}
394-
395-
/*
396-
* call-seq:
397-
* rsa.private_encrypt(string) => String
398-
* rsa.private_encrypt(string, padding) => String
399-
*
400-
* Encrypt _string_ with the private key. _padding_ defaults to PKCS1_PADDING.
401-
* The encrypted string output can be decrypted using #public_decrypt.
402-
*/
403-
static VALUE
404-
ossl_rsa_private_encrypt(int argc, VALUE *argv, VALUE self)
405-
{
406-
RSA *rsa;
407-
const BIGNUM *rsa_n;
408-
int buf_len, pad;
409-
VALUE str, buffer, padding;
410-
411-
GetRSA(self, rsa);
412-
RSA_get0_key(rsa, &rsa_n, NULL, NULL);
413-
if (!rsa_n)
414-
ossl_raise(eRSAError, "incomplete RSA");
415-
if (!RSA_PRIVATE(self, rsa))
416-
ossl_raise(eRSAError, "private key needed.");
417-
rb_scan_args(argc, argv, "11", &buffer, &padding);
418-
pad = (argc == 1) ? RSA_PKCS1_PADDING : NUM2INT(padding);
419-
StringValue(buffer);
420-
str = rb_str_new(0, RSA_size(rsa));
421-
buf_len = RSA_private_encrypt(RSTRING_LENINT(buffer), (unsigned char *)RSTRING_PTR(buffer),
422-
(unsigned char *)RSTRING_PTR(str), rsa, pad);
423-
if (buf_len < 0) ossl_raise(eRSAError, NULL);
424-
rb_str_set_len(str, buf_len);
425-
426-
return str;
427-
}
428-
429-
/*
430-
* call-seq:
431-
* rsa.private_decrypt(string) => String
432-
* rsa.private_decrypt(string, padding) => String
433-
*
434-
* Decrypt _string_, which has been encrypted with the public key, with the
435-
* private key. _padding_ defaults to PKCS1_PADDING.
436-
*/
437-
static VALUE
438-
ossl_rsa_private_decrypt(int argc, VALUE *argv, VALUE self)
439-
{
440-
RSA *rsa;
441-
const BIGNUM *rsa_n;
442-
int buf_len, pad;
443-
VALUE str, buffer, padding;
444-
445-
GetRSA(self, rsa);
446-
RSA_get0_key(rsa, &rsa_n, NULL, NULL);
447-
if (!rsa_n)
448-
ossl_raise(eRSAError, "incomplete RSA");
449-
if (!RSA_PRIVATE(self, rsa))
450-
ossl_raise(eRSAError, "private key needed.");
451-
rb_scan_args(argc, argv, "11", &buffer, &padding);
452-
pad = (argc == 1) ? RSA_PKCS1_PADDING : NUM2INT(padding);
453-
StringValue(buffer);
454-
str = rb_str_new(0, RSA_size(rsa));
455-
buf_len = RSA_private_decrypt(RSTRING_LENINT(buffer), (unsigned char *)RSTRING_PTR(buffer),
456-
(unsigned char *)RSTRING_PTR(str), rsa, pad);
457-
if (buf_len < 0) ossl_raise(eRSAError, NULL);
458-
rb_str_set_len(str, buf_len);
459-
460-
return str;
461-
}
462-
463331
/*
464332
* call-seq:
465333
* rsa.sign_pss(digest, data, salt_length:, mgf1_hash:) -> String
@@ -844,10 +712,6 @@ Init_ossl_rsa(void)
844712
rb_define_alias(cRSA, "to_s", "export");
845713
rb_define_method(cRSA, "to_der", ossl_rsa_to_der, 0);
846714
rb_define_method(cRSA, "public_key", ossl_rsa_to_public_key, 0);
847-
rb_define_method(cRSA, "public_encrypt", ossl_rsa_public_encrypt, -1);
848-
rb_define_method(cRSA, "public_decrypt", ossl_rsa_public_decrypt, -1);
849-
rb_define_method(cRSA, "private_encrypt", ossl_rsa_private_encrypt, -1);
850-
rb_define_method(cRSA, "private_decrypt", ossl_rsa_private_decrypt, -1);
851715
rb_define_method(cRSA, "sign_pss", ossl_rsa_sign_pss, -1);
852716
rb_define_method(cRSA, "verify_pss", ossl_rsa_verify_pss, -1);
853717

@@ -865,11 +729,6 @@ Init_ossl_rsa(void)
865729

866730
rb_define_method(cRSA, "params", ossl_rsa_get_params, 0);
867731

868-
DefRSAConst(PKCS1_PADDING);
869-
DefRSAConst(SSLV23_PADDING);
870-
DefRSAConst(NO_PADDING);
871-
DefRSAConst(PKCS1_OAEP_PADDING);
872-
873732
/*
874733
* TODO: Test it
875734
rb_define_method(cRSA, "blinding_on!", ossl_rsa_blinding_on, 0);

lib/openssl/pkey.rb

+106
Original file line numberDiff line numberDiff line change
@@ -71,5 +71,111 @@ def to_bn(conversion_form = group.point_conversion_form)
7171

7272
class RSA
7373
include OpenSSL::Marshal
74+
75+
# :call-seq:
76+
# rsa.private_encrypt(string) -> String
77+
# rsa.private_encrypt(string, padding) -> String
78+
#
79+
# Encrypt +string+ with the private key. +padding+ defaults to
80+
# PKCS1_PADDING. The encrypted string output can be decrypted using
81+
# #public_decrypt.
82+
#
83+
# <b>Deprecated in version 2.3</b>.
84+
# Consider using PKey::PKey#sign_raw and PKey::PKey#verify_raw, and
85+
# PKey::PKey#verify_recover instead.
86+
def private_encrypt(string, padding = PKCS1_PADDING)
87+
n or raise OpenSSL::PKey::RSAError, "incomplete RSA"
88+
private? or raise OpenSSL::PKey::RSAError, "private key needed."
89+
begin
90+
sign_raw(nil, string, {
91+
"rsa_padding_mode" => translate_padding_mode(padding),
92+
})
93+
rescue OpenSSL::PKey::PKeyError
94+
raise OpenSSL::PKey::RSAError, $!.message
95+
end
96+
end
97+
98+
# :call-seq:
99+
# rsa.public_decrypt(string) -> String
100+
# rsa.public_decrypt(string, padding) -> String
101+
#
102+
# Decrypt +string+, which has been encrypted with the private key, with the
103+
# public key. +padding+ defaults to PKCS1_PADDING.
104+
#
105+
# <b>Deprecated in version 2.3</b>.
106+
# Consider using PKey::PKey#sign_raw and PKey::PKey#verify_raw, and
107+
# PKey::PKey#verify_recover instead.
108+
def public_decrypt(string, padding = PKCS1_PADDING)
109+
n or raise OpenSSL::PKey::RSAError, "incomplete RSA"
110+
begin
111+
verify_recover(nil, string, {
112+
"rsa_padding_mode" => translate_padding_mode(padding),
113+
})
114+
rescue OpenSSL::PKey::PKeyError
115+
raise OpenSSL::PKey::RSAError, $!.message
116+
end
117+
end
118+
119+
# :call-seq:
120+
# rsa.public_encrypt(string) -> String
121+
# rsa.public_encrypt(string, padding) -> String
122+
#
123+
# Encrypt +string+ with the public key. +padding+ defaults to
124+
# PKCS1_PADDING. The encrypted string output can be decrypted using
125+
# #private_decrypt.
126+
#
127+
# <b>Deprecated in version 2.3</b>.
128+
# Consider using PKey::PKey#encrypt and PKey::PKey#decrypt instead.
129+
def public_encrypt(data, padding = PKCS1_PADDING)
130+
n or raise OpenSSL::PKey::RSAError, "incomplete RSA"
131+
begin
132+
encrypt(data, {
133+
"rsa_padding_mode" => translate_padding_mode(padding),
134+
})
135+
rescue OpenSSL::PKey::PKeyError
136+
raise OpenSSL::PKey::RSAError, $!.message
137+
end
138+
end
139+
140+
# :call-seq:
141+
# rsa.private_decrypt(string) -> String
142+
# rsa.private_decrypt(string, padding) -> String
143+
#
144+
# Decrypt +string+, which has been encrypted with the public key, with the
145+
# private key. +padding+ defaults to PKCS1_PADDING.
146+
#
147+
# <b>Deprecated in version 2.3</b>.
148+
# Consider using PKey::PKey#encrypt and PKey::PKey#decrypt instead.
149+
def private_decrypt(data, padding = PKCS1_PADDING)
150+
n or raise OpenSSL::PKey::RSAError, "incomplete RSA"
151+
private? or raise OpenSSL::PKey::RSAError, "private key needed."
152+
begin
153+
decrypt(data, {
154+
"rsa_padding_mode" => translate_padding_mode(padding),
155+
})
156+
rescue OpenSSL::PKey::PKeyError
157+
raise OpenSSL::PKey::RSAError, $!.message
158+
end
159+
end
160+
161+
PKCS1_PADDING = 1
162+
SSLV23_PADDING = 2
163+
NO_PADDING = 3
164+
PKCS1_OAEP_PADDING = 4
165+
166+
private def translate_padding_mode(num)
167+
case num
168+
when PKCS1_PADDING
169+
"pkcs1"
170+
when SSLV23_PADDING
171+
"sslv23"
172+
when NO_PADDING
173+
"none"
174+
when PKCS1_OAEP_PADDING
175+
"oaep"
176+
else
177+
raise OpenSSL::PKey::PKeyError, "unsupported padding mode"
178+
end
179+
end
74180
end
75181
end

0 commit comments

Comments
 (0)