diff options
author | Kazuki Yamaguchi <k@rhe.jp> | 2020-05-27 20:35:37 +0900 |
---|---|---|
committer | Kazuki Yamaguchi <k@rhe.jp> | 2020-05-28 01:04:33 +0900 |
commit | 5db40f5d34e614e20d9788f0d615032438922174 (patch) | |
tree | f63e73c4c2a05485cf83797b2b3afe1c0dd2fbd9 | |
parent | 93213b2730a45fe997b8e581c64c42e13cd9abde (diff) | |
download | ruby-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.rb | 40 | ||||
-rw-r--r-- | test/openssl/test_digest.rb | 7 |
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")) |