diff --git a/ChangeLog b/ChangeLog index 0e106b8458..903ad46ca9 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,16 @@ +Mon Dec 6 01:32:31 2004 GOTOU Yuuzou + + * ext/openssl/ossl_pkey_rsa.c (ossl_rsa_public_encrypt, + ossl_rsa_public_decrypt, ossl_rsa_private_encrypt, + ossl_rsa_private_decrypt): should take an optional argument + to specify padding mode. [ruby-talk:122539] + + * ext/openssl/ossl_pkey_rsa.c (Init_ossl_rsa): add new constants + PKCS1_PADDING, SSLV23_PADDING, NO_PADDING and PKCS1_OAEP_PADDING + under OpenSSL::PKey::RSA. + + * test/openssl/test_pkey_rsa.rb: new file. + Sun Dec 5 19:39:17 2004 Nobuyoshi Nakada * lib/optparse.rb (OptionParser::Completion#complete): new parameter @@ -966,7 +979,7 @@ Thu Nov 4 03:11:33 2004 Yukihiro Matsumoto * ext/socket/socket.c (s_recvfrom): tmplock input buffer. [ruby-dev:24705] -Wed Nov 3 22:24:17 2004 GOTOU Yuuzou +Wed Nov 3 22:24:17 2004 Daigo Moriwaki * lib/webrick/httpauth/digestauth.rb: use Base64.encode64 to avoid warnings. diff --git a/ext/openssl/ossl_pkey_rsa.c b/ext/openssl/ossl_pkey_rsa.c index f8b3ae1387..75b02d23ec 100644 --- a/ext/openssl/ossl_pkey_rsa.c +++ b/ext/openssl/ossl_pkey_rsa.c @@ -252,18 +252,20 @@ ossl_rsa_to_der(VALUE self) #define ossl_rsa_buf_size(pkey) (RSA_size((pkey)->pkey.rsa)+16) static VALUE -ossl_rsa_public_encrypt(VALUE self, VALUE buffer) +ossl_rsa_public_encrypt(int argc, VALUE *argv, VALUE self) { EVP_PKEY *pkey; - int buf_len; - VALUE str; - + int buf_len, pad; + VALUE str, buffer, padding; + GetPKeyRSA(self, pkey); + rb_scan_args(argc, argv, "11", &buffer, &padding); + pad = (argc == 1) ? RSA_PKCS1_PADDING : NUM2INT(padding); StringValue(buffer); str = rb_str_new(0, ossl_rsa_buf_size(pkey)); buf_len = RSA_public_encrypt(RSTRING(buffer)->len, RSTRING(buffer)->ptr, RSTRING(str)->ptr, pkey->pkey.rsa, - RSA_PKCS1_PADDING); + pad); if (buf_len < 0) ossl_raise(eRSAError, NULL); RSTRING(str)->len = buf_len; RSTRING(str)->ptr[buf_len] = 0; @@ -272,41 +274,20 @@ ossl_rsa_public_encrypt(VALUE self, VALUE buffer) } static VALUE -ossl_rsa_public_decrypt(VALUE self, VALUE buffer) +ossl_rsa_public_decrypt(int argc, VALUE *argv, VALUE self) { EVP_PKEY *pkey; - int buf_len; - VALUE str; + int buf_len, pad; + VALUE str, buffer, padding; GetPKeyRSA(self, pkey); + rb_scan_args(argc, argv, "11", &buffer, &padding); + pad = (argc == 1) ? RSA_PKCS1_PADDING : NUM2INT(padding); StringValue(buffer); str = rb_str_new(0, ossl_rsa_buf_size(pkey)); buf_len = RSA_public_decrypt(RSTRING(buffer)->len, RSTRING(buffer)->ptr, RSTRING(str)->ptr, pkey->pkey.rsa, - RSA_PKCS1_PADDING); - if(buf_len < 0) ossl_raise(eRSAError, NULL); - RSTRING(str)->len = buf_len; - RSTRING(str)->ptr[buf_len] = 0; - - return str; -} - -static VALUE -ossl_rsa_private_encrypt(VALUE self, VALUE buffer) -{ - EVP_PKEY *pkey; - int buf_len; - VALUE str; - - GetPKeyRSA(self, pkey); - if (!RSA_PRIVATE(pkey->pkey.rsa)) { - ossl_raise(eRSAError, "PRIVATE key needed for this operation!"); - } - StringValue(buffer); - str = rb_str_new(0, ossl_rsa_buf_size(pkey)); - buf_len = RSA_private_encrypt(RSTRING(buffer)->len, RSTRING(buffer)->ptr, - RSTRING(str)->ptr, pkey->pkey.rsa, - RSA_PKCS1_PADDING); + pad); if (buf_len < 0) ossl_raise(eRSAError, NULL); RSTRING(str)->len = buf_len; RSTRING(str)->ptr[buf_len] = 0; @@ -315,21 +296,48 @@ ossl_rsa_private_encrypt(VALUE self, VALUE buffer) } static VALUE -ossl_rsa_private_decrypt(VALUE self, VALUE buffer) +ossl_rsa_private_encrypt(int argc, VALUE *argv, VALUE self) { EVP_PKEY *pkey; - int buf_len; - VALUE str; + int buf_len, pad; + VALUE str, buffer, padding; GetPKeyRSA(self, pkey); if (!RSA_PRIVATE(pkey->pkey.rsa)) { - ossl_raise(eRSAError, "Private RSA key needed!"); + ossl_raise(eRSAError, "private key needed."); + } + rb_scan_args(argc, argv, "11", &buffer, &padding); + pad = (argc == 1) ? RSA_PKCS1_PADDING : NUM2INT(padding); + StringValue(buffer); + str = rb_str_new(0, ossl_rsa_buf_size(pkey)); + buf_len = RSA_private_encrypt(RSTRING(buffer)->len, RSTRING(buffer)->ptr, + RSTRING(str)->ptr, pkey->pkey.rsa, + pad); + if (buf_len < 0) ossl_raise(eRSAError, NULL); + RSTRING(str)->len = buf_len; + RSTRING(str)->ptr[buf_len] = 0; + + return str; +} + +static VALUE +ossl_rsa_private_decrypt(int argc, VALUE *argv, VALUE self) +{ + EVP_PKEY *pkey; + int buf_len, pad; + VALUE str, buffer, padding; + + GetPKeyRSA(self, pkey); + if (!RSA_PRIVATE(pkey->pkey.rsa)) { + ossl_raise(eRSAError, "private key needed."); } + rb_scan_args(argc, argv, "11", &buffer, &padding); + pad = (argc == 1) ? RSA_PKCS1_PADDING : NUM2INT(padding); StringValue(buffer); str = rb_str_new(0, ossl_rsa_buf_size(pkey)); buf_len = RSA_private_decrypt(RSTRING(buffer)->len, RSTRING(buffer)->ptr, RSTRING(str)->ptr, pkey->pkey.rsa, - RSA_PKCS1_PADDING); + pad); if (buf_len < 0) ossl_raise(eRSAError, NULL); RSTRING(str)->len = buf_len; RSTRING(str)->ptr[buf_len] = 0; @@ -451,6 +459,8 @@ OSSL_PKEY_BN(rsa, iqmp); /* * INIT */ +#define DefRSAConst(x) rb_define_const(cRSA, #x,INT2FIX(RSA_##x)) + void Init_ossl_rsa() { @@ -469,10 +479,10 @@ Init_ossl_rsa() rb_define_alias(cRSA, "to_s", "export"); rb_define_method(cRSA, "to_der", ossl_rsa_to_der, 0); rb_define_method(cRSA, "public_key", ossl_rsa_to_public_key, 0); - rb_define_method(cRSA, "public_encrypt", ossl_rsa_public_encrypt, 1); - rb_define_method(cRSA, "public_decrypt", ossl_rsa_public_decrypt, 1); - rb_define_method(cRSA, "private_encrypt", ossl_rsa_private_encrypt, 1); - rb_define_method(cRSA, "private_decrypt", ossl_rsa_private_decrypt, 1); + rb_define_method(cRSA, "public_encrypt", ossl_rsa_public_encrypt, -1); + rb_define_method(cRSA, "public_decrypt", ossl_rsa_public_decrypt, -1); + rb_define_method(cRSA, "private_encrypt", ossl_rsa_private_encrypt, -1); + rb_define_method(cRSA, "private_decrypt", ossl_rsa_private_decrypt, -1); DEF_OSSL_PKEY_BN(cRSA, rsa, n); DEF_OSSL_PKEY_BN(cRSA, rsa, e); @@ -485,6 +495,11 @@ Init_ossl_rsa() rb_define_method(cRSA, "params", ossl_rsa_get_params, 0); + DefRSAConst(PKCS1_PADDING); + DefRSAConst(SSLV23_PADDING); + DefRSAConst(NO_PADDING); + DefRSAConst(PKCS1_OAEP_PADDING); + /* * TODO: Test it rb_define_method(cRSA, "blinding_on!", ossl_rsa_blinding_on, 0); diff --git a/test/openssl/test_pkey_rsa.rb b/test/openssl/test_pkey_rsa.rb new file mode 100644 index 0000000000..36eb2b77eb --- /dev/null +++ b/test/openssl/test_pkey_rsa.rb @@ -0,0 +1,38 @@ +begin + require "openssl" + require File.join(File.dirname(__FILE__), "utils.rb") +rescue LoadError +end +require 'test/unit' + +if defined?(OpenSSL) + +class OpenSSL::TestPKeyRSA < Test::Unit::TestCase + def test_padding + key = OpenSSL::PKey::RSA.new(512, 3) + + # Need right size for raw mode + plain0 = "x" * (512/8) + cipher = key.private_encrypt(plain0, OpenSSL::PKey::RSA::NO_PADDING) + plain1 = key.public_decrypt(cipher, OpenSSL::PKey::RSA::NO_PADDING) + assert_equal(plain0, plain1) + + # Need smaller size for pkcs1 mode + plain0 = "x" * (512/8 - 11) + cipher1 = key.private_encrypt(plain0, OpenSSL::PKey::RSA::PKCS1_PADDING) + plain1 = key.public_decrypt(cipher1, OpenSSL::PKey::RSA::PKCS1_PADDING) + assert_equal(plain0, plain1) + + cipherdef = key.private_encrypt(plain0) # PKCS1_PADDING is default + plain1 = key.public_decrypt(cipherdef) + assert_equal(plain0, plain1) + assert_equal(cipher1, cipherdef) + + # Failure cases + assert_raise(ArgumentError){ key.private_encrypt() } + assert_raise(ArgumentError){ key.private_encrypt("hi", 1, nil) } + assert_raise(OpenSSL::PKey::RSAError){ key.private_encrypt(plain0, 666) } + end +end + +end