Skip to content

Commit

Permalink
Merge pull request #382 from rhenium/ky/pkey-encrypt-decrypt
Browse files Browse the repository at this point in the history
pkey: implement PKey#encrypt, #decrypt, #sign_raw, #verify_raw, and #verify_recover
  • Loading branch information
rhenium authored May 25, 2021
2 parents 508ae95 + ce805ad commit 809646e
Show file tree
Hide file tree
Showing 8 changed files with 684 additions and 317 deletions.
377 changes: 375 additions & 2 deletions ext/openssl/ossl_pkey.c

Large diffs are not rendered by default.

88 changes: 0 additions & 88 deletions ext/openssl/ossl_pkey_dsa.c
Original file line number Diff line number Diff line change
Expand Up @@ -264,92 +264,6 @@ ossl_dsa_get_params(VALUE self)
return hash;
}

/*
* call-seq:
* dsa.syssign(string) -> aString
*
* Computes and returns the DSA signature of _string_, where _string_ is
* expected to be an already-computed message digest of the original input
* data. The signature is issued using the private key of this DSA instance.
*
* === Parameters
* * _string_ is a message digest of the original input data to be signed.
*
* === Example
* dsa = OpenSSL::PKey::DSA.new(2048)
* doc = "Sign me"
* digest = OpenSSL::Digest.digest('SHA1', doc)
* sig = dsa.syssign(digest)
*
*
*/
static VALUE
ossl_dsa_sign(VALUE self, VALUE data)
{
DSA *dsa;
const BIGNUM *dsa_q;
unsigned int buf_len;
VALUE str;

GetDSA(self, dsa);
DSA_get0_pqg(dsa, NULL, &dsa_q, NULL);
if (!dsa_q)
ossl_raise(eDSAError, "incomplete DSA");
if (!DSA_PRIVATE(self, dsa))
ossl_raise(eDSAError, "Private DSA key needed!");
StringValue(data);
str = rb_str_new(0, DSA_size(dsa));
if (!DSA_sign(0, (unsigned char *)RSTRING_PTR(data), RSTRING_LENINT(data),
(unsigned char *)RSTRING_PTR(str),
&buf_len, dsa)) { /* type is ignored (0) */
ossl_raise(eDSAError, NULL);
}
rb_str_set_len(str, buf_len);

return str;
}

/*
* call-seq:
* dsa.sysverify(digest, sig) -> true | false
*
* Verifies whether the signature is valid given the message digest input. It
* does so by validating _sig_ using the public key of this DSA instance.
*
* === Parameters
* * _digest_ is a message digest of the original input data to be signed
* * _sig_ is a DSA signature value
*
* === Example
* dsa = OpenSSL::PKey::DSA.new(2048)
* doc = "Sign me"
* digest = OpenSSL::Digest.digest('SHA1', doc)
* sig = dsa.syssign(digest)
* puts dsa.sysverify(digest, sig) # => true
*
*/
static VALUE
ossl_dsa_verify(VALUE self, VALUE digest, VALUE sig)
{
DSA *dsa;
int ret;

GetDSA(self, dsa);
StringValue(digest);
StringValue(sig);
/* type is ignored (0) */
ret = DSA_verify(0, (unsigned char *)RSTRING_PTR(digest), RSTRING_LENINT(digest),
(unsigned char *)RSTRING_PTR(sig), RSTRING_LENINT(sig), dsa);
if (ret < 0) {
ossl_raise(eDSAError, NULL);
}
else if (ret == 1) {
return Qtrue;
}

return Qfalse;
}

/*
* Document-method: OpenSSL::PKey::DSA#set_pqg
* call-seq:
Expand Down Expand Up @@ -404,8 +318,6 @@ Init_ossl_dsa(void)
rb_define_alias(cDSA, "to_pem", "export");
rb_define_alias(cDSA, "to_s", "export");
rb_define_method(cDSA, "to_der", ossl_dsa_to_der, 0);
rb_define_method(cDSA, "syssign", ossl_dsa_sign, 1);
rb_define_method(cDSA, "sysverify", ossl_dsa_verify, 2);

DEF_OSSL_PKEY_BN(cDSA, dsa, p);
DEF_OSSL_PKEY_BN(cDSA, dsa, q);
Expand Down
55 changes: 0 additions & 55 deletions ext/openssl/ossl_pkey_ec.c
Original file line number Diff line number Diff line change
Expand Up @@ -471,57 +471,6 @@ static VALUE ossl_ec_key_check_key(VALUE self)
return Qtrue;
}

/*
* call-seq:
* key.dsa_sign_asn1(data) => String
*
* See the OpenSSL documentation for ECDSA_sign()
*/
static VALUE ossl_ec_key_dsa_sign_asn1(VALUE self, VALUE data)
{
EC_KEY *ec;
unsigned int buf_len;
VALUE str;

GetEC(self, ec);
StringValue(data);

if (EC_KEY_get0_private_key(ec) == NULL)
ossl_raise(eECError, "Private EC key needed!");

str = rb_str_new(0, ECDSA_size(ec));
if (ECDSA_sign(0, (unsigned char *) RSTRING_PTR(data), RSTRING_LENINT(data), (unsigned char *) RSTRING_PTR(str), &buf_len, ec) != 1)
ossl_raise(eECError, "ECDSA_sign");
rb_str_set_len(str, buf_len);

return str;
}

/*
* call-seq:
* key.dsa_verify_asn1(data, sig) => true or false
*
* See the OpenSSL documentation for ECDSA_verify()
*/
static VALUE ossl_ec_key_dsa_verify_asn1(VALUE self, VALUE data, VALUE sig)
{
EC_KEY *ec;

GetEC(self, ec);
StringValue(data);
StringValue(sig);

switch (ECDSA_verify(0, (unsigned char *) RSTRING_PTR(data), RSTRING_LENINT(data), (unsigned char *) RSTRING_PTR(sig), (int)RSTRING_LEN(sig), ec)) {
case 1: return Qtrue;
case 0: return Qfalse;
default: break;
}

ossl_raise(eECError, "ECDSA_verify");

UNREACHABLE;
}

/*
* OpenSSL::PKey::EC::Group
*/
Expand Down Expand Up @@ -1583,10 +1532,6 @@ void Init_ossl_ec(void)
rb_define_alias(cEC, "generate_key", "generate_key!");
rb_define_method(cEC, "check_key", ossl_ec_key_check_key, 0);

rb_define_method(cEC, "dsa_sign_asn1", ossl_ec_key_dsa_sign_asn1, 1);
rb_define_method(cEC, "dsa_verify_asn1", ossl_ec_key_dsa_verify_asn1, 2);
/* do_sign/do_verify */

rb_define_method(cEC, "export", ossl_ec_key_export, -1);
rb_define_alias(cEC, "to_pem", "export");
rb_define_method(cEC, "to_der", ossl_ec_key_to_der, 0);
Expand Down
141 changes: 0 additions & 141 deletions ext/openssl/ossl_pkey_rsa.c
Original file line number Diff line number Diff line change
Expand Up @@ -229,138 +229,6 @@ ossl_rsa_to_der(VALUE self)
return ossl_pkey_export_spki(self, 1);
}

/*
* call-seq:
* rsa.public_encrypt(string) => String
* rsa.public_encrypt(string, padding) => String
*
* Encrypt _string_ with the public key. _padding_ defaults to PKCS1_PADDING.
* The encrypted string output can be decrypted using #private_decrypt.
*/
static VALUE
ossl_rsa_public_encrypt(int argc, VALUE *argv, VALUE self)
{
RSA *rsa;
const BIGNUM *rsa_n;
int buf_len, pad;
VALUE str, buffer, padding;

GetRSA(self, rsa);
RSA_get0_key(rsa, &rsa_n, NULL, NULL);
if (!rsa_n)
ossl_raise(eRSAError, "incomplete RSA");
rb_scan_args(argc, argv, "11", &buffer, &padding);
pad = (argc == 1) ? RSA_PKCS1_PADDING : NUM2INT(padding);
StringValue(buffer);
str = rb_str_new(0, RSA_size(rsa));
buf_len = RSA_public_encrypt(RSTRING_LENINT(buffer), (unsigned char *)RSTRING_PTR(buffer),
(unsigned char *)RSTRING_PTR(str), rsa, pad);
if (buf_len < 0) ossl_raise(eRSAError, NULL);
rb_str_set_len(str, buf_len);

return str;
}

/*
* call-seq:
* rsa.public_decrypt(string) => String
* rsa.public_decrypt(string, padding) => String
*
* Decrypt _string_, which has been encrypted with the private key, with the
* public key. _padding_ defaults to PKCS1_PADDING.
*/
static VALUE
ossl_rsa_public_decrypt(int argc, VALUE *argv, VALUE self)
{
RSA *rsa;
const BIGNUM *rsa_n;
int buf_len, pad;
VALUE str, buffer, padding;

GetRSA(self, rsa);
RSA_get0_key(rsa, &rsa_n, NULL, NULL);
if (!rsa_n)
ossl_raise(eRSAError, "incomplete RSA");
rb_scan_args(argc, argv, "11", &buffer, &padding);
pad = (argc == 1) ? RSA_PKCS1_PADDING : NUM2INT(padding);
StringValue(buffer);
str = rb_str_new(0, RSA_size(rsa));
buf_len = RSA_public_decrypt(RSTRING_LENINT(buffer), (unsigned char *)RSTRING_PTR(buffer),
(unsigned char *)RSTRING_PTR(str), rsa, pad);
if (buf_len < 0) ossl_raise(eRSAError, NULL);
rb_str_set_len(str, buf_len);

return str;
}

/*
* call-seq:
* rsa.private_encrypt(string) => String
* rsa.private_encrypt(string, padding) => String
*
* Encrypt _string_ with the private key. _padding_ defaults to PKCS1_PADDING.
* The encrypted string output can be decrypted using #public_decrypt.
*/
static VALUE
ossl_rsa_private_encrypt(int argc, VALUE *argv, VALUE self)
{
RSA *rsa;
const BIGNUM *rsa_n;
int buf_len, pad;
VALUE str, buffer, padding;

GetRSA(self, rsa);
RSA_get0_key(rsa, &rsa_n, NULL, NULL);
if (!rsa_n)
ossl_raise(eRSAError, "incomplete RSA");
if (!RSA_PRIVATE(self, rsa))
ossl_raise(eRSAError, "private key needed.");
rb_scan_args(argc, argv, "11", &buffer, &padding);
pad = (argc == 1) ? RSA_PKCS1_PADDING : NUM2INT(padding);
StringValue(buffer);
str = rb_str_new(0, RSA_size(rsa));
buf_len = RSA_private_encrypt(RSTRING_LENINT(buffer), (unsigned char *)RSTRING_PTR(buffer),
(unsigned char *)RSTRING_PTR(str), rsa, pad);
if (buf_len < 0) ossl_raise(eRSAError, NULL);
rb_str_set_len(str, buf_len);

return str;
}

/*
* call-seq:
* rsa.private_decrypt(string) => String
* rsa.private_decrypt(string, padding) => String
*
* Decrypt _string_, which has been encrypted with the public key, with the
* private key. _padding_ defaults to PKCS1_PADDING.
*/
static VALUE
ossl_rsa_private_decrypt(int argc, VALUE *argv, VALUE self)
{
RSA *rsa;
const BIGNUM *rsa_n;
int buf_len, pad;
VALUE str, buffer, padding;

GetRSA(self, rsa);
RSA_get0_key(rsa, &rsa_n, NULL, NULL);
if (!rsa_n)
ossl_raise(eRSAError, "incomplete RSA");
if (!RSA_PRIVATE(self, rsa))
ossl_raise(eRSAError, "private key needed.");
rb_scan_args(argc, argv, "11", &buffer, &padding);
pad = (argc == 1) ? RSA_PKCS1_PADDING : NUM2INT(padding);
StringValue(buffer);
str = rb_str_new(0, RSA_size(rsa));
buf_len = RSA_private_decrypt(RSTRING_LENINT(buffer), (unsigned char *)RSTRING_PTR(buffer),
(unsigned char *)RSTRING_PTR(str), rsa, pad);
if (buf_len < 0) ossl_raise(eRSAError, NULL);
rb_str_set_len(str, buf_len);

return str;
}

/*
* call-seq:
* rsa.sign_pss(digest, data, salt_length:, mgf1_hash:) -> String
Expand Down Expand Up @@ -657,10 +525,6 @@ Init_ossl_rsa(void)
rb_define_alias(cRSA, "to_pem", "export");
rb_define_alias(cRSA, "to_s", "export");
rb_define_method(cRSA, "to_der", ossl_rsa_to_der, 0);
rb_define_method(cRSA, "public_encrypt", ossl_rsa_public_encrypt, -1);
rb_define_method(cRSA, "public_decrypt", ossl_rsa_public_decrypt, -1);
rb_define_method(cRSA, "private_encrypt", ossl_rsa_private_encrypt, -1);
rb_define_method(cRSA, "private_decrypt", ossl_rsa_private_decrypt, -1);
rb_define_method(cRSA, "sign_pss", ossl_rsa_sign_pss, -1);
rb_define_method(cRSA, "verify_pss", ossl_rsa_verify_pss, -1);

Expand All @@ -678,11 +542,6 @@ Init_ossl_rsa(void)

rb_define_method(cRSA, "params", ossl_rsa_get_params, 0);

DefRSAConst(PKCS1_PADDING);
DefRSAConst(SSLV23_PADDING);
DefRSAConst(NO_PADDING);
DefRSAConst(PKCS1_OAEP_PADDING);

/*
* TODO: Test it
rb_define_method(cRSA, "blinding_on!", ossl_rsa_blinding_on, 0);
Expand Down
Loading

0 comments on commit 809646e

Please sign in to comment.