diff options
author | Kazuki Yamaguchi <k@rhe.jp> | 2021-04-15 18:37:34 +0900 |
---|---|---|
committer | Kazuki Yamaguchi <k@rhe.jp> | 2021-12-20 19:07:59 +0900 |
commit | 1c4d75f21ba70623f1d31d56bea2bd2e346a1e91 (patch) | |
tree | 3e33af618344f7f6225d31a77bea20622eb021de | |
parent | 4403c3cf3ce7fbac7573d3b8e6c0d3ecd0aaa969 (diff) | |
download | ruby-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.rb | 1 | ||||
-rw-r--r-- | ext/openssl/ossl_bn.c | 17 | ||||
-rw-r--r-- | ext/openssl/ossl_bn.h | 3 | ||||
-rw-r--r-- | ext/openssl/ossl_pkey.c | 74 | ||||
-rw-r--r-- | ext/openssl/ossl_pkey_dh.c | 27 | ||||
-rw-r--r-- | ext/openssl/ossl_pkey_dsa.c | 27 | ||||
-rw-r--r-- | ext/openssl/ossl_pkey_ec.c | 28 | ||||
-rw-r--r-- | ext/openssl/ossl_pkey_rsa.c | 36 | ||||
-rw-r--r-- | lib/openssl/pkey.rb | 36 | ||||
-rw-r--r-- | test/openssl/test_pkey_dh.rb | 39 | ||||
-rw-r--r-- | test/openssl/test_pkey_dsa.rb | 29 | ||||
-rw-r--r-- | test/openssl/test_pkey_ec.rb | 8 | ||||
-rw-r--r-- | test/openssl/test_pkey_rsa.rb | 48 |
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 = ¶ms[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, ¶ms) != 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]) |