Skip to content

Commit 0bf51da

Browse files
committed
Add compare? method to OpenSSL::PKey that wraps EVP_PKEY_cmp.
Explicitly check for type given some conflicting statements within openssl's documentation around EVP_PKEY_cmp and EVP_PKEY_ASN1_METHOD(3). Add documentation with an example for compare?
1 parent b362c0a commit 0bf51da

File tree

2 files changed

+57
-0
lines changed

2 files changed

+57
-0
lines changed

ext/openssl/ossl_pkey.c

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -732,6 +732,44 @@ ossl_pkey_public_to_pem(VALUE self)
732732
return ossl_pkey_export_spki(self, 0);
733733
}
734734

735+
/*
736+
* call-seq:
737+
* pkey.compare?(another_pkey) -> true | false
738+
*
739+
* Used primarily to check if an OpenSSL::X509::Certificate#public_key compares to its private key.
740+
*
741+
* == Example
742+
* x509 = OpenSSL::X509::Certificate.new(pem_encoded_certificate)
743+
* rsa_key = OpenSSL::PKey::RSA.new(pem_encoded_private_key)
744+
*
745+
* rsa_key.compare?(x509.public_key) => true | false
746+
*/
747+
static VALUE
748+
ossl_pkey_compare(VALUE self, VALUE other)
749+
{
750+
int ret;
751+
EVP_PKEY *selfPKey;
752+
EVP_PKEY *otherPKey;
753+
754+
GetPKey(self, selfPKey);
755+
GetPKey(other, otherPKey);
756+
757+
/* Explicitly check the key type given EVP_PKEY_ASN1_METHOD(3)
758+
* docs param_cmp could return any negative number.
759+
*/
760+
if (EVP_PKEY_id(selfPKey) != EVP_PKEY_id(otherPKey))
761+
ossl_raise(rb_eTypeError, "cannot match different PKey types");
762+
763+
ret = EVP_PKEY_cmp(selfPKey, otherPKey);
764+
765+
if (ret == 0)
766+
return Qfalse;
767+
else if (ret == 1)
768+
return Qtrue;
769+
else
770+
ossl_raise(ePKeyError, "EVP_PKEY_cmp");
771+
}
772+
735773
/*
736774
* call-seq:
737775
* pkey.sign(digest, data) -> String
@@ -1031,6 +1069,7 @@ Init_ossl_pkey(void)
10311069
rb_define_method(cPKey, "private_to_pem", ossl_pkey_private_to_pem, -1);
10321070
rb_define_method(cPKey, "public_to_der", ossl_pkey_public_to_der, 0);
10331071
rb_define_method(cPKey, "public_to_pem", ossl_pkey_public_to_pem, 0);
1072+
rb_define_method(cPKey, "compare?", ossl_pkey_compare, 1);
10341073

10351074
rb_define_method(cPKey, "sign", ossl_pkey_sign, 2);
10361075
rb_define_method(cPKey, "verify", ossl_pkey_verify, 3);

test/openssl/test_pkey.rb

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -151,4 +151,22 @@ def test_x25519
151151
assert_equal bob_pem, bob.public_to_pem
152152
assert_equal [shared_secret].pack("H*"), alice.derive(bob)
153153
end
154+
155+
def test_compare?
156+
key1 = Fixtures.pkey("rsa1024")
157+
key2 = Fixtures.pkey("rsa1024")
158+
key3 = Fixtures.pkey("rsa2048")
159+
key4 = Fixtures.pkey("dh-1")
160+
161+
assert_equal(true, key1.compare?(key2))
162+
assert_equal(true, key1.public_key.compare?(key2))
163+
assert_equal(true, key2.compare?(key1))
164+
assert_equal(true, key2.public_key.compare?(key1))
165+
166+
assert_equal(false, key1.compare?(key3))
167+
168+
assert_raise(TypeError) do
169+
key1.compare?(key4)
170+
end
171+
end
154172
end

0 commit comments

Comments
 (0)