diff options
author | emboss <emboss@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2011-06-12 20:39:38 +0000 |
---|---|---|
committer | emboss <emboss@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2011-06-12 20:39:38 +0000 |
commit | bbb3cfb12b16c7681a58e9a16cec49c37edab1ab (patch) | |
tree | 27d8a24a2f44b9e153f577cb68fb0faa54aa1fac /ext | |
parent | 7b614a53dd50508410c48113dce87abfc003df6b (diff) | |
download | ruby-bbb3cfb12b16c7681a58e9a16cec49c37edab1ab.tar.gz |
* ext/openssl/ossl_pkey.c: added PKey.read module function that allow
reading arbitrary public/private keys from DER-/PEM-encoded File or
string instances.
* ext/openssl/ossl_pkey_dh.c: improved documentation.
* test/openssl/utils.rb: added EC test key.
* test/openssl/test_pkey_rsa.rb
test/openssl/test_pkey_dsa.rb: Test PKey.read. Reuse keys from
OpenSSL::TestUtils.
* test/openssl/test_pkey_ec.rb: Created test file for EC tests.
Test PKey.read.
[Ruby 1.9 - Feature #4424] [ruby-core:35330]
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@32036 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
Diffstat (limited to 'ext')
-rw-r--r-- | ext/openssl/ossl_pkey.c | 53 | ||||
-rw-r--r-- | ext/openssl/ossl_pkey_dh.c | 19 |
2 files changed, 66 insertions, 6 deletions
diff --git a/ext/openssl/ossl_pkey.c b/ext/openssl/ossl_pkey.c index 69747ca44a..0bd9dda549 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 */ @@ -85,6 +88,54 @@ ossl_pkey_new_from_file(VALUE filename) return ossl_pkey_new(pkey); } +/* + * 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. + */ +static VALUE +ossl_pkey_new_from_data(int argc, VALUE *argv, VALUE self) +{ + FILE *fp; + EVP_PKEY *pkey; + 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); + } + } + } + + BIO_free(bio); + if (!pkey) + ossl_raise(rb_eArgError, "Could not parse PKey"); + return ossl_pkey_new(pkey); +} + EVP_PKEY * GetPKeyPtr(VALUE obj) { @@ -330,6 +381,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_dh.c b/ext/openssl/ossl_pkey_dh.c index 3f1ebda8d0..834261087a 100644 --- a/ext/openssl/ossl_pkey_dh.c +++ b/ext/openssl/ossl_pkey_dh.c @@ -338,15 +338,17 @@ ossl_dh_to_text(VALUE self) * call-seq: * dh.public_key -> aDH * - * Returns a new DH instance that carries just the public information. - * If the current instance has also private information, this will no + * Returns a new DH instance that carries just the public information, i.e. + * the prime +p+ and the generator +g+, but no public/private key yet. Such + * a pair may be generated using DH#generate_key!. + * If the current instance already contains private information, this will no * longer be present in the new instance. This feature is helpful for * publishing the public information without leaking any of the private * information. * * === Example * dh = OpenSSL::PKey::DH.new(2048) # has public and private information - * pub_key = dh.public_key # has only the public part available + * pub_key = dh.public_key # contains only prime and generator * pub_key_der = pub_key.to_der # it's safe to publish this */ static VALUE @@ -394,10 +396,15 @@ ossl_dh_check_params(VALUE self) /* * call-seq: - * dh.generate_key -> self + * dh.generate_key! -> self * - * Generates a private key unless one already exists. It also computes the - * public key for the generated private key. + * Generates a private and public key unless one already exists. + * + * === Example + * dh = OpenSSL::PKey::DH.new(2048) + * public_key = dh.public_key #contains no private/public key yet + * public_key.generate_key! + * puts public_key.private? # => true */ static VALUE ossl_dh_generate_key(VALUE self) |