aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKazuki Yamaguchi <k@rhe.jp>2020-05-27 20:35:37 +0900
committerKazuki Yamaguchi <k@rhe.jp>2020-05-28 01:04:33 +0900
commit5db40f5d34e614e20d9788f0d615032438922174 (patch)
treef63e73c4c2a05485cf83797b2b3afe1c0dd2fbd9
parent93213b2730a45fe997b8e581c64c42e13cd9abde (diff)
downloadruby-openssl-ky/digest-digest-shim.tar.gz
digest: redefine ::Digest constants with OpenSSL::Digest onesky/digest-digest-shim
Replace the C implementations from the digest standard library with OpenSSL::Digest ones for increased performance. This makes Digest::SHA1 an alias of OpenSSL::Digest::SHA1, for instance. At the time of writing the digest library uses OpenSSL too, if it is detected on compile-time. However, I'm proposing a patch to remove that code path[1]. The digest library currently uses the legacy low level API of OpenSSL, whose use has been discouraged for years for multiple reasons. While it could also be rewritten to use the newer EVP API, that requires a breaking change in the Digest framework interface. Also, it's not desirable to have two identical code (Digest and OpenSSL::Digest) as part of the standard library. OpenSSL::Digest inherits from Digest::Class and also implements all methods provided by Digest::Base. Therefore, it should be fully compatible from the perspective of features. Note that, however, this is potentially a breaking change if user code extends Digest::Base for some reason. class Digest::Class include Digest::Instance end class Digest::Base < Digest::Class; end class Digest::SHA1 < Digest::Base; end class Digest::SHA256 < Digest::Base; end ... class OpenSSL::Digest < Digest::Class; end [1] XXX
-rw-r--r--lib/openssl/digest.rb40
-rw-r--r--test/openssl/test_digest.rb7
2 files changed, 47 insertions, 0 deletions
diff --git a/lib/openssl/digest.rb b/lib/openssl/digest.rb
index 2ff8398e..898733c3 100644
--- a/lib/openssl/digest.rb
+++ b/lib/openssl/digest.rb
@@ -71,3 +71,43 @@ module OpenSSL
module_function :Digest
end # OpenSSL
+
+# The 'digest' standard library providesa ::Digest, a framework for message
+# digest algorithms and bundles basic implementations of commonly used
+# algorithms.
+#
+# Ruby/OpenSSL provides a more efficient implementation of those algorithms
+# in OpenSSL::Digest, which also inherts from Digest::Class and has the
+# same interface as ::Digest.
+#
+# This redefines the constants in ::Digest with the OpenSSL implementations.
+# The original constants are renamed to add "_DEFAULT" to their original name.
+module Digest
+ rename_builtin = proc { |name|
+ begin
+ default = const_get(name)
+ rescue LoadError
+ else
+ const_set(:"#{name}_DEFAULT", default)
+ remove_const(name)
+ end
+ }
+
+ # OpenSSL::Digest.new("RIPEMD160")
+ RMD160 = OpenSSL::Digest::RIPEMD160 if rename_builtin.(:RMD160)
+
+ # OpenSSL::Digest.new("MD5")
+ MD5 = OpenSSL::Digest::MD5 if rename_builtin.(:MD5)
+
+ # OpenSSL::Digest.new("SHA1")
+ SHA1 = OpenSSL::Digest::SHA1 if rename_builtin.(:SHA1)
+
+ # OpenSSL::Digest.new("SHA256")
+ SHA256 = OpenSSL::Digest::SHA256 if rename_builtin.(:SHA256)
+
+ # OpenSSL::Digest.new("SHA384")
+ SHA384 = OpenSSL::Digest::SHA384 if rename_builtin.(:SHA384)
+
+ # OpenSSL::Digest.new("SHA512")
+ SHA512 = OpenSSL::Digest::SHA512 if rename_builtin.(:SHA512)
+end
diff --git a/test/openssl/test_digest.rb b/test/openssl/test_digest.rb
index 8d7046e8..efaa656c 100644
--- a/test/openssl/test_digest.rb
+++ b/test/openssl/test_digest.rb
@@ -61,6 +61,13 @@ class OpenSSL::TestDigest < OpenSSL::TestCase
end
end
+ def test_toplevel_digest_constants
+ assert_same(OpenSSL::Digest::RIPEMD160, Digest::RMD160)
+ %w{MD5 SHA1 SHA256 SHA384 SHA512}.each do |name|
+ assert_same(OpenSSL::Digest.const_get(name), Digest.const_get(name))
+ end
+ end
+
def test_digest_by_oid_and_name
check_digest(OpenSSL::ASN1::ObjectId.new("MD5"))
check_digest(OpenSSL::ASN1::ObjectId.new("SHA1"))