Skip to content

Commit

Permalink
pkey: implement #to_text using EVP API
Browse files Browse the repository at this point in the history
Use EVP_PKEY_print_private() instead of the low-level API *_print()
functions, such as RSA_print().

EVP_PKEY_print_*() family was added in OpenSSL 1.0.0.

Note that it falls back to EVP_PKEY_print_public() and
EVP_PKEY_print_params() as necessary. This is required for EVP_PKEY_DH
type for which _private() fails if the private component is not set in
the pkey object.

Since the new API works in the same way for all key types, we now
implement #to_text in the base class OpenSSL::PKey::PKey rather than in
each subclass.
  • Loading branch information
rhenium committed Apr 15, 2021
1 parent d172036 commit e0b4c56
Show file tree
Hide file tree
Showing 6 changed files with 43 additions and 116 deletions.
38 changes: 38 additions & 0 deletions ext/openssl/ossl_pkey.c
Original file line number Diff line number Diff line change
Expand Up @@ -539,6 +539,43 @@ ossl_pkey_inspect(VALUE self)
OBJ_nid2sn(nid));
}

/*
* call-seq:
* pkey.to_text -> string
*
* Dumps key parameters, public key, and private key components contained in
* the key into a human-readable text.
*
* This is intended for debugging purpose.
*
* See also the man page EVP_PKEY_print_private(3).
*/
static VALUE
ossl_pkey_to_text(VALUE self)
{
EVP_PKEY *pkey;
BIO *bio;

GetPKey(self, pkey);
if (!(bio = BIO_new(BIO_s_mem())))
ossl_raise(ePKeyError, "BIO_new");

if (EVP_PKEY_print_private(bio, pkey, 0, NULL) == 1)
goto out;
OSSL_BIO_reset(bio);
if (EVP_PKEY_print_public(bio, pkey, 0, NULL) == 1)
goto out;
OSSL_BIO_reset(bio);
if (EVP_PKEY_print_params(bio, pkey, 0, NULL) == 1)
goto out;

BIO_free(bio);
ossl_raise(ePKeyError, "EVP_PKEY_print_params");

out:
return ossl_membio2str(bio);
}

VALUE
ossl_pkey_export_traditional(int argc, VALUE *argv, VALUE self, int to_der)
{
Expand Down Expand Up @@ -1077,6 +1114,7 @@ Init_ossl_pkey(void)
rb_define_method(cPKey, "initialize", ossl_pkey_initialize, 0);
rb_define_method(cPKey, "oid", ossl_pkey_oid, 0);
rb_define_method(cPKey, "inspect", ossl_pkey_inspect, 0);
rb_define_method(cPKey, "to_text", ossl_pkey_to_text, 0);
rb_define_method(cPKey, "private_to_der", ossl_pkey_private_to_der, -1);
rb_define_method(cPKey, "private_to_pem", ossl_pkey_private_to_pem, -1);
rb_define_method(cPKey, "public_to_der", ossl_pkey_public_to_der, 0);
Expand Down
29 changes: 0 additions & 29 deletions ext/openssl/ossl_pkey_dh.c
Original file line number Diff line number Diff line change
Expand Up @@ -266,34 +266,6 @@ ossl_dh_get_params(VALUE self)
return hash;
}

/*
* call-seq:
* dh.to_text -> aString
*
* Prints all parameters of key to buffer
* INSECURE: PRIVATE INFORMATIONS CAN LEAK OUT!!!
* Don't use :-)) (I's up to you)
*/
static VALUE
ossl_dh_to_text(VALUE self)
{
DH *dh;
BIO *out;
VALUE str;

GetDH(self, dh);
if (!(out = BIO_new(BIO_s_mem()))) {
ossl_raise(eDHError, NULL);
}
if (!DHparams_print(out, dh)) {
BIO_free(out);
ossl_raise(eDHError, NULL);
}
str = ossl_membio2str(out);

return str;
}

/*
* call-seq:
* dh.public_key -> aDH
Expand Down Expand Up @@ -426,7 +398,6 @@ Init_ossl_dh(void)
rb_define_method(cDH, "initialize_copy", ossl_dh_initialize_copy, 1);
rb_define_method(cDH, "public?", ossl_dh_is_public, 0);
rb_define_method(cDH, "private?", ossl_dh_is_private, 0);
rb_define_method(cDH, "to_text", ossl_dh_to_text, 0);
rb_define_method(cDH, "export", ossl_dh_export, 0);
rb_define_alias(cDH, "to_pem", "export");
rb_define_alias(cDH, "to_s", "export");
Expand Down
29 changes: 0 additions & 29 deletions ext/openssl/ossl_pkey_dsa.c
Original file line number Diff line number Diff line change
Expand Up @@ -264,34 +264,6 @@ ossl_dsa_get_params(VALUE self)
return hash;
}

/*
* call-seq:
* dsa.to_text -> aString
*
* Prints all parameters of key to buffer
* INSECURE: PRIVATE INFORMATIONS CAN LEAK OUT!!!
* Don't use :-)) (I's up to you)
*/
static VALUE
ossl_dsa_to_text(VALUE self)
{
DSA *dsa;
BIO *out;
VALUE str;

GetDSA(self, dsa);
if (!(out = BIO_new(BIO_s_mem()))) {
ossl_raise(eDSAError, NULL);
}
if (!DSA_print(out, dsa, 0)) { /* offset = 0 */
BIO_free(out);
ossl_raise(eDSAError, NULL);
}
str = ossl_membio2str(out);

return str;
}

/*
* call-seq:
* dsa.public_key -> aDSA
Expand Down Expand Up @@ -469,7 +441,6 @@ Init_ossl_dsa(void)

rb_define_method(cDSA, "public?", ossl_dsa_is_public, 0);
rb_define_method(cDSA, "private?", ossl_dsa_is_private, 0);
rb_define_method(cDSA, "to_text", ossl_dsa_to_text, 0);
rb_define_method(cDSA, "export", ossl_dsa_export, -1);
rb_define_alias(cDSA, "to_pem", "export");
rb_define_alias(cDSA, "to_s", "export");
Expand Down
27 changes: 0 additions & 27 deletions ext/openssl/ossl_pkey_ec.c
Original file line number Diff line number Diff line change
Expand Up @@ -412,32 +412,6 @@ ossl_ec_key_to_der(VALUE self)
else
return ossl_pkey_export_spki(self, 1);
}

/*
* call-seq:
* key.to_text => String
*
* See the OpenSSL documentation for EC_KEY_print()
*/
static VALUE ossl_ec_key_to_text(VALUE self)
{
EC_KEY *ec;
BIO *out;
VALUE str;

GetEC(self, ec);
if (!(out = BIO_new(BIO_s_mem()))) {
ossl_raise(eECError, "BIO_new(BIO_s_mem())");
}
if (!EC_KEY_print(out, ec, 0)) {
BIO_free(out);
ossl_raise(eECError, "EC_KEY_print");
}
str = ossl_membio2str(out);

return str;
}

/*
* call-seq:
* key.generate_key! => self
Expand Down Expand Up @@ -1601,7 +1575,6 @@ void Init_ossl_ec(void)
rb_define_method(cEC, "export", ossl_ec_key_export, -1);
rb_define_alias(cEC, "to_pem", "export");
rb_define_method(cEC, "to_der", ossl_ec_key_to_der, 0);
rb_define_method(cEC, "to_text", ossl_ec_key_to_text, 0);


rb_define_alloc_func(cEC_GROUP, ossl_ec_group_alloc);
Expand Down
31 changes: 0 additions & 31 deletions ext/openssl/ossl_pkey_rsa.c
Original file line number Diff line number Diff line change
Expand Up @@ -587,36 +587,6 @@ ossl_rsa_get_params(VALUE self)
return hash;
}

/*
* call-seq:
* rsa.to_text => String
*
* THIS METHOD IS INSECURE, PRIVATE INFORMATION CAN LEAK OUT!!!
*
* Dumps all parameters of a keypair to a String
*
* Don't use :-)) (It's up to you)
*/
static VALUE
ossl_rsa_to_text(VALUE self)
{
RSA *rsa;
BIO *out;
VALUE str;

GetRSA(self, rsa);
if (!(out = BIO_new(BIO_s_mem()))) {
ossl_raise(eRSAError, NULL);
}
if (!RSA_print(out, rsa, 0)) { /* offset = 0 */
BIO_free(out);
ossl_raise(eRSAError, NULL);
}
str = ossl_membio2str(out);

return str;
}

/*
* call-seq:
* rsa.public_key -> RSA
Expand Down Expand Up @@ -738,7 +708,6 @@ Init_ossl_rsa(void)

rb_define_method(cRSA, "public?", ossl_rsa_is_public, 0);
rb_define_method(cRSA, "private?", ossl_rsa_is_private, 0);
rb_define_method(cRSA, "to_text", ossl_rsa_to_text, 0);
rb_define_method(cRSA, "export", ossl_rsa_export, -1);
rb_define_alias(cRSA, "to_pem", "export");
rb_define_alias(cRSA, "to_s", "export");
Expand Down
5 changes: 5 additions & 0 deletions test/openssl/test_pkey.rb
Original file line number Diff line number Diff line change
Expand Up @@ -169,4 +169,9 @@ def test_compare?
key1.compare?(key4)
end
end

def test_to_text
rsa = Fixtures.pkey("rsa1024")
assert_include rsa.to_text, "publicExponent"
end
end

0 comments on commit e0b4c56

Please sign in to comment.