Skip to content

Commit 717fe3f

Browse files
committed
Add private?/public? methods and Marshal support to OpenSSL::PKey::PKey
1 parent 93213b2 commit 717fe3f

File tree

3 files changed

+68
-0
lines changed

3 files changed

+68
-0
lines changed

ext/openssl/ossl_pkey.c

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -568,6 +568,25 @@ ossl_pkey_inspect(VALUE self)
568568
OBJ_nid2sn(nid));
569569
}
570570

571+
/*
572+
* call-seq:
573+
* key.private? => true or false
574+
*
575+
* Returns whether this PKey instance has a private key. The private key can
576+
* be retrieved with PKey#private_to_{der,pem,raw}.
577+
*/
578+
static VALUE ossl_pkey_is_private(VALUE self)
579+
{
580+
EVP_PKEY *pkey;
581+
size_t len;
582+
583+
GetPKey(self, pkey);
584+
len = EVP_PKEY_size(pkey);
585+
unsigned char str[len];
586+
587+
return EVP_PKEY_get_raw_private_key(pkey, str, &len) == 1 ? Qtrue : Qfalse;
588+
}
589+
571590
VALUE
572591
ossl_pkey_export_traditional(int argc, VALUE *argv, VALUE self, int to_der)
573592
{
@@ -708,6 +727,25 @@ ossl_pkey_export_spki(VALUE self, int to_der)
708727
return ossl_membio2str(bio);
709728
}
710729

730+
/*
731+
* call-seq:
732+
* key.public? => true or false
733+
*
734+
* Returns whether this PKey instance has a public key. The public key can
735+
* be retrieved with PKey#public_to_{der,pem,raw}.
736+
*/
737+
static VALUE ossl_pkey_is_public(VALUE self)
738+
{
739+
EVP_PKEY *pkey;
740+
size_t len;
741+
742+
GetPKey(self, pkey);
743+
len = EVP_PKEY_size(pkey);
744+
unsigned char str[len];
745+
746+
return EVP_PKEY_get_raw_public_key(pkey, str, &len) == 1 ? Qtrue : Qfalse;
747+
}
748+
711749
/*
712750
* call-seq:
713751
* pkey.public_to_der -> string
@@ -1027,8 +1065,10 @@ Init_ossl_pkey(void)
10271065
rb_define_method(cPKey, "initialize", ossl_pkey_initialize, 0);
10281066
rb_define_method(cPKey, "oid", ossl_pkey_oid, 0);
10291067
rb_define_method(cPKey, "inspect", ossl_pkey_inspect, 0);
1068+
rb_define_method(cPKey, "private?", ossl_pkey_is_private, 0);
10301069
rb_define_method(cPKey, "private_to_der", ossl_pkey_private_to_der, -1);
10311070
rb_define_method(cPKey, "private_to_pem", ossl_pkey_private_to_pem, -1);
1071+
rb_define_method(cPKey, "public?", ossl_pkey_is_public, 0);
10321072
rb_define_method(cPKey, "public_to_der", ossl_pkey_public_to_der, 0);
10331073
rb_define_method(cPKey, "public_to_pem", ossl_pkey_public_to_pem, 0);
10341074

lib/openssl/pkey.rb

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,20 @@ def to_bn(conversion_form = group.point_conversion_form)
6969
end
7070
end
7171

72+
class PKey
73+
def self._load(string)
74+
OpenSSL::PKey.read(string)
75+
end
76+
77+
def _dump(_level)
78+
if private?
79+
private_to_der
80+
else
81+
public_to_der
82+
end
83+
end
84+
end
85+
7286
class RSA
7387
include OpenSSL::Marshal
7488
end

test/openssl/test_pkey.rb

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -103,8 +103,18 @@ def test_ed25519
103103
assert_instance_of OpenSSL::PKey::PKey, priv
104104
assert_instance_of OpenSSL::PKey::PKey, pub
105105
assert_equal priv_pem, priv.private_to_pem
106+
assert_equal true, priv.private?
107+
assert_equal true, priv.public?
108+
priv_deserialized = Marshal.load(Marshal.dump(priv))
109+
assert_equal priv.private_to_der, priv_deserialized.private_to_der
110+
106111
assert_equal pub_pem, priv.public_to_pem
107112
assert_equal pub_pem, pub.public_to_pem
113+
assert_equal false, pub.private?
114+
assert_equal true, pub.public?
115+
pub_deserialized = Marshal.load(Marshal.dump(pub))
116+
assert_equal pub.public_to_der, pub_deserialized.public_to_der
117+
108118

109119
sig = [<<~EOF.gsub(/[^0-9a-f]/, "")].pack("H*")
110120
92a009a9f0d4cab8720e820b5f642540
@@ -150,5 +160,9 @@ def test_x25519
150160
assert_equal alice_pem, alice.private_to_pem
151161
assert_equal bob_pem, bob.public_to_pem
152162
assert_equal [shared_secret].pack("H*"), alice.derive(bob)
163+
alice_deserialized = Marshal.load(Marshal.dump(alice))
164+
assert_equal alice.private_to_der, alice_deserialized.private_to_der
165+
bob_deserialized = Marshal.load(Marshal.dump(bob))
166+
assert_equal bob.public_to_der, bob_deserialized.public_to_der
153167
end
154168
end

0 commit comments

Comments
 (0)