Skip to content

Commit

Permalink
pkey/dsa: refactor DSA#sys{sign,verify} with PKey#{sign,verify}_raw
Browse files Browse the repository at this point in the history
With the newly added OpenSSL::PKey::PKey#{sign,verify}_raw,
OpenSSL::PKey::DSA's low level signing operation methods can be
implemented in Ruby. The definitions are now in lib/openssl/pkey.rb.
  • Loading branch information
rhenium committed Aug 21, 2020
1 parent 5476ed2 commit 96b92c5
Show file tree
Hide file tree
Showing 2 changed files with 54 additions and 88 deletions.
88 changes: 0 additions & 88 deletions ext/openssl/ossl_pkey_dsa.c
Original file line number Diff line number Diff line change
Expand Up @@ -422,92 +422,6 @@ ossl_dsa_to_public_key(VALUE self)
return obj;
}

/*
* 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 @@ -565,8 +479,6 @@ Init_ossl_dsa(void)
rb_define_alias(cDSA, "to_s", "export");
rb_define_method(cDSA, "to_der", ossl_dsa_to_der, 0);
rb_define_method(cDSA, "public_key", ossl_dsa_to_public_key, 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
54 changes: 54 additions & 0 deletions lib/openssl/pkey.rb
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,60 @@ def compute_key(pub_bn)

class DSA
include OpenSSL::Marshal

# :call-seq:
# dsa.syssign(string) -> string
#
# 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.
#
# Deprecated in version 3.0. Consider using OpenSSL::PKey::PKey#sign_raw
# and OpenSSL::PKey::PKey#verify_raw instead.
#
# string::
# 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)
#
# # With legacy #syssign and #sysverify:
# sig = dsa.syssign(digest)
# p dsa.sysverify(digest, sig) #=> true
#
# # With #sign_raw and #verify_raw:
# sig = dsa.sign_raw(nil, digest)
# p dsa.verify_raw(nil, sig, digest) #=> true
def syssign(string)
q or raise OpenSSL::PKey::DSAError, "incomplete DSA"
private? or raise OpenSSL::PKey::DSAError, "Private DSA key needed!"
begin
sign_raw(nil, string)
rescue OpenSSL::PKey::PKeyError
raise OpenSSL::PKey::DSAError, $!.message
end
end

# :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.
#
# Deprecated in version 3.0. Consider using OpenSSL::PKey::PKey#sign_raw
# and OpenSSL::PKey::PKey#verify_raw instead.
#
# digest::
# A message digest of the original input data to be signed.
# sig::
# A DSA signature value.
def sysverify(digest, sig)
verify_raw(nil, sig, digest)
rescue OpenSSL::PKey::PKeyError
raise OpenSSL::PKey::DSAError, $!.message
end
end

if defined?(EC)
Expand Down

0 comments on commit 96b92c5

Please sign in to comment.