aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKazuki Yamaguchi <k@rhe.jp>2021-04-15 18:37:34 +0900
committerKazuki Yamaguchi <k@rhe.jp>2021-12-20 19:07:59 +0900
commit1c4d75f21ba70623f1d31d56bea2bd2e346a1e91 (patch)
tree3e33af618344f7f6225d31a77bea20622eb021de
parent4403c3cf3ce7fbac7573d3b8e6c0d3ecd0aaa969 (diff)
downloadruby-openssl-1c4d75f21ba70623f1d31d56bea2bd2e346a1e91.tar.gz
pkey: add PKey#to_data wrapping EVP_PKEY_todata()
EVP_PKEY_todata() returns all key components contained in an EVP_PKEY object as an array of OSSL_PARAM. This is useful as the replacement for low-level API which is used to implement #params. EVP_PKEY_todata() currently only exists in OpenSSL 3.0.0.
-rw-r--r--ext/openssl/extconf.rb1
-rw-r--r--ext/openssl/ossl_bn.c17
-rw-r--r--ext/openssl/ossl_bn.h3
-rw-r--r--ext/openssl/ossl_pkey.c74
-rw-r--r--ext/openssl/ossl_pkey_dh.c27
-rw-r--r--ext/openssl/ossl_pkey_dsa.c27
-rw-r--r--ext/openssl/ossl_pkey_ec.c28
-rw-r--r--ext/openssl/ossl_pkey_rsa.c36
-rw-r--r--lib/openssl/pkey.rb36
-rw-r--r--test/openssl/test_pkey_dh.rb39
-rw-r--r--test/openssl/test_pkey_dsa.rb29
-rw-r--r--test/openssl/test_pkey_ec.rb8
-rw-r--r--test/openssl/test_pkey_rsa.rb48
13 files changed, 322 insertions, 51 deletions
diff --git a/ext/openssl/extconf.rb b/ext/openssl/extconf.rb
index fedcb930..234365b5 100644
--- a/ext/openssl/extconf.rb
+++ b/ext/openssl/extconf.rb
@@ -180,6 +180,7 @@ have_func("EVP_MD_CTX_get0_md")
have_func("EVP_MD_CTX_get_pkey_ctx")
have_func("EVP_PKEY_eq")
have_func("EVP_PKEY_dup")
+have_func("EVP_PKEY_todata")
Logging::message "=== Checking done. ===\n"
diff --git a/ext/openssl/ossl_bn.c b/ext/openssl/ossl_bn.c
index 56fa0ec3..a28feff7 100644
--- a/ext/openssl/ossl_bn.c
+++ b/ext/openssl/ossl_bn.c
@@ -74,6 +74,23 @@ ossl_bn_new(const BIGNUM *bn)
return obj;
}
+#ifdef HAVE_EVP_PKEY_TODATA
+VALUE
+ossl_bn_new_from_native(const void *data, size_t data_size)
+{
+ BIGNUM *bn;
+ VALUE obj;
+
+ obj = NewBN(cBN);
+ bn = BN_native2bn(data, data_size, NULL);
+ if (!bn)
+ ossl_raise(eBNError, "BN_native2bn");
+ SetBN(obj, bn);
+
+ return obj;
+}
+#endif
+
static BIGNUM *
integer_to_bnptr(VALUE obj, BIGNUM *orig)
{
diff --git a/ext/openssl/ossl_bn.h b/ext/openssl/ossl_bn.h
index 1cc041fc..c44fa5b0 100644
--- a/ext/openssl/ossl_bn.h
+++ b/ext/openssl/ossl_bn.h
@@ -19,6 +19,9 @@ BN_CTX *ossl_bn_ctx_get(void);
#define GetBNPtr(obj) ossl_bn_value_ptr(&(obj))
VALUE ossl_bn_new(const BIGNUM *);
+#ifdef HAVE_EVP_PKEY_TODATA
+VALUE ossl_bn_new_from_native(const void *data, size_t data_size);
+#endif
BIGNUM *ossl_bn_value_ptr(volatile VALUE *);
void Init_ossl_bn(void);
diff --git a/ext/openssl/ossl_pkey.c b/ext/openssl/ossl_pkey.c
index 2a4835a2..160a1c85 100644
--- a/ext/openssl/ossl_pkey.c
+++ b/ext/openssl/ossl_pkey.c
@@ -645,6 +645,79 @@ ossl_pkey_to_text(VALUE self)
return ossl_membio2str(bio);
}
+#ifdef HAVE_EVP_PKEY_TODATA
+static VALUE
+ossl_params_to_hash(VALUE paramsv)
+{
+ const OSSL_PARAM *params = (void *)paramsv;
+ VALUE hash = rb_hash_new();
+ size_t i;
+
+ for (i = 0; params[i].key; i++) {
+ const OSSL_PARAM *p = &params[i];
+ VALUE key = ID2SYM(rb_intern(p->key)), value = Qundef;
+
+ switch (p->data_type) {
+ case OSSL_PARAM_INTEGER:
+ // FIXME
+ value = ossl_bn_new_from_native(p->data, p->data_size);
+ break;
+ case OSSL_PARAM_UNSIGNED_INTEGER:
+ value = ossl_bn_new_from_native(p->data, p->data_size);
+ break;
+ case OSSL_PARAM_UTF8_STRING:
+ value = rb_enc_str_new(p->data, p->data_size, rb_utf8_encoding());
+ break;
+ case OSSL_PARAM_OCTET_STRING:
+ value = rb_str_new(p->data, p->data_size);
+ break;
+ default:
+ OSSL_Debug("ossl_params_to_hash: " \
+ "unsupported data type %d for key %s",
+ (int)p->data_type, p->key);
+ break;
+ }
+ if (value != Qundef)
+ rb_hash_aset(hash, key, value);
+ }
+ return hash;
+}
+#endif
+
+/*
+ * call-seq:
+ * pkey.to_data -> hash
+ *
+ * Returns all information about the key in a Hash. This includes the key
+ * parameters, public and private key components, and all other miscellaneous
+ * information returned by the algorithm implementation.
+ *
+ * The key names vary depending on the algorithm and also the implementation.
+ *
+ * See also the man page EVP_PKEY_todata(3).
+ */
+static VALUE
+ossl_pkey_to_data(VALUE self)
+{
+#ifdef HAVE_EVP_PKEY_TODATA
+ EVP_PKEY *pkey;
+ OSSL_PARAM *params;
+ VALUE hash;
+ int state;
+
+ GetPKey(self, pkey);
+ if (EVP_PKEY_todata(pkey, OSSL_KEYMGMT_SELECT_ALL, &params) != 1)
+ ossl_raise(ePKeyError, "EVP_PKEY_todata");
+ hash = rb_protect(ossl_params_to_hash, (VALUE)params, &state);
+ OSSL_PARAM_free(params);
+ if (state)
+ rb_jump_tag(state);
+ return hash;
+#else
+ return rb_hash_new();
+#endif
+}
+
VALUE
ossl_pkey_export_traditional(int argc, VALUE *argv, VALUE self, int to_der)
{
@@ -1557,6 +1630,7 @@ Init_ossl_pkey(void)
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, "to_data", ossl_pkey_to_data, 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);
diff --git a/ext/openssl/ossl_pkey_dh.c b/ext/openssl/ossl_pkey_dh.c
index 696455dc..97b1730c 100644
--- a/ext/openssl/ossl_pkey_dh.c
+++ b/ext/openssl/ossl_pkey_dh.c
@@ -269,16 +269,10 @@ ossl_dh_to_der(VALUE self)
return str;
}
-/*
- * call-seq:
- * dh.params -> hash
- *
- * Stores all parameters of key to the hash
- * INSECURE: PRIVATE INFORMATIONS CAN LEAK OUT!!!
- * Don't use :-)) (I's up to you)
- */
+#ifndef HAVE_EVP_PKEY_TODATA
+/* :nodoc: */
static VALUE
-ossl_dh_get_params(VALUE self)
+ossl_dh_to_data(VALUE self)
{
DH *dh;
VALUE hash;
@@ -289,14 +283,15 @@ ossl_dh_get_params(VALUE self)
DH_get0_key(dh, &pub_key, &priv_key);
hash = rb_hash_new();
- rb_hash_aset(hash, rb_str_new2("p"), ossl_bn_new(p));
- rb_hash_aset(hash, rb_str_new2("q"), ossl_bn_new(q));
- rb_hash_aset(hash, rb_str_new2("g"), ossl_bn_new(g));
- rb_hash_aset(hash, rb_str_new2("pub_key"), ossl_bn_new(pub_key));
- rb_hash_aset(hash, rb_str_new2("priv_key"), ossl_bn_new(priv_key));
+ rb_hash_aset(hash, ID2SYM(rb_intern("p")), p ? ossl_bn_new(p) : Qnil);
+ rb_hash_aset(hash, ID2SYM(rb_intern("q")), q ? ossl_bn_new(q) : Qnil);
+ rb_hash_aset(hash, ID2SYM(rb_intern("g")), g ? ossl_bn_new(g) : Qnil);
+ rb_hash_aset(hash, ID2SYM(rb_intern("pub")), pub_key ? ossl_bn_new(pub_key) : Qnil);
+ rb_hash_aset(hash, ID2SYM(rb_intern("priv")), priv_key ? ossl_bn_new(priv_key) : Qnil);
return hash;
}
+#endif
/*
* call-seq:
@@ -429,7 +424,9 @@ Init_ossl_dh(void)
rb_define_method(cDH, "set_pqg", ossl_dh_set_pqg, 3);
rb_define_method(cDH, "set_key", ossl_dh_set_key, 2);
- rb_define_method(cDH, "params", ossl_dh_get_params, 0);
+#ifndef HAVE_EVP_PKEY_TODATA
+ rb_define_method(cDH, "to_data", ossl_dh_to_data, 0);
+#endif
}
#else /* defined NO_DH */
diff --git a/ext/openssl/ossl_pkey_dsa.c b/ext/openssl/ossl_pkey_dsa.c
index 25404aa7..aded059a 100644
--- a/ext/openssl/ossl_pkey_dsa.c
+++ b/ext/openssl/ossl_pkey_dsa.c
@@ -254,16 +254,10 @@ ossl_dsa_to_der(VALUE self)
}
-/*
- * call-seq:
- * dsa.params -> hash
- *
- * Stores all parameters of key to the hash
- * INSECURE: PRIVATE INFORMATIONS CAN LEAK OUT!!!
- * Don't use :-)) (I's up to you)
- */
+#ifndef HAVE_EVP_PKEY_TODATA
+/* :nodoc: */
static VALUE
-ossl_dsa_get_params(VALUE self)
+ossl_dsa_to_data(VALUE self)
{
DSA *dsa;
VALUE hash;
@@ -274,14 +268,15 @@ ossl_dsa_get_params(VALUE self)
DSA_get0_key(dsa, &pub_key, &priv_key);
hash = rb_hash_new();
- rb_hash_aset(hash, rb_str_new2("p"), ossl_bn_new(p));
- rb_hash_aset(hash, rb_str_new2("q"), ossl_bn_new(q));
- rb_hash_aset(hash, rb_str_new2("g"), ossl_bn_new(g));
- rb_hash_aset(hash, rb_str_new2("pub_key"), ossl_bn_new(pub_key));
- rb_hash_aset(hash, rb_str_new2("priv_key"), ossl_bn_new(priv_key));
+ rb_hash_aset(hash, ID2SYM(rb_intern("p")), p ? ossl_bn_new(p) : Qnil);
+ rb_hash_aset(hash, ID2SYM(rb_intern("q")), q ? ossl_bn_new(q) : Qnil);
+ rb_hash_aset(hash, ID2SYM(rb_intern("g")), g ? ossl_bn_new(g) : Qnil);
+ rb_hash_aset(hash, ID2SYM(rb_intern("pub")), pub_key ? ossl_bn_new(pub_key) : Qnil);
+ rb_hash_aset(hash, ID2SYM(rb_intern("priv")), priv_key ? ossl_bn_new(priv_key) : Qnil);
return hash;
}
+#endif
/*
* Document-method: OpenSSL::PKey::DSA#set_pqg
@@ -348,7 +343,9 @@ Init_ossl_dsa(void)
rb_define_method(cDSA, "set_pqg", ossl_dsa_set_pqg, 3);
rb_define_method(cDSA, "set_key", ossl_dsa_set_key, 2);
- rb_define_method(cDSA, "params", ossl_dsa_get_params, 0);
+#ifndef HAVE_EVP_PKEY_TODATA
+ rb_define_method(cDSA, "to_data", ossl_dsa_to_data, 0);
+#endif
}
#else /* defined NO_DSA */
diff --git a/ext/openssl/ossl_pkey_ec.c b/ext/openssl/ossl_pkey_ec.c
index dee21544..9831c315 100644
--- a/ext/openssl/ossl_pkey_ec.c
+++ b/ext/openssl/ossl_pkey_ec.c
@@ -500,6 +500,31 @@ static VALUE ossl_ec_key_check_key(VALUE self)
return Qtrue;
}
+#ifndef HAVE_EVP_PKEY_TODATA
+/* :nodoc: */
+static VALUE
+ossl_ec_key_to_data(VALUE self)
+{
+ EC_KEY *ec;
+ const EC_GROUP *group;
+ const BIGNUM *priv;
+ int nid;
+ VALUE hash;
+
+ /* FIXME: INCOMPLETE: What about non-named curves? Other components? */
+ GetEC(self, ec);
+ group = EC_KEY_get0_group(ec);
+ nid = EC_GROUP_get_curve_name(group);
+ priv = EC_KEY_get0_private_key(ec);
+
+ hash = rb_hash_new();
+ rb_hash_aset(hash, ID2SYM(rb_intern("group")), rb_str_new2(OBJ_nid2sn(nid)));
+ rb_hash_aset(hash, ID2SYM(rb_intern("priv")), priv ? ossl_bn_new(priv) : Qnil);
+
+ return hash;
+}
+#endif
+
/*
* OpenSSL::PKey::EC::Group
*/
@@ -1570,6 +1595,9 @@ void Init_ossl_ec(void)
rb_define_alias(cEC, "to_pem", "export");
rb_define_method(cEC, "to_der", ossl_ec_key_to_der, 0);
+#ifndef HAVE_EVP_PKEY_TODATA
+ rb_define_method(cEC, "to_data", ossl_ec_key_to_data, 0);
+#endif
rb_define_alloc_func(cEC_GROUP, ossl_ec_group_alloc);
rb_define_method(cEC_GROUP, "initialize", ossl_ec_group_initialize, -1);
diff --git a/ext/openssl/ossl_pkey_rsa.c b/ext/openssl/ossl_pkey_rsa.c
index 4d66010f..c731ce00 100644
--- a/ext/openssl/ossl_pkey_rsa.c
+++ b/ext/openssl/ossl_pkey_rsa.c
@@ -439,19 +439,10 @@ ossl_rsa_verify_pss(int argc, VALUE *argv, VALUE self)
ossl_raise(eRSAError, NULL);
}
-/*
- * call-seq:
- * rsa.params => hash
- *
- * THIS METHOD IS INSECURE, PRIVATE INFORMATION CAN LEAK OUT!!!
- *
- * Stores all parameters of key to the hash. The hash has keys 'n', 'e', 'd',
- * 'p', 'q', 'dmp1', 'dmq1', 'iqmp'.
- *
- * Don't use :-)) (It's up to you)
- */
+#ifndef HAVE_EVP_PKEY_TODATA
+/* :nodoc: */
static VALUE
-ossl_rsa_get_params(VALUE self)
+ossl_rsa_to_data(VALUE self)
{
RSA *rsa;
VALUE hash;
@@ -463,17 +454,18 @@ ossl_rsa_get_params(VALUE self)
RSA_get0_crt_params(rsa, &dmp1, &dmq1, &iqmp);
hash = rb_hash_new();
- rb_hash_aset(hash, rb_str_new2("n"), ossl_bn_new(n));
- rb_hash_aset(hash, rb_str_new2("e"), ossl_bn_new(e));
- rb_hash_aset(hash, rb_str_new2("d"), ossl_bn_new(d));
- rb_hash_aset(hash, rb_str_new2("p"), ossl_bn_new(p));
- rb_hash_aset(hash, rb_str_new2("q"), ossl_bn_new(q));
- rb_hash_aset(hash, rb_str_new2("dmp1"), ossl_bn_new(dmp1));
- rb_hash_aset(hash, rb_str_new2("dmq1"), ossl_bn_new(dmq1));
- rb_hash_aset(hash, rb_str_new2("iqmp"), ossl_bn_new(iqmp));
+ rb_hash_aset(hash, ID2SYM(rb_intern("n")), n ? ossl_bn_new(n) : Qnil);
+ rb_hash_aset(hash, ID2SYM(rb_intern("e")), e ? ossl_bn_new(e) : Qnil);
+ rb_hash_aset(hash, ID2SYM(rb_intern("d")), d ? ossl_bn_new(d) : Qnil);
+ rb_hash_aset(hash, ID2SYM(rb_intern("rsa-factor1")), p ? ossl_bn_new(p) : Qnil);
+ rb_hash_aset(hash, ID2SYM(rb_intern("rsa-factor2")), q ? ossl_bn_new(q) : Qnil);
+ rb_hash_aset(hash, ID2SYM(rb_intern("rsa-exponent1")), dmp1 ? ossl_bn_new(dmp1) : Qnil);
+ rb_hash_aset(hash, ID2SYM(rb_intern("rsa-exponent2")), dmq1 ? ossl_bn_new(dmq1) : Qnil);
+ rb_hash_aset(hash, ID2SYM(rb_intern("rsa-coefficient1")), iqmp ? ossl_bn_new(iqmp) : Qnil);
return hash;
}
+#endif
/*
* Document-method: OpenSSL::PKey::RSA#set_key
@@ -562,7 +554,9 @@ Init_ossl_rsa(void)
rb_define_method(cRSA, "set_factors", ossl_rsa_set_factors, 2);
rb_define_method(cRSA, "set_crt_params", ossl_rsa_set_crt_params, 3);
- rb_define_method(cRSA, "params", ossl_rsa_get_params, 0);
+#ifndef HAVE_EVP_PKEY_TODATA
+ rb_define_method(cRSA, "to_data", ossl_rsa_to_data, 0);
+#endif
/*
* TODO: Test it
diff --git a/lib/openssl/pkey.rb b/lib/openssl/pkey.rb
index c3e06290..447f7788 100644
--- a/lib/openssl/pkey.rb
+++ b/lib/openssl/pkey.rb
@@ -10,6 +10,17 @@ module OpenSSL::PKey
class DH
include OpenSSL::Marshal
+ def params
+ data = to_data
+ {
+ "p" => data[:p] || 0.to_bn,
+ "q" => data[:q] || 0.to_bn,
+ "g" => data[:g] || 0.to_bn,
+ "pub_key" => data[:pub] || 0.to_bn,
+ "priv_key" => data[:priv] || 0.to_bn,
+ }
+ end
+
# :call-seq:
# dh.public_key -> dhnew
#
@@ -138,6 +149,17 @@ module OpenSSL::PKey
class DSA
include OpenSSL::Marshal
+ def params
+ data = to_data
+ {
+ "p" => data[:p] || 0.to_bn,
+ "q" => data[:q] || 0.to_bn,
+ "g" => data[:g] || 0.to_bn,
+ "pub_key" => data[:pub] || 0.to_bn,
+ "priv_key" => data[:priv] || 0.to_bn,
+ }
+ end
+
# :call-seq:
# dsa.public_key -> dsanew
#
@@ -305,6 +327,20 @@ module OpenSSL::PKey
class RSA
include OpenSSL::Marshal
+ def params
+ data = to_data
+ {
+ "n" => data[:n] || 0.to_bn,
+ "e" => data[:e] || 0.to_bn,
+ "d" => data[:d] || 0.to_bn,
+ "p" => data[:"rsa-factor1"] || 0.to_bn,
+ "q" => data[:"rsa-factor2"] || 0.to_bn,
+ "dmp1" => data[:"rsa-exponent1"] || 0.to_bn,
+ "dmq1" => data[:"rsa-exponent2"] || 0.to_bn,
+ "iqmp" => data[:"rsa-coefficient1"] || 0.to_bn,
+ }
+ end
+
# :call-seq:
# rsa.public_key -> rsanew
#
diff --git a/test/openssl/test_pkey_dh.rb b/test/openssl/test_pkey_dh.rb
index 161af189..17d573aa 100644
--- a/test/openssl/test_pkey_dh.rb
+++ b/test/openssl/test_pkey_dh.rb
@@ -135,6 +135,15 @@ class OpenSSL::TestPKeyDH < OpenSSL::PKeyTestCase
assert_equal [dh3.pub_key, dh3.priv_key], [dh4.pub_key, dh4.priv_key]
end
+ def test_set_components
+ dh1 = Fixtures.pkey("dh-1")
+ dh2 = Fixtures.pkey("dh1024")
+ assert_not_equal dh1.to_der, dh2.to_der
+
+ dh2.set_pqg(dh1.p, dh1.q, dh1.g)
+ assert_equal dh1.to_der, dh2.to_der
+ end if !openssl?(3, 0, 0)
+
def test_marshal
dh = Fixtures.pkey("dh1024")
deserialized = Marshal.load(Marshal.dump(dh))
@@ -142,6 +151,36 @@ class OpenSSL::TestPKeyDH < OpenSSL::PKeyTestCase
assert_equal dh.to_der, deserialized.to_der
end
+ def test_to_data
+ # PKCS #3 DH - q does not exist
+ dh = OpenSSL::PKey.generate_key(Fixtures.pkey("dh1024"))
+
+ # #params
+ params_keys = %w{p g pub_key priv_key}
+ params = dh.params
+ assert_equal [], params_keys - params.keys
+
+ # #to_data; may contain additional entries
+ data_keys = %w{p g pub priv}
+ data = dh.to_data
+ assert_equal [], data_keys.map(&:intern) - data.keys
+
+ # Check value
+ assert_equal dh.p, params["p"]
+ assert_equal dh.p, data[:p]
+ assert_equal 1024, dh.p.num_bits
+ assert_equal true, dh.p.prime?
+
+ params_keys.each_with_index do |pk, i|
+ dk = data_keys[i]
+ getter_value = dh.public_send(pk)
+
+ assert_kind_of OpenSSL::BN, getter_value
+ assert_equal getter_value, params[pk]
+ assert_equal getter_value, data[dk.intern]
+ end
+ end
+
private
def assert_no_key(dh)
diff --git a/test/openssl/test_pkey_dsa.rb b/test/openssl/test_pkey_dsa.rb
index 726b7dbf..982dce7c 100644
--- a/test/openssl/test_pkey_dsa.rb
+++ b/test/openssl/test_pkey_dsa.rb
@@ -223,6 +223,35 @@ fWLOqqkzFeRrYMDzUpl36XktY6Yq8EJYlW9pCMmBVNy/dQ==
assert_equal key.to_der, deserialized.to_der
end
+ def test_to_data
+ dsa = Fixtures.pkey("dsa1024")
+
+ # #params and gettters
+ params_keys = %w{p q g pub_key priv_key}
+ params = dsa.params
+ assert_equal [], params_keys - params.keys
+
+ # #to_data; may contain additional entries
+ data_keys = %w{p q g pub priv}
+ data = dsa.to_data
+ assert_equal [], data_keys.map(&:intern) - data.keys
+
+ # Check value
+ assert_equal dsa.p, params["p"]
+ assert_equal dsa.p, data[:p]
+ assert_equal 1024, dsa.p.num_bits
+ assert_equal true, dsa.p.prime?
+
+ params_keys.each_with_index do |pk, i|
+ dk = data_keys[i]
+ getter_value = dsa.public_send(pk)
+
+ assert_kind_of OpenSSL::BN, getter_value
+ assert_equal getter_value, params[pk]
+ assert_equal getter_value, data[dk.intern]
+ end
+ end
+
private
def assert_same_dsa(expected, key)
check_component(expected, key, [:p, :q, :g, :pub_key, :priv_key])
diff --git a/test/openssl/test_pkey_ec.rb b/test/openssl/test_pkey_ec.rb
index ffe5a94e..4670c10a 100644
--- a/test/openssl/test_pkey_ec.rb
+++ b/test/openssl/test_pkey_ec.rb
@@ -72,6 +72,14 @@ class OpenSSL::TestEC < OpenSSL::PKeyTestCase
assert_equal key.to_der, deserialized.to_der
end
+ def test_to_data
+ p256 = Fixtures.pkey("p256")
+
+ data = p256.to_data
+ assert_equal "prime256v1", data[:group]
+ assert_equal p256.private_key, data[:priv]
+ end
+
def test_check_key
key0 = Fixtures.pkey("p256")
assert_equal(true, key0.check_key)
diff --git a/test/openssl/test_pkey_rsa.rb b/test/openssl/test_pkey_rsa.rb
index 4bb39ed4..5030af16 100644
--- a/test/openssl/test_pkey_rsa.rb
+++ b/test/openssl/test_pkey_rsa.rb
@@ -535,6 +535,54 @@ class OpenSSL::TestPKeyRSA < OpenSSL::PKeyTestCase
assert_equal key.to_der, deserialized.to_der
end
+ def test_to_data
+ rsa = Fixtures.pkey("rsa2048")
+
+ # #params
+ params_keys = %w{n e d p q dmp1 dmq1 iqmp}
+ params = rsa.params
+ assert_equal [], params_keys - params.keys
+
+ # #to_data; may contain additional keys
+ data_keys = %w{n e d rsa-factor1 rsa-factor2 rsa-exponent1 rsa-exponent2 rsa-coefficient1}
+ data = rsa.to_data
+ assert_equal [], data_keys.map(&:intern) - data.keys
+
+ # Check value
+ assert_equal rsa.n, params["n"]
+ assert_equal rsa.n, data[:n]
+ assert_equal 2048, rsa.n.num_bits
+
+ params_keys.each_with_index do |pk, i|
+ dk = data_keys[i]
+ getter_value = rsa.public_send(pk)
+
+ assert_kind_of OpenSSL::BN, getter_value
+ assert_equal getter_value, params[pk]
+ assert_equal getter_value, data[dk.intern]
+ end
+ end
+
+ def test_to_data_public
+ rsa = OpenSSL::PKey.read(Fixtures.pkey("rsa2048").public_to_der)
+
+ # params: missing components will be BN 0
+ params = rsa.params
+ assert_equal %w{n e d p q dmp1 dmq1 iqmp}, params.keys
+ assert_equal 65537.to_bn, params["e"]
+ assert_equal 0.to_bn, params["d"]
+
+ # to_data
+ data = rsa.to_data
+ assert_equal [], %i{n e} - data.keys
+ assert_equal nil, data[:d]
+ assert_equal 65537.to_bn, data[:e]
+
+ # #d returns nil
+ assert_equal 65537.to_bn, rsa.e
+ assert_equal nil, rsa.d
+ end
+
private
def assert_same_rsa(expected, key)
check_component(expected, key, [:n, :e, :d, :p, :q, :dmp1, :dmq1, :iqmp])