From b245b67d9e325824f3869d839a16d06c6a1e8392 Mon Sep 17 00:00:00 2001 From: Akinori MUSHA Date: Mon, 27 Sep 2021 16:31:55 +0900 Subject: [ruby/digest] Place common parts in lib and engine specific parts under ext/**/lib https://github.com/ruby/digest/commit/8d7496c3be --- ext/digest/bubblebabble/lib/bubblebabble.rb | 9 -- ext/digest/digest.gemspec | 55 +++-------- ext/digest/lib/digest.rb | 113 --------------------- ext/digest/lib/digest/loader.rb | 3 + ext/digest/lib/digest/sha2/loader.rb | 3 + ext/digest/md5/lib/md5.rb | 9 -- ext/digest/rmd160/lib/rmd160.rb | 9 -- ext/digest/sha1/lib/sha1.rb | 9 -- ext/digest/sha2/lib/sha2.rb | 147 ---------------------------- lib/digest.rb | 110 +++++++++++++++++++++ lib/digest/sha2.rb | 142 +++++++++++++++++++++++++++ 11 files changed, 269 insertions(+), 340 deletions(-) delete mode 100644 ext/digest/bubblebabble/lib/bubblebabble.rb delete mode 100644 ext/digest/lib/digest.rb create mode 100644 ext/digest/lib/digest/loader.rb create mode 100644 ext/digest/lib/digest/sha2/loader.rb delete mode 100644 ext/digest/md5/lib/md5.rb delete mode 100644 ext/digest/rmd160/lib/rmd160.rb delete mode 100644 ext/digest/sha1/lib/sha1.rb delete mode 100644 ext/digest/sha2/lib/sha2.rb create mode 100644 lib/digest.rb create mode 100644 lib/digest/sha2.rb diff --git a/ext/digest/bubblebabble/lib/bubblebabble.rb b/ext/digest/bubblebabble/lib/bubblebabble.rb deleted file mode 100644 index 8ad06c7740..0000000000 --- a/ext/digest/bubblebabble/lib/bubblebabble.rb +++ /dev/null @@ -1,9 +0,0 @@ -# frozen_string_literal: false - -require 'digest' - -if RUBY_ENGINE == 'jruby' - JRuby::Util.load_ext("org.jruby.ext.digest.BubbleBabble") -else - require 'digest/bubblebabble.so' -end diff --git a/ext/digest/digest.gemspec b/ext/digest/digest.gemspec index f9357b0f23..151d1607b6 100644 --- a/ext/digest/digest.gemspec +++ b/ext/digest/digest.gemspec @@ -12,60 +12,27 @@ Gem::Specification.new do |spec| spec.homepage = "https://github.com/ruby/digest" spec.licenses = ["Ruby", "BSD-2-Clause"] - spec.files = [ - "LICENSE.txt", "README.md", - - "ext/digest/defs.h", "ext/digest/digest.c", "ext/digest/digest.h", - "ext/digest/digest_conf.rb", "ext/digest/extconf.rb", - "ext/digest/lib/digest.rb", - - "ext/digest/bubblebabble/bubblebabble.c", - "ext/digest/bubblebabble/extconf.rb", - - "ext/digest/md5/extconf.rb", "ext/digest/md5/md5.c", - "ext/digest/md5/md5.h", "ext/digest/md5/md5cc.h", - "ext/digest/md5/md5init.c", - - "ext/digest/rmd160/extconf.rb", "ext/digest/rmd160/rmd160.c", - "ext/digest/rmd160/rmd160.h", "ext/digest/rmd160/rmd160init.c", - - "ext/digest/sha1/extconf.rb", "ext/digest/sha1/sha1.c", - "ext/digest/sha1/sha1.h", "ext/digest/sha1/sha1cc.h", - "ext/digest/sha1/sha1init.c", - - "ext/digest/sha2/extconf.rb", "ext/digest/sha2/lib/sha2.rb", - "ext/digest/sha2/sha2.c", "ext/digest/sha2/sha2.h", - "ext/digest/sha2/sha2cc.h", "ext/digest/sha2/sha2init.c", - - "ext/openssl/deprecation.rb", - "ext/digest/test.sh", + spec.files = [ + "LICENSE.txt", + "README.md", + *Dir["lib/digest{.rb,/**/*.rb}"], ] spec.required_ruby_version = ">= 2.5.0" spec.bindir = "exe" spec.executables = [] - spec.require_paths = ["lib"] if Gem::Platform === spec.platform and spec.platform =~ 'java' or RUBY_ENGINE == 'jruby' spec.platform = 'java' - spec.files.concat [ - "lib/digest.jar", - "lib/digest/md5.rb", - "lib/digest/sha1.rb", - "lib/digest/sha2.rb", - "lib/digest/rmd160.rb", - "lib/digest/bubblebabble.rb" - ] + + spec.files += Dir["ext/java/**/*.{rb,java}"] + spec.require_paths = %w[lib ext/java/org/jruby/ext/digest/lib] else - spec.extensions = %w[ - ext/digest/extconf.rb - ext/digest/bubblebabble/extconf.rb - ext/digest/md5/extconf.rb - ext/digest/rmd160/extconf.rb - ext/digest/sha1/extconf.rb - ext/digest/sha2/extconf.rb - ] + spec.extensions = Dir["ext/digest/**/extconf.rb"] + + spec.files += Dir["ext/digest/**/*.{rb,c,h,sh}"] + spec.require_paths = %w[lib] end spec.metadata["msys2_mingw_dependencies"] = "openssl" diff --git a/ext/digest/lib/digest.rb b/ext/digest/lib/digest.rb deleted file mode 100644 index 912198811b..0000000000 --- a/ext/digest/lib/digest.rb +++ /dev/null @@ -1,113 +0,0 @@ -# frozen_string_literal: false -if RUBY_ENGINE == 'jruby' - JRuby::Util.load_ext("org.jruby.ext.digest.DigestLibrary") -else - require 'digest.so' -end - -module Digest - # A mutex for Digest(). - REQUIRE_MUTEX = Thread::Mutex.new - - def self.const_missing(name) # :nodoc: - case name - when :SHA256, :SHA384, :SHA512 - lib = 'digest/sha2' - else - lib = File.join('digest', name.to_s.downcase) - end - - begin - require lib - rescue LoadError - raise LoadError, "library not found for class Digest::#{name} -- #{lib}", caller(1) - end - unless Digest.const_defined?(name) - raise NameError, "uninitialized constant Digest::#{name}", caller(1) - end - Digest.const_get(name) - end - - class ::Digest::Class - # Creates a digest object and reads a given file, _name_. - # Optional arguments are passed to the constructor of the digest - # class. - # - # p Digest::SHA256.file("X11R6.8.2-src.tar.bz2").hexdigest - # # => "f02e3c85572dc9ad7cb77c2a638e3be24cc1b5bea9fdbb0b0299c9668475c534" - def self.file(name, *args) - new(*args).file(name) - end - - # Returns the base64 encoded hash value of a given _string_. The - # return value is properly padded with '=' and contains no line - # feeds. - def self.base64digest(str, *args) - [digest(str, *args)].pack('m0') - end - end - - module Instance - # Updates the digest with the contents of a given file _name_ and - # returns self. - def file(name) - File.open(name, "rb") {|f| - buf = "" - while f.read(16384, buf) - update buf - end - } - self - end - - # If none is given, returns the resulting hash value of the digest - # in a base64 encoded form, keeping the digest's state. - # - # If a +string+ is given, returns the hash value for the given - # +string+ in a base64 encoded form, resetting the digest to the - # initial state before and after the process. - # - # In either case, the return value is properly padded with '=' and - # contains no line feeds. - def base64digest(str = nil) - [str ? digest(str) : digest].pack('m0') - end - - # Returns the resulting hash value and resets the digest to the - # initial state. - def base64digest! - [digest!].pack('m0') - end - end -end - -# call-seq: -# Digest(name) -> digest_subclass -# -# Returns a Digest subclass by +name+ in a thread-safe manner even -# when on-demand loading is involved. -# -# require 'digest' -# -# Digest("MD5") -# # => Digest::MD5 -# -# Digest(:SHA256) -# # => Digest::SHA256 -# -# Digest(:Foo) -# # => LoadError: library not found for class Digest::Foo -- digest/foo -def Digest(name) - const = name.to_sym - Digest::REQUIRE_MUTEX.synchronize { - # Ignore autoload's because it is void when we have #const_missing - Digest.const_missing(const) - } -rescue LoadError - # Constants do not necessarily rely on digest/*. - if Digest.const_defined?(const) - Digest.const_get(const) - else - raise - end -end diff --git a/ext/digest/lib/digest/loader.rb b/ext/digest/lib/digest/loader.rb new file mode 100644 index 0000000000..6b989e07be --- /dev/null +++ b/ext/digest/lib/digest/loader.rb @@ -0,0 +1,3 @@ +# frozen_string_literal: true + +require 'digest.so' diff --git a/ext/digest/lib/digest/sha2/loader.rb b/ext/digest/lib/digest/sha2/loader.rb new file mode 100644 index 0000000000..7d6d04a59c --- /dev/null +++ b/ext/digest/lib/digest/sha2/loader.rb @@ -0,0 +1,3 @@ +# frozen_string_literal: true + +require 'digest/sha2.so' diff --git a/ext/digest/md5/lib/md5.rb b/ext/digest/md5/lib/md5.rb deleted file mode 100644 index 3748f9d187..0000000000 --- a/ext/digest/md5/lib/md5.rb +++ /dev/null @@ -1,9 +0,0 @@ -# frozen_string_literal: false - -require 'digest' - -if RUBY_ENGINE == 'jruby' - JRuby::Util.load_ext("org.jruby.ext.digest.MD5") -else - require 'digest/md5.so' -end diff --git a/ext/digest/rmd160/lib/rmd160.rb b/ext/digest/rmd160/lib/rmd160.rb deleted file mode 100644 index eabb92a496..0000000000 --- a/ext/digest/rmd160/lib/rmd160.rb +++ /dev/null @@ -1,9 +0,0 @@ -# frozen_string_literal: false - -require 'digest' - -if RUBY_ENGINE == 'jruby' - JRuby::Util.load_ext("org.jruby.ext.digest.RMD160") -else - require 'digest/rmd160.so' -end diff --git a/ext/digest/sha1/lib/sha1.rb b/ext/digest/sha1/lib/sha1.rb deleted file mode 100644 index 864997b1f6..0000000000 --- a/ext/digest/sha1/lib/sha1.rb +++ /dev/null @@ -1,9 +0,0 @@ -# frozen_string_literal: false - -require 'digest' - -if RUBY_ENGINE == 'jruby' - JRuby::Util.load_ext("org.jruby.ext.digest.SHA1") -else - require 'digest/sha1.so' -end diff --git a/ext/digest/sha2/lib/sha2.rb b/ext/digest/sha2/lib/sha2.rb deleted file mode 100644 index 22e099768c..0000000000 --- a/ext/digest/sha2/lib/sha2.rb +++ /dev/null @@ -1,147 +0,0 @@ -# frozen_string_literal: false -#-- -# sha2.rb - defines Digest::SHA2 class which wraps up the SHA256, -# SHA384, and SHA512 classes. -#++ -# Copyright (c) 2006 Akinori MUSHA -# -# All rights reserved. You can redistribute and/or modify it under the same -# terms as Ruby. -# -# $Id$ - -require 'digest' - -if RUBY_ENGINE == 'jruby' - JRuby::Util.load_ext("org.jruby.ext.digest.SHA2") -else - require 'digest/sha2.so' -end - -module Digest - # - # A meta digest provider class for SHA256, SHA384 and SHA512. - # - # FIPS 180-2 describes SHA2 family of digest algorithms. It defines - # three algorithms: - # * one which works on chunks of 512 bits and returns a 256-bit - # digest (SHA256), - # * one which works on chunks of 1024 bits and returns a 384-bit - # digest (SHA384), - # * and one which works on chunks of 1024 bits and returns a 512-bit - # digest (SHA512). - # - # ==Examples - # require 'digest' - # - # # Compute a complete digest - # Digest::SHA2.hexdigest 'abc' # => "ba7816bf8..." - # Digest::SHA2.new(256).hexdigest 'abc' # => "ba7816bf8..." - # Digest::SHA256.hexdigest 'abc' # => "ba7816bf8..." - # - # Digest::SHA2.new(384).hexdigest 'abc' # => "cb00753f4..." - # Digest::SHA384.hexdigest 'abc' # => "cb00753f4..." - # - # Digest::SHA2.new(512).hexdigest 'abc' # => "ddaf35a19..." - # Digest::SHA512.hexdigest 'abc' # => "ddaf35a19..." - # - # # Compute digest by chunks - # sha2 = Digest::SHA2.new # =># - # sha2.update "ab" - # sha2 << "c" # alias for #update - # sha2.hexdigest # => "ba7816bf8..." - # - # # Use the same object to compute another digest - # sha2.reset - # sha2 << "message" - # sha2.hexdigest # => "ab530a13e..." - # - class SHA2 < Digest::Class - # call-seq: - # Digest::SHA2.new(bitlen = 256) -> digest_obj - # - # Create a new SHA2 hash object with a given bit length. - # - # Valid bit lengths are 256, 384 and 512. - def initialize(bitlen = 256) - case bitlen - when 256 - @sha2 = Digest::SHA256.new - when 384 - @sha2 = Digest::SHA384.new - when 512 - @sha2 = Digest::SHA512.new - else - raise ArgumentError, "unsupported bit length: %s" % bitlen.inspect - end - @bitlen = bitlen - end - - # call-seq: - # digest_obj.reset -> digest_obj - # - # Reset the digest to the initial state and return self. - def reset - @sha2.reset - self - end - - # call-seq: - # digest_obj.update(string) -> digest_obj - # digest_obj << string -> digest_obj - # - # Update the digest using a given _string_ and return self. - def update(str) - @sha2.update(str) - self - end - alias << update - - def finish # :nodoc: - @sha2.digest! - end - private :finish - - - # call-seq: - # digest_obj.block_length -> Integer - # - # Return the block length of the digest in bytes. - # - # Digest::SHA256.new.block_length * 8 - # # => 512 - # Digest::SHA384.new.block_length * 8 - # # => 1024 - # Digest::SHA512.new.block_length * 8 - # # => 1024 - def block_length - @sha2.block_length - end - - # call-seq: - # digest_obj.digest_length -> Integer - # - # Return the length of the hash value (the digest) in bytes. - # - # Digest::SHA256.new.digest_length * 8 - # # => 256 - # Digest::SHA384.new.digest_length * 8 - # # => 384 - # Digest::SHA512.new.digest_length * 8 - # # => 512 - # - # For example, digests produced by Digest::SHA256 will always be 32 bytes - # (256 bits) in size. - def digest_length - @sha2.digest_length - end - - def initialize_copy(other) # :nodoc: - @sha2 = other.instance_eval { @sha2.clone } - end - - def inspect # :nodoc: - "#<%s:%d %s>" % [self.class.name, @bitlen, hexdigest] - end - end -end diff --git a/lib/digest.rb b/lib/digest.rb new file mode 100644 index 0000000000..b5ff067e44 --- /dev/null +++ b/lib/digest.rb @@ -0,0 +1,110 @@ +# frozen_string_literal: false + +require 'digest/loader' + +module Digest + # A mutex for Digest(). + REQUIRE_MUTEX = Thread::Mutex.new + + def self.const_missing(name) # :nodoc: + case name + when :SHA256, :SHA384, :SHA512 + lib = 'digest/sha2' + else + lib = File.join('digest', name.to_s.downcase) + end + + begin + require lib + rescue LoadError + raise LoadError, "library not found for class Digest::#{name} -- #{lib}", caller(1) + end + unless Digest.const_defined?(name) + raise NameError, "uninitialized constant Digest::#{name}", caller(1) + end + Digest.const_get(name) + end + + class ::Digest::Class + # Creates a digest object and reads a given file, _name_. + # Optional arguments are passed to the constructor of the digest + # class. + # + # p Digest::SHA256.file("X11R6.8.2-src.tar.bz2").hexdigest + # # => "f02e3c85572dc9ad7cb77c2a638e3be24cc1b5bea9fdbb0b0299c9668475c534" + def self.file(name, *args) + new(*args).file(name) + end + + # Returns the base64 encoded hash value of a given _string_. The + # return value is properly padded with '=' and contains no line + # feeds. + def self.base64digest(str, *args) + [digest(str, *args)].pack('m0') + end + end + + module Instance + # Updates the digest with the contents of a given file _name_ and + # returns self. + def file(name) + File.open(name, "rb") {|f| + buf = "" + while f.read(16384, buf) + update buf + end + } + self + end + + # If none is given, returns the resulting hash value of the digest + # in a base64 encoded form, keeping the digest's state. + # + # If a +string+ is given, returns the hash value for the given + # +string+ in a base64 encoded form, resetting the digest to the + # initial state before and after the process. + # + # In either case, the return value is properly padded with '=' and + # contains no line feeds. + def base64digest(str = nil) + [str ? digest(str) : digest].pack('m0') + end + + # Returns the resulting hash value and resets the digest to the + # initial state. + def base64digest! + [digest!].pack('m0') + end + end +end + +# call-seq: +# Digest(name) -> digest_subclass +# +# Returns a Digest subclass by +name+ in a thread-safe manner even +# when on-demand loading is involved. +# +# require 'digest' +# +# Digest("MD5") +# # => Digest::MD5 +# +# Digest(:SHA256) +# # => Digest::SHA256 +# +# Digest(:Foo) +# # => LoadError: library not found for class Digest::Foo -- digest/foo +def Digest(name) + const = name.to_sym + Digest::REQUIRE_MUTEX.synchronize { + # Ignore autoload's because it is void when we have #const_missing + Digest.const_missing(const) + } +rescue LoadError + # Constants do not necessarily rely on digest/*. + if Digest.const_defined?(const) + Digest.const_get(const) + else + raise + end +end diff --git a/lib/digest/sha2.rb b/lib/digest/sha2.rb new file mode 100644 index 0000000000..f17593a206 --- /dev/null +++ b/lib/digest/sha2.rb @@ -0,0 +1,142 @@ +# frozen_string_literal: false +#-- +# sha2.rb - defines Digest::SHA2 class which wraps up the SHA256, +# SHA384, and SHA512 classes. +#++ +# Copyright (c) 2006 Akinori MUSHA +# +# All rights reserved. You can redistribute and/or modify it under the same +# terms as Ruby. +# +# $Id$ + +require 'digest' +require 'digest/sha2/loader' + +module Digest + # + # A meta digest provider class for SHA256, SHA384 and SHA512. + # + # FIPS 180-2 describes SHA2 family of digest algorithms. It defines + # three algorithms: + # * one which works on chunks of 512 bits and returns a 256-bit + # digest (SHA256), + # * one which works on chunks of 1024 bits and returns a 384-bit + # digest (SHA384), + # * and one which works on chunks of 1024 bits and returns a 512-bit + # digest (SHA512). + # + # ==Examples + # require 'digest' + # + # # Compute a complete digest + # Digest::SHA2.hexdigest 'abc' # => "ba7816bf8..." + # Digest::SHA2.new(256).hexdigest 'abc' # => "ba7816bf8..." + # Digest::SHA256.hexdigest 'abc' # => "ba7816bf8..." + # + # Digest::SHA2.new(384).hexdigest 'abc' # => "cb00753f4..." + # Digest::SHA384.hexdigest 'abc' # => "cb00753f4..." + # + # Digest::SHA2.new(512).hexdigest 'abc' # => "ddaf35a19..." + # Digest::SHA512.hexdigest 'abc' # => "ddaf35a19..." + # + # # Compute digest by chunks + # sha2 = Digest::SHA2.new # =># + # sha2.update "ab" + # sha2 << "c" # alias for #update + # sha2.hexdigest # => "ba7816bf8..." + # + # # Use the same object to compute another digest + # sha2.reset + # sha2 << "message" + # sha2.hexdigest # => "ab530a13e..." + # + class SHA2 < Digest::Class + # call-seq: + # Digest::SHA2.new(bitlen = 256) -> digest_obj + # + # Create a new SHA2 hash object with a given bit length. + # + # Valid bit lengths are 256, 384 and 512. + def initialize(bitlen = 256) + case bitlen + when 256 + @sha2 = Digest::SHA256.new + when 384 + @sha2 = Digest::SHA384.new + when 512 + @sha2 = Digest::SHA512.new + else + raise ArgumentError, "unsupported bit length: %s" % bitlen.inspect + end + @bitlen = bitlen + end + + # call-seq: + # digest_obj.reset -> digest_obj + # + # Reset the digest to the initial state and return self. + def reset + @sha2.reset + self + end + + # call-seq: + # digest_obj.update(string) -> digest_obj + # digest_obj << string -> digest_obj + # + # Update the digest using a given _string_ and return self. + def update(str) + @sha2.update(str) + self + end + alias << update + + def finish # :nodoc: + @sha2.digest! + end + private :finish + + + # call-seq: + # digest_obj.block_length -> Integer + # + # Return the block length of the digest in bytes. + # + # Digest::SHA256.new.block_length * 8 + # # => 512 + # Digest::SHA384.new.block_length * 8 + # # => 1024 + # Digest::SHA512.new.block_length * 8 + # # => 1024 + def block_length + @sha2.block_length + end + + # call-seq: + # digest_obj.digest_length -> Integer + # + # Return the length of the hash value (the digest) in bytes. + # + # Digest::SHA256.new.digest_length * 8 + # # => 256 + # Digest::SHA384.new.digest_length * 8 + # # => 384 + # Digest::SHA512.new.digest_length * 8 + # # => 512 + # + # For example, digests produced by Digest::SHA256 will always be 32 bytes + # (256 bits) in size. + def digest_length + @sha2.digest_length + end + + def initialize_copy(other) # :nodoc: + @sha2 = other.instance_eval { @sha2.clone } + end + + def inspect # :nodoc: + "#<%s:%d %s>" % [self.class.name, @bitlen, hexdigest] + end + end +end -- cgit v1.2.3