aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authoremboss <emboss@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2011-05-13 19:25:18 +0000
committeremboss <emboss@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2011-05-13 19:25:18 +0000
commitcb57042beeac1f6acc424cc1339acfa198d5ac8b (patch)
treef86bc5e99cdf3db0f2ce8e8b76ff920e8bc24859
parentf342dde667a2de0d727f14b8b8992485eb60ebe8 (diff)
downloadruby-cb57042beeac1f6acc424cc1339acfa198d5ac8b.tar.gz
Sat May 14 04:19:06 2011 Martin Bosslet <Martin.Bosslet@googlemail.com>
* NEWS: Describe altered behaviour for RSA and DSA public key encoding. [Ruby 1.9 - Bug #4421, Bug #4422] [ruby-core:35327,35328] Previous revision: 31553 git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@31554 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
-rw-r--r--ChangeLog6
-rw-r--r--NEWS6
-rw-r--r--ext/openssl/ossl_digest.c2
-rw-r--r--ext/openssl/ossl_pkey.c60
-rw-r--r--ext/openssl/ossl_pkey.h2
-rw-r--r--test/openssl/test_pkey_rsa.rb42
6 files changed, 103 insertions, 15 deletions
diff --git a/ChangeLog b/ChangeLog
index ddf7adc6cb..ffdb43b399 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,9 @@
+Sat May 14 04:19:06 2011 Martin Bosslet <Martin.Bosslet@googlemail.com>
+
+ * NEWS: Describe altered behaviour for RSA and DSA public key
+ encoding. [Ruby 1.9 - Bug #4421, Bug #4422]
+ [ruby-core:35327,35328]
+
Sat May 14 02:57:52 2011 Eric Hodel <drbrain@segment7.net>
* lib/ipaddr.rb (unless Socket): Document valid*? methods. Patch by
diff --git a/NEWS b/NEWS
index 698453b43e..1a9a14a9c3 100644
--- a/NEWS
+++ b/NEWS
@@ -98,6 +98,12 @@ with all sufficient information, see the ChangeLog file.
* net/http
* SNI (Server Name Indication) supported for HTTPS.
+* openssl
+ * PKey::RSA and PKey::DSA now use the generic X.509 encoding scheme
+ (e.g. used in a X.509 certificate's Subject Public Key Info) when
+ exporting public keys to DER or PEM. Backward compatibility is
+ ensured by (already existing) fallbacks during creation.
+
* optparse
* support for bash/zsh completion.
diff --git a/ext/openssl/ossl_digest.c b/ext/openssl/ossl_digest.c
index 2b76fe7a49..9f3d2697af 100644
--- a/ext/openssl/ossl_digest.c
+++ b/ext/openssl/ossl_digest.c
@@ -239,6 +239,8 @@ Init_ossl_digest()
mOSSL = rb_define_module("OpenSSL"); /* let rdoc know about mOSSL */
#endif
+ /* Allows you to compute cryptographic hashes of arbitrary data.
+ */
cDigest = rb_define_class_under(mOSSL, "Digest", rb_path2class("Digest::Class"));
eDigestError = rb_define_class_under(cDigest, "DigestError", eOSSLError);
diff --git a/ext/openssl/ossl_pkey.c b/ext/openssl/ossl_pkey.c
index b5047bec26..d6940acda4 100644
--- a/ext/openssl/ossl_pkey.c
+++ b/ext/openssl/ossl_pkey.c
@@ -18,6 +18,9 @@ VALUE cPKey;
VALUE ePKeyError;
ID id_private_q;
+#define reset_bio(b) (void)BIO_reset((b)); \
+ (void)ERR_get_error();
+
/*
* callback for generating keys
*/
@@ -65,23 +68,50 @@ ossl_pkey_new(EVP_PKEY *pkey)
return Qnil; /* not reached */
}
-VALUE
-ossl_pkey_new_from_file(VALUE filename)
+/*
+ * call-seq:
+ * OpenSSL::PKey.read(string [, pwd ] ) -> PKey
+ * OpenSSL::PKey.read(file [, pwd ]) -> PKey
+ *
+ * === Parameters
+ * * +string+ is a DER- or PEM-encoded string containing an arbitrary private
+ * or public key.
+ * * +file+ is an instance of +File+ containing a DER- or PEM-encoded
+ * arbitrary private or public key.
+ * * +pwd+ is an optional password in case +string+ or +file+ is an encrypted
+ * PEM resource.
+ */
+VALUE
+ossl_pkey_new_from_data(int argc, VALUE *argv, VALUE self)
{
- FILE *fp;
EVP_PKEY *pkey;
-
- SafeStringValue(filename);
- if (!(fp = fopen(RSTRING_PTR(filename), "r"))) {
- ossl_raise(ePKeyError, "%s", strerror(errno));
+ BIO *bio;
+ VALUE data, pass;
+ char *passwd = NULL;
+
+ rb_scan_args(argc, argv, "11", &data, &pass);
+
+ bio = ossl_obj2bio(data);
+ if (!(pkey = d2i_PrivateKey_bio(bio, NULL))) {
+ reset_bio(bio);
+ if (!NIL_P(pass)) {
+ passwd = StringValuePtr(pass);
+ }
+ if (!(pkey = PEM_read_bio_PrivateKey(bio, NULL, ossl_pem_passwd_cb, passwd))) {
+ reset_bio(bio);
+ if (!(pkey = d2i_PUBKEY_bio(bio, NULL))) {
+ reset_bio(bio);
+ if (!NIL_P(pass)) {
+ passwd = StringValuePtr(pass);
+ }
+ pkey = PEM_read_bio_PUBKEY(bio, NULL, ossl_pem_passwd_cb, passwd);
+ }
+ }
}
-
- pkey = PEM_read_PrivateKey(fp, NULL, ossl_pem_passwd_cb, NULL);
- fclose(fp);
- if (!pkey) {
- ossl_raise(ePKeyError, NULL);
- }
-
+
+ BIO_free(bio);
+ if (!pkey)
+ ossl_raise(rb_eArgError, "Could not parse PKey");
return ossl_pkey_new(pkey);
}
@@ -221,6 +251,8 @@ Init_ossl_pkey()
cPKey = rb_define_class_under(mPKey, "PKey", rb_cObject);
+ rb_define_module_function(mPKey, "read", ossl_pkey_new_from_data, -1);
+
rb_define_alloc_func(cPKey, ossl_pkey_alloc);
rb_define_method(cPKey, "initialize", ossl_pkey_initialize, 0);
diff --git a/ext/openssl/ossl_pkey.h b/ext/openssl/ossl_pkey.h
index 5e3329d326..4b19164585 100644
--- a/ext/openssl/ossl_pkey.h
+++ b/ext/openssl/ossl_pkey.h
@@ -41,7 +41,7 @@ extern ID id_private_q;
void ossl_generate_cb(int, int, void *);
VALUE ossl_pkey_new(EVP_PKEY *);
-VALUE ossl_pkey_new_from_file(VALUE);
+VALUE ossl_pkey_new_from_data(int, VALUE *, VALUE);
EVP_PKEY *GetPKeyPtr(VALUE);
EVP_PKEY *DupPKeyPtr(VALUE);
EVP_PKEY *GetPrivPKeyPtr(VALUE);
diff --git a/test/openssl/test_pkey_rsa.rb b/test/openssl/test_pkey_rsa.rb
index f42748ed22..6a1f9e79d1 100644
--- a/test/openssl/test_pkey_rsa.rb
+++ b/test/openssl/test_pkey_rsa.rb
@@ -46,6 +46,48 @@ class OpenSSL::TestPKeyRSA < Test::Unit::TestCase
OpenSSL::PKey::RSA.new pem
assert_equal([], OpenSSL.errors)
end
+
+ def test_read_private_key_der
+ der = OpenSSL::TestUtils::TEST_KEY_RSA1024.to_der
+ key = OpenSSL::PKey.read(der)
+ assert(key.private?)
+ assert_equal(der, key.to_der)
+ end
+
+ def test_read_private_key_pem
+ pem = OpenSSL::TestUtils::TEST_KEY_RSA1024.to_pem
+ key = OpenSSL::PKey.read(pem)
+ assert(key.private?)
+ assert_equal(pem, key.to_pem)
+ end
+
+ def test_read_public_key_der
+ der = OpenSSL::TestUtils::TEST_KEY_RSA1024.public_key.to_der
+ key = OpenSSL::PKey.read(der)
+ assert(!key.private?)
+ assert_equal(der, key.to_der)
+ end
+
+ def test_read_public_key_pem
+ pem = OpenSSL::TestUtils::TEST_KEY_RSA1024.public_key.to_pem
+ key = OpenSSL::PKey.read(pem)
+ assert(!key.private?)
+ assert_equal(pem, key.to_pem)
+ end
+
+ def test_read_private_key_pem_pw
+ pem = OpenSSL::TestUtils::TEST_KEY_RSA1024.to_pem(OpenSSL::Cipher.new('AES-128-CBC'), 'secret')
+ #callback form for password
+ key = OpenSSL::PKey.read(pem) do
+ 'secret'
+ end
+ assert(key.private?)
+ # pass password directly
+ key = OpenSSL::PKey.read(pem, 'secret')
+ assert(key.private?)
+ #omit pem equality check, will be different due to cipher iv
+ end
+
end
end