Skip to content

Commit 8f7467f

Browse files
committed
Add OpenSSL::PKey.private_new, #private_to_raw and public equivalents
1 parent 717fe3f commit 8f7467f

File tree

2 files changed

+127
-0
lines changed

2 files changed

+127
-0
lines changed

ext/openssl/ossl_pkey.c

Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -532,6 +532,56 @@ ossl_pkey_initialize(VALUE self)
532532
return self;
533533
}
534534

535+
/*
536+
* call-seq:
537+
* OpenSSL::PKey.private_new(algo, string) -> PKey
538+
*
539+
* See the OpenSSL documentation for EVP_PKEY_new_raw_private_key()
540+
*/
541+
542+
static VALUE
543+
ossl_pkey_initialize_private(VALUE self, VALUE type, VALUE key)
544+
{
545+
EVP_PKEY *pkey;
546+
int nid;
547+
size_t keylen;
548+
549+
nid = OBJ_sn2nid(StringValueCStr(type));
550+
if(!nid) ossl_raise(ePKeyError, "unknown OID `%"PRIsVALUE"'", type);
551+
552+
keylen = RSTRING_LEN(key);
553+
pkey = EVP_PKEY_new_raw_private_key(nid, NULL, (unsigned char *)RSTRING_PTR(key), keylen);
554+
if (!pkey)
555+
ossl_raise(ePKeyError, "Could not parse PKey");
556+
557+
return ossl_pkey_new(pkey);
558+
}
559+
560+
/*
561+
* call-seq:
562+
* OpenSSL::PKey.public_new(algo, string) -> PKey
563+
*
564+
* See the OpenSSL documentation for EVP_PKEY_new_raw_public_key()
565+
*/
566+
567+
static VALUE
568+
ossl_pkey_initialize_public(VALUE self, VALUE type, VALUE key)
569+
{
570+
EVP_PKEY *pkey;
571+
int nid;
572+
size_t keylen;
573+
574+
nid = OBJ_sn2nid(StringValueCStr(type));
575+
if(!nid) ossl_raise(ePKeyError, "unknown OID `%"PRIsVALUE"'", type);
576+
577+
keylen = RSTRING_LEN(key);
578+
pkey = EVP_PKEY_new_raw_public_key(nid, NULL, (unsigned char *)RSTRING_PTR(key), keylen);
579+
if (!pkey)
580+
ossl_raise(ePKeyError, "Could not parse PKey");
581+
582+
return ossl_pkey_new(pkey);
583+
}
584+
535585
/*
536586
* call-seq:
537587
* pkey.oid -> string
@@ -702,6 +752,30 @@ ossl_pkey_private_to_pem(int argc, VALUE *argv, VALUE self)
702752
return do_pkcs8_export(argc, argv, self, 0);
703753
}
704754

755+
/*
756+
* call-seq:
757+
* key.private_to_raw => string
758+
*
759+
* See the OpenSSL documentation for EVP_PKEY_get_raw_private_key()
760+
*/
761+
static VALUE ossl_pkey_private_to_raw(VALUE self)
762+
{
763+
EVP_PKEY *pkey;
764+
VALUE str;
765+
size_t len;
766+
767+
GetPKey(self, pkey);
768+
EVP_PKEY_get_raw_private_key(pkey, NULL, &len);
769+
str = rb_str_new(NULL, len);
770+
771+
if (EVP_PKEY_get_raw_private_key(pkey, (unsigned char *)RSTRING_PTR(str), &len) != 1)
772+
ossl_raise(ePKeyError, "EVP_PKEY_get_raw_private_key");
773+
774+
rb_str_set_len(str, len);
775+
776+
return str;
777+
}
778+
705779
VALUE
706780
ossl_pkey_export_spki(VALUE self, int to_der)
707781
{
@@ -770,6 +844,30 @@ ossl_pkey_public_to_pem(VALUE self)
770844
return ossl_pkey_export_spki(self, 0);
771845
}
772846

847+
/*
848+
* call-seq:
849+
* key.public_to_raw => string
850+
*
851+
* See the OpenSSL documentation for EVP_PKEY_get_raw_public_key()
852+
*/
853+
static VALUE ossl_pkey_public_to_raw(VALUE self)
854+
{
855+
EVP_PKEY *pkey;
856+
VALUE str;
857+
size_t len;
858+
859+
GetPKey(self, pkey);
860+
EVP_PKEY_get_raw_public_key(pkey, NULL, &len);
861+
str = rb_str_new(NULL, len);
862+
863+
if (EVP_PKEY_get_raw_public_key(pkey, (unsigned char *)RSTRING_PTR(str), &len) != 1)
864+
ossl_raise(ePKeyError, "EVP_PKEY_get_raw_public_key");
865+
866+
rb_str_set_len(str, len);
867+
868+
return str;
869+
}
870+
773871
/*
774872
* call-seq:
775873
* pkey.sign(digest, data) -> String
@@ -1060,6 +1158,8 @@ Init_ossl_pkey(void)
10601158
rb_define_module_function(mPKey, "read", ossl_pkey_new_from_data, -1);
10611159
rb_define_module_function(mPKey, "generate_parameters", ossl_pkey_s_generate_parameters, -1);
10621160
rb_define_module_function(mPKey, "generate_key", ossl_pkey_s_generate_key, -1);
1161+
rb_define_module_function(mPKey, "private_new", ossl_pkey_initialize_private, 2);
1162+
rb_define_module_function(mPKey, "public_new", ossl_pkey_initialize_public, 2);
10631163

10641164
rb_define_alloc_func(cPKey, ossl_pkey_alloc);
10651165
rb_define_method(cPKey, "initialize", ossl_pkey_initialize, 0);
@@ -1068,9 +1168,11 @@ Init_ossl_pkey(void)
10681168
rb_define_method(cPKey, "private?", ossl_pkey_is_private, 0);
10691169
rb_define_method(cPKey, "private_to_der", ossl_pkey_private_to_der, -1);
10701170
rb_define_method(cPKey, "private_to_pem", ossl_pkey_private_to_pem, -1);
1171+
rb_define_method(cPKey, "private_to_raw", ossl_pkey_private_to_raw, 0);
10711172
rb_define_method(cPKey, "public?", ossl_pkey_is_public, 0);
10721173
rb_define_method(cPKey, "public_to_der", ossl_pkey_public_to_der, 0);
10731174
rb_define_method(cPKey, "public_to_pem", ossl_pkey_public_to_pem, 0);
1175+
rb_define_method(cPKey, "public_to_raw", ossl_pkey_public_to_raw, 0);
10741176

10751177
rb_define_method(cPKey, "sign", ossl_pkey_sign, 2);
10761178
rb_define_method(cPKey, "verify", ossl_pkey_verify, 3);

test/openssl/test_pkey.rb

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -107,13 +107,21 @@ def test_ed25519
107107
assert_equal true, priv.public?
108108
priv_deserialized = Marshal.load(Marshal.dump(priv))
109109
assert_equal priv.private_to_der, priv_deserialized.private_to_der
110+
assert_equal "4ccd089b28ff96da9db6c346ec114e0f5b8a319f35aba624da8cf6ed4fb8a6fb",
111+
priv.private_to_raw.unpack1("H*")
112+
assert_equal OpenSSL::PKey.private_new("ED25519", priv.private_to_raw).private_to_pem,
113+
priv.private_to_pem
110114

111115
assert_equal pub_pem, priv.public_to_pem
112116
assert_equal pub_pem, pub.public_to_pem
113117
assert_equal false, pub.private?
114118
assert_equal true, pub.public?
115119
pub_deserialized = Marshal.load(Marshal.dump(pub))
116120
assert_equal pub.public_to_der, pub_deserialized.public_to_der
121+
assert_equal "3d4017c3e843895a92b70aa74d1b7ebc9c982ccf2ec4968cc0cd55f12af4660c",
122+
priv.public_to_raw.unpack1("H*")
123+
assert_equal OpenSSL::PKey.public_new("ED25519", priv.public_to_raw).public_to_pem,
124+
pub.public_to_pem
117125

118126

119127
sig = [<<~EOF.gsub(/[^0-9a-f]/, "")].pack("H*")
@@ -164,5 +172,22 @@ def test_x25519
164172
assert_equal alice.private_to_der, alice_deserialized.private_to_der
165173
bob_deserialized = Marshal.load(Marshal.dump(bob))
166174
assert_equal bob.public_to_der, bob_deserialized.public_to_der
175+
assert_equal "77076d0a7318a57d3c16c17251b26645df4c2f87ebc0992ab177fba51db92c2a",
176+
alice.private_to_raw.unpack1("H*")
177+
assert_equal OpenSSL::PKey.private_new("X25519", alice.private_to_raw).private_to_pem,
178+
alice.private_to_pem
179+
assert_equal "de9edb7d7b7dc1b4d35b61c2ece435373f8343c85b78674dadfc7e146f882b4f",
180+
bob.public_to_raw.unpack1("H*")
181+
assert_equal OpenSSL::PKey.public_new("X25519", bob.public_to_raw).public_to_pem,
182+
bob.public_to_pem
183+
end
184+
185+
def raw_initialize
186+
pend "Ed25519 is not implemented" unless OpenSSL::OPENSSL_VERSION_NUMBER >= 0x10101000 && # >= v1.1.1
187+
188+
assert_raise(OpenSSL::PKey::PKeyError) { OpenSSL::PKey.private_new("foo123", "xxx") }
189+
assert_raise(OpenSSL::PKey::PKeyError) { OpenSSL::PKey.private_new("ED25519", "xxx") }
190+
assert_raise(OpenSSL::PKey::PKeyError) { OpenSSL::PKey.public_new("foo123", "xxx") }
191+
assert_raise(OpenSSL::PKey::PKeyError) { OpenSSL::PKey.public_new("ED25519", "xxx") }
167192
end
168193
end

0 commit comments

Comments
 (0)