From 96b92c51d2f3a782cb7bc72673aa90dde2daf750 Mon Sep 17 00:00:00 2001 From: Kazuki Yamaguchi Date: Fri, 10 Jul 2020 13:51:18 +0900 Subject: [PATCH] pkey/dsa: refactor DSA#sys{sign,verify} with PKey#{sign,verify}_raw 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. --- ext/openssl/ossl_pkey_dsa.c | 88 ------------------------------------- lib/openssl/pkey.rb | 54 +++++++++++++++++++++++ 2 files changed, 54 insertions(+), 88 deletions(-) diff --git a/ext/openssl/ossl_pkey_dsa.c b/ext/openssl/ossl_pkey_dsa.c index 0e68f7f27..ba9693ce1 100644 --- a/ext/openssl/ossl_pkey_dsa.c +++ b/ext/openssl/ossl_pkey_dsa.c @@ -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: @@ -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); diff --git a/lib/openssl/pkey.rb b/lib/openssl/pkey.rb index fc0454200..1164b1ce4 100644 --- a/lib/openssl/pkey.rb +++ b/lib/openssl/pkey.rb @@ -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)