-
Notifications
You must be signed in to change notification settings - Fork 175
OpenSSL::PKey convenience methods #373
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -532,6 +532,56 @@ ossl_pkey_initialize(VALUE self) | |
return self; | ||
} | ||
|
||
/* | ||
* call-seq: | ||
* OpenSSL::PKey.private_new(algo, string) -> PKey | ||
* | ||
* See the OpenSSL documentation for EVP_PKEY_new_raw_private_key() | ||
*/ | ||
|
||
static VALUE | ||
ossl_pkey_initialize_private(VALUE self, VALUE type, VALUE key) | ||
{ | ||
EVP_PKEY *pkey; | ||
int nid; | ||
size_t keylen; | ||
|
||
nid = OBJ_sn2nid(StringValueCStr(type)); | ||
if(!nid) ossl_raise(ePKeyError, "unknown OID `%"PRIsVALUE"'", type); | ||
|
||
keylen = RSTRING_LEN(key); | ||
pkey = EVP_PKEY_new_raw_private_key(nid, NULL, (unsigned char *)RSTRING_PTR(key), keylen); | ||
if (!pkey) | ||
ossl_raise(ePKeyError, "Could not parse PKey"); | ||
|
||
return ossl_pkey_new(pkey); | ||
} | ||
|
||
/* | ||
* call-seq: | ||
* OpenSSL::PKey.public_new(algo, string) -> PKey | ||
* | ||
* See the OpenSSL documentation for EVP_PKEY_new_raw_public_key() | ||
*/ | ||
|
||
static VALUE | ||
ossl_pkey_initialize_public(VALUE self, VALUE type, VALUE key) | ||
{ | ||
EVP_PKEY *pkey; | ||
int nid; | ||
size_t keylen; | ||
|
||
nid = OBJ_sn2nid(StringValueCStr(type)); | ||
if(!nid) ossl_raise(ePKeyError, "unknown OID `%"PRIsVALUE"'", type); | ||
|
||
keylen = RSTRING_LEN(key); | ||
pkey = EVP_PKEY_new_raw_public_key(nid, NULL, (unsigned char *)RSTRING_PTR(key), keylen); | ||
if (!pkey) | ||
ossl_raise(ePKeyError, "Could not parse PKey"); | ||
|
||
return ossl_pkey_new(pkey); | ||
} | ||
|
||
/* | ||
* call-seq: | ||
* pkey.oid -> string | ||
|
@@ -568,6 +618,25 @@ ossl_pkey_inspect(VALUE self) | |
OBJ_nid2sn(nid)); | ||
} | ||
|
||
/* | ||
* call-seq: | ||
* key.private? => true or false | ||
* | ||
* Returns whether this PKey instance has a private key. The private key can | ||
* be retrieved with PKey#private_to_{der,pem,raw}. | ||
*/ | ||
static VALUE ossl_pkey_is_private(VALUE self) | ||
{ | ||
EVP_PKEY *pkey; | ||
size_t len; | ||
|
||
GetPKey(self, pkey); | ||
len = EVP_PKEY_size(pkey); | ||
unsigned char str[len]; | ||
|
||
return EVP_PKEY_get_raw_private_key(pkey, str, &len) == 1 ? Qtrue : Qfalse; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'm pretty sure I'm not doing this right. According to https://www.openssl.org/docs/man1.1.1/man3/EVP_PKEY_get_raw_private_key.html:
However if I pass NULL instead of str the tests fail 🤔 |
||
} | ||
|
||
VALUE | ||
ossl_pkey_export_traditional(int argc, VALUE *argv, VALUE self, int to_der) | ||
{ | ||
|
@@ -683,6 +752,30 @@ ossl_pkey_private_to_pem(int argc, VALUE *argv, VALUE self) | |
return do_pkcs8_export(argc, argv, self, 0); | ||
} | ||
|
||
/* | ||
* call-seq: | ||
* key.private_to_raw => string | ||
* | ||
* See the OpenSSL documentation for EVP_PKEY_get_raw_private_key() | ||
*/ | ||
static VALUE ossl_pkey_private_to_raw(VALUE self) | ||
{ | ||
EVP_PKEY *pkey; | ||
VALUE str; | ||
size_t len; | ||
|
||
GetPKey(self, pkey); | ||
EVP_PKEY_get_raw_private_key(pkey, NULL, &len); | ||
str = rb_str_new(NULL, len); | ||
|
||
if (EVP_PKEY_get_raw_private_key(pkey, (unsigned char *)RSTRING_PTR(str), &len) != 1) | ||
ossl_raise(ePKeyError, "EVP_PKEY_get_raw_private_key"); | ||
|
||
rb_str_set_len(str, len); | ||
|
||
return str; | ||
} | ||
|
||
VALUE | ||
ossl_pkey_export_spki(VALUE self, int to_der) | ||
{ | ||
|
@@ -708,6 +801,25 @@ ossl_pkey_export_spki(VALUE self, int to_der) | |
return ossl_membio2str(bio); | ||
} | ||
|
||
/* | ||
* call-seq: | ||
* key.public? => true or false | ||
* | ||
* Returns whether this PKey instance has a public key. The public key can | ||
* be retrieved with PKey#public_to_{der,pem,raw}. | ||
*/ | ||
static VALUE ossl_pkey_is_public(VALUE self) | ||
{ | ||
EVP_PKEY *pkey; | ||
size_t len; | ||
|
||
GetPKey(self, pkey); | ||
len = EVP_PKEY_size(pkey); | ||
unsigned char str[len]; | ||
|
||
return EVP_PKEY_get_raw_public_key(pkey, str, &len) == 1 ? Qtrue : Qfalse; | ||
} | ||
|
||
/* | ||
* call-seq: | ||
* pkey.public_to_der -> string | ||
|
@@ -732,6 +844,30 @@ ossl_pkey_public_to_pem(VALUE self) | |
return ossl_pkey_export_spki(self, 0); | ||
} | ||
|
||
/* | ||
* call-seq: | ||
* key.public_to_raw => string | ||
* | ||
* See the OpenSSL documentation for EVP_PKEY_get_raw_public_key() | ||
*/ | ||
static VALUE ossl_pkey_public_to_raw(VALUE self) | ||
{ | ||
EVP_PKEY *pkey; | ||
VALUE str; | ||
size_t len; | ||
|
||
GetPKey(self, pkey); | ||
EVP_PKEY_get_raw_public_key(pkey, NULL, &len); | ||
str = rb_str_new(NULL, len); | ||
|
||
if (EVP_PKEY_get_raw_public_key(pkey, (unsigned char *)RSTRING_PTR(str), &len) != 1) | ||
ossl_raise(ePKeyError, "EVP_PKEY_get_raw_public_key"); | ||
|
||
rb_str_set_len(str, len); | ||
|
||
return str; | ||
} | ||
|
||
/* | ||
* call-seq: | ||
* pkey.sign(digest, data) -> String | ||
|
@@ -1022,15 +1158,21 @@ Init_ossl_pkey(void) | |
rb_define_module_function(mPKey, "read", ossl_pkey_new_from_data, -1); | ||
rb_define_module_function(mPKey, "generate_parameters", ossl_pkey_s_generate_parameters, -1); | ||
rb_define_module_function(mPKey, "generate_key", ossl_pkey_s_generate_key, -1); | ||
rb_define_module_function(mPKey, "private_new", ossl_pkey_initialize_private, 2); | ||
rb_define_module_function(mPKey, "public_new", ossl_pkey_initialize_public, 2); | ||
|
||
rb_define_alloc_func(cPKey, ossl_pkey_alloc); | ||
rb_define_method(cPKey, "initialize", ossl_pkey_initialize, 0); | ||
rb_define_method(cPKey, "oid", ossl_pkey_oid, 0); | ||
rb_define_method(cPKey, "inspect", ossl_pkey_inspect, 0); | ||
rb_define_method(cPKey, "private?", ossl_pkey_is_private, 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, "private_to_raw", ossl_pkey_private_to_raw, 0); | ||
rb_define_method(cPKey, "public?", ossl_pkey_is_public, 0); | ||
rb_define_method(cPKey, "public_to_der", ossl_pkey_public_to_der, 0); | ||
rb_define_method(cPKey, "public_to_pem", ossl_pkey_public_to_pem, 0); | ||
rb_define_method(cPKey, "public_to_raw", ossl_pkey_public_to_raw, 0); | ||
|
||
rb_define_method(cPKey, "sign", ossl_pkey_sign, 2); | ||
rb_define_method(cPKey, "verify", ossl_pkey_verify, 3); | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please use EVP_PKEY_asn1_find_str() instead of OBJ_sn2nid().
pkey_generate() is currently doing this. I think it should be extracted as a function.