├── .document ├── .git-blame-ignore-revs ├── .github ├── CODEOWNERS ├── dependabot.yml └── workflows │ ├── ci.yml │ └── push_gem.yml ├── .gitignore ├── Gemfile ├── LICENSE.txt ├── README.md ├── Rakefile ├── bin ├── console └── setup ├── digest.gemspec ├── ext ├── digest │ ├── .document │ ├── bubblebabble │ │ ├── bubblebabble.c │ │ └── extconf.rb │ ├── defs.h │ ├── digest.c │ ├── digest.h │ ├── digest_conf.rb │ ├── extconf.rb │ ├── lib │ │ └── digest │ │ │ ├── loader.rb │ │ │ └── sha2 │ │ │ └── loader.rb │ ├── md5 │ │ ├── extconf.rb │ │ ├── md5.c │ │ ├── md5.h │ │ ├── md5cc.h │ │ └── md5init.c │ ├── rmd160 │ │ ├── extconf.rb │ │ ├── rmd160.c │ │ ├── rmd160.h │ │ └── rmd160init.c │ ├── sha1 │ │ ├── extconf.rb │ │ ├── sha1.c │ │ ├── sha1.h │ │ ├── sha1cc.h │ │ └── sha1init.c │ └── sha2 │ │ ├── extconf.rb │ │ ├── sha2.c │ │ ├── sha2.h │ │ ├── sha2cc.h │ │ └── sha2init.c └── java │ └── org │ └── jruby │ └── ext │ └── digest │ ├── BubbleBabble.java │ ├── DigestLibrary.java │ ├── MD5.java │ ├── RMD160.java │ ├── RubyDigest.java │ ├── SHA1.java │ ├── SHA2.java │ └── lib │ └── digest │ ├── bubblebabble.rb │ ├── loader.rb │ ├── md5.rb │ ├── rmd160.rb │ ├── sha1.rb │ └── sha2 │ └── loader.rb ├── lib ├── digest.rb └── digest │ ├── sha2.rb │ └── version.rb ├── rakelib └── epoch.rake └── test ├── digest ├── digest │ └── foo.rb ├── test_digest.rb ├── test_digest_extend.rb └── test_ractor.rb └── lib ├── helper.rb └── with_different_ofs.rb /.document: -------------------------------------------------------------------------------- 1 | LICENSE.txt 2 | README.md 3 | ext/digest/ 4 | lib/digest.rb 5 | lib/digest/sha2.rb 6 | -------------------------------------------------------------------------------- /.git-blame-ignore-revs: -------------------------------------------------------------------------------- 1 | # This is a file used by GitHub to ignore the following commits on `git blame`. 2 | # 3 | # You can also do the same thing in your local repository with: 4 | # $ git config --local blame.ignoreRevsFile .git-blame-ignore-revs 5 | 6 | # Expand tabs 7 | 23531965bcfed3e269b6e57eb706a1432056bcd4 8 | 9 | # Revert tab-expansion in external files 10 | 5ca2b5b91e3157c2c46b9059bb928b808b051bf9 11 | -------------------------------------------------------------------------------- /.github/CODEOWNERS: -------------------------------------------------------------------------------- 1 | * @knu 2 | -------------------------------------------------------------------------------- /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | version: 2 2 | updates: 3 | - package-ecosystem: 'github-actions' 4 | directory: '/' 5 | schedule: 6 | interval: 'weekly' 7 | -------------------------------------------------------------------------------- /.github/workflows/ci.yml: -------------------------------------------------------------------------------- 1 | name: CI 2 | 3 | on: 4 | push: 5 | pull_request: 6 | schedule: 7 | - cron: '15 9 * * *' 8 | 9 | jobs: 10 | ruby-versions: 11 | uses: ruby/actions/.github/workflows/ruby_versions.yml@master 12 | with: 13 | engine: cruby 14 | # versions: ["debug"] 15 | min_version: 2.7 16 | 17 | host: 18 | needs: ruby-versions 19 | name: ${{ matrix.os }} ${{ matrix.ruby }} 20 | if: ${{ github.repository == 'ruby/digest' || github.event_name != 'schedule' }} 21 | runs-on: ${{ matrix.os }} 22 | strategy: 23 | fail-fast: false 24 | matrix: 25 | os: 26 | - ubuntu-24.04 27 | - ubuntu-22.04 28 | - macos-14 29 | - macos-13 30 | - windows-latest 31 | ruby: ${{ fromJson(needs.ruby-versions.outputs.versions) }} 32 | include: 33 | - { os: windows-latest, ruby: ucrt } 34 | - { os: windows-latest, ruby: mswin } 35 | - { os: ubuntu-22.04, ruby: jruby } 36 | - { os: ubuntu-22.04, ruby: jruby-head } 37 | exclude: 38 | - { os: windows-latest, ruby: debug } 39 | - { os: windows-latest, ruby: head } 40 | 41 | steps: 42 | - uses: actions/checkout@v4 43 | 44 | - name: Set up Ruby 45 | uses: ruby/setup-ruby@v1 46 | with: 47 | ruby-version: ${{ matrix.ruby }} 48 | bundler-cache: true # 'bundle install' and cache 49 | 50 | - run: ruby --version 51 | 52 | - run: bundle exec rake compile 53 | 54 | - run: bundle exec rake build 55 | 56 | - run: bundle exec rake test 57 | continue-on-error: ${{ matrix.ignore-error }} 58 | 59 | - name: Integration test 60 | run: bundle exec rake check 61 | continue-on-error: >- 62 | ${{ 63 | matrix.ignore-pkg-error || 64 | (matrix.ruby == 'debug') || 65 | false }} 66 | -------------------------------------------------------------------------------- /.github/workflows/push_gem.yml: -------------------------------------------------------------------------------- 1 | name: Publish gem to rubygems.org 2 | 3 | on: 4 | push: 5 | tags: 6 | - 'v*' 7 | 8 | permissions: 9 | contents: read 10 | 11 | jobs: 12 | push: 13 | if: github.repository == 'ruby/digest' 14 | runs-on: ubuntu-latest 15 | 16 | environment: 17 | name: rubygems.org 18 | url: https://rubygems.org/gems/digest 19 | 20 | permissions: 21 | contents: write 22 | id-token: write 23 | 24 | strategy: 25 | matrix: 26 | ruby: ["3.3", "jruby"] 27 | 28 | steps: 29 | - name: Harden Runner 30 | uses: step-security/harden-runner@0634a2670c59f64b4a01f0f96f84700a4088b9f0 # v2.12.0 31 | with: 32 | egress-policy: audit 33 | 34 | - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 35 | 36 | - name: Set up Ruby 37 | uses: ruby/setup-ruby@eaecf785f6a34567a6d97f686bbb7bccc1ac1e5c # v1.237.0 38 | with: 39 | ruby-version: ${{ matrix.ruby }} 40 | 41 | # https://github.com/rubygems/rubygems/issues/5882 42 | - name: Install dependencies and build for JRuby 43 | run: | 44 | sudo apt install default-jdk maven 45 | gem update --system 46 | gem install ruby-maven rake-compiler --no-document 47 | rake compile 48 | if: matrix.ruby == 'jruby' 49 | 50 | - name: Install dependencies 51 | run: bundle install --jobs 4 --retry 3 52 | 53 | - name: Publish to RubyGems 54 | uses: rubygems/release-gem@a25424ba2ba8b387abc8ef40807c2c85b96cbe32 # v1.1.1 55 | 56 | - name: Create GitHub release 57 | run: | 58 | tag_name="$(git describe --tags --abbrev=0)" 59 | gh release create "${tag_name}" --verify-tag --generate-notes 60 | env: 61 | GITHUB_TOKEN: ${{ secrets.MATZBOT_GITHUB_WORKFLOW_TOKEN }} 62 | if: matrix.ruby != 'jruby' 63 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /.bundle/ 2 | /.yardoc 3 | /Gemfile.lock 4 | /_yardoc/ 5 | /coverage/ 6 | /doc/ 7 | /pkg/ 8 | /spec/reports/ 9 | /tmp/ 10 | /lib/digest/loader.rb 11 | /lib/digest/sha2/loader.rb 12 | lib/*.jar 13 | *.bundle 14 | *.so 15 | *.o 16 | .*.time 17 | Makefile 18 | lib/digest/loader.rb 19 | lib/digest/sha2/loader.rb 20 | -------------------------------------------------------------------------------- /Gemfile: -------------------------------------------------------------------------------- 1 | source "https://rubygems.org" 2 | 3 | gem "rake" 4 | group :development do 5 | gem "rake-compiler" 6 | gem "test-unit" 7 | gem "test-unit-ruby-core" 8 | end 9 | -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- 1 | Copyright (C) 1993-2013 Yukihiro Matsumoto. All rights reserved. 2 | 3 | Redistribution and use in source and binary forms, with or without 4 | modification, are permitted provided that the following conditions 5 | are met: 6 | 1. Redistributions of source code must retain the above copyright 7 | notice, this list of conditions and the following disclaimer. 8 | 2. Redistributions in binary form must reproduce the above copyright 9 | notice, this list of conditions and the following disclaimer in the 10 | documentation and/or other materials provided with the 11 | distribution. 12 | 13 | THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 14 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 15 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 16 | ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 17 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 18 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 19 | OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 20 | HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 21 | LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 22 | OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 23 | SUCH DAMAGE. 24 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Digest 2 | 3 | ![CI](https://github.com/ruby/digest/workflows/CI/badge.svg?branch=master&event=push) 4 | 5 | This module provides a framework for message digest libraries. 6 | 7 | You may want to look at OpenSSL::Digest as it supports more algorithms. 8 | 9 | A cryptographic hash function is a procedure that takes data and returns a fixed bit string: the hash value, also known as _digest_. Hash functions are also called one-way functions, it is easy to compute a digest from a message, but it is infeasible to generate a message from a digest. 10 | 11 | ## Installation 12 | 13 | Add this line to your application's Gemfile: 14 | 15 | ```ruby 16 | gem 'digest' 17 | ``` 18 | 19 | And then execute: 20 | 21 | $ bundle 22 | 23 | Or install it yourself as: 24 | 25 | $ gem install digest 26 | 27 | ## Usage 28 | 29 | ```ruby 30 | require 'digest' 31 | 32 | # Compute a complete digest 33 | Digest::SHA256.digest 'message' #=> "\xABS\n\x13\xE4Y..." 34 | 35 | sha256 = Digest::SHA256.new 36 | sha256.digest 'message' #=> "\xABS\n\x13\xE4Y..." 37 | 38 | # Other encoding formats 39 | Digest::SHA256.hexdigest 'message' #=> "ab530a13e459..." 40 | Digest::SHA256.base64digest 'message' #=> "q1MKE+RZFJgr..." 41 | 42 | # Compute digest by chunks 43 | md5 = Digest::MD5.new 44 | md5.update 'message1' 45 | md5 << 'message2' # << is an alias for update 46 | 47 | md5.hexdigest #=> "94af09c09bb9..." 48 | 49 | # Compute digest for a file 50 | sha256 = Digest::SHA256.file 'testfile' 51 | sha256.hexdigest 52 | ``` 53 | 54 | Additionally digests can be encoded in "bubble babble" format as a sequence of consonants and vowels which is more recognizable and comparable than a hexadecimal digest. 55 | 56 | ```ruby 57 | require 'digest/bubblebabble' 58 | 59 | Digest::SHA256.bubblebabble 'message' #=> "xopoh-fedac-fenyh-..." 60 | ``` 61 | 62 | See the bubble babble specification at http://web.mit.edu/kenta/www/one/bubblebabble/spec/jrtrjwzi/draft-huima-01.txt. 63 | 64 | ## Digest algorithms 65 | 66 | Different digest algorithms (or hash functions) are available: 67 | 68 | ``` 69 | MD5:: 70 | See RFC 1321 The MD5 Message-Digest Algorithm 71 | RIPEMD-160:: 72 | As Digest::RMD160. 73 | See http://homes.esat.kuleuven.be/~bosselae/ripemd160.html. 74 | SHA1:: 75 | See FIPS 180 Secure Hash Standard. 76 | SHA2 family:: 77 | See FIPS 180 Secure Hash Standard which defines the following algorithms: 78 | SHA512 79 | SHA384 80 | SHA256 81 | ``` 82 | 83 | The latest versions of the FIPS publications can be found here: http://csrc.nist.gov/publications/PubsFIPS.html. 84 | 85 | ## For Gem developers 86 | 87 | If you want to use digest algorithms in your C extension, you can use the `digest.h` header file provided by digest gem. You should add the following code to your `extconf.rb`: 88 | 89 | ```ruby 90 | spec = Gem::Specification.find_by_name("digest") 91 | source_dir = File.join(spec.full_gem_path, "ext", "digest") 92 | $INCFLAGS += " -I#{source_dir}" 93 | ``` 94 | 95 | ## Development 96 | 97 | After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake test` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment. 98 | 99 | To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org). 100 | 101 | ## Contributing 102 | 103 | Bug reports and pull requests are welcome on GitHub at https://github.com/ruby/digest. 104 | 105 | ## License 106 | 107 | The gem is available as open source under the terms of the [2-Clause BSD License](https://opensource.org/licenses/BSD-2-Clause). 108 | -------------------------------------------------------------------------------- /Rakefile: -------------------------------------------------------------------------------- 1 | require "bundler/gem_tasks" 2 | require "rake/testtask" 3 | 4 | Rake::TestTask.new(:test) do |t| 5 | t.libs << "test" << "test/lib" << "lib" 6 | if RUBY_ENGINE == "jruby" 7 | t.libs << "ext/java/org/jruby/ext/digest/lib" 8 | else 9 | t.libs << "ext/digest/lib" 10 | end 11 | t.ruby_opts << "-rhelper" 12 | t.test_files = FileList["test/**/test_*.rb"] 13 | end 14 | 15 | if RUBY_ENGINE == "jruby" 16 | require "rake/javaextensiontask" 17 | Rake::JavaExtensionTask.new("digest") do |ext| 18 | ext.source_version = "1.8" 19 | ext.target_version = "1.8" 20 | ext.ext_dir = "ext/java" 21 | end 22 | 23 | task :build => :compile 24 | else 25 | require "rake/extensiontask" 26 | Rake::ExtensionTask.new("digest") 27 | %w[bubblebabble md5 rmd160 sha1 sha2].each do |ext| 28 | Rake::ExtensionTask.new("digest/#{ext}") 29 | end 30 | end 31 | 32 | task :check do 33 | Bundler.with_unbundled_env do 34 | spec = Gem::Specification::load("digest.gemspec") 35 | version = spec.version.to_s 36 | 37 | gem = "pkg/digest-#{version}#{"-java" if RUBY_ENGINE == "jruby"}.gem" 38 | File.size?(gem) or abort "gem not built!" 39 | 40 | require "envutil" 41 | 42 | require 'tmpdir' 43 | status = Dir.mktmpdir do |tmpdir| 44 | tmpdir = File.realpath(tmpdir) 45 | sh "gem", "install", "--install-dir", tmpdir, "--no-document", gem 46 | 47 | _, _, status = EnvUtil.invoke_ruby([{"GEM_HOME"=>tmpdir}], <<~EOS) 48 | version = #{version.dump} 49 | gem "digest", version 50 | loaded_version = Gem.loaded_specs["digest"].version.to_s 51 | 52 | if loaded_version == version 53 | puts "digest \#{loaded_version} is loaded." 54 | else 55 | abort "digest \#{loaded_version} is loaded instead of \#{version}!" 56 | end 57 | 58 | require "digest" 59 | 60 | name = RUBY_ENGINE == "jruby" ? "/digest.rb" : "/digest.#{RbConfig::CONFIG["DLEXT"]}" 61 | found = $".select {|path| path.end_with?(name)} 62 | unless found.size == 1 and found.first.start_with?(#{tmpdir.dump}) 63 | abort "Unexpected digest is loaded: \#{found.inspect}" 64 | end 65 | 66 | string = "digest" 67 | actual = Digest::SHA256.hexdigest(string) 68 | expected = "0bf474896363505e5ea5e5d6ace8ebfb13a760a409b1fb467d428fc716f9f284" 69 | puts "sha256(\#{string.dump}) = \#{actual.dump}" 70 | 71 | if actual != expected 72 | abort "no! expected to be \#{expected.dump}!" 73 | end 74 | EOS 75 | status 76 | end 77 | 78 | if status.success? 79 | puts "check succeeded!" 80 | else 81 | warn "check failed!" 82 | exit status.exitstatus 83 | end 84 | end 85 | end 86 | 87 | task :default => :test 88 | -------------------------------------------------------------------------------- /bin/console: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | 3 | require "bundler/setup" 4 | require "digest" 5 | 6 | # You can add fixtures and/or initialization code here to make experimenting 7 | # with your gem easier. You can also use a different console, if you like. 8 | 9 | # (If you use this, don't forget to add pry to your Gemfile!) 10 | # require "pry" 11 | # Pry.start 12 | 13 | require "irb" 14 | IRB.start(__FILE__) 15 | -------------------------------------------------------------------------------- /bin/setup: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | set -euo pipefail 3 | IFS=$'\n\t' 4 | set -vx 5 | 6 | bundle install 7 | 8 | # Do any other automated setup that you need to do here 9 | -------------------------------------------------------------------------------- /digest.gemspec: -------------------------------------------------------------------------------- 1 | # coding: utf-8 2 | # frozen_string_literal: true 3 | 4 | Gem::Specification.new do |spec| 5 | version_module = Module.new do 6 | version_rb = File.join(__dir__, "lib/digest/version.rb") 7 | module_eval(File.read(version_rb), version_rb) 8 | end 9 | 10 | spec.name = "digest" 11 | spec.version = version_module::Digest::VERSION 12 | spec.authors = ["Akinori MUSHA"] 13 | spec.email = ["knu@idaemons.org"] 14 | 15 | spec.summary = %q{Provides a framework for message digest libraries.} 16 | spec.description = %q{Provides a framework for message digest libraries.} 17 | spec.homepage = "https://github.com/ruby/digest" 18 | spec.licenses = ["Ruby", "BSD-2-Clause"] 19 | 20 | spec.files = [ 21 | "LICENSE.txt", 22 | "README.md", 23 | *Dir["lib/digest{.rb,/**/*.rb}"], 24 | ] 25 | 26 | spec.required_ruby_version = ">= 2.5.0" 27 | 28 | spec.bindir = "exe" 29 | spec.executables = [] 30 | 31 | if Gem::Platform === spec.platform and spec.platform =~ 'java' or RUBY_ENGINE == 'jruby' 32 | spec.platform = 'java' 33 | 34 | spec.files += Dir["ext/java/**/*.{rb,java}", "lib/digest.jar"] 35 | spec.require_paths = %w[lib ext/java/org/jruby/ext/digest/lib] 36 | else 37 | spec.extensions = Dir["ext/digest/**/extconf.rb"] 38 | 39 | spec.files += Dir["ext/digest/**/{*.{rb,c,h,sh},depend}"] 40 | spec.require_paths = %w[lib] 41 | end 42 | 43 | spec.metadata["msys2_mingw_dependencies"] = "openssl" 44 | end 45 | -------------------------------------------------------------------------------- /ext/digest/.document: -------------------------------------------------------------------------------- 1 | digest.c 2 | bubblebabble/bubblebabble.c 3 | */*init.c 4 | -------------------------------------------------------------------------------- /ext/digest/bubblebabble/bubblebabble.c: -------------------------------------------------------------------------------- 1 | /************************************************ 2 | 3 | bubblebabble.c - BubbleBabble encoding support 4 | 5 | $Author$ 6 | created at: Fri Oct 13 18:31:42 JST 2006 7 | 8 | Copyright (C) 2006 Akinori MUSHA 9 | 10 | $Id$ 11 | 12 | ************************************************/ 13 | 14 | #include 15 | #include "../digest.h" 16 | 17 | static ID id_digest; 18 | 19 | static VALUE 20 | bubblebabble_str_new(VALUE str_digest) 21 | { 22 | char *digest; 23 | size_t digest_len; 24 | VALUE str; 25 | char *p; 26 | size_t i, j, seed = 1; 27 | static const char vowels[] = { 28 | 'a', 'e', 'i', 'o', 'u', 'y' 29 | }; 30 | static const char consonants[] = { 31 | 'b', 'c', 'd', 'f', 'g', 'h', 'k', 'l', 'm', 'n', 32 | 'p', 'r', 's', 't', 'v', 'z', 'x' 33 | }; 34 | 35 | StringValue(str_digest); 36 | digest = RSTRING_PTR(str_digest); 37 | digest_len = RSTRING_LEN(str_digest); 38 | 39 | if ((LONG_MAX - 2) / 3 < (digest_len | 1)) { 40 | rb_raise(rb_eRuntimeError, "digest string too long"); 41 | } 42 | 43 | str = rb_str_new(0, (digest_len | 1) * 3 + 2); 44 | p = RSTRING_PTR(str); 45 | 46 | i = j = 0; 47 | p[j++] = 'x'; 48 | 49 | for (;;) { 50 | unsigned char byte1, byte2; 51 | 52 | if (i >= digest_len) { 53 | p[j++] = vowels[seed % 6]; 54 | p[j++] = consonants[16]; 55 | p[j++] = vowels[seed / 6]; 56 | break; 57 | } 58 | 59 | byte1 = digest[i++]; 60 | p[j++] = vowels[(((byte1 >> 6) & 3) + seed) % 6]; 61 | p[j++] = consonants[(byte1 >> 2) & 15]; 62 | p[j++] = vowels[((byte1 & 3) + (seed / 6)) % 6]; 63 | 64 | if (i >= digest_len) { 65 | break; 66 | } 67 | 68 | byte2 = digest[i++]; 69 | p[j++] = consonants[(byte2 >> 4) & 15]; 70 | p[j++] = '-'; 71 | p[j++] = consonants[byte2 & 15]; 72 | 73 | seed = (seed * 5 + byte1 * 7 + byte2) % 36; 74 | } 75 | 76 | p[j] = 'x'; 77 | 78 | return str; 79 | } 80 | 81 | /* Document-method: Digest::bubblebabble 82 | * 83 | * call-seq: 84 | * Digest.bubblebabble(string) -> bubblebabble_string 85 | * 86 | * Returns a BubbleBabble encoded version of a given _string_. 87 | */ 88 | static VALUE 89 | rb_digest_s_bubblebabble(VALUE klass, VALUE str) 90 | { 91 | return bubblebabble_str_new(str); 92 | } 93 | 94 | /* Document-method: Digest::Class::bubblebabble 95 | * 96 | * call-seq: 97 | * Digest::Class.bubblebabble(string, ...) -> hash_string 98 | * 99 | * Returns the BubbleBabble encoded hash value of a given _string_. 100 | */ 101 | static VALUE 102 | rb_digest_class_s_bubblebabble(int argc, VALUE *argv, VALUE klass) 103 | { 104 | return bubblebabble_str_new(rb_funcallv(klass, id_digest, argc, argv)); 105 | } 106 | 107 | /* Document-method: Digest::Instance#bubblebabble 108 | * 109 | * call-seq: 110 | * digest_obj.bubblebabble -> hash_string 111 | * 112 | * Returns the resulting hash value in a Bubblebabble encoded form. 113 | */ 114 | static VALUE 115 | rb_digest_instance_bubblebabble(VALUE self) 116 | { 117 | return bubblebabble_str_new(rb_funcall(self, id_digest, 0)); 118 | } 119 | 120 | /* 121 | * This module adds some methods to Digest classes to perform 122 | * BubbleBabble encoding. 123 | */ 124 | void 125 | Init_bubblebabble(void) 126 | { 127 | #undef rb_intern 128 | VALUE rb_mDigest, rb_mDigest_Instance, rb_cDigest_Class; 129 | 130 | rb_require("digest"); 131 | 132 | #if 0 133 | rb_mDigest = rb_define_module("Digest"); 134 | rb_mDigest_Instance = rb_define_module_under(rb_mDigest, "Instance"); 135 | rb_cDigest_Class = rb_define_class_under(rb_mDigest, "Class", rb_cObject); 136 | #endif 137 | rb_mDigest = rb_digest_namespace(); 138 | rb_mDigest_Instance = rb_const_get(rb_mDigest, rb_intern_const("Instance")); 139 | rb_cDigest_Class = rb_const_get(rb_mDigest, rb_intern_const("Class")); 140 | 141 | rb_define_module_function(rb_mDigest, "bubblebabble", rb_digest_s_bubblebabble, 1); 142 | rb_define_singleton_method(rb_cDigest_Class, "bubblebabble", rb_digest_class_s_bubblebabble, -1); 143 | rb_define_method(rb_mDigest_Instance, "bubblebabble", rb_digest_instance_bubblebabble, 0); 144 | 145 | id_digest = rb_intern("digest"); 146 | } 147 | -------------------------------------------------------------------------------- /ext/digest/bubblebabble/extconf.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: false 2 | require 'mkmf' 3 | 4 | create_makefile('digest/bubblebabble') 5 | -------------------------------------------------------------------------------- /ext/digest/defs.h: -------------------------------------------------------------------------------- 1 | /* -*- C -*- 2 | * $Id$ 3 | */ 4 | 5 | #ifndef DEFS_H 6 | #define DEFS_H 7 | 8 | #include "ruby.h" 9 | #include 10 | 11 | #if defined(HAVE_SYS_CDEFS_H) 12 | # include 13 | #endif 14 | #if !defined(__BEGIN_DECLS) 15 | # define __BEGIN_DECLS 16 | # define __END_DECLS 17 | #endif 18 | 19 | #define RB_DIGEST_DIAGNOSTIC(compiler, op, flag) _Pragma(STRINGIZE(compiler diagnostic op flag)) 20 | #ifdef RBIMPL_WARNING_IGNORED 21 | # define RB_DIGEST_WARNING_IGNORED(flag) RBIMPL_WARNING_IGNORED(flag) 22 | # define RB_DIGEST_WARNING_PUSH() RBIMPL_WARNING_PUSH() 23 | # define RB_DIGEST_WARNING_POP() RBIMPL_WARNING_POP() 24 | #elif defined(__clang__) 25 | # define RB_DIGEST_WARNING_IGNORED(flag) RB_DIGEST_DIAGNOSTIC(clang, ignored, #flag) 26 | # define RB_DIGEST_WARNING_PUSH() _Pragma("clang diagnostic push") 27 | # define RB_DIGEST_WARNING_POP() _Pragma("clang diagnostic pop") 28 | #else /* __GNUC__ */ 29 | # define RB_DIGEST_WARNING_IGNORED(flag) RB_DIGEST_DIAGNOSTIC(GCC, ignored, #flag) 30 | # define RB_DIGEST_WARNING_PUSH() _Pragma("GCC diagnostic push") 31 | # define RB_DIGEST_WARNING_POP() _Pragma("GCC diagnostic pop") 32 | #endif 33 | #ifdef RBIMPL_HAS_WARNING 34 | # define RB_DIGEST_HAS_WARNING(_) RBIMPL_HAS_WARNING(_) 35 | #elif defined(__has_warning) 36 | # define RB_DIGEST_HAS_WARNING(_) __has_warning(_) 37 | #else 38 | # define RB_DIGEST_HAS_WARNING(_) 0 39 | #endif 40 | 41 | #endif /* DEFS_H */ 42 | -------------------------------------------------------------------------------- /ext/digest/digest.c: -------------------------------------------------------------------------------- 1 | /************************************************ 2 | 3 | digest.c - 4 | 5 | $Author$ 6 | created at: Fri May 25 08:57:27 JST 2001 7 | 8 | Copyright (C) 1995-2001 Yukihiro Matsumoto 9 | Copyright (C) 2001-2006 Akinori MUSHA 10 | 11 | $RoughId: digest.c,v 1.16 2001/07/13 15:38:27 knu Exp $ 12 | $Id$ 13 | 14 | ************************************************/ 15 | 16 | #include "digest.h" 17 | 18 | static VALUE rb_mDigest; 19 | static VALUE rb_mDigest_Instance; 20 | static VALUE rb_cDigest_Class; 21 | static VALUE rb_cDigest_Base; 22 | 23 | static ID id_reset, id_update, id_finish, id_digest, id_hexdigest, id_digest_length; 24 | static ID id_metadata; 25 | 26 | RUBY_EXTERN void Init_digest_base(void); 27 | 28 | /* 29 | * Document-module: Digest 30 | * 31 | * This module provides a framework for message digest libraries. 32 | * 33 | * You may want to look at OpenSSL::Digest as it supports more algorithms. 34 | * 35 | * A cryptographic hash function is a procedure that takes data and returns a 36 | * fixed bit string: the hash value, also known as _digest_. Hash functions 37 | * are also called one-way functions, it is easy to compute a digest from 38 | * a message, but it is infeasible to generate a message from a digest. 39 | * 40 | * == Examples 41 | * 42 | * require 'digest' 43 | * 44 | * # Compute a complete digest 45 | * Digest::SHA256.digest 'message' #=> "\xABS\n\x13\xE4Y..." 46 | * 47 | * sha256 = Digest::SHA256.new 48 | * sha256.digest 'message' #=> "\xABS\n\x13\xE4Y..." 49 | * 50 | * # Other encoding formats 51 | * Digest::SHA256.hexdigest 'message' #=> "ab530a13e459..." 52 | * Digest::SHA256.base64digest 'message' #=> "q1MKE+RZFJgr..." 53 | * 54 | * # Compute digest by chunks 55 | * md5 = Digest::MD5.new 56 | * md5.update 'message1' 57 | * md5 << 'message2' # << is an alias for update 58 | * 59 | * md5.hexdigest #=> "94af09c09bb9..." 60 | * 61 | * # Compute digest for a file 62 | * sha256 = Digest::SHA256.file 'testfile' 63 | * sha256.hexdigest 64 | * 65 | * Additionally digests can be encoded in "bubble babble" format as a sequence 66 | * of consonants and vowels which is more recognizable and comparable than a 67 | * hexadecimal digest. 68 | * 69 | * require 'digest/bubblebabble' 70 | * 71 | * Digest::SHA256.bubblebabble 'message' #=> "xopoh-fedac-fenyh-..." 72 | * 73 | * See the bubble babble specification at 74 | * http://web.mit.edu/kenta/www/one/bubblebabble/spec/jrtrjwzi/draft-huima-01.txt. 75 | * 76 | * == Digest algorithms 77 | * 78 | * Different digest algorithms (or hash functions) are available: 79 | * 80 | * MD5:: 81 | * See RFC 1321 The MD5 Message-Digest Algorithm 82 | * RIPEMD-160:: 83 | * As Digest::RMD160. 84 | * See http://homes.esat.kuleuven.be/~bosselae/ripemd160.html. 85 | * SHA1:: 86 | * See FIPS 180 Secure Hash Standard. 87 | * SHA2 family:: 88 | * See FIPS 180 Secure Hash Standard which defines the following algorithms: 89 | * * SHA512 90 | * * SHA384 91 | * * SHA256 92 | * 93 | * The latest versions of the FIPS publications can be found here: 94 | * http://csrc.nist.gov/publications/PubsFIPS.html. 95 | */ 96 | 97 | static VALUE 98 | hexencode_str_new(VALUE str_digest) 99 | { 100 | char *digest; 101 | size_t digest_len; 102 | size_t i; 103 | VALUE str; 104 | char *p; 105 | static const char hex[] = { 106 | '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 107 | 'a', 'b', 'c', 'd', 'e', 'f' 108 | }; 109 | 110 | StringValue(str_digest); 111 | digest = RSTRING_PTR(str_digest); 112 | digest_len = RSTRING_LEN(str_digest); 113 | 114 | if (LONG_MAX / 2 < digest_len) { 115 | rb_raise(rb_eRuntimeError, "digest string too long"); 116 | } 117 | 118 | str = rb_usascii_str_new(0, digest_len * 2); 119 | 120 | for (i = 0, p = RSTRING_PTR(str); i < digest_len; i++) { 121 | unsigned char byte = digest[i]; 122 | 123 | p[i + i] = hex[byte >> 4]; 124 | p[i + i + 1] = hex[byte & 0x0f]; 125 | } 126 | 127 | RB_GC_GUARD(str_digest); 128 | 129 | return str; 130 | } 131 | 132 | /* 133 | * call-seq: 134 | * Digest.hexencode(string) -> hexencoded_string 135 | * 136 | * Generates a hex-encoded version of a given _string_. 137 | */ 138 | static VALUE 139 | rb_digest_s_hexencode(VALUE klass, VALUE str) 140 | { 141 | return hexencode_str_new(str); 142 | } 143 | 144 | NORETURN(static void rb_digest_instance_method_unimpl(VALUE self, const char *method)); 145 | 146 | /* 147 | * Document-module: Digest::Instance 148 | * 149 | * This module provides instance methods for a digest implementation 150 | * object to calculate message digest values. 151 | */ 152 | 153 | static void 154 | rb_digest_instance_method_unimpl(VALUE self, const char *method) 155 | { 156 | rb_raise(rb_eRuntimeError, "%s does not implement %s()", 157 | rb_obj_classname(self), method); 158 | } 159 | 160 | /* 161 | * call-seq: 162 | * digest_obj.update(string) -> digest_obj 163 | * digest_obj << string -> digest_obj 164 | * 165 | * Updates the digest using a given _string_ and returns self. 166 | * 167 | * The update() method and the left-shift operator are overridden by 168 | * each implementation subclass. (One should be an alias for the 169 | * other) 170 | */ 171 | static VALUE 172 | rb_digest_instance_update(VALUE self, VALUE str) 173 | { 174 | rb_digest_instance_method_unimpl(self, "update"); 175 | 176 | UNREACHABLE; 177 | } 178 | 179 | /* 180 | * call-seq: 181 | * digest_obj.instance_eval { finish } -> digest_obj 182 | * 183 | * Finishes the digest and returns the resulting hash value. 184 | * 185 | * This method is overridden by each implementation subclass and often 186 | * made private, because some of those subclasses may leave internal 187 | * data uninitialized. Do not call this method from outside. Use 188 | * #digest!() instead, which ensures that internal data be reset for 189 | * security reasons. 190 | */ 191 | static VALUE 192 | rb_digest_instance_finish(VALUE self) 193 | { 194 | rb_digest_instance_method_unimpl(self, "finish"); 195 | 196 | UNREACHABLE; 197 | } 198 | 199 | /* 200 | * call-seq: 201 | * digest_obj.reset -> digest_obj 202 | * 203 | * Resets the digest to the initial state and returns self. 204 | * 205 | * This method is overridden by each implementation subclass. 206 | */ 207 | static VALUE 208 | rb_digest_instance_reset(VALUE self) 209 | { 210 | rb_digest_instance_method_unimpl(self, "reset"); 211 | 212 | UNREACHABLE; 213 | } 214 | 215 | /* 216 | * call-seq: 217 | * digest_obj.new -> another_digest_obj 218 | * 219 | * Returns a new, initialized copy of the digest object. Equivalent 220 | * to digest_obj.clone().reset(). 221 | */ 222 | static VALUE 223 | rb_digest_instance_new(VALUE self) 224 | { 225 | VALUE clone = rb_obj_clone(self); 226 | rb_funcall(clone, id_reset, 0); 227 | return clone; 228 | } 229 | 230 | /* 231 | * call-seq: 232 | * digest_obj.digest -> string 233 | * digest_obj.digest(string) -> string 234 | * 235 | * If none is given, returns the resulting hash value of the digest, 236 | * keeping the digest's state. 237 | * 238 | * If a _string_ is given, returns the hash value for the given 239 | * _string_, resetting the digest to the initial state before and 240 | * after the process. 241 | */ 242 | static VALUE 243 | rb_digest_instance_digest(int argc, VALUE *argv, VALUE self) 244 | { 245 | VALUE str, value; 246 | 247 | if (rb_scan_args(argc, argv, "01", &str) > 0) { 248 | rb_funcall(self, id_reset, 0); 249 | rb_funcall(self, id_update, 1, str); 250 | value = rb_funcall(self, id_finish, 0); 251 | rb_funcall(self, id_reset, 0); 252 | } else { 253 | value = rb_funcall(rb_obj_clone(self), id_finish, 0); 254 | } 255 | 256 | return value; 257 | } 258 | 259 | /* 260 | * call-seq: 261 | * digest_obj.digest! -> string 262 | * 263 | * Returns the resulting hash value and resets the digest to the 264 | * initial state. 265 | */ 266 | static VALUE 267 | rb_digest_instance_digest_bang(VALUE self) 268 | { 269 | VALUE value = rb_funcall(self, id_finish, 0); 270 | rb_funcall(self, id_reset, 0); 271 | 272 | return value; 273 | } 274 | 275 | /* 276 | * call-seq: 277 | * digest_obj.hexdigest -> string 278 | * digest_obj.hexdigest(string) -> string 279 | * 280 | * If none is given, returns the resulting hash value of the digest in 281 | * a hex-encoded form, keeping the digest's state. 282 | * 283 | * If a _string_ is given, returns the hash value for the given 284 | * _string_ in a hex-encoded form, resetting the digest to the initial 285 | * state before and after the process. 286 | */ 287 | static VALUE 288 | rb_digest_instance_hexdigest(int argc, VALUE *argv, VALUE self) 289 | { 290 | VALUE str, value; 291 | 292 | if (rb_scan_args(argc, argv, "01", &str) > 0) { 293 | rb_funcall(self, id_reset, 0); 294 | rb_funcall(self, id_update, 1, str); 295 | value = rb_funcall(self, id_finish, 0); 296 | rb_funcall(self, id_reset, 0); 297 | } else { 298 | value = rb_funcall(rb_obj_clone(self), id_finish, 0); 299 | } 300 | 301 | return hexencode_str_new(value); 302 | } 303 | 304 | /* 305 | * call-seq: 306 | * digest_obj.hexdigest! -> string 307 | * 308 | * Returns the resulting hash value in a hex-encoded form and resets 309 | * the digest to the initial state. 310 | */ 311 | static VALUE 312 | rb_digest_instance_hexdigest_bang(VALUE self) 313 | { 314 | VALUE value = rb_funcall(self, id_finish, 0); 315 | rb_funcall(self, id_reset, 0); 316 | 317 | return hexencode_str_new(value); 318 | } 319 | 320 | /* 321 | * call-seq: 322 | * digest_obj.to_s -> string 323 | * 324 | * Returns digest_obj.hexdigest(). 325 | */ 326 | static VALUE 327 | rb_digest_instance_to_s(VALUE self) 328 | { 329 | return rb_funcall(self, id_hexdigest, 0); 330 | } 331 | 332 | /* 333 | * call-seq: 334 | * digest_obj.inspect -> string 335 | * 336 | * Creates a printable version of the digest object. 337 | */ 338 | static VALUE 339 | rb_digest_instance_inspect(VALUE self) 340 | { 341 | VALUE str; 342 | size_t digest_len = 32; /* about this size at least */ 343 | const char *cname; 344 | 345 | cname = rb_obj_classname(self); 346 | 347 | /* # */ 348 | str = rb_str_buf_new(2 + strlen(cname) + 2 + digest_len * 2 + 1); 349 | rb_str_buf_cat2(str, "#<"); 350 | rb_str_buf_cat2(str, cname); 351 | rb_str_buf_cat2(str, ": "); 352 | rb_str_buf_append(str, rb_digest_instance_hexdigest(0, 0, self)); 353 | rb_str_buf_cat2(str, ">"); 354 | return str; 355 | } 356 | 357 | /* 358 | * call-seq: 359 | * digest_obj == another_digest_obj -> boolean 360 | * digest_obj == string -> boolean 361 | * 362 | * If a string is given, checks whether it is equal to the hex-encoded 363 | * hash value of the digest object. If another digest instance is 364 | * given, checks whether they have the same hash value. Otherwise 365 | * returns false. 366 | */ 367 | static VALUE 368 | rb_digest_instance_equal(VALUE self, VALUE other) 369 | { 370 | VALUE str1, str2; 371 | 372 | if (rb_obj_is_kind_of(other, rb_mDigest_Instance) == Qtrue) { 373 | str1 = rb_digest_instance_digest(0, 0, self); 374 | str2 = rb_digest_instance_digest(0, 0, other); 375 | } else { 376 | str1 = rb_digest_instance_to_s(self); 377 | str2 = rb_check_string_type(other); 378 | if (NIL_P(str2)) return Qfalse; 379 | } 380 | 381 | /* never blindly assume that subclass methods return strings */ 382 | StringValue(str1); 383 | StringValue(str2); 384 | 385 | if (RSTRING_LEN(str1) == RSTRING_LEN(str2) && 386 | rb_str_cmp(str1, str2) == 0) { 387 | return Qtrue; 388 | } 389 | return Qfalse; 390 | } 391 | 392 | /* 393 | * call-seq: 394 | * digest_obj.digest_length -> integer 395 | * 396 | * Returns the length of the hash value of the digest. 397 | * 398 | * This method should be overridden by each implementation subclass. 399 | * If not, digest_obj.digest().length() is returned. 400 | */ 401 | static VALUE 402 | rb_digest_instance_digest_length(VALUE self) 403 | { 404 | /* subclasses really should redefine this method */ 405 | VALUE digest = rb_digest_instance_digest(0, 0, self); 406 | 407 | /* never blindly assume that #digest() returns a string */ 408 | StringValue(digest); 409 | return LONG2NUM(RSTRING_LEN(digest)); 410 | } 411 | 412 | /* 413 | * call-seq: 414 | * digest_obj.length -> integer 415 | * digest_obj.size -> integer 416 | * 417 | * Returns digest_obj.digest_length(). 418 | */ 419 | static VALUE 420 | rb_digest_instance_length(VALUE self) 421 | { 422 | return rb_funcall(self, id_digest_length, 0); 423 | } 424 | 425 | /* 426 | * call-seq: 427 | * digest_obj.block_length -> integer 428 | * 429 | * Returns the block length of the digest. 430 | * 431 | * This method is overridden by each implementation subclass. 432 | */ 433 | static VALUE 434 | rb_digest_instance_block_length(VALUE self) 435 | { 436 | rb_digest_instance_method_unimpl(self, "block_length"); 437 | 438 | UNREACHABLE; 439 | } 440 | 441 | /* 442 | * Document-class: Digest::Class 443 | * 444 | * This module stands as a base class for digest implementation 445 | * classes. 446 | */ 447 | 448 | /* 449 | * call-seq: 450 | * Digest::Class.digest(string, *parameters) -> hash_string 451 | * 452 | * Returns the hash value of a given _string_. This is equivalent to 453 | * Digest::Class.new(*parameters).digest(string), where extra 454 | * _parameters_, if any, are passed through to the constructor and the 455 | * _string_ is passed to #digest(). 456 | */ 457 | static VALUE 458 | rb_digest_class_s_digest(int argc, VALUE *argv, VALUE klass) 459 | { 460 | VALUE str; 461 | volatile VALUE obj; 462 | 463 | if (argc < 1) { 464 | rb_raise(rb_eArgError, "no data given"); 465 | } 466 | 467 | str = *argv++; 468 | argc--; 469 | 470 | StringValue(str); 471 | 472 | obj = rb_obj_alloc(klass); 473 | rb_obj_call_init(obj, argc, argv); 474 | 475 | return rb_funcall(obj, id_digest, 1, str); 476 | } 477 | 478 | /* 479 | * call-seq: 480 | * Digest::Class.hexdigest(string[, ...]) -> hash_string 481 | * 482 | * Returns the hex-encoded hash value of a given _string_. This is 483 | * almost equivalent to 484 | * Digest.hexencode(Digest::Class.new(*parameters).digest(string)). 485 | */ 486 | static VALUE 487 | rb_digest_class_s_hexdigest(int argc, VALUE *argv, VALUE klass) 488 | { 489 | return hexencode_str_new(rb_funcallv(klass, id_digest, argc, argv)); 490 | } 491 | 492 | /* :nodoc: */ 493 | static VALUE 494 | rb_digest_class_init(VALUE self) 495 | { 496 | return self; 497 | } 498 | 499 | /* 500 | * Document-class: Digest::Base 501 | * 502 | * This abstract class provides a common interface to message digest 503 | * implementation classes written in C. 504 | * 505 | * ==Write a Digest subclass in C 506 | * Digest::Base provides a common interface to message digest 507 | * classes written in C. These classes must provide a struct 508 | * of type rb_digest_metadata_t: 509 | * typedef int (*rb_digest_hash_init_func_t)(void *); 510 | * typedef void (*rb_digest_hash_update_func_t)(void *, unsigned char *, size_t); 511 | * typedef int (*rb_digest_hash_finish_func_t)(void *, unsigned char *); 512 | * 513 | * typedef struct { 514 | * int api_version; 515 | * size_t digest_len; 516 | * size_t block_len; 517 | * size_t ctx_size; 518 | * rb_digest_hash_init_func_t init_func; 519 | * rb_digest_hash_update_func_t update_func; 520 | * rb_digest_hash_finish_func_t finish_func; 521 | * } rb_digest_metadata_t; 522 | * 523 | * This structure must be set as an instance variable named +metadata+ 524 | * (without the +@+ in front of the name). By example: 525 | * static const rb_digest_metadata_t sha1 = { 526 | * RUBY_DIGEST_API_VERSION, 527 | * SHA1_DIGEST_LENGTH, 528 | * SHA1_BLOCK_LENGTH, 529 | * sizeof(SHA1_CTX), 530 | * (rb_digest_hash_init_func_t)SHA1_Init, 531 | * (rb_digest_hash_update_func_t)SHA1_Update, 532 | * (rb_digest_hash_finish_func_t)SHA1_Finish, 533 | * }; 534 | * 535 | * 536 | * rb_ivar_set(cDigest_SHA1, rb_intern("metadata"), 537 | * rb_digest_make_metadata(&sha1)); 538 | */ 539 | 540 | #ifdef DIGEST_USE_RB_EXT_RESOLVE_SYMBOL 541 | static const rb_data_type_t metadata_type = { 542 | "digest/metadata", 543 | {0}, 544 | }; 545 | 546 | RUBY_FUNC_EXPORTED VALUE 547 | rb_digest_wrap_metadata(const rb_digest_metadata_t *meta) 548 | { 549 | return rb_obj_freeze(TypedData_Wrap_Struct(0, &metadata_type, (void *)meta)); 550 | } 551 | #endif 552 | 553 | static rb_digest_metadata_t * 554 | get_metadata_ptr(VALUE obj) 555 | { 556 | rb_digest_metadata_t *algo; 557 | 558 | #ifdef DIGEST_USE_RB_EXT_RESOLVE_SYMBOL 559 | if (!rb_typeddata_is_kind_of(obj, &metadata_type)) return 0; 560 | algo = RTYPEDDATA_DATA(obj); 561 | #else 562 | # undef RUBY_UNTYPED_DATA_WARNING 563 | # define RUBY_UNTYPED_DATA_WARNING 0 564 | Data_Get_Struct(obj, rb_digest_metadata_t, algo); 565 | #endif 566 | 567 | return algo; 568 | } 569 | 570 | static rb_digest_metadata_t * 571 | get_digest_base_metadata(VALUE klass) 572 | { 573 | VALUE p; 574 | VALUE obj; 575 | rb_digest_metadata_t *algo; 576 | 577 | for (p = klass; !NIL_P(p); p = rb_class_superclass(p)) { 578 | if (rb_ivar_defined(p, id_metadata)) { 579 | obj = rb_ivar_get(p, id_metadata); 580 | break; 581 | } 582 | } 583 | 584 | if (NIL_P(p)) 585 | rb_raise(rb_eRuntimeError, "Digest::Base cannot be directly inherited in Ruby"); 586 | 587 | algo = get_metadata_ptr(obj); 588 | if (!algo) { 589 | if (p == klass) 590 | rb_raise(rb_eTypeError, "%"PRIsVALUE"::metadata is not initialized properly", 591 | klass); 592 | else 593 | rb_raise(rb_eTypeError, "%"PRIsVALUE"(%"PRIsVALUE")::metadata is not initialized properly", 594 | klass, p); 595 | } 596 | 597 | switch (algo->api_version) { 598 | case 3: 599 | break; 600 | 601 | /* 602 | * put conversion here if possible when API is updated 603 | */ 604 | 605 | default: 606 | rb_raise(rb_eRuntimeError, "Incompatible digest API version"); 607 | } 608 | 609 | return algo; 610 | } 611 | 612 | static rb_digest_metadata_t * 613 | get_digest_obj_metadata(VALUE obj) 614 | { 615 | return get_digest_base_metadata(rb_obj_class(obj)); 616 | } 617 | 618 | static const rb_data_type_t digest_type = { 619 | "digest", 620 | {0, RUBY_TYPED_DEFAULT_FREE, 0,}, 621 | 0, 0, 622 | (RUBY_TYPED_FREE_IMMEDIATELY|RUBY_TYPED_WB_PROTECTED), 623 | }; 624 | 625 | static inline void 626 | algo_init(const rb_digest_metadata_t *algo, void *pctx) 627 | { 628 | if (algo->init_func(pctx) != 1) { 629 | rb_raise(rb_eRuntimeError, "Digest initialization failed."); 630 | } 631 | } 632 | 633 | static VALUE 634 | rb_digest_base_alloc(VALUE klass) 635 | { 636 | rb_digest_metadata_t *algo; 637 | VALUE obj; 638 | void *pctx; 639 | 640 | if (klass == rb_cDigest_Base) { 641 | rb_raise(rb_eNotImpError, "Digest::Base is an abstract class"); 642 | } 643 | 644 | algo = get_digest_base_metadata(klass); 645 | 646 | obj = rb_data_typed_object_zalloc(klass, algo->ctx_size, &digest_type); 647 | pctx = RTYPEDDATA_DATA(obj); 648 | algo_init(algo, pctx); 649 | 650 | return obj; 651 | } 652 | 653 | /* :nodoc: */ 654 | static VALUE 655 | rb_digest_base_copy(VALUE copy, VALUE obj) 656 | { 657 | rb_digest_metadata_t *algo; 658 | void *pctx1, *pctx2; 659 | 660 | if (copy == obj) return copy; 661 | 662 | rb_check_frozen(copy); 663 | 664 | algo = get_digest_obj_metadata(copy); 665 | if (algo != get_digest_obj_metadata(obj)) 666 | rb_raise(rb_eTypeError, "different algorithms"); 667 | 668 | TypedData_Get_Struct(obj, void, &digest_type, pctx1); 669 | TypedData_Get_Struct(copy, void, &digest_type, pctx2); 670 | memcpy(pctx2, pctx1, algo->ctx_size); 671 | 672 | return copy; 673 | } 674 | 675 | /* 676 | * call-seq: digest_base.reset -> digest_base 677 | * 678 | * Reset the digest to its initial state and return +self+. 679 | */ 680 | static VALUE 681 | rb_digest_base_reset(VALUE self) 682 | { 683 | rb_digest_metadata_t *algo; 684 | void *pctx; 685 | 686 | algo = get_digest_obj_metadata(self); 687 | 688 | TypedData_Get_Struct(self, void, &digest_type, pctx); 689 | 690 | algo_init(algo, pctx); 691 | 692 | return self; 693 | } 694 | 695 | /* 696 | * call-seq: 697 | * digest_base.update(string) -> digest_base 698 | * digest_base << string -> digest_base 699 | * 700 | * Update the digest using given _string_ and return +self+. 701 | */ 702 | static VALUE 703 | rb_digest_base_update(VALUE self, VALUE str) 704 | { 705 | rb_digest_metadata_t *algo; 706 | void *pctx; 707 | 708 | algo = get_digest_obj_metadata(self); 709 | 710 | TypedData_Get_Struct(self, void, &digest_type, pctx); 711 | 712 | StringValue(str); 713 | algo->update_func(pctx, (unsigned char *)RSTRING_PTR(str), RSTRING_LEN(str)); 714 | RB_GC_GUARD(str); 715 | 716 | return self; 717 | } 718 | 719 | /* :nodoc: */ 720 | static VALUE 721 | rb_digest_base_finish(VALUE self) 722 | { 723 | rb_digest_metadata_t *algo; 724 | void *pctx; 725 | VALUE str; 726 | 727 | algo = get_digest_obj_metadata(self); 728 | 729 | TypedData_Get_Struct(self, void, &digest_type, pctx); 730 | 731 | str = rb_str_new(0, algo->digest_len); 732 | algo->finish_func(pctx, (unsigned char *)RSTRING_PTR(str)); 733 | 734 | /* avoid potential coredump caused by use of a finished context */ 735 | algo_init(algo, pctx); 736 | 737 | return str; 738 | } 739 | 740 | /* 741 | * call-seq: digest_base.digest_length -> Integer 742 | * 743 | * Return the length of the hash value in bytes. 744 | */ 745 | static VALUE 746 | rb_digest_base_digest_length(VALUE self) 747 | { 748 | rb_digest_metadata_t *algo; 749 | 750 | algo = get_digest_obj_metadata(self); 751 | 752 | return SIZET2NUM(algo->digest_len); 753 | } 754 | 755 | /* 756 | * call-seq: digest_base.block_length -> Integer 757 | * 758 | * Return the block length of the digest in bytes. 759 | */ 760 | static VALUE 761 | rb_digest_base_block_length(VALUE self) 762 | { 763 | rb_digest_metadata_t *algo; 764 | 765 | algo = get_digest_obj_metadata(self); 766 | 767 | return SIZET2NUM(algo->block_len); 768 | } 769 | 770 | void 771 | Init_digest(void) 772 | { 773 | #undef rb_intern 774 | id_reset = rb_intern("reset"); 775 | id_update = rb_intern("update"); 776 | id_finish = rb_intern("finish"); 777 | id_digest = rb_intern("digest"); 778 | id_hexdigest = rb_intern("hexdigest"); 779 | id_digest_length = rb_intern("digest_length"); 780 | id_metadata = rb_id_metadata(); 781 | InitVM(digest); 782 | } 783 | 784 | void 785 | InitVM_digest(void) 786 | { 787 | /* 788 | * module Digest 789 | */ 790 | rb_mDigest = rb_define_module("Digest"); 791 | 792 | #ifdef HAVE_RB_EXT_RACTOR_SAFE 793 | rb_ext_ractor_safe(true); 794 | #endif 795 | 796 | /* module functions */ 797 | rb_define_module_function(rb_mDigest, "hexencode", rb_digest_s_hexencode, 1); 798 | 799 | /* 800 | * module Digest::Instance 801 | */ 802 | rb_mDigest_Instance = rb_define_module_under(rb_mDigest, "Instance"); 803 | 804 | /* instance methods that should be overridden */ 805 | rb_define_method(rb_mDigest_Instance, "update", rb_digest_instance_update, 1); 806 | rb_define_method(rb_mDigest_Instance, "<<", rb_digest_instance_update, 1); 807 | rb_define_private_method(rb_mDigest_Instance, "finish", rb_digest_instance_finish, 0); 808 | rb_define_method(rb_mDigest_Instance, "reset", rb_digest_instance_reset, 0); 809 | rb_define_method(rb_mDigest_Instance, "digest_length", rb_digest_instance_digest_length, 0); 810 | rb_define_method(rb_mDigest_Instance, "block_length", rb_digest_instance_block_length, 0); 811 | 812 | /* instance methods that may be overridden */ 813 | rb_define_method(rb_mDigest_Instance, "==", rb_digest_instance_equal, 1); 814 | rb_define_method(rb_mDigest_Instance, "inspect", rb_digest_instance_inspect, 0); 815 | 816 | /* instance methods that need not usually be overridden */ 817 | rb_define_method(rb_mDigest_Instance, "new", rb_digest_instance_new, 0); 818 | rb_define_method(rb_mDigest_Instance, "digest", rb_digest_instance_digest, -1); 819 | rb_define_method(rb_mDigest_Instance, "digest!", rb_digest_instance_digest_bang, 0); 820 | rb_define_method(rb_mDigest_Instance, "hexdigest", rb_digest_instance_hexdigest, -1); 821 | rb_define_method(rb_mDigest_Instance, "hexdigest!", rb_digest_instance_hexdigest_bang, 0); 822 | rb_define_method(rb_mDigest_Instance, "to_s", rb_digest_instance_to_s, 0); 823 | rb_define_method(rb_mDigest_Instance, "length", rb_digest_instance_length, 0); 824 | rb_define_method(rb_mDigest_Instance, "size", rb_digest_instance_length, 0); 825 | 826 | /* 827 | * class Digest::Class 828 | */ 829 | rb_cDigest_Class = rb_define_class_under(rb_mDigest, "Class", rb_cObject); 830 | rb_define_method(rb_cDigest_Class, "initialize", rb_digest_class_init, 0); 831 | rb_include_module(rb_cDigest_Class, rb_mDigest_Instance); 832 | 833 | /* class methods */ 834 | rb_define_singleton_method(rb_cDigest_Class, "digest", rb_digest_class_s_digest, -1); 835 | rb_define_singleton_method(rb_cDigest_Class, "hexdigest", rb_digest_class_s_hexdigest, -1); 836 | 837 | /* class Digest::Base < Digest::Class */ 838 | rb_cDigest_Base = rb_define_class_under(rb_mDigest, "Base", rb_cDigest_Class); 839 | 840 | rb_define_alloc_func(rb_cDigest_Base, rb_digest_base_alloc); 841 | 842 | rb_define_method(rb_cDigest_Base, "initialize_copy", rb_digest_base_copy, 1); 843 | rb_define_method(rb_cDigest_Base, "reset", rb_digest_base_reset, 0); 844 | rb_define_method(rb_cDigest_Base, "update", rb_digest_base_update, 1); 845 | rb_define_method(rb_cDigest_Base, "<<", rb_digest_base_update, 1); 846 | rb_define_private_method(rb_cDigest_Base, "finish", rb_digest_base_finish, 0); 847 | rb_define_method(rb_cDigest_Base, "digest_length", rb_digest_base_digest_length, 0); 848 | rb_define_method(rb_cDigest_Base, "block_length", rb_digest_base_block_length, 0); 849 | } 850 | -------------------------------------------------------------------------------- /ext/digest/digest.h: -------------------------------------------------------------------------------- 1 | /************************************************ 2 | 3 | digest.h - header file for ruby digest modules 4 | 5 | $Author$ 6 | created at: Fri May 25 08:54:56 JST 2001 7 | 8 | 9 | Copyright (C) 2001-2006 Akinori MUSHA 10 | 11 | $RoughId: digest.h,v 1.3 2001/07/13 15:38:27 knu Exp $ 12 | $Id$ 13 | 14 | ************************************************/ 15 | 16 | #include "ruby.h" 17 | 18 | #define RUBY_DIGEST_API_VERSION 3 19 | 20 | typedef int (*rb_digest_hash_init_func_t)(void *); 21 | typedef void (*rb_digest_hash_update_func_t)(void *, unsigned char *, size_t); 22 | typedef int (*rb_digest_hash_finish_func_t)(void *, unsigned char *); 23 | 24 | typedef struct { 25 | int api_version; 26 | size_t digest_len; 27 | size_t block_len; 28 | size_t ctx_size; 29 | rb_digest_hash_init_func_t init_func; 30 | rb_digest_hash_update_func_t update_func; 31 | rb_digest_hash_finish_func_t finish_func; 32 | } rb_digest_metadata_t; 33 | 34 | #define DEFINE_UPDATE_FUNC_FOR_UINT(name) \ 35 | void \ 36 | rb_digest_##name##_update(void *ctx, unsigned char *ptr, size_t size) \ 37 | { \ 38 | const unsigned int stride = 16384; \ 39 | \ 40 | for (; size > stride; size -= stride, ptr += stride) { \ 41 | name##_Update(ctx, ptr, stride); \ 42 | } \ 43 | /* Since size <= stride, size should fit into an unsigned int */ \ 44 | if (size > 0) name##_Update(ctx, ptr, (unsigned int)size); \ 45 | } 46 | 47 | #define DEFINE_FINISH_FUNC_FROM_FINAL(name) \ 48 | int \ 49 | rb_digest_##name##_finish(void *ctx, unsigned char *ptr) \ 50 | { \ 51 | return name##_Final(ptr, ctx); \ 52 | } 53 | 54 | static inline VALUE 55 | rb_digest_namespace(void) 56 | { 57 | rb_require("digest"); 58 | return rb_path2class("Digest"); 59 | } 60 | 61 | static inline ID 62 | rb_id_metadata(void) 63 | { 64 | return rb_intern_const("metadata"); 65 | } 66 | 67 | #if !defined(HAVE_RB_EXT_RESOLVE_SYMBOL) 68 | #elif !defined(RUBY_UNTYPED_DATA_WARNING) 69 | # error RUBY_UNTYPED_DATA_WARNING is not defined 70 | #elif RUBY_UNTYPED_DATA_WARNING 71 | /* rb_ext_resolve_symbol() has been defined since Ruby 3.3, but digest 72 | * bundled with 3.3 didn't use it. */ 73 | # define DIGEST_USE_RB_EXT_RESOLVE_SYMBOL 1 74 | #endif 75 | 76 | static inline VALUE 77 | rb_digest_make_metadata(const rb_digest_metadata_t *meta) 78 | { 79 | #if defined(EXTSTATIC) && EXTSTATIC 80 | /* The extension is built as a static library, so safe to refer to 81 | * rb_digest_wrap_metadata directly. */ 82 | extern VALUE rb_digest_wrap_metadata(const rb_digest_metadata_t *meta); 83 | return rb_digest_wrap_metadata(meta); 84 | #else 85 | /* The extension is built as a shared library, so we can't refer 86 | * to rb_digest_wrap_metadata directly. */ 87 | # ifdef DIGEST_USE_RB_EXT_RESOLVE_SYMBOL 88 | /* If rb_ext_resolve_symbol() is available, use it to get the address of 89 | * rb_digest_wrap_metadata. */ 90 | typedef VALUE (*wrapper_func_type)(const rb_digest_metadata_t *meta); 91 | static wrapper_func_type wrapper; 92 | if (!wrapper) { 93 | wrapper = (wrapper_func_type)(uintptr_t) 94 | rb_ext_resolve_symbol("digest.so", "rb_digest_wrap_metadata"); 95 | if (!wrapper) rb_raise(rb_eLoadError, "rb_digest_wrap_metadata not found"); 96 | } 97 | return wrapper(meta); 98 | # else 99 | /* If rb_ext_resolve_symbol() is not available, keep using untyped 100 | * data. */ 101 | # undef RUBY_UNTYPED_DATA_WARNING 102 | # define RUBY_UNTYPED_DATA_WARNING 0 103 | return rb_obj_freeze(Data_Wrap_Struct(0, 0, 0, (void *)meta)); 104 | # endif 105 | #endif 106 | } 107 | -------------------------------------------------------------------------------- /ext/digest/digest_conf.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: false 2 | 3 | def digest_conf(name) 4 | unless with_config("bundled-#{name}") 5 | case cc = with_config("common-digest", true) 6 | when true, false 7 | else 8 | cc = cc.split(/[\s,]++/).any? {|pat| File.fnmatch?(pat, name)} 9 | end 10 | if cc and File.exist?("#$srcdir/#{name}cc.h") and 11 | have_header("CommonCrypto/CommonDigest.h") 12 | $defs << "-D#{name.upcase}_USE_COMMONDIGEST" 13 | $headers << "#{name}cc.h" 14 | return :commondigest 15 | end 16 | end 17 | $objs << "#{name}.#{$OBJEXT}" 18 | return 19 | end 20 | -------------------------------------------------------------------------------- /ext/digest/extconf.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: false 2 | # $RoughId: extconf.rb,v 1.6 2001/07/13 15:38:27 knu Exp $ 3 | # $Id$ 4 | 5 | require "mkmf" 6 | 7 | $INSTALLFILES = { 8 | "digest.h" => "$(HDRDIR)" 9 | } if $extmk 10 | 11 | create_makefile("digest") 12 | -------------------------------------------------------------------------------- /ext/digest/lib/digest/loader.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require 'digest.so' 4 | -------------------------------------------------------------------------------- /ext/digest/lib/digest/sha2/loader.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require 'digest/sha2.so' 4 | -------------------------------------------------------------------------------- /ext/digest/md5/extconf.rb: -------------------------------------------------------------------------------- 1 | # -*- coding: us-ascii -*- 2 | # frozen_string_literal: false 3 | # $RoughId: extconf.rb,v 1.3 2001/08/14 19:54:51 knu Exp $ 4 | # $Id$ 5 | 6 | require "mkmf" 7 | require File.expand_path("../../digest_conf", __FILE__) 8 | 9 | $objs = [ "md5init.#{$OBJEXT}" ] 10 | 11 | digest_conf("md5") 12 | 13 | have_header("sys/cdefs.h") 14 | 15 | $preload = %w[digest] 16 | 17 | create_makefile("digest/md5") 18 | -------------------------------------------------------------------------------- /ext/digest/md5/md5.c: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (C) 1999, 2000 Aladdin Enterprises. All rights reserved. 3 | 4 | This software is provided 'as-is', without any express or implied 5 | warranty. In no event will the authors be held liable for any damages 6 | arising from the use of this software. 7 | 8 | Permission is granted to anyone to use this software for any purpose, 9 | including commercial applications, and to alter it and redistribute it 10 | freely, subject to the following restrictions: 11 | 12 | 1. The origin of this software must not be misrepresented; you must not 13 | claim that you wrote the original software. If you use this software 14 | in a product, an acknowledgment in the product documentation would be 15 | appreciated but is not required. 16 | 2. Altered source versions must be plainly marked as such, and must not be 17 | misrepresented as being the original software. 18 | 3. This notice may not be removed or altered from any source distribution. 19 | 20 | L. Peter Deutsch 21 | ghost@aladdin.com 22 | 23 | */ 24 | 25 | /* 26 | Independent implementation of MD5 (RFC 1321). 27 | 28 | This code implements the MD5 Algorithm defined in RFC 1321. 29 | It is derived directly from the text of the RFC and not from the 30 | reference implementation. 31 | 32 | The original and principal author of md5.c is L. Peter Deutsch 33 | . Other authors are noted in the change history 34 | that follows (in reverse chronological order): 35 | 36 | 2000-07-03 lpd Patched to eliminate warnings about "constant is 37 | unsigned in ANSI C, signed in traditional"; 38 | made test program self-checking. 39 | 1999-11-04 lpd Edited comments slightly for automatic TOC extraction. 40 | 1999-10-18 lpd Fixed typo in header comment (ansi2knr rather than md5). 41 | 1999-05-03 lpd Original version. 42 | */ 43 | 44 | /* 45 | This code was modified for use in Ruby. 46 | 47 | - Akinori MUSHA 48 | */ 49 | 50 | /*$OrigId: md5c.c,v 1.2 2001/03/26 08:57:14 matz Exp $ */ 51 | /*$RoughId: md5.c,v 1.2 2001/07/13 19:48:41 knu Exp $ */ 52 | /*$Id$ */ 53 | 54 | #include "md5.h" 55 | 56 | #ifdef TEST 57 | /* 58 | * Compile with -DTEST to create a self-contained executable test program. 59 | * The test program should print out the same values as given in section 60 | * A.5 of RFC 1321, reproduced below. 61 | */ 62 | #include 63 | int 64 | main(void) 65 | { 66 | static const char *const test[7*2] = { 67 | "", "d41d8cd98f00b204e9800998ecf8427e", 68 | "a", "0cc175b9c0f1b6a831c399e269772661", 69 | "abc", "900150983cd24fb0d6963f7d28e17f72", 70 | "message digest", "f96b697d7cb7938d525a2f31aaf161d0", 71 | "abcdefghijklmnopqrstuvwxyz", "c3fcd3d76192e4007dfb496cca67e13b", 72 | "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789", 73 | "d174ab98d277d9f5a5611c2c9f419d9f", 74 | "12345678901234567890123456789012345678901234567890123456789012345678901234567890", "57edf4a22be3c955ac49da2e2107b67a" 75 | }; 76 | int i; 77 | 78 | for (i = 0; i < 7*2; i += 2) { 79 | MD5_CTX state; 80 | uint8_t digest[16]; 81 | char hex_output[16*2 + 1]; 82 | int di; 83 | 84 | MD5_Init(&state); 85 | MD5_Update(&state, (const uint8_t *)test[i], strlen(test[i])); 86 | MD5_Final(digest, &state); 87 | printf("MD5 (\"%s\") = ", test[i]); 88 | for (di = 0; di < 16; ++di) 89 | sprintf(hex_output + di * 2, "%02x", digest[di]); 90 | puts(hex_output); 91 | if (strcmp(hex_output, test[i + 1])) 92 | printf("**** ERROR, should be: %s\n", test[i + 1]); 93 | } 94 | return 0; 95 | } 96 | #endif /* TEST */ 97 | 98 | 99 | /* 100 | * For reference, here is the program that computed the T values. 101 | */ 102 | #ifdef COMPUTE_T_VALUES 103 | #include 104 | int 105 | main(void) 106 | { 107 | int i; 108 | for (i = 1; i <= 64; ++i) { 109 | unsigned long v = (unsigned long)(4294967296.0 * fabs(sin((double)i))); 110 | 111 | /* 112 | * The following nonsense is only to avoid compiler warnings about 113 | * "integer constant is unsigned in ANSI C, signed with -traditional". 114 | */ 115 | if (v >> 31) { 116 | printf("#define T%d /* 0x%08lx */ (T_MASK ^ 0x%08lx)\n", i, 117 | v, (unsigned long)(unsigned int)(~v)); 118 | } else { 119 | printf("#define T%d 0x%08lx\n", i, v); 120 | } 121 | } 122 | return 0; 123 | } 124 | #endif /* COMPUTE_T_VALUES */ 125 | /* 126 | * End of T computation program. 127 | */ 128 | #ifdef T_MASK 129 | #undef T_MASK 130 | #endif 131 | #define T_MASK ((uint32_t)~0) 132 | #define T1 /* 0xd76aa478 */ (T_MASK ^ 0x28955b87) 133 | #define T2 /* 0xe8c7b756 */ (T_MASK ^ 0x173848a9) 134 | #define T3 0x242070db 135 | #define T4 /* 0xc1bdceee */ (T_MASK ^ 0x3e423111) 136 | #define T5 /* 0xf57c0faf */ (T_MASK ^ 0x0a83f050) 137 | #define T6 0x4787c62a 138 | #define T7 /* 0xa8304613 */ (T_MASK ^ 0x57cfb9ec) 139 | #define T8 /* 0xfd469501 */ (T_MASK ^ 0x02b96afe) 140 | #define T9 0x698098d8 141 | #define T10 /* 0x8b44f7af */ (T_MASK ^ 0x74bb0850) 142 | #define T11 /* 0xffff5bb1 */ (T_MASK ^ 0x0000a44e) 143 | #define T12 /* 0x895cd7be */ (T_MASK ^ 0x76a32841) 144 | #define T13 0x6b901122 145 | #define T14 /* 0xfd987193 */ (T_MASK ^ 0x02678e6c) 146 | #define T15 /* 0xa679438e */ (T_MASK ^ 0x5986bc71) 147 | #define T16 0x49b40821 148 | #define T17 /* 0xf61e2562 */ (T_MASK ^ 0x09e1da9d) 149 | #define T18 /* 0xc040b340 */ (T_MASK ^ 0x3fbf4cbf) 150 | #define T19 0x265e5a51 151 | #define T20 /* 0xe9b6c7aa */ (T_MASK ^ 0x16493855) 152 | #define T21 /* 0xd62f105d */ (T_MASK ^ 0x29d0efa2) 153 | #define T22 0x02441453 154 | #define T23 /* 0xd8a1e681 */ (T_MASK ^ 0x275e197e) 155 | #define T24 /* 0xe7d3fbc8 */ (T_MASK ^ 0x182c0437) 156 | #define T25 0x21e1cde6 157 | #define T26 /* 0xc33707d6 */ (T_MASK ^ 0x3cc8f829) 158 | #define T27 /* 0xf4d50d87 */ (T_MASK ^ 0x0b2af278) 159 | #define T28 0x455a14ed 160 | #define T29 /* 0xa9e3e905 */ (T_MASK ^ 0x561c16fa) 161 | #define T30 /* 0xfcefa3f8 */ (T_MASK ^ 0x03105c07) 162 | #define T31 0x676f02d9 163 | #define T32 /* 0x8d2a4c8a */ (T_MASK ^ 0x72d5b375) 164 | #define T33 /* 0xfffa3942 */ (T_MASK ^ 0x0005c6bd) 165 | #define T34 /* 0x8771f681 */ (T_MASK ^ 0x788e097e) 166 | #define T35 0x6d9d6122 167 | #define T36 /* 0xfde5380c */ (T_MASK ^ 0x021ac7f3) 168 | #define T37 /* 0xa4beea44 */ (T_MASK ^ 0x5b4115bb) 169 | #define T38 0x4bdecfa9 170 | #define T39 /* 0xf6bb4b60 */ (T_MASK ^ 0x0944b49f) 171 | #define T40 /* 0xbebfbc70 */ (T_MASK ^ 0x4140438f) 172 | #define T41 0x289b7ec6 173 | #define T42 /* 0xeaa127fa */ (T_MASK ^ 0x155ed805) 174 | #define T43 /* 0xd4ef3085 */ (T_MASK ^ 0x2b10cf7a) 175 | #define T44 0x04881d05 176 | #define T45 /* 0xd9d4d039 */ (T_MASK ^ 0x262b2fc6) 177 | #define T46 /* 0xe6db99e5 */ (T_MASK ^ 0x1924661a) 178 | #define T47 0x1fa27cf8 179 | #define T48 /* 0xc4ac5665 */ (T_MASK ^ 0x3b53a99a) 180 | #define T49 /* 0xf4292244 */ (T_MASK ^ 0x0bd6ddbb) 181 | #define T50 0x432aff97 182 | #define T51 /* 0xab9423a7 */ (T_MASK ^ 0x546bdc58) 183 | #define T52 /* 0xfc93a039 */ (T_MASK ^ 0x036c5fc6) 184 | #define T53 0x655b59c3 185 | #define T54 /* 0x8f0ccc92 */ (T_MASK ^ 0x70f3336d) 186 | #define T55 /* 0xffeff47d */ (T_MASK ^ 0x00100b82) 187 | #define T56 /* 0x85845dd1 */ (T_MASK ^ 0x7a7ba22e) 188 | #define T57 0x6fa87e4f 189 | #define T58 /* 0xfe2ce6e0 */ (T_MASK ^ 0x01d3191f) 190 | #define T59 /* 0xa3014314 */ (T_MASK ^ 0x5cfebceb) 191 | #define T60 0x4e0811a1 192 | #define T61 /* 0xf7537e82 */ (T_MASK ^ 0x08ac817d) 193 | #define T62 /* 0xbd3af235 */ (T_MASK ^ 0x42c50dca) 194 | #define T63 0x2ad7d2bb 195 | #define T64 /* 0xeb86d391 */ (T_MASK ^ 0x14792c6e) 196 | 197 | 198 | static void 199 | md5_process(MD5_CTX *pms, const uint8_t *data /*[64]*/) 200 | { 201 | uint32_t 202 | a = pms->state[0], b = pms->state[1], 203 | c = pms->state[2], d = pms->state[3]; 204 | uint32_t t; 205 | 206 | #ifdef WORDS_BIGENDIAN 207 | 208 | /* 209 | * On big-endian machines, we must arrange the bytes in the right 210 | * order. (This also works on machines of unknown byte order.) 211 | */ 212 | uint32_t X[16]; 213 | const uint8_t *xp = data; 214 | int i; 215 | 216 | for (i = 0; i < 16; ++i, xp += 4) 217 | X[i] = xp[0] + (xp[1] << 8) + (xp[2] << 16) + (xp[3] << 24); 218 | 219 | #else 220 | 221 | /* 222 | * On little-endian machines, we can process properly aligned data 223 | * without copying it. 224 | */ 225 | uint32_t xbuf[16]; 226 | const uint32_t *X; 227 | 228 | if (!(((uintptr_t)data) & 3)) { 229 | /* data are properly aligned */ 230 | X = (const uint32_t *)data; 231 | } else { 232 | /* not aligned */ 233 | memcpy(xbuf, data, 64); 234 | X = xbuf; 235 | } 236 | #endif 237 | 238 | #define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32 - (n)))) 239 | 240 | /* Round 1. */ 241 | /* Let [abcd k s i] denote the operation 242 | a = b + ((a + F(b,c,d) + X[k] + T[i]) <<< s). */ 243 | #define F(x, y, z) (((x) & (y)) | (~(x) & (z))) 244 | #define SET(a, b, c, d, k, s, Ti)\ 245 | t = a + F(b,c,d) + X[k] + Ti;\ 246 | a = ROTATE_LEFT(t, s) + b 247 | /* Do the following 16 operations. */ 248 | SET(a, b, c, d, 0, 7, T1); 249 | SET(d, a, b, c, 1, 12, T2); 250 | SET(c, d, a, b, 2, 17, T3); 251 | SET(b, c, d, a, 3, 22, T4); 252 | SET(a, b, c, d, 4, 7, T5); 253 | SET(d, a, b, c, 5, 12, T6); 254 | SET(c, d, a, b, 6, 17, T7); 255 | SET(b, c, d, a, 7, 22, T8); 256 | SET(a, b, c, d, 8, 7, T9); 257 | SET(d, a, b, c, 9, 12, T10); 258 | SET(c, d, a, b, 10, 17, T11); 259 | SET(b, c, d, a, 11, 22, T12); 260 | SET(a, b, c, d, 12, 7, T13); 261 | SET(d, a, b, c, 13, 12, T14); 262 | SET(c, d, a, b, 14, 17, T15); 263 | SET(b, c, d, a, 15, 22, T16); 264 | #undef SET 265 | 266 | /* Round 2. */ 267 | /* Let [abcd k s i] denote the operation 268 | a = b + ((a + G(b,c,d) + X[k] + T[i]) <<< s). */ 269 | #define G(x, y, z) (((x) & (z)) | ((y) & ~(z))) 270 | #define SET(a, b, c, d, k, s, Ti)\ 271 | t = a + G(b,c,d) + X[k] + Ti;\ 272 | a = ROTATE_LEFT(t, s) + b 273 | /* Do the following 16 operations. */ 274 | SET(a, b, c, d, 1, 5, T17); 275 | SET(d, a, b, c, 6, 9, T18); 276 | SET(c, d, a, b, 11, 14, T19); 277 | SET(b, c, d, a, 0, 20, T20); 278 | SET(a, b, c, d, 5, 5, T21); 279 | SET(d, a, b, c, 10, 9, T22); 280 | SET(c, d, a, b, 15, 14, T23); 281 | SET(b, c, d, a, 4, 20, T24); 282 | SET(a, b, c, d, 9, 5, T25); 283 | SET(d, a, b, c, 14, 9, T26); 284 | SET(c, d, a, b, 3, 14, T27); 285 | SET(b, c, d, a, 8, 20, T28); 286 | SET(a, b, c, d, 13, 5, T29); 287 | SET(d, a, b, c, 2, 9, T30); 288 | SET(c, d, a, b, 7, 14, T31); 289 | SET(b, c, d, a, 12, 20, T32); 290 | #undef SET 291 | 292 | /* Round 3. */ 293 | /* Let [abcd k s t] denote the operation 294 | a = b + ((a + H(b,c,d) + X[k] + T[i]) <<< s). */ 295 | #define H(x, y, z) ((x) ^ (y) ^ (z)) 296 | #define SET(a, b, c, d, k, s, Ti)\ 297 | t = a + H(b,c,d) + X[k] + Ti;\ 298 | a = ROTATE_LEFT(t, s) + b 299 | /* Do the following 16 operations. */ 300 | SET(a, b, c, d, 5, 4, T33); 301 | SET(d, a, b, c, 8, 11, T34); 302 | SET(c, d, a, b, 11, 16, T35); 303 | SET(b, c, d, a, 14, 23, T36); 304 | SET(a, b, c, d, 1, 4, T37); 305 | SET(d, a, b, c, 4, 11, T38); 306 | SET(c, d, a, b, 7, 16, T39); 307 | SET(b, c, d, a, 10, 23, T40); 308 | SET(a, b, c, d, 13, 4, T41); 309 | SET(d, a, b, c, 0, 11, T42); 310 | SET(c, d, a, b, 3, 16, T43); 311 | SET(b, c, d, a, 6, 23, T44); 312 | SET(a, b, c, d, 9, 4, T45); 313 | SET(d, a, b, c, 12, 11, T46); 314 | SET(c, d, a, b, 15, 16, T47); 315 | SET(b, c, d, a, 2, 23, T48); 316 | #undef SET 317 | 318 | /* Round 4. */ 319 | /* Let [abcd k s t] denote the operation 320 | a = b + ((a + I(b,c,d) + X[k] + T[i]) <<< s). */ 321 | #define I(x, y, z) ((y) ^ ((x) | ~(z))) 322 | #define SET(a, b, c, d, k, s, Ti)\ 323 | t = a + I(b,c,d) + X[k] + Ti;\ 324 | a = ROTATE_LEFT(t, s) + b 325 | /* Do the following 16 operations. */ 326 | SET(a, b, c, d, 0, 6, T49); 327 | SET(d, a, b, c, 7, 10, T50); 328 | SET(c, d, a, b, 14, 15, T51); 329 | SET(b, c, d, a, 5, 21, T52); 330 | SET(a, b, c, d, 12, 6, T53); 331 | SET(d, a, b, c, 3, 10, T54); 332 | SET(c, d, a, b, 10, 15, T55); 333 | SET(b, c, d, a, 1, 21, T56); 334 | SET(a, b, c, d, 8, 6, T57); 335 | SET(d, a, b, c, 15, 10, T58); 336 | SET(c, d, a, b, 6, 15, T59); 337 | SET(b, c, d, a, 13, 21, T60); 338 | SET(a, b, c, d, 4, 6, T61); 339 | SET(d, a, b, c, 11, 10, T62); 340 | SET(c, d, a, b, 2, 15, T63); 341 | SET(b, c, d, a, 9, 21, T64); 342 | #undef SET 343 | 344 | /* Then perform the following additions. (That is increment each 345 | of the four registers by the value it had before this block 346 | was started.) */ 347 | pms->state[0] += a; 348 | pms->state[1] += b; 349 | pms->state[2] += c; 350 | pms->state[3] += d; 351 | } 352 | 353 | int 354 | MD5_Init(MD5_CTX *pms) 355 | { 356 | pms->count[0] = pms->count[1] = 0; 357 | pms->state[0] = 0x67452301; 358 | pms->state[1] = /*0xefcdab89*/ T_MASK ^ 0x10325476; 359 | pms->state[2] = /*0x98badcfe*/ T_MASK ^ 0x67452301; 360 | pms->state[3] = 0x10325476; 361 | return 1; 362 | } 363 | 364 | void 365 | MD5_Update(MD5_CTX *pms, const uint8_t *data, size_t nbytes) 366 | { 367 | const uint8_t *p = data; 368 | size_t left = nbytes; 369 | size_t offset = (pms->count[0] >> 3) & 63; 370 | uint32_t nbits = (uint32_t)(nbytes << 3); 371 | 372 | if (nbytes == 0) 373 | return; 374 | 375 | /* Update the message length. */ 376 | pms->count[1] += nbytes >> 29; 377 | pms->count[0] += nbits; 378 | if (pms->count[0] < nbits) 379 | pms->count[1]++; 380 | 381 | /* Process an initial partial block. */ 382 | if (offset) { 383 | size_t copy = (offset + nbytes > 64 ? 64 - offset : nbytes); 384 | 385 | memcpy(pms->buffer + offset, p, copy); 386 | if (offset + copy < 64) 387 | return; 388 | p += copy; 389 | left -= copy; 390 | md5_process(pms, pms->buffer); 391 | } 392 | 393 | /* Process full blocks. */ 394 | for (; left >= 64; p += 64, left -= 64) 395 | md5_process(pms, p); 396 | 397 | /* Process a final partial block. */ 398 | if (left) 399 | memcpy(pms->buffer, p, left); 400 | } 401 | 402 | int 403 | MD5_Finish(MD5_CTX *pms, uint8_t *digest) 404 | { 405 | static const uint8_t pad[64] = { 406 | 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 407 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 408 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 409 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 410 | }; 411 | uint8_t data[8]; 412 | size_t i; 413 | 414 | /* Save the length before padding. */ 415 | for (i = 0; i < 8; ++i) 416 | data[i] = (uint8_t)(pms->count[i >> 2] >> ((i & 3) << 3)); 417 | /* Pad to 56 bytes mod 64. */ 418 | MD5_Update(pms, pad, ((55 - (pms->count[0] >> 3)) & 63) + 1); 419 | /* Append the length. */ 420 | MD5_Update(pms, data, 8); 421 | for (i = 0; i < 16; ++i) 422 | digest[i] = (uint8_t)(pms->state[i >> 2] >> ((i & 3) << 3)); 423 | return 1; 424 | } 425 | -------------------------------------------------------------------------------- /ext/digest/md5/md5.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (C) 1999 Aladdin Enterprises. All rights reserved. 3 | 4 | This software is provided 'as-is', without any express or implied 5 | warranty. In no event will the authors be held liable for any damages 6 | arising from the use of this software. 7 | 8 | Permission is granted to anyone to use this software for any purpose, 9 | including commercial applications, and to alter it and redistribute it 10 | freely, subject to the following restrictions: 11 | 12 | 1. The origin of this software must not be misrepresented; you must not 13 | claim that you wrote the original software. If you use this software 14 | in a product, an acknowledgment in the product documentation would be 15 | appreciated but is not required. 16 | 2. Altered source versions must be plainly marked as such, and must not be 17 | misrepresented as being the original software. 18 | 3. This notice may not be removed or altered from any source distribution. 19 | 20 | L. Peter Deutsch 21 | ghost@aladdin.com 22 | 23 | */ 24 | /* 25 | Independent implementation of MD5 (RFC 1321). 26 | 27 | This code implements the MD5 Algorithm defined in RFC 1321. 28 | It is derived directly from the text of the RFC and not from the 29 | reference implementation. 30 | 31 | The original and principal author of md5.h is L. Peter Deutsch 32 | . Other authors are noted in the change history 33 | that follows (in reverse chronological order): 34 | 35 | 1999-11-04 lpd Edited comments slightly for automatic TOC extraction. 36 | 1999-10-18 lpd Fixed typo in header comment (ansi2knr rather than md5); 37 | added conditionalization for C++ compilation from Martin 38 | Purschke . 39 | 1999-05-03 lpd Original version. 40 | */ 41 | 42 | /* $OrigId: md5.h,v 1.2 2001/03/26 08:57:14 matz Exp $ */ 43 | /* $RoughId: md5.h,v 1.3 2002/02/24 08:14:31 knu Exp $ */ 44 | /* $Id$ */ 45 | 46 | #ifndef MD5_INCLUDED 47 | # define MD5_INCLUDED 48 | 49 | #include "../defs.h" 50 | 51 | /* 52 | * This code has some adaptations for the Ghostscript environment, but it 53 | * will compile and run correctly in any environment with 8-bit chars and 54 | * 32-bit ints. Specifically, it assumes that if the following are 55 | * defined, they have the same meaning as in Ghostscript: P1, P2, P3. 56 | */ 57 | 58 | /* Define the state of the MD5 Algorithm. */ 59 | typedef struct md5_state_s { 60 | uint32_t count[2]; /* message length in bits, lsw first */ 61 | uint32_t state[4]; /* digest buffer */ 62 | uint8_t buffer[64]; /* accumulate block */ 63 | } MD5_CTX; 64 | 65 | #ifdef RUBY 66 | /* avoid name clash */ 67 | #define MD5_Init rb_Digest_MD5_Init 68 | #define MD5_Update rb_Digest_MD5_Update 69 | #define MD5_Finish rb_Digest_MD5_Finish 70 | #endif 71 | 72 | int MD5_Init _((MD5_CTX *pms)); 73 | void MD5_Update _((MD5_CTX *pms, const uint8_t *data, size_t nbytes)); 74 | int MD5_Finish _((MD5_CTX *pms, uint8_t *digest)); 75 | 76 | #define MD5_BLOCK_LENGTH 64 77 | #define MD5_DIGEST_LENGTH 16 78 | #define MD5_DIGEST_STRING_LENGTH (MD5_DIGEST_LENGTH * 2 + 1) 79 | 80 | #endif /* MD5_INCLUDED */ 81 | -------------------------------------------------------------------------------- /ext/digest/md5/md5cc.h: -------------------------------------------------------------------------------- 1 | #define COMMON_DIGEST_FOR_OPENSSL 1 2 | #include 3 | 4 | #ifdef __GNUC__ 5 | RB_DIGEST_WARNING_IGNORED(-Wdeprecated-declarations) 6 | /* Suppress deprecation warnings of MD5 from Xcode 11.1 */ 7 | /* Although we know MD5 is deprecated too, provide just for backward 8 | * compatibility, as well as Apple does. */ 9 | #endif 10 | 11 | #define MD5_BLOCK_LENGTH CC_MD5_BLOCK_BYTES 12 | 13 | static DEFINE_UPDATE_FUNC_FOR_UINT(MD5) 14 | static DEFINE_FINISH_FUNC_FROM_FINAL(MD5) 15 | 16 | #undef MD5_Update 17 | #undef MD5_Finish 18 | #define MD5_Update rb_digest_MD5_update 19 | #define MD5_Finish rb_digest_MD5_finish 20 | 21 | /* 22 | * Pre-10.6 defines are with args, which don't match the argless use in 23 | * the function pointer inits. Thus, we redefine MD5_Init as well. 24 | * This is a NOP on 10.6+. 25 | */ 26 | #undef MD5_Init 27 | #define MD5_Init CC_MD5_Init 28 | -------------------------------------------------------------------------------- /ext/digest/md5/md5init.c: -------------------------------------------------------------------------------- 1 | /* $RoughId: md5init.c,v 1.2 2001/07/13 19:49:10 knu Exp $ */ 2 | /* $Id$ */ 3 | 4 | #include 5 | #include "../digest.h" 6 | #include "../defs.h" 7 | #if defined(MD5_USE_COMMONDIGEST) 8 | #include "md5cc.h" 9 | #else 10 | #include "md5.h" 11 | #endif 12 | 13 | static const rb_digest_metadata_t md5 = { 14 | RUBY_DIGEST_API_VERSION, 15 | MD5_DIGEST_LENGTH, 16 | MD5_BLOCK_LENGTH, 17 | sizeof(MD5_CTX), 18 | (rb_digest_hash_init_func_t)MD5_Init, 19 | (rb_digest_hash_update_func_t)MD5_Update, 20 | (rb_digest_hash_finish_func_t)MD5_Finish, 21 | }; 22 | 23 | /* 24 | * Document-class: Digest::MD5 < Digest::Base 25 | * A class for calculating message digests using the MD5 26 | * Message-Digest Algorithm by RSA Data Security, Inc., described in 27 | * RFC1321. 28 | * 29 | * MD5 calculates a digest of 128 bits (16 bytes). 30 | * 31 | * == Examples 32 | * require 'digest' 33 | * 34 | * # Compute a complete digest 35 | * Digest::MD5.hexdigest 'abc' #=> "90015098..." 36 | * 37 | * # Compute digest by chunks 38 | * md5 = Digest::MD5.new # =># 39 | * md5.update "ab" 40 | * md5 << "c" # alias for #update 41 | * md5.hexdigest # => "90015098..." 42 | * 43 | * # Use the same object to compute another digest 44 | * md5.reset 45 | * md5 << "message" 46 | * md5.hexdigest # => "78e73102..." 47 | */ 48 | void 49 | Init_md5(void) 50 | { 51 | VALUE mDigest, cDigest_Base, cDigest_MD5; 52 | 53 | #if 0 54 | mDigest = rb_define_module("Digest"); /* let rdoc know */ 55 | #endif 56 | mDigest = rb_digest_namespace(); 57 | cDigest_Base = rb_const_get(mDigest, rb_intern_const("Base")); 58 | 59 | cDigest_MD5 = rb_define_class_under(mDigest, "MD5", cDigest_Base); 60 | rb_iv_set(cDigest_MD5, "metadata", rb_digest_make_metadata(&md5)); 61 | } 62 | -------------------------------------------------------------------------------- /ext/digest/rmd160/extconf.rb: -------------------------------------------------------------------------------- 1 | # -*- coding: us-ascii -*- 2 | # frozen_string_literal: false 3 | # $RoughId: extconf.rb,v 1.3 2001/08/14 19:54:51 knu Exp $ 4 | # $Id$ 5 | 6 | require "mkmf" 7 | require File.expand_path("../../digest_conf", __FILE__) 8 | 9 | if try_static_assert("RUBY_API_VERSION_MAJOR < 3", "ruby/version.h") 10 | $defs << "-DNDEBUG" 11 | end 12 | 13 | $objs = [ "rmd160init.#{$OBJEXT}" ] 14 | 15 | digest_conf("rmd160") 16 | 17 | have_header("sys/cdefs.h") 18 | 19 | $preload = %w[digest] 20 | 21 | create_makefile("digest/rmd160") 22 | -------------------------------------------------------------------------------- /ext/digest/rmd160/rmd160.c: -------------------------------------------------------------------------------- 1 | /* $NetBSD: rmd160.c,v 1.1.1.1 2001/03/06 11:21:05 agc Exp $ */ 2 | /* $RoughId: rmd160.c,v 1.2 2001/07/13 19:49:10 knu Exp $ */ 3 | /* $Id$ */ 4 | 5 | /********************************************************************\ 6 | * 7 | * FILE: rmd160.c 8 | * 9 | * CONTENTS: A sample C-implementation of the RIPEMD-160 10 | * hash-function. 11 | * TARGET: any computer with an ANSI C compiler 12 | * 13 | * AUTHOR: Antoon Bosselaers, ESAT-COSIC 14 | * (Arranged for libc by Todd C. Miller) 15 | * DATE: 1 March 1996 16 | * VERSION: 1.0 17 | * 18 | * Copyright (c) Katholieke Universiteit Leuven 19 | * 1996, All Rights Reserved 20 | * 21 | \********************************************************************/ 22 | 23 | #include "rmd160.h" 24 | 25 | #ifndef lint 26 | /* __RCSID("$NetBSD: rmd160.c,v 1.1.1.1 2001/03/06 11:21:05 agc Exp $"); */ 27 | #endif /* not lint */ 28 | 29 | /* header files */ 30 | 31 | #ifdef HAVE_SYS_ENDIAN_H_ 32 | #include 33 | #endif 34 | 35 | #ifdef HAVE_MACHINE_ENDIAN_H_ 36 | #include 37 | #endif 38 | 39 | /* #include "namespace.h" */ 40 | 41 | #include 42 | #include 43 | #include 44 | #include 45 | 46 | #ifndef _DIAGASSERT 47 | #define _DIAGASSERT(cond) assert(cond) 48 | #endif 49 | 50 | 51 | /********************************************************************/ 52 | 53 | /* macro definitions */ 54 | 55 | /* collect four bytes into one word: */ 56 | #define BYTES_TO_DWORD(strptr) \ 57 | (((uint32_t) *((strptr)+3) << 24) | \ 58 | ((uint32_t) *((strptr)+2) << 16) | \ 59 | ((uint32_t) *((strptr)+1) << 8) | \ 60 | ((uint32_t) *(strptr))) 61 | 62 | /* ROL(x, n) cyclically rotates x over n bits to the left */ 63 | /* x must be of an unsigned 32 bits type and 0 <= n < 32. */ 64 | #define ROL(x, n) (((x) << (n)) | ((x) >> (32-(n)))) 65 | 66 | /* the three basic functions F(), G() and H() */ 67 | #define F(x, y, z) ((x) ^ (y) ^ (z)) 68 | #define G(x, y, z) (((x) & (y)) | (~(x) & (z))) 69 | #define H(x, y, z) (((x) | ~(y)) ^ (z)) 70 | #define I(x, y, z) (((x) & (z)) | ((y) & ~(z))) 71 | #define J(x, y, z) ((x) ^ ((y) | ~(z))) 72 | 73 | /* the eight basic operations FF() through III() */ 74 | #define FF(a, b, c, d, e, x, s) { \ 75 | (a) += F((b), (c), (d)) + (x); \ 76 | (a) = ROL((a), (s)) + (e); \ 77 | (c) = ROL((c), 10); \ 78 | } 79 | #define GG(a, b, c, d, e, x, s) { \ 80 | (a) += G((b), (c), (d)) + (x) + 0x5a827999U; \ 81 | (a) = ROL((a), (s)) + (e); \ 82 | (c) = ROL((c), 10); \ 83 | } 84 | #define HH(a, b, c, d, e, x, s) { \ 85 | (a) += H((b), (c), (d)) + (x) + 0x6ed9eba1U; \ 86 | (a) = ROL((a), (s)) + (e); \ 87 | (c) = ROL((c), 10); \ 88 | } 89 | #define II(a, b, c, d, e, x, s) { \ 90 | (a) += I((b), (c), (d)) + (x) + 0x8f1bbcdcU; \ 91 | (a) = ROL((a), (s)) + (e); \ 92 | (c) = ROL((c), 10); \ 93 | } 94 | #define JJ(a, b, c, d, e, x, s) { \ 95 | (a) += J((b), (c), (d)) + (x) + 0xa953fd4eU; \ 96 | (a) = ROL((a), (s)) + (e); \ 97 | (c) = ROL((c), 10); \ 98 | } 99 | #define FFF(a, b, c, d, e, x, s) { \ 100 | (a) += F((b), (c), (d)) + (x); \ 101 | (a) = ROL((a), (s)) + (e); \ 102 | (c) = ROL((c), 10); \ 103 | } 104 | #define GGG(a, b, c, d, e, x, s) { \ 105 | (a) += G((b), (c), (d)) + (x) + 0x7a6d76e9U; \ 106 | (a) = ROL((a), (s)) + (e); \ 107 | (c) = ROL((c), 10); \ 108 | } 109 | #define HHH(a, b, c, d, e, x, s) { \ 110 | (a) += H((b), (c), (d)) + (x) + 0x6d703ef3U; \ 111 | (a) = ROL((a), (s)) + (e); \ 112 | (c) = ROL((c), 10); \ 113 | } 114 | #define III(a, b, c, d, e, x, s) { \ 115 | (a) += I((b), (c), (d)) + (x) + 0x5c4dd124U; \ 116 | (a) = ROL((a), (s)) + (e); \ 117 | (c) = ROL((c), 10); \ 118 | } 119 | #define JJJ(a, b, c, d, e, x, s) { \ 120 | (a) += J((b), (c), (d)) + (x) + 0x50a28be6U; \ 121 | (a) = ROL((a), (s)) + (e); \ 122 | (c) = ROL((c), 10); \ 123 | } 124 | 125 | /********************************************************************/ 126 | 127 | int 128 | RMD160_Init(RMD160_CTX *context) 129 | { 130 | 131 | _DIAGASSERT(context != NULL); 132 | 133 | /* ripemd-160 initialization constants */ 134 | context->state[0] = 0x67452301U; 135 | context->state[1] = 0xefcdab89U; 136 | context->state[2] = 0x98badcfeU; 137 | context->state[3] = 0x10325476U; 138 | context->state[4] = 0xc3d2e1f0U; 139 | context->length[0] = context->length[1] = 0; 140 | context->buflen = 0; 141 | return 1; 142 | } 143 | 144 | /********************************************************************/ 145 | 146 | void 147 | RMD160_Transform(uint32_t state[5], const uint32_t block[16]) 148 | { 149 | uint32_t aa, bb, cc, dd, ee; 150 | uint32_t aaa, bbb, ccc, ddd, eee; 151 | 152 | _DIAGASSERT(state != NULL); 153 | _DIAGASSERT(block != NULL); 154 | 155 | aa = aaa = state[0]; 156 | bb = bbb = state[1]; 157 | cc = ccc = state[2]; 158 | dd = ddd = state[3]; 159 | ee = eee = state[4]; 160 | 161 | /* round 1 */ 162 | FF(aa, bb, cc, dd, ee, block[ 0], 11); 163 | FF(ee, aa, bb, cc, dd, block[ 1], 14); 164 | FF(dd, ee, aa, bb, cc, block[ 2], 15); 165 | FF(cc, dd, ee, aa, bb, block[ 3], 12); 166 | FF(bb, cc, dd, ee, aa, block[ 4], 5); 167 | FF(aa, bb, cc, dd, ee, block[ 5], 8); 168 | FF(ee, aa, bb, cc, dd, block[ 6], 7); 169 | FF(dd, ee, aa, bb, cc, block[ 7], 9); 170 | FF(cc, dd, ee, aa, bb, block[ 8], 11); 171 | FF(bb, cc, dd, ee, aa, block[ 9], 13); 172 | FF(aa, bb, cc, dd, ee, block[10], 14); 173 | FF(ee, aa, bb, cc, dd, block[11], 15); 174 | FF(dd, ee, aa, bb, cc, block[12], 6); 175 | FF(cc, dd, ee, aa, bb, block[13], 7); 176 | FF(bb, cc, dd, ee, aa, block[14], 9); 177 | FF(aa, bb, cc, dd, ee, block[15], 8); 178 | 179 | /* round 2 */ 180 | GG(ee, aa, bb, cc, dd, block[ 7], 7); 181 | GG(dd, ee, aa, bb, cc, block[ 4], 6); 182 | GG(cc, dd, ee, aa, bb, block[13], 8); 183 | GG(bb, cc, dd, ee, aa, block[ 1], 13); 184 | GG(aa, bb, cc, dd, ee, block[10], 11); 185 | GG(ee, aa, bb, cc, dd, block[ 6], 9); 186 | GG(dd, ee, aa, bb, cc, block[15], 7); 187 | GG(cc, dd, ee, aa, bb, block[ 3], 15); 188 | GG(bb, cc, dd, ee, aa, block[12], 7); 189 | GG(aa, bb, cc, dd, ee, block[ 0], 12); 190 | GG(ee, aa, bb, cc, dd, block[ 9], 15); 191 | GG(dd, ee, aa, bb, cc, block[ 5], 9); 192 | GG(cc, dd, ee, aa, bb, block[ 2], 11); 193 | GG(bb, cc, dd, ee, aa, block[14], 7); 194 | GG(aa, bb, cc, dd, ee, block[11], 13); 195 | GG(ee, aa, bb, cc, dd, block[ 8], 12); 196 | 197 | /* round 3 */ 198 | HH(dd, ee, aa, bb, cc, block[ 3], 11); 199 | HH(cc, dd, ee, aa, bb, block[10], 13); 200 | HH(bb, cc, dd, ee, aa, block[14], 6); 201 | HH(aa, bb, cc, dd, ee, block[ 4], 7); 202 | HH(ee, aa, bb, cc, dd, block[ 9], 14); 203 | HH(dd, ee, aa, bb, cc, block[15], 9); 204 | HH(cc, dd, ee, aa, bb, block[ 8], 13); 205 | HH(bb, cc, dd, ee, aa, block[ 1], 15); 206 | HH(aa, bb, cc, dd, ee, block[ 2], 14); 207 | HH(ee, aa, bb, cc, dd, block[ 7], 8); 208 | HH(dd, ee, aa, bb, cc, block[ 0], 13); 209 | HH(cc, dd, ee, aa, bb, block[ 6], 6); 210 | HH(bb, cc, dd, ee, aa, block[13], 5); 211 | HH(aa, bb, cc, dd, ee, block[11], 12); 212 | HH(ee, aa, bb, cc, dd, block[ 5], 7); 213 | HH(dd, ee, aa, bb, cc, block[12], 5); 214 | 215 | /* round 4 */ 216 | II(cc, dd, ee, aa, bb, block[ 1], 11); 217 | II(bb, cc, dd, ee, aa, block[ 9], 12); 218 | II(aa, bb, cc, dd, ee, block[11], 14); 219 | II(ee, aa, bb, cc, dd, block[10], 15); 220 | II(dd, ee, aa, bb, cc, block[ 0], 14); 221 | II(cc, dd, ee, aa, bb, block[ 8], 15); 222 | II(bb, cc, dd, ee, aa, block[12], 9); 223 | II(aa, bb, cc, dd, ee, block[ 4], 8); 224 | II(ee, aa, bb, cc, dd, block[13], 9); 225 | II(dd, ee, aa, bb, cc, block[ 3], 14); 226 | II(cc, dd, ee, aa, bb, block[ 7], 5); 227 | II(bb, cc, dd, ee, aa, block[15], 6); 228 | II(aa, bb, cc, dd, ee, block[14], 8); 229 | II(ee, aa, bb, cc, dd, block[ 5], 6); 230 | II(dd, ee, aa, bb, cc, block[ 6], 5); 231 | II(cc, dd, ee, aa, bb, block[ 2], 12); 232 | 233 | /* round 5 */ 234 | JJ(bb, cc, dd, ee, aa, block[ 4], 9); 235 | JJ(aa, bb, cc, dd, ee, block[ 0], 15); 236 | JJ(ee, aa, bb, cc, dd, block[ 5], 5); 237 | JJ(dd, ee, aa, bb, cc, block[ 9], 11); 238 | JJ(cc, dd, ee, aa, bb, block[ 7], 6); 239 | JJ(bb, cc, dd, ee, aa, block[12], 8); 240 | JJ(aa, bb, cc, dd, ee, block[ 2], 13); 241 | JJ(ee, aa, bb, cc, dd, block[10], 12); 242 | JJ(dd, ee, aa, bb, cc, block[14], 5); 243 | JJ(cc, dd, ee, aa, bb, block[ 1], 12); 244 | JJ(bb, cc, dd, ee, aa, block[ 3], 13); 245 | JJ(aa, bb, cc, dd, ee, block[ 8], 14); 246 | JJ(ee, aa, bb, cc, dd, block[11], 11); 247 | JJ(dd, ee, aa, bb, cc, block[ 6], 8); 248 | JJ(cc, dd, ee, aa, bb, block[15], 5); 249 | JJ(bb, cc, dd, ee, aa, block[13], 6); 250 | 251 | /* parallel round 1 */ 252 | JJJ(aaa, bbb, ccc, ddd, eee, block[ 5], 8); 253 | JJJ(eee, aaa, bbb, ccc, ddd, block[14], 9); 254 | JJJ(ddd, eee, aaa, bbb, ccc, block[ 7], 9); 255 | JJJ(ccc, ddd, eee, aaa, bbb, block[ 0], 11); 256 | JJJ(bbb, ccc, ddd, eee, aaa, block[ 9], 13); 257 | JJJ(aaa, bbb, ccc, ddd, eee, block[ 2], 15); 258 | JJJ(eee, aaa, bbb, ccc, ddd, block[11], 15); 259 | JJJ(ddd, eee, aaa, bbb, ccc, block[ 4], 5); 260 | JJJ(ccc, ddd, eee, aaa, bbb, block[13], 7); 261 | JJJ(bbb, ccc, ddd, eee, aaa, block[ 6], 7); 262 | JJJ(aaa, bbb, ccc, ddd, eee, block[15], 8); 263 | JJJ(eee, aaa, bbb, ccc, ddd, block[ 8], 11); 264 | JJJ(ddd, eee, aaa, bbb, ccc, block[ 1], 14); 265 | JJJ(ccc, ddd, eee, aaa, bbb, block[10], 14); 266 | JJJ(bbb, ccc, ddd, eee, aaa, block[ 3], 12); 267 | JJJ(aaa, bbb, ccc, ddd, eee, block[12], 6); 268 | 269 | /* parallel round 2 */ 270 | III(eee, aaa, bbb, ccc, ddd, block[ 6], 9); 271 | III(ddd, eee, aaa, bbb, ccc, block[11], 13); 272 | III(ccc, ddd, eee, aaa, bbb, block[ 3], 15); 273 | III(bbb, ccc, ddd, eee, aaa, block[ 7], 7); 274 | III(aaa, bbb, ccc, ddd, eee, block[ 0], 12); 275 | III(eee, aaa, bbb, ccc, ddd, block[13], 8); 276 | III(ddd, eee, aaa, bbb, ccc, block[ 5], 9); 277 | III(ccc, ddd, eee, aaa, bbb, block[10], 11); 278 | III(bbb, ccc, ddd, eee, aaa, block[14], 7); 279 | III(aaa, bbb, ccc, ddd, eee, block[15], 7); 280 | III(eee, aaa, bbb, ccc, ddd, block[ 8], 12); 281 | III(ddd, eee, aaa, bbb, ccc, block[12], 7); 282 | III(ccc, ddd, eee, aaa, bbb, block[ 4], 6); 283 | III(bbb, ccc, ddd, eee, aaa, block[ 9], 15); 284 | III(aaa, bbb, ccc, ddd, eee, block[ 1], 13); 285 | III(eee, aaa, bbb, ccc, ddd, block[ 2], 11); 286 | 287 | /* parallel round 3 */ 288 | HHH(ddd, eee, aaa, bbb, ccc, block[15], 9); 289 | HHH(ccc, ddd, eee, aaa, bbb, block[ 5], 7); 290 | HHH(bbb, ccc, ddd, eee, aaa, block[ 1], 15); 291 | HHH(aaa, bbb, ccc, ddd, eee, block[ 3], 11); 292 | HHH(eee, aaa, bbb, ccc, ddd, block[ 7], 8); 293 | HHH(ddd, eee, aaa, bbb, ccc, block[14], 6); 294 | HHH(ccc, ddd, eee, aaa, bbb, block[ 6], 6); 295 | HHH(bbb, ccc, ddd, eee, aaa, block[ 9], 14); 296 | HHH(aaa, bbb, ccc, ddd, eee, block[11], 12); 297 | HHH(eee, aaa, bbb, ccc, ddd, block[ 8], 13); 298 | HHH(ddd, eee, aaa, bbb, ccc, block[12], 5); 299 | HHH(ccc, ddd, eee, aaa, bbb, block[ 2], 14); 300 | HHH(bbb, ccc, ddd, eee, aaa, block[10], 13); 301 | HHH(aaa, bbb, ccc, ddd, eee, block[ 0], 13); 302 | HHH(eee, aaa, bbb, ccc, ddd, block[ 4], 7); 303 | HHH(ddd, eee, aaa, bbb, ccc, block[13], 5); 304 | 305 | /* parallel round 4 */ 306 | GGG(ccc, ddd, eee, aaa, bbb, block[ 8], 15); 307 | GGG(bbb, ccc, ddd, eee, aaa, block[ 6], 5); 308 | GGG(aaa, bbb, ccc, ddd, eee, block[ 4], 8); 309 | GGG(eee, aaa, bbb, ccc, ddd, block[ 1], 11); 310 | GGG(ddd, eee, aaa, bbb, ccc, block[ 3], 14); 311 | GGG(ccc, ddd, eee, aaa, bbb, block[11], 14); 312 | GGG(bbb, ccc, ddd, eee, aaa, block[15], 6); 313 | GGG(aaa, bbb, ccc, ddd, eee, block[ 0], 14); 314 | GGG(eee, aaa, bbb, ccc, ddd, block[ 5], 6); 315 | GGG(ddd, eee, aaa, bbb, ccc, block[12], 9); 316 | GGG(ccc, ddd, eee, aaa, bbb, block[ 2], 12); 317 | GGG(bbb, ccc, ddd, eee, aaa, block[13], 9); 318 | GGG(aaa, bbb, ccc, ddd, eee, block[ 9], 12); 319 | GGG(eee, aaa, bbb, ccc, ddd, block[ 7], 5); 320 | GGG(ddd, eee, aaa, bbb, ccc, block[10], 15); 321 | GGG(ccc, ddd, eee, aaa, bbb, block[14], 8); 322 | 323 | /* parallel round 5 */ 324 | FFF(bbb, ccc, ddd, eee, aaa, block[12] , 8); 325 | FFF(aaa, bbb, ccc, ddd, eee, block[15] , 5); 326 | FFF(eee, aaa, bbb, ccc, ddd, block[10] , 12); 327 | FFF(ddd, eee, aaa, bbb, ccc, block[ 4] , 9); 328 | FFF(ccc, ddd, eee, aaa, bbb, block[ 1] , 12); 329 | FFF(bbb, ccc, ddd, eee, aaa, block[ 5] , 5); 330 | FFF(aaa, bbb, ccc, ddd, eee, block[ 8] , 14); 331 | FFF(eee, aaa, bbb, ccc, ddd, block[ 7] , 6); 332 | FFF(ddd, eee, aaa, bbb, ccc, block[ 6] , 8); 333 | FFF(ccc, ddd, eee, aaa, bbb, block[ 2] , 13); 334 | FFF(bbb, ccc, ddd, eee, aaa, block[13] , 6); 335 | FFF(aaa, bbb, ccc, ddd, eee, block[14] , 5); 336 | FFF(eee, aaa, bbb, ccc, ddd, block[ 0] , 15); 337 | FFF(ddd, eee, aaa, bbb, ccc, block[ 3] , 13); 338 | FFF(ccc, ddd, eee, aaa, bbb, block[ 9] , 11); 339 | FFF(bbb, ccc, ddd, eee, aaa, block[11] , 11); 340 | 341 | /* combine results */ 342 | ddd += cc + state[1]; /* final result for state[0] */ 343 | state[1] = state[2] + dd + eee; 344 | state[2] = state[3] + ee + aaa; 345 | state[3] = state[4] + aa + bbb; 346 | state[4] = state[0] + bb + ccc; 347 | state[0] = ddd; 348 | } 349 | 350 | /********************************************************************/ 351 | 352 | void 353 | RMD160_Update(RMD160_CTX *context, const uint8_t *data, size_t nbytes) 354 | { 355 | uint32_t X[16]; 356 | uint32_t ofs = 0; 357 | uint32_t i; 358 | #ifdef WORDS_BIGENDIAN 359 | uint32_t j; 360 | #endif 361 | 362 | _DIAGASSERT(context != NULL); 363 | _DIAGASSERT(data != NULL); 364 | 365 | /* update length[] */ 366 | #if SIZEOF_SIZE_T * CHAR_BIT > 32 367 | context->length[1] += (uint32_t)((context->length[0] + nbytes) >> 32); 368 | #else 369 | if (context->length[0] + nbytes < context->length[0]) 370 | context->length[1]++; /* overflow to msb of length */ 371 | #endif 372 | context->length[0] += (uint32_t)nbytes; 373 | 374 | (void)memset(X, 0, sizeof(X)); 375 | 376 | if ( context->buflen + nbytes < 64 ) 377 | { 378 | (void)memcpy(context->bbuffer + context->buflen, data, nbytes); 379 | context->buflen += (uint32_t)nbytes; 380 | } 381 | else 382 | { 383 | /* process first block */ 384 | ofs = 64 - context->buflen; 385 | (void)memcpy(context->bbuffer + context->buflen, data, ofs); 386 | #ifndef WORDS_BIGENDIAN 387 | (void)memcpy(X, context->bbuffer, sizeof(X)); 388 | #else 389 | for (j=0; j < 16; j++) 390 | X[j] = BYTES_TO_DWORD(context->bbuffer + (4 * j)); 391 | #endif 392 | RMD160_Transform(context->state, X); 393 | nbytes -= ofs; 394 | 395 | /* process remaining complete blocks */ 396 | for (i = 0; i < (nbytes >> 6); i++) { 397 | #ifndef WORDS_BIGENDIAN 398 | (void)memcpy(X, data + (64 * i) + ofs, sizeof(X)); 399 | #else 400 | for (j=0; j < 16; j++) 401 | X[j] = BYTES_TO_DWORD(data + (64 * i) + (4 * j) + ofs); 402 | #endif 403 | RMD160_Transform(context->state, X); 404 | } 405 | 406 | /* 407 | * Put last bytes from data into context's buffer 408 | */ 409 | context->buflen = (uint32_t)nbytes & 63; 410 | memcpy(context->bbuffer, data + (64 * i) + ofs, context->buflen); 411 | } 412 | } 413 | 414 | /********************************************************************/ 415 | 416 | int 417 | RMD160_Finish(RMD160_CTX *context, uint8_t digest[20]) 418 | { 419 | uint32_t i; 420 | uint32_t X[16]; 421 | #ifdef WORDS_BIGENDIAN 422 | uint32_t j; 423 | #endif 424 | 425 | _DIAGASSERT(digest != NULL); 426 | _DIAGASSERT(context != NULL); 427 | 428 | /* append the bit m_n == 1 */ 429 | context->bbuffer[context->buflen] = (uint8_t)'\200'; 430 | 431 | (void)memset(context->bbuffer + context->buflen + 1, 0, 432 | 63 - context->buflen); 433 | #ifndef WORDS_BIGENDIAN 434 | (void)memcpy(X, context->bbuffer, sizeof(X)); 435 | #else 436 | for (j=0; j < 16; j++) 437 | X[j] = BYTES_TO_DWORD(context->bbuffer + (4 * j)); 438 | #endif 439 | if ((context->buflen) > 55) { 440 | /* length goes to next block */ 441 | RMD160_Transform(context->state, X); 442 | (void)memset(X, 0, sizeof(X)); 443 | } 444 | 445 | /* append length in bits */ 446 | X[14] = context->length[0] << 3; 447 | X[15] = (context->length[0] >> 29) | 448 | (context->length[1] << 3); 449 | RMD160_Transform(context->state, X); 450 | 451 | if (digest != NULL) { 452 | for (i = 0; i < 20; i += 4) { 453 | /* extracts the 8 least significant bits. */ 454 | digest[i] = context->state[i>>2]; 455 | digest[i + 1] = (context->state[i>>2] >> 8); 456 | digest[i + 2] = (context->state[i>>2] >> 16); 457 | digest[i + 3] = (context->state[i>>2] >> 24); 458 | } 459 | } 460 | return 1; 461 | } 462 | 463 | /************************ end of file rmd160.c **********************/ 464 | -------------------------------------------------------------------------------- /ext/digest/rmd160/rmd160.h: -------------------------------------------------------------------------------- 1 | /* $NetBSD: rmd160.h,v 1.2 2000/07/07 10:47:06 ad Exp $ */ 2 | /* $RoughId: rmd160.h,v 1.3 2002/02/24 08:14:31 knu Exp $ */ 3 | /* $Id$ */ 4 | 5 | /********************************************************************\ 6 | * 7 | * FILE: rmd160.h 8 | * 9 | * CONTENTS: Header file for a sample C-implementation of the 10 | * RIPEMD-160 hash-function. 11 | * TARGET: any computer with an ANSI C compiler 12 | * 13 | * AUTHOR: Antoon Bosselaers, ESAT-COSIC 14 | * DATE: 1 March 1996 15 | * VERSION: 1.0 16 | * 17 | * Copyright (c) Katholieke Universiteit Leuven 18 | * 1996, All Rights Reserved 19 | * 20 | \********************************************************************/ 21 | 22 | /* 23 | * from OpenBSD: rmd160.h,v 1.4 1999/08/16 09:59:04 millert Exp 24 | */ 25 | 26 | #ifndef _RMD160_H_ 27 | #define _RMD160_H_ 28 | 29 | #include "../defs.h" 30 | 31 | typedef struct { 32 | uint32_t state[5]; /* state (ABCDE) */ 33 | uint32_t length[2]; /* number of bits */ 34 | uint8_t bbuffer[64]; /* overflow buffer */ 35 | uint32_t buflen; /* number of chars in bbuffer */ 36 | } RMD160_CTX; 37 | 38 | #ifdef RUBY 39 | #define RMD160_Init rb_Digest_RMD160_Init 40 | #define RMD160_Transform rb_Digest_RMD160_Transform 41 | #define RMD160_Update rb_Digest_RMD160_Update 42 | #define RMD160_Finish rb_Digest_RMD160_Finish 43 | #endif 44 | 45 | __BEGIN_DECLS 46 | int RMD160_Init _((RMD160_CTX *)); 47 | void RMD160_Transform _((uint32_t[5], const uint32_t[16])); 48 | void RMD160_Update _((RMD160_CTX *, const uint8_t *, size_t)); 49 | int RMD160_Finish _((RMD160_CTX *, uint8_t[20])); 50 | __END_DECLS 51 | 52 | #define RMD160_BLOCK_LENGTH 64 53 | #define RMD160_DIGEST_LENGTH 20 54 | #define RMD160_DIGEST_STRING_LENGTH (RMD160_DIGEST_LENGTH * 2 + 1) 55 | 56 | #endif /* !_RMD160_H_ */ 57 | -------------------------------------------------------------------------------- /ext/digest/rmd160/rmd160init.c: -------------------------------------------------------------------------------- 1 | /* $RoughId: rmd160init.c,v 1.3 2001/07/13 20:00:43 knu Exp $ */ 2 | /* $Id$ */ 3 | 4 | #include 5 | #include "../digest.h" 6 | #include "rmd160.h" 7 | 8 | static const rb_digest_metadata_t rmd160 = { 9 | RUBY_DIGEST_API_VERSION, 10 | RMD160_DIGEST_LENGTH, 11 | RMD160_BLOCK_LENGTH, 12 | sizeof(RMD160_CTX), 13 | (rb_digest_hash_init_func_t)RMD160_Init, 14 | (rb_digest_hash_update_func_t)RMD160_Update, 15 | (rb_digest_hash_finish_func_t)RMD160_Finish, 16 | }; 17 | 18 | /* 19 | * Document-class: Digest::RMD160 < Digest::Base 20 | * A class for calculating message digests using RIPEMD-160 21 | * cryptographic hash function, designed by Hans Dobbertin, Antoon 22 | * Bosselaers, and Bart Preneel. 23 | * 24 | * RMD160 calculates a digest of 160 bits (20 bytes). 25 | * 26 | * == Examples 27 | * require 'digest' 28 | * 29 | * # Compute a complete digest 30 | * Digest::RMD160.hexdigest 'abc' #=> "8eb208f7..." 31 | * 32 | * # Compute digest by chunks 33 | * rmd160 = Digest::RMD160.new # =># 34 | * rmd160.update "ab" 35 | * rmd160 << "c" # alias for #update 36 | * rmd160.hexdigest # => "8eb208f7..." 37 | * 38 | * # Use the same object to compute another digest 39 | * rmd160.reset 40 | * rmd160 << "message" 41 | * rmd160.hexdigest # => "1dddbe1b..." 42 | */ 43 | void 44 | Init_rmd160(void) 45 | { 46 | VALUE mDigest, cDigest_Base, cDigest_RMD160; 47 | 48 | #if 0 49 | mDigest = rb_define_module("Digest"); /* let rdoc know */ 50 | #endif 51 | mDigest = rb_digest_namespace(); 52 | cDigest_Base = rb_const_get(mDigest, rb_intern_const("Base")); 53 | 54 | cDigest_RMD160 = rb_define_class_under(mDigest, "RMD160", cDigest_Base); 55 | rb_iv_set(cDigest_RMD160, "metadata", rb_digest_make_metadata(&rmd160)); 56 | } 57 | -------------------------------------------------------------------------------- /ext/digest/sha1/extconf.rb: -------------------------------------------------------------------------------- 1 | # -*- coding: us-ascii -*- 2 | # frozen_string_literal: false 3 | # $RoughId: extconf.rb,v 1.3 2001/08/14 19:54:51 knu Exp $ 4 | # $Id$ 5 | 6 | require "mkmf" 7 | require File.expand_path("../../digest_conf", __FILE__) 8 | 9 | $objs = [ "sha1init.#{$OBJEXT}" ] 10 | 11 | digest_conf("sha1") 12 | 13 | have_header("sys/cdefs.h") 14 | 15 | $preload = %w[digest] 16 | 17 | create_makefile("digest/sha1") 18 | -------------------------------------------------------------------------------- /ext/digest/sha1/sha1.c: -------------------------------------------------------------------------------- 1 | /* $NetBSD: sha1.c,v 1.2 2001/03/22 09:51:48 agc Exp $ */ 2 | /* $OpenBSD: sha1.c,v 1.9 1997/07/23 21:12:32 kstailey Exp $ */ 3 | /* $RoughId: sha1.c,v 1.2 2001/07/13 19:49:10 knu Exp $ */ 4 | /* $Id$ */ 5 | 6 | /* 7 | * SHA-1 in C 8 | * By Steve Reid 9 | * 100% Public Domain 10 | * 11 | * Test Vectors (from FIPS PUB 180-1) 12 | * "abc" 13 | * A9993E36 4706816A BA3E2571 7850C26C 9CD0D89D 14 | * "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq" 15 | * 84983E44 1C3BD26E BAAE4AA1 F95129E5 E54670F1 16 | * A million repetitions of "a" 17 | * 34AA973C D4C4DAA4 F61EEB2B DBAD2731 6534016F 18 | */ 19 | 20 | #include "sha1.h" 21 | 22 | #define SHA1HANDSOFF /* Copies data before messing with it. */ 23 | 24 | #if defined(_KERNEL) || defined(_STANDALONE) 25 | #include 26 | #include 27 | #define _DIAGASSERT(x) (void)0 28 | #else 29 | /* #include "namespace.h" */ 30 | #include 31 | #include 32 | #endif 33 | 34 | #ifndef _DIAGASSERT 35 | #define _DIAGASSERT(cond) assert(cond) 36 | #endif 37 | 38 | /* 39 | * XXX Kludge until there is resolution regarding mem*() functions 40 | * XXX in the kernel. 41 | */ 42 | #if defined(_KERNEL) || defined(_STANDALONE) 43 | #define memcpy(s, d, l) bcopy((d), (s), (l)) 44 | #endif 45 | 46 | #define rol(value, bits) (((value) << (bits)) | ((value) >> (32 - (bits)))) 47 | 48 | /* 49 | * blk0() and blk() perform the initial expand. 50 | * I got the idea of expanding during the round function from SSLeay 51 | */ 52 | #ifndef WORDS_BIGENDIAN 53 | # define blk0(i) (block->l[i] = (rol(block->l[i],24)&0xFF00FF00) \ 54 | |(rol(block->l[i],8)&0x00FF00FF)) 55 | #else 56 | # define blk0(i) block->l[i] 57 | #endif 58 | #define blk(i) (block->l[i&15] = rol(block->l[(i+13)&15]^block->l[(i+8)&15] \ 59 | ^block->l[(i+2)&15]^block->l[i&15],1)) 60 | 61 | /* 62 | * (R0+R1), R2, R3, R4 are the different operations (rounds) used in SHA1 63 | */ 64 | #define R0(v,w,x,y,z,i) z+=((w&(x^y))^y)+blk0(i)+0x5A827999+rol(v,5);w=rol(w,30); 65 | #define R1(v,w,x,y,z,i) z+=((w&(x^y))^y)+blk(i)+0x5A827999+rol(v,5);w=rol(w,30); 66 | #define R2(v,w,x,y,z,i) z+=(w^x^y)+blk(i)+0x6ED9EBA1+rol(v,5);w=rol(w,30); 67 | #define R3(v,w,x,y,z,i) z+=(((w|x)&y)|(w&x))+blk(i)+0x8F1BBCDC+rol(v,5);w=rol(w,30); 68 | #define R4(v,w,x,y,z,i) z+=(w^x^y)+blk(i)+0xCA62C1D6+rol(v,5);w=rol(w,30); 69 | 70 | 71 | typedef union { 72 | uint8_t c[64]; 73 | uint32_t l[16]; 74 | } CHAR64LONG16; 75 | 76 | #ifdef __sparc_v9__ 77 | void do_R01(uint32_t *a, uint32_t *b, uint32_t *c, uint32_t *d, uint32_t *e, CHAR64LONG16 *); 78 | void do_R2(uint32_t *a, uint32_t *b, uint32_t *c, uint32_t *d, uint32_t *e, CHAR64LONG16 *); 79 | void do_R3(uint32_t *a, uint32_t *b, uint32_t *c, uint32_t *d, uint32_t *e, CHAR64LONG16 *); 80 | void do_R4(uint32_t *a, uint32_t *b, uint32_t *c, uint32_t *d, uint32_t *e, CHAR64LONG16 *); 81 | 82 | #define nR0(v,w,x,y,z,i) R0(*v,*w,*x,*y,*z,i) 83 | #define nR1(v,w,x,y,z,i) R1(*v,*w,*x,*y,*z,i) 84 | #define nR2(v,w,x,y,z,i) R2(*v,*w,*x,*y,*z,i) 85 | #define nR3(v,w,x,y,z,i) R3(*v,*w,*x,*y,*z,i) 86 | #define nR4(v,w,x,y,z,i) R4(*v,*w,*x,*y,*z,i) 87 | 88 | void 89 | do_R01(uint32_t *a, uint32_t *b, uint32_t *c, uint32_t *d, uint32_t *e, CHAR64LONG16 *block) 90 | { 91 | nR0(a,b,c,d,e, 0); nR0(e,a,b,c,d, 1); nR0(d,e,a,b,c, 2); nR0(c,d,e,a,b, 3); 92 | nR0(b,c,d,e,a, 4); nR0(a,b,c,d,e, 5); nR0(e,a,b,c,d, 6); nR0(d,e,a,b,c, 7); 93 | nR0(c,d,e,a,b, 8); nR0(b,c,d,e,a, 9); nR0(a,b,c,d,e,10); nR0(e,a,b,c,d,11); 94 | nR0(d,e,a,b,c,12); nR0(c,d,e,a,b,13); nR0(b,c,d,e,a,14); nR0(a,b,c,d,e,15); 95 | nR1(e,a,b,c,d,16); nR1(d,e,a,b,c,17); nR1(c,d,e,a,b,18); nR1(b,c,d,e,a,19); 96 | } 97 | 98 | void 99 | do_R2(uint32_t *a, uint32_t *b, uint32_t *c, uint32_t *d, uint32_t *e, CHAR64LONG16 *block) 100 | { 101 | nR2(a,b,c,d,e,20); nR2(e,a,b,c,d,21); nR2(d,e,a,b,c,22); nR2(c,d,e,a,b,23); 102 | nR2(b,c,d,e,a,24); nR2(a,b,c,d,e,25); nR2(e,a,b,c,d,26); nR2(d,e,a,b,c,27); 103 | nR2(c,d,e,a,b,28); nR2(b,c,d,e,a,29); nR2(a,b,c,d,e,30); nR2(e,a,b,c,d,31); 104 | nR2(d,e,a,b,c,32); nR2(c,d,e,a,b,33); nR2(b,c,d,e,a,34); nR2(a,b,c,d,e,35); 105 | nR2(e,a,b,c,d,36); nR2(d,e,a,b,c,37); nR2(c,d,e,a,b,38); nR2(b,c,d,e,a,39); 106 | } 107 | 108 | void 109 | do_R3(uint32_t *a, uint32_t *b, uint32_t *c, uint32_t *d, uint32_t *e, CHAR64LONG16 *block) 110 | { 111 | nR3(a,b,c,d,e,40); nR3(e,a,b,c,d,41); nR3(d,e,a,b,c,42); nR3(c,d,e,a,b,43); 112 | nR3(b,c,d,e,a,44); nR3(a,b,c,d,e,45); nR3(e,a,b,c,d,46); nR3(d,e,a,b,c,47); 113 | nR3(c,d,e,a,b,48); nR3(b,c,d,e,a,49); nR3(a,b,c,d,e,50); nR3(e,a,b,c,d,51); 114 | nR3(d,e,a,b,c,52); nR3(c,d,e,a,b,53); nR3(b,c,d,e,a,54); nR3(a,b,c,d,e,55); 115 | nR3(e,a,b,c,d,56); nR3(d,e,a,b,c,57); nR3(c,d,e,a,b,58); nR3(b,c,d,e,a,59); 116 | } 117 | 118 | void 119 | do_R4(uint32_t *a, uint32_t *b, uint32_t *c, uint32_t *d, uint32_t *e, CHAR64LONG16 *block) 120 | { 121 | nR4(a,b,c,d,e,60); nR4(e,a,b,c,d,61); nR4(d,e,a,b,c,62); nR4(c,d,e,a,b,63); 122 | nR4(b,c,d,e,a,64); nR4(a,b,c,d,e,65); nR4(e,a,b,c,d,66); nR4(d,e,a,b,c,67); 123 | nR4(c,d,e,a,b,68); nR4(b,c,d,e,a,69); nR4(a,b,c,d,e,70); nR4(e,a,b,c,d,71); 124 | nR4(d,e,a,b,c,72); nR4(c,d,e,a,b,73); nR4(b,c,d,e,a,74); nR4(a,b,c,d,e,75); 125 | nR4(e,a,b,c,d,76); nR4(d,e,a,b,c,77); nR4(c,d,e,a,b,78); nR4(b,c,d,e,a,79); 126 | } 127 | #endif 128 | 129 | /* 130 | * Hash a single 512-bit block. This is the core of the algorithm. 131 | */ 132 | void SHA1_Transform(uint32_t state[5], const uint8_t buffer[64]) 133 | { 134 | uint32_t a, b, c, d, e; 135 | CHAR64LONG16 *block; 136 | 137 | #ifdef SHA1HANDSOFF 138 | CHAR64LONG16 workspace; 139 | #endif 140 | 141 | _DIAGASSERT(buffer != 0); 142 | _DIAGASSERT(state != 0); 143 | 144 | #ifdef SHA1HANDSOFF 145 | block = &workspace; 146 | (void)memcpy(block, buffer, 64); 147 | #else 148 | block = (CHAR64LONG16 *)(void *)buffer; 149 | #endif 150 | 151 | /* Copy context->state[] to working vars */ 152 | a = state[0]; 153 | b = state[1]; 154 | c = state[2]; 155 | d = state[3]; 156 | e = state[4]; 157 | 158 | #ifdef __sparc_v9__ 159 | do_R01(&a, &b, &c, &d, &e, block); 160 | do_R2(&a, &b, &c, &d, &e, block); 161 | do_R3(&a, &b, &c, &d, &e, block); 162 | do_R4(&a, &b, &c, &d, &e, block); 163 | #else 164 | /* 4 rounds of 20 operations each. Loop unrolled. */ 165 | R0(a,b,c,d,e, 0); R0(e,a,b,c,d, 1); R0(d,e,a,b,c, 2); R0(c,d,e,a,b, 3); 166 | R0(b,c,d,e,a, 4); R0(a,b,c,d,e, 5); R0(e,a,b,c,d, 6); R0(d,e,a,b,c, 7); 167 | R0(c,d,e,a,b, 8); R0(b,c,d,e,a, 9); R0(a,b,c,d,e,10); R0(e,a,b,c,d,11); 168 | R0(d,e,a,b,c,12); R0(c,d,e,a,b,13); R0(b,c,d,e,a,14); R0(a,b,c,d,e,15); 169 | R1(e,a,b,c,d,16); R1(d,e,a,b,c,17); R1(c,d,e,a,b,18); R1(b,c,d,e,a,19); 170 | R2(a,b,c,d,e,20); R2(e,a,b,c,d,21); R2(d,e,a,b,c,22); R2(c,d,e,a,b,23); 171 | R2(b,c,d,e,a,24); R2(a,b,c,d,e,25); R2(e,a,b,c,d,26); R2(d,e,a,b,c,27); 172 | R2(c,d,e,a,b,28); R2(b,c,d,e,a,29); R2(a,b,c,d,e,30); R2(e,a,b,c,d,31); 173 | R2(d,e,a,b,c,32); R2(c,d,e,a,b,33); R2(b,c,d,e,a,34); R2(a,b,c,d,e,35); 174 | R2(e,a,b,c,d,36); R2(d,e,a,b,c,37); R2(c,d,e,a,b,38); R2(b,c,d,e,a,39); 175 | R3(a,b,c,d,e,40); R3(e,a,b,c,d,41); R3(d,e,a,b,c,42); R3(c,d,e,a,b,43); 176 | R3(b,c,d,e,a,44); R3(a,b,c,d,e,45); R3(e,a,b,c,d,46); R3(d,e,a,b,c,47); 177 | R3(c,d,e,a,b,48); R3(b,c,d,e,a,49); R3(a,b,c,d,e,50); R3(e,a,b,c,d,51); 178 | R3(d,e,a,b,c,52); R3(c,d,e,a,b,53); R3(b,c,d,e,a,54); R3(a,b,c,d,e,55); 179 | R3(e,a,b,c,d,56); R3(d,e,a,b,c,57); R3(c,d,e,a,b,58); R3(b,c,d,e,a,59); 180 | R4(a,b,c,d,e,60); R4(e,a,b,c,d,61); R4(d,e,a,b,c,62); R4(c,d,e,a,b,63); 181 | R4(b,c,d,e,a,64); R4(a,b,c,d,e,65); R4(e,a,b,c,d,66); R4(d,e,a,b,c,67); 182 | R4(c,d,e,a,b,68); R4(b,c,d,e,a,69); R4(a,b,c,d,e,70); R4(e,a,b,c,d,71); 183 | R4(d,e,a,b,c,72); R4(c,d,e,a,b,73); R4(b,c,d,e,a,74); R4(a,b,c,d,e,75); 184 | R4(e,a,b,c,d,76); R4(d,e,a,b,c,77); R4(c,d,e,a,b,78); R4(b,c,d,e,a,79); 185 | #endif 186 | 187 | /* Add the working vars back into context.state[] */ 188 | state[0] += a; 189 | state[1] += b; 190 | state[2] += c; 191 | state[3] += d; 192 | state[4] += e; 193 | 194 | /* Wipe variables */ 195 | a = b = c = d = e = 0; 196 | } 197 | 198 | 199 | /* 200 | * SHA1_Init - Initialize new context 201 | */ 202 | int SHA1_Init(SHA1_CTX *context) 203 | { 204 | 205 | _DIAGASSERT(context != 0); 206 | 207 | /* SHA1 initialization constants */ 208 | context->state[0] = 0x67452301; 209 | context->state[1] = 0xEFCDAB89; 210 | context->state[2] = 0x98BADCFE; 211 | context->state[3] = 0x10325476; 212 | context->state[4] = 0xC3D2E1F0; 213 | context->count[0] = context->count[1] = 0; 214 | return 1; 215 | } 216 | 217 | 218 | /* 219 | * Run your data through this. 220 | */ 221 | void SHA1_Update(SHA1_CTX *context, const uint8_t *data, size_t len) 222 | { 223 | uint32_t i, j; 224 | 225 | _DIAGASSERT(context != 0); 226 | _DIAGASSERT(data != 0); 227 | 228 | j = context->count[0]; 229 | if ((context->count[0] += len << 3) < j) 230 | context->count[1] += (len>>29)+1; 231 | j = (j >> 3) & 63; 232 | if ((j + len) > 63) { 233 | (void)memcpy(&context->buffer[j], data, (i = 64-j)); 234 | SHA1_Transform(context->state, context->buffer); 235 | for ( ; i + 63 < len; i += 64) { 236 | RB_DIGEST_WARNING_PUSH(); 237 | #if defined(__GNUC__) && !defined(__clang__) && __GNUC__ >= 11 238 | RB_DIGEST_WARNING_IGNORED(-Wstringop-overread); 239 | #endif 240 | SHA1_Transform(context->state, &data[i]); 241 | RB_DIGEST_WARNING_POP(); 242 | } 243 | j = 0; 244 | } else { 245 | i = 0; 246 | } 247 | (void)memcpy(&context->buffer[j], &data[i], len - i); 248 | } 249 | 250 | 251 | /* 252 | * Add padding and return the message digest. 253 | */ 254 | int SHA1_Finish(SHA1_CTX* context, uint8_t digest[20]) 255 | { 256 | size_t i; 257 | uint8_t finalcount[8]; 258 | 259 | _DIAGASSERT(digest != 0); 260 | _DIAGASSERT(context != 0); 261 | 262 | for (i = 0; i < 8; i++) { 263 | finalcount[i] = (uint8_t)((context->count[(i >= 4 ? 0 : 1)] 264 | >> ((3-(i & 3)) * 8) ) & 255); /* Endian independent */ 265 | } 266 | SHA1_Update(context, (const uint8_t *)"\200", 1); 267 | while ((context->count[0] & 504) != 448) 268 | SHA1_Update(context, (const uint8_t *)"\0", 1); 269 | SHA1_Update(context, finalcount, 8); /* Should cause a SHA1_Transform() */ 270 | 271 | if (digest) { 272 | for (i = 0; i < 20; i++) 273 | digest[i] = (uint8_t) 274 | ((context->state[i>>2] >> ((3-(i & 3)) * 8) ) & 255); 275 | } 276 | return 1; 277 | } 278 | -------------------------------------------------------------------------------- /ext/digest/sha1/sha1.h: -------------------------------------------------------------------------------- 1 | /* $NetBSD: sha1.h,v 1.2 1998/05/29 22:55:44 thorpej Exp $ */ 2 | /* $RoughId: sha1.h,v 1.3 2002/02/24 08:14:32 knu Exp $ */ 3 | /* $Id$ */ 4 | 5 | /* 6 | * SHA-1 in C 7 | * By Steve Reid 8 | * 100% Public Domain 9 | */ 10 | 11 | #ifndef _SYS_SHA1_H_ 12 | #define _SYS_SHA1_H_ 13 | 14 | #include "../defs.h" 15 | 16 | typedef struct { 17 | uint32_t state[5]; 18 | uint32_t count[2]; 19 | uint8_t buffer[64]; 20 | } SHA1_CTX; 21 | 22 | #ifdef RUBY 23 | /* avoid name clash */ 24 | #define SHA1_Transform rb_Digest_SHA1_Transform 25 | #define SHA1_Init rb_Digest_SHA1_Init 26 | #define SHA1_Update rb_Digest_SHA1_Update 27 | #define SHA1_Finish rb_Digest_SHA1_Finish 28 | #endif 29 | 30 | void SHA1_Transform _((uint32_t state[5], const uint8_t buffer[64])); 31 | int SHA1_Init _((SHA1_CTX *context)); 32 | void SHA1_Update _((SHA1_CTX *context, const uint8_t *data, size_t len)); 33 | int SHA1_Finish _((SHA1_CTX *context, uint8_t digest[20])); 34 | 35 | #define SHA1_BLOCK_LENGTH 64 36 | #define SHA1_DIGEST_LENGTH 20 37 | #define SHA1_DIGEST_STRING_LENGTH (SHA1_DIGEST_LENGTH * 2 + 1) 38 | 39 | #endif /* _SYS_SHA1_H_ */ 40 | -------------------------------------------------------------------------------- /ext/digest/sha1/sha1cc.h: -------------------------------------------------------------------------------- 1 | #define COMMON_DIGEST_FOR_OPENSSL 1 2 | #include 3 | 4 | #define SHA1_BLOCK_LENGTH CC_SHA1_BLOCK_BYTES 5 | #define SHA1_DIGEST_LENGTH CC_SHA1_DIGEST_LENGTH 6 | #define SHA1_CTX CC_SHA1_CTX 7 | 8 | static DEFINE_UPDATE_FUNC_FOR_UINT(SHA1) 9 | static DEFINE_FINISH_FUNC_FROM_FINAL(SHA1) 10 | 11 | #undef SHA1_Update 12 | #undef SHA1_Finish 13 | #define SHA1_Update rb_digest_SHA1_update 14 | #define SHA1_Finish rb_digest_SHA1_finish 15 | 16 | /* 17 | * Pre-10.6 defines are with args, which don't match the argless use in 18 | * the function pointer inits. Thus, we redefine SHA1_Init as well. 19 | * This is a NOP on 10.6+. 20 | */ 21 | #undef SHA1_Init 22 | #define SHA1_Init CC_SHA1_Init 23 | -------------------------------------------------------------------------------- /ext/digest/sha1/sha1init.c: -------------------------------------------------------------------------------- 1 | /* $RoughId: sha1init.c,v 1.2 2001/07/13 19:49:10 knu Exp $ */ 2 | /* $Id$ */ 3 | 4 | #include 5 | #include "../digest.h" 6 | #if defined(SHA1_USE_COMMONDIGEST) 7 | #include "sha1cc.h" 8 | #else 9 | #include "sha1.h" 10 | #endif 11 | 12 | static const rb_digest_metadata_t sha1 = { 13 | RUBY_DIGEST_API_VERSION, 14 | SHA1_DIGEST_LENGTH, 15 | SHA1_BLOCK_LENGTH, 16 | sizeof(SHA1_CTX), 17 | (rb_digest_hash_init_func_t)SHA1_Init, 18 | (rb_digest_hash_update_func_t)SHA1_Update, 19 | (rb_digest_hash_finish_func_t)SHA1_Finish, 20 | }; 21 | 22 | /* 23 | * Document-class: Digest::SHA1 < Digest::Base 24 | * A class for calculating message digests using the SHA-1 Secure Hash 25 | * Algorithm by NIST (the US' National Institute of Standards and 26 | * Technology), described in FIPS PUB 180-1. 27 | * 28 | * See Digest::Instance for digest API. 29 | * 30 | * SHA-1 calculates a digest of 160 bits (20 bytes). 31 | * 32 | * == Examples 33 | * require 'digest' 34 | * 35 | * # Compute a complete digest 36 | * Digest::SHA1.hexdigest 'abc' #=> "a9993e36..." 37 | * 38 | * # Compute digest by chunks 39 | * sha1 = Digest::SHA1.new # =># 40 | * sha1.update "ab" 41 | * sha1 << "c" # alias for #update 42 | * sha1.hexdigest # => "a9993e36..." 43 | * 44 | * # Use the same object to compute another digest 45 | * sha1.reset 46 | * sha1 << "message" 47 | * sha1.hexdigest # => "6f9b9af3..." 48 | */ 49 | void 50 | Init_sha1(void) 51 | { 52 | VALUE mDigest, cDigest_Base, cDigest_SHA1; 53 | 54 | #if 0 55 | mDigest = rb_define_module("Digest"); /* let rdoc know */ 56 | #endif 57 | mDigest = rb_digest_namespace(); 58 | cDigest_Base = rb_const_get(mDigest, rb_intern_const("Base")); 59 | 60 | cDigest_SHA1 = rb_define_class_under(mDigest, "SHA1", cDigest_Base); 61 | rb_iv_set(cDigest_SHA1, "metadata", rb_digest_make_metadata(&sha1)); 62 | } 63 | -------------------------------------------------------------------------------- /ext/digest/sha2/extconf.rb: -------------------------------------------------------------------------------- 1 | # -*- coding: us-ascii -*- 2 | # frozen_string_literal: false 3 | # $RoughId: extconf.rb,v 1.4 2001/08/14 19:54:51 knu Exp $ 4 | # $Id$ 5 | 6 | require "mkmf" 7 | require File.expand_path("../../digest_conf", __FILE__) 8 | 9 | $objs = [ "sha2init.#{$OBJEXT}" ] 10 | 11 | unless digest_conf("sha2") 12 | have_type("u_int8_t") 13 | end 14 | 15 | have_header("sys/cdefs.h") 16 | 17 | $preload = %w[digest] 18 | 19 | create_makefile("digest/sha2") 20 | -------------------------------------------------------------------------------- /ext/digest/sha2/sha2.h: -------------------------------------------------------------------------------- 1 | /* 2 | * FILE: sha2.h 3 | * AUTHOR: Aaron D. Gifford - http://www.aarongifford.com/ 4 | * 5 | * Copyright (c) 2000-2001, Aaron D. Gifford 6 | * All rights reserved. 7 | * 8 | * Redistribution and use in source and binary forms, with or without 9 | * modification, are permitted provided that the following conditions 10 | * are met: 11 | * 1. Redistributions of source code must retain the above copyright 12 | * notice, this list of conditions and the following disclaimer. 13 | * 2. Redistributions in binary form must reproduce the above copyright 14 | * notice, this list of conditions and the following disclaimer in the 15 | * documentation and/or other materials provided with the distribution. 16 | * 3. Neither the name of the copyright holder nor the names of contributors 17 | * may be used to endorse or promote products derived from this software 18 | * without specific prior written permission. 19 | * 20 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTOR(S) ``AS IS'' AND 21 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 23 | * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTOR(S) BE LIABLE 24 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 25 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 26 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 27 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 28 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 29 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 30 | * SUCH DAMAGE. 31 | * 32 | * $OrigId: sha2.h,v 1.1 2001/11/08 00:02:01 adg Exp adg $ 33 | * $RoughId: sha2.h,v 1.3 2002/02/24 08:14:32 knu Exp $ 34 | * $Id$ 35 | */ 36 | 37 | #ifndef __SHA2_H__ 38 | #define __SHA2_H__ 39 | 40 | #ifdef __cplusplus 41 | extern "C" { 42 | #endif 43 | 44 | 45 | /* 46 | * Import u_intXX_t size_t type definitions from system headers. You 47 | * may need to change this, or define these things yourself in this 48 | * file. 49 | */ 50 | #include 51 | 52 | #ifdef RUBY 53 | # ifdef HAVE_PROTOTYPES 54 | # undef NOPROTO 55 | # else 56 | # define NOPROTO 57 | # endif /* HAVE_PROTOTYPES */ 58 | # ifndef BYTE_ORDER 59 | # define LITTLE_ENDIAN 1234 60 | # define BIG_ENDIAN 4321 61 | # ifdef WORDS_BIGENDIAN 62 | # define BYTE_ORDER BIG_ENDIAN 63 | # else 64 | # define BYTE_ORDER LITTLE_ENDIAN 65 | # endif 66 | # endif /* BYTE_ORDER */ 67 | # define SHA2_USE_INTTYPES_H 68 | #else /* RUBY */ 69 | #ifdef SHA2_USE_INTTYPES_H 70 | 71 | #include 72 | 73 | #endif /* SHA2_USE_INTTYPES_H */ 74 | #endif /* RUBY */ 75 | 76 | 77 | /*** SHA-256/384/512 Various Length Definitions ***********************/ 78 | #define SHA256_BLOCK_LENGTH 64 79 | #define SHA256_DIGEST_LENGTH 32 80 | #define SHA256_DIGEST_STRING_LENGTH (SHA256_DIGEST_LENGTH * 2 + 1) 81 | #define SHA384_BLOCK_LENGTH 128 82 | #define SHA384_DIGEST_LENGTH 48 83 | #define SHA384_DIGEST_STRING_LENGTH (SHA384_DIGEST_LENGTH * 2 + 1) 84 | #define SHA512_BLOCK_LENGTH 128 85 | #define SHA512_DIGEST_LENGTH 64 86 | #define SHA512_DIGEST_STRING_LENGTH (SHA512_DIGEST_LENGTH * 2 + 1) 87 | 88 | 89 | /*** SHA-256/384/512 Context Structures *******************************/ 90 | /* NOTE: If your architecture does not define either u_intXX_t types or 91 | * uintXX_t (from inttypes.h), you may need to define things by hand 92 | * for your system: 93 | */ 94 | #ifndef SHA2_USE_INTTYPES_H 95 | # ifdef HAVE_U_INT8_T 96 | typedef u_int8_t uint8_t; /* 1-byte (8-bits) */ 97 | typedef u_int32_t uint32_t; /* 4-bytes (32-bits) */ 98 | typedef u_int64_t uint64_t; /* 8-bytes (64-bits) */ 99 | # else 100 | typedef unsigned char uint8_t; /* 1-byte (8-bits) */ 101 | typedef unsigned int uint32_t; /* 4-bytes (32-bits) */ 102 | typedef unsigned long long uint64_t; /* 8-bytes (64-bits) */ 103 | # endif 104 | #endif 105 | 106 | /* 107 | * Most BSD systems already define u_intXX_t types, as does Linux. 108 | * Some systems, however, like Compaq's Tru64 Unix instead can use 109 | * uintXX_t types defined by very recent ANSI C standards and included 110 | * in the file: 111 | * 112 | * #include 113 | * 114 | * If you choose to use then please define: 115 | * 116 | * #define SHA2_USE_INTTYPES_H 117 | * 118 | * Or on the command line during compile: 119 | * 120 | * cc -DSHA2_USE_INTTYPES_H ... 121 | */ 122 | typedef struct _SHA256_CTX { 123 | uint32_t state[8]; 124 | uint64_t bitcount; 125 | uint8_t buffer[SHA256_BLOCK_LENGTH]; 126 | } SHA256_CTX; 127 | typedef struct _SHA512_CTX { 128 | uint64_t state[8]; 129 | uint64_t bitcount[2]; 130 | uint8_t buffer[SHA512_BLOCK_LENGTH]; 131 | } SHA512_CTX; 132 | 133 | typedef SHA512_CTX SHA384_CTX; 134 | 135 | 136 | /*** SHA-256/384/512 Function Prototypes ******************************/ 137 | #ifdef RUBY 138 | #define SHA256_Init rb_Digest_SHA256_Init 139 | #define SHA256_Update rb_Digest_SHA256_Update 140 | #define SHA256_Finish rb_Digest_SHA256_Finish 141 | #define SHA256_Data rb_Digest_SHA256_Data 142 | #define SHA256_End rb_Digest_SHA256_End 143 | #define SHA256_Last rb_Digest_SHA256_Last 144 | #define SHA256_Transform rb_Digest_SHA256_Transform 145 | #define SHA256_Final(d, c) SHA256_Finish(c, d) 146 | 147 | #define SHA384_Init rb_Digest_SHA384_Init 148 | #define SHA384_Update rb_Digest_SHA384_Update 149 | #define SHA384_Finish rb_Digest_SHA384_Finish 150 | #define SHA384_Data rb_Digest_SHA384_Data 151 | #define SHA384_End rb_Digest_SHA384_End 152 | #define SHA384_Last rb_Digest_SHA384_Last 153 | #define SHA384_Transform rb_Digest_SHA384_Transform 154 | #define SHA384_Final(d, c) SHA384_Finish(c, d) 155 | 156 | #define SHA512_Init rb_Digest_SHA512_Init 157 | #define SHA512_Update rb_Digest_SHA512_Update 158 | #define SHA512_Finish rb_Digest_SHA512_Finish 159 | #define SHA512_Data rb_Digest_SHA512_Data 160 | #define SHA512_End rb_Digest_SHA512_End 161 | #define SHA512_Last rb_Digest_SHA512_Last 162 | #define SHA512_Transform rb_Digest_SHA512_Transform 163 | #define SHA512_Final(d, c) SHA512_Finish(c, d) 164 | #endif /* RUBY */ 165 | 166 | #ifndef NOPROTO 167 | 168 | int SHA256_Init(SHA256_CTX *); 169 | void SHA256_Update(SHA256_CTX*, const uint8_t*, size_t); 170 | int SHA256_Final(uint8_t[SHA256_DIGEST_LENGTH], SHA256_CTX*); 171 | char* SHA256_End(SHA256_CTX*, char[SHA256_DIGEST_STRING_LENGTH]); 172 | char* SHA256_Data(const uint8_t*, size_t, char[SHA256_DIGEST_STRING_LENGTH]); 173 | 174 | int SHA384_Init(SHA384_CTX*); 175 | void SHA384_Update(SHA384_CTX*, const uint8_t*, size_t); 176 | int SHA384_Final(uint8_t[SHA384_DIGEST_LENGTH], SHA384_CTX*); 177 | char* SHA384_End(SHA384_CTX*, char[SHA384_DIGEST_STRING_LENGTH]); 178 | char* SHA384_Data(const uint8_t*, size_t, char[SHA384_DIGEST_STRING_LENGTH]); 179 | 180 | int SHA512_Init(SHA512_CTX*); 181 | void SHA512_Update(SHA512_CTX*, const uint8_t*, size_t); 182 | int SHA512_Final(uint8_t[SHA512_DIGEST_LENGTH], SHA512_CTX*); 183 | char* SHA512_End(SHA512_CTX*, char[SHA512_DIGEST_STRING_LENGTH]); 184 | char* SHA512_Data(const uint8_t*, size_t, char[SHA512_DIGEST_STRING_LENGTH]); 185 | 186 | #else /* NOPROTO */ 187 | 188 | int SHA256_Init(); 189 | void SHA256_Update(); 190 | #ifdef RUBY 191 | int SHA256_Finish(); 192 | #else 193 | int SHA256_Final(); 194 | #endif /* RUBY */ 195 | char* SHA256_End(); 196 | char* SHA256_Data(); 197 | 198 | int SHA384_Init(); 199 | void SHA384_Update(); 200 | #ifdef RUBY 201 | int SHA384_Finish(); 202 | #else 203 | int SHA384_Final(); 204 | #endif /* RUBY */ 205 | char* SHA384_End(); 206 | char* SHA384_Data(); 207 | 208 | int SHA512_Init(); 209 | void SHA512_Update(); 210 | #ifdef RUBY 211 | int SHA512_Finish(); 212 | #else 213 | int SHA512_Final(); 214 | #endif /* RUBY */ 215 | char* SHA512_End(); 216 | char* SHA512_Data(); 217 | 218 | #endif /* NOPROTO */ 219 | 220 | #ifdef __cplusplus 221 | } 222 | #endif /* __cplusplus */ 223 | 224 | #endif /* __SHA2_H__ */ 225 | 226 | -------------------------------------------------------------------------------- /ext/digest/sha2/sha2cc.h: -------------------------------------------------------------------------------- 1 | #define COMMON_DIGEST_FOR_OPENSSL 1 2 | #include 3 | 4 | /* 5 | * Prior to 10.5, OpenSSL-compatible definitions are missing for 6 | * SHA2 macros, though the CC_ versions are present. 7 | * Add the missing definitions we actually use here if needed. 8 | * Note that the definitions are the argless 10.6+-style. 9 | * The weird CTX mismatch is copied from the 10.6 header. 10 | */ 11 | #ifndef SHA256_DIGEST_LENGTH 12 | #define SHA256_DIGEST_LENGTH CC_SHA256_DIGEST_LENGTH 13 | #define SHA256_CTX CC_SHA256_CTX 14 | #define SHA256_Update CC_SHA256_Update 15 | #define SHA256_Final CC_SHA256_Final 16 | #endif /* !defined SHA256_DIGEST_LENGTH */ 17 | 18 | #ifndef SHA384_DIGEST_LENGTH 19 | #define SHA384_DIGEST_LENGTH CC_SHA384_DIGEST_LENGTH 20 | #define SHA512_CTX CC_SHA512_CTX 21 | #define SHA384_Update CC_SHA384_Update 22 | #define SHA384_Final CC_SHA384_Final 23 | #endif /* !defined SHA384_DIGEST_LENGTH */ 24 | 25 | #ifndef SHA512_DIGEST_LENGTH 26 | #define SHA512_DIGEST_LENGTH CC_SHA512_DIGEST_LENGTH 27 | #define SHA512_Update CC_SHA512_Update 28 | #define SHA512_Final CC_SHA512_Final 29 | #endif /* !defined SHA512_DIGEST_LENGTH */ 30 | 31 | #define SHA256_BLOCK_LENGTH CC_SHA256_BLOCK_BYTES 32 | #define SHA384_BLOCK_LENGTH CC_SHA384_BLOCK_BYTES 33 | #define SHA512_BLOCK_LENGTH CC_SHA512_BLOCK_BYTES 34 | 35 | #define SHA384_CTX CC_SHA512_CTX 36 | 37 | static DEFINE_UPDATE_FUNC_FOR_UINT(SHA256) 38 | static DEFINE_FINISH_FUNC_FROM_FINAL(SHA256) 39 | static DEFINE_UPDATE_FUNC_FOR_UINT(SHA384) 40 | static DEFINE_FINISH_FUNC_FROM_FINAL(SHA384) 41 | static DEFINE_UPDATE_FUNC_FOR_UINT(SHA512) 42 | static DEFINE_FINISH_FUNC_FROM_FINAL(SHA512) 43 | 44 | 45 | #undef SHA256_Update 46 | #undef SHA256_Finish 47 | #define SHA256_Update rb_digest_SHA256_update 48 | #define SHA256_Finish rb_digest_SHA256_finish 49 | 50 | #undef SHA384_Update 51 | #undef SHA384_Finish 52 | #define SHA384_Update rb_digest_SHA384_update 53 | #define SHA384_Finish rb_digest_SHA384_finish 54 | 55 | #undef SHA512_Update 56 | #undef SHA512_Finish 57 | #define SHA512_Update rb_digest_SHA512_update 58 | #define SHA512_Finish rb_digest_SHA512_finish 59 | 60 | /* 61 | * Pre-10.6 defines are with args, which don't match the argless use in 62 | * the function pointer inits. Thus, we redefine SHA*_Init as well. 63 | * This is a NOP on 10.6+. 64 | */ 65 | #undef SHA256_Init 66 | #define SHA256_Init CC_SHA256_Init 67 | #undef SHA384_Init 68 | #define SHA384_Init CC_SHA384_Init 69 | #undef SHA512_Init 70 | #define SHA512_Init CC_SHA512_Init 71 | -------------------------------------------------------------------------------- /ext/digest/sha2/sha2init.c: -------------------------------------------------------------------------------- 1 | /* $RoughId: sha2init.c,v 1.3 2001/07/13 20:00:43 knu Exp $ */ 2 | /* $Id$ */ 3 | 4 | #include 5 | #include "../digest.h" 6 | #if defined(SHA2_USE_COMMONDIGEST) 7 | #include "sha2cc.h" 8 | #else 9 | #include "sha2.h" 10 | #endif 11 | 12 | #define FOREACH_BITLEN(func) func(256) func(384) func(512) 13 | 14 | #define DEFINE_ALGO_METADATA(bitlen) \ 15 | static const rb_digest_metadata_t sha##bitlen = { \ 16 | RUBY_DIGEST_API_VERSION, \ 17 | SHA##bitlen##_DIGEST_LENGTH, \ 18 | SHA##bitlen##_BLOCK_LENGTH, \ 19 | sizeof(SHA##bitlen##_CTX), \ 20 | (rb_digest_hash_init_func_t)SHA##bitlen##_Init, \ 21 | (rb_digest_hash_update_func_t)SHA##bitlen##_Update, \ 22 | (rb_digest_hash_finish_func_t)SHA##bitlen##_Finish, \ 23 | }; 24 | 25 | FOREACH_BITLEN(DEFINE_ALGO_METADATA) 26 | 27 | /* 28 | * Document-class: Digest::SHA256 < Digest::Base 29 | * 30 | * Classes for calculating message digests using the SHA-256/384/512 31 | * Secure Hash Algorithm(s) by NIST (the US' National Institute of 32 | * Standards and Technology), described in FIPS PUB 180-2. 33 | * 34 | * See SHA2. 35 | */ 36 | /* 37 | * Document-class: Digest::SHA384 < Digest::Base 38 | * 39 | * Classes for calculating message digests using the SHA-256/384/512 40 | * Secure Hash Algorithm(s) by NIST (the US' National Institute of 41 | * Standards and Technology), described in FIPS PUB 180-2. 42 | * 43 | * See SHA2. 44 | */ 45 | /* 46 | * Document-class: Digest::SHA512 < Digest::Base 47 | * 48 | * Classes for calculating message digests using the SHA-256/384/512 49 | * Secure Hash Algorithm(s) by NIST (the US' National Institute of 50 | * Standards and Technology), described in FIPS PUB 180-2. 51 | * 52 | * See SHA2. 53 | */ 54 | void 55 | Init_sha2(void) 56 | { 57 | VALUE mDigest, cDigest_Base, cDigest_SHA2; 58 | ID id_metadata = rb_id_metadata(); 59 | 60 | #if 0 61 | mDigest = rb_define_module("Digest"); /* let rdoc know */ 62 | #endif 63 | mDigest = rb_digest_namespace(); 64 | cDigest_Base = rb_const_get(mDigest, rb_intern_const("Base")); 65 | 66 | cDigest_SHA2 = rb_define_class_under(mDigest, "SHA256", cDigest_Base); 67 | rb_ivar_set(cDigest_SHA2, id_metadata, rb_digest_make_metadata(&sha256)); 68 | 69 | cDigest_SHA2 = rb_define_class_under(mDigest, "SHA384", cDigest_Base); 70 | rb_ivar_set(cDigest_SHA2, id_metadata, rb_digest_make_metadata(&sha384)); 71 | 72 | cDigest_SHA2 = rb_define_class_under(mDigest, "SHA512", cDigest_Base); 73 | rb_ivar_set(cDigest_SHA2, id_metadata, rb_digest_make_metadata(&sha512)); 74 | } 75 | -------------------------------------------------------------------------------- /ext/java/org/jruby/ext/digest/BubbleBabble.java: -------------------------------------------------------------------------------- 1 | /* 2 | **** BEGIN LICENSE BLOCK ***** 3 | * BSD 2-Clause License 4 | * 5 | * Copyright (c) 2010, Charles Oliver Nutter 6 | * All rights reserved. 7 | * 8 | * Redistribution and use in source and binary forms, with or without 9 | * modification, are permitted provided that the following conditions are met: 10 | * 11 | * 1. Redistributions of source code must retain the above copyright notice, this 12 | * list of conditions and the following disclaimer. 13 | * 14 | * 2. Redistributions in binary form must reproduce the above copyright notice, 15 | * this list of conditions and the following disclaimer in the documentation 16 | * and/or other materials provided with the distribution. 17 | * 18 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 19 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 20 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 21 | * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 22 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 23 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 24 | * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 25 | * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 26 | * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 27 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 | ***** END LICENSE BLOCK *****/ 29 | 30 | package org.jruby.ext.digest; 31 | 32 | import org.jruby.Ruby; 33 | import org.jruby.runtime.load.Library; 34 | import org.jruby.util.ByteList; 35 | 36 | import java.io.IOException; 37 | 38 | public class BubbleBabble implements Library { 39 | 40 | public void load(final Ruby runtime, boolean wrap) throws IOException { 41 | RubyDigest.createDigestBubbleBabble(runtime); 42 | } 43 | 44 | /** 45 | * Ported from OpenSSH (https://github.com/openssh/openssh-portable/blob/957fbceb0f3166e41b76fdb54075ab3b9cc84cba/sshkey.c#L942-L987) 46 | * 47 | * OpenSSH License Notice 48 | * 49 | * Copyright (c) 2000, 2001 Markus Friedl. All rights reserved. 50 | * Copyright (c) 2008 Alexander von Gernler. All rights reserved. 51 | * Copyright (c) 2010,2011 Damien Miller. All rights reserved. 52 | * 53 | * Redistribution and use in source and binary forms, with or without 54 | * modification, are permitted provided that the following conditions 55 | * are met: 56 | * 1. Redistributions of source code must retain the above copyright 57 | * notice, this list of conditions and the following disclaimer. 58 | * 2. Redistributions in binary form must reproduce the above copyright 59 | * notice, this list of conditions and the following disclaimer in the 60 | * documentation and/or other materials provided with the distribution. 61 | * 62 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 63 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 64 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 65 | * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 66 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 67 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 68 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 69 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 70 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 71 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 72 | */ 73 | public static ByteList bubblebabble(byte[] message, int begin, int length) { 74 | char[] vowels = new char[]{'a', 'e', 'i', 'o', 'u', 'y'}; 75 | char[] consonants = new char[]{'b', 'c', 'd', 'f', 'g', 'h', 'k', 'l', 'm', 76 | 'n', 'p', 'r', 's', 't', 'v', 'z', 'x'}; 77 | 78 | long seed = 1; 79 | 80 | ByteList retval = new ByteList(); 81 | 82 | int rounds = (length / 2) + 1; 83 | retval.append('x'); 84 | for (int i = 0; i < rounds; i++) { 85 | int idx0, idx1, idx2, idx3, idx4; 86 | 87 | if ((i + 1 < rounds) || (length % 2 != 0)) { 88 | long b = message[begin + 2 * i] & 0xFF; 89 | idx0 = (int) ((((b >> 6) & 3) + seed) % 6) & 0xFFFFFFFF; 90 | idx1 = (int) (((b) >> 2) & 15) & 0xFFFFFFFF; 91 | idx2 = (int) (((b & 3) + (seed / 6)) % 6) & 0xFFFFFFFF; 92 | retval.append(vowels[idx0]); 93 | retval.append(consonants[idx1]); 94 | retval.append(vowels[idx2]); 95 | if ((i + 1) < rounds) { 96 | long b2 = message[begin + (2 * i) + 1] & 0xFF; 97 | idx3 = (int) ((b2 >> 4) & 15) & 0xFFFFFFFF; 98 | idx4 = (int) ((b2) & 15) & 0xFFFFFFFF; 99 | retval.append(consonants[idx3]); 100 | retval.append('-'); 101 | retval.append(consonants[idx4]); 102 | seed = ((seed * 5) + 103 | ((b * 7) + 104 | b2)) % 36; 105 | } 106 | } else { 107 | idx0 = (int) (seed % 6) & 0xFFFFFFFF; 108 | idx1 = 16; 109 | idx2 = (int) (seed / 6) & 0xFFFFFFFF; 110 | retval.append(vowels[idx0]); 111 | retval.append(consonants[idx1]); 112 | retval.append(vowels[idx2]); 113 | } 114 | } 115 | retval.append('x'); 116 | 117 | return retval; 118 | } 119 | } 120 | -------------------------------------------------------------------------------- /ext/java/org/jruby/ext/digest/DigestLibrary.java: -------------------------------------------------------------------------------- 1 | /* 2 | **** BEGIN LICENSE BLOCK ***** 3 | * BSD 2-Clause License 4 | * 5 | * Copyright (C) 2006 Ola Bini 6 | * All rights reserved. 7 | * 8 | * Redistribution and use in source and binary forms, with or without 9 | * modification, are permitted provided that the following conditions are met: 10 | * 11 | * 1. Redistributions of source code must retain the above copyright notice, this 12 | * list of conditions and the following disclaimer. 13 | * 14 | * 2. Redistributions in binary form must reproduce the above copyright notice, 15 | * this list of conditions and the following disclaimer in the documentation 16 | * and/or other materials provided with the distribution. 17 | * 18 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 19 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 20 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 21 | * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 22 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 23 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 24 | * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 25 | * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 26 | * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 27 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 | ***** END LICENSE BLOCK *****/ 29 | 30 | package org.jruby.ext.digest; 31 | 32 | import java.io.IOException; 33 | 34 | import org.jruby.Ruby; 35 | import org.jruby.runtime.load.Library; 36 | 37 | /** 38 | * @author Ola Bini 39 | */ 40 | public class DigestLibrary implements Library { 41 | public void load(final Ruby runtime, boolean wrap) throws IOException { 42 | org.jruby.ext.digest.RubyDigest.createDigest(runtime); 43 | } 44 | }// DigestLibrary 45 | -------------------------------------------------------------------------------- /ext/java/org/jruby/ext/digest/MD5.java: -------------------------------------------------------------------------------- 1 | /* 2 | **** BEGIN LICENSE BLOCK ***** 3 | * BSD 2-Clause License 4 | * 5 | * Copyright (c) 2010, Charles Oliver Nutter 6 | * All rights reserved. 7 | * 8 | * Redistribution and use in source and binary forms, with or without 9 | * modification, are permitted provided that the following conditions are met: 10 | * 11 | * 1. Redistributions of source code must retain the above copyright notice, this 12 | * list of conditions and the following disclaimer. 13 | * 14 | * 2. Redistributions in binary form must reproduce the above copyright notice, 15 | * this list of conditions and the following disclaimer in the documentation 16 | * and/or other materials provided with the distribution. 17 | * 18 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 19 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 20 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 21 | * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 22 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 23 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 24 | * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 25 | * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 26 | * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 27 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 | ***** END LICENSE BLOCK *****/ 29 | 30 | package org.jruby.ext.digest; 31 | 32 | import java.io.IOException; 33 | import org.jruby.Ruby; 34 | import org.jruby.runtime.load.Library; 35 | 36 | public class MD5 implements Library { 37 | 38 | public void load(final Ruby runtime, boolean wrap) throws IOException { 39 | org.jruby.ext.digest.RubyDigest.createDigestMD5(runtime); 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /ext/java/org/jruby/ext/digest/RMD160.java: -------------------------------------------------------------------------------- 1 | /* 2 | **** BEGIN LICENSE BLOCK ***** 3 | * BSD 2-Clause License 4 | * 5 | * Copyright (c) 2010, Charles Oliver Nutter 6 | * All rights reserved. 7 | * 8 | * Redistribution and use in source and binary forms, with or without 9 | * modification, are permitted provided that the following conditions are met: 10 | * 11 | * 1. Redistributions of source code must retain the above copyright notice, this 12 | * list of conditions and the following disclaimer. 13 | * 14 | * 2. Redistributions in binary form must reproduce the above copyright notice, 15 | * this list of conditions and the following disclaimer in the documentation 16 | * and/or other materials provided with the distribution. 17 | * 18 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 19 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 20 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 21 | * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 22 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 23 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 24 | * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 25 | * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 26 | * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 27 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 | ***** END LICENSE BLOCK *****/ 29 | 30 | package org.jruby.ext.digest; 31 | 32 | import java.io.IOException; 33 | import org.jruby.Ruby; 34 | import org.jruby.runtime.load.Library; 35 | 36 | public class RMD160 implements Library { 37 | 38 | public void load(final Ruby runtime, boolean wrap) throws IOException { 39 | org.jruby.ext.digest.RubyDigest.createDigestRMD160(runtime); 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /ext/java/org/jruby/ext/digest/RubyDigest.java: -------------------------------------------------------------------------------- 1 | /* 2 | **** BEGIN LICENSE BLOCK ***** 3 | * BSD 2-Clause License 4 | * 5 | * Copyright (C) 2006, 2007 Ola Bini 6 | * Copyright (C) 2007 Nick Sieger 7 | * Copyright (C) 2008 Vladimir Sizikov 8 | * Copyright (C) 2009 Joseph LaFata 9 | * All rights reserved. 10 | * 11 | * Redistribution and use in source and binary forms, with or without 12 | * modification, are permitted provided that the following conditions are met: 13 | * 14 | * 1. Redistributions of source code must retain the above copyright notice, this 15 | * list of conditions and the following disclaimer. 16 | * 17 | * 2. Redistributions in binary form must reproduce the above copyright notice, 18 | * this list of conditions and the following disclaimer in the documentation 19 | * and/or other materials provided with the distribution. 20 | * 21 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 22 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 24 | * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 25 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 26 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 27 | * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 28 | * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 29 | * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 30 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 31 | ***** END LICENSE BLOCK *****/ 32 | 33 | package org.jruby.ext.digest; 34 | 35 | import java.security.MessageDigest; 36 | import java.security.NoSuchAlgorithmException; 37 | import java.security.Provider; 38 | import java.util.HashMap; 39 | import java.util.Map; 40 | 41 | import org.jcodings.specific.USASCIIEncoding; 42 | import org.jruby.Ruby; 43 | import org.jruby.RubyClass; 44 | import org.jruby.RubyFixnum; 45 | import org.jruby.RubyModule; 46 | import org.jruby.RubyObject; 47 | import org.jruby.RubyString; 48 | 49 | import org.jruby.anno.JRubyClass; 50 | import org.jruby.anno.JRubyMethod; 51 | import org.jruby.anno.JRubyModule; 52 | import org.jruby.exceptions.RaiseException; 53 | import org.jruby.runtime.Block; 54 | import org.jruby.runtime.ThreadContext; 55 | import org.jruby.runtime.Visibility; 56 | import org.jruby.runtime.builtin.IRubyObject; 57 | import org.jruby.util.ArraySupport; 58 | import org.jruby.util.ByteList; 59 | import org.jruby.util.log.Logger; 60 | import org.jruby.util.log.LoggerFactory; 61 | 62 | /** 63 | * @author Ola Bini 64 | */ 65 | @JRubyModule(name="Digest") 66 | public class RubyDigest { 67 | 68 | private static final Map CLONEABLE_DIGESTS = new HashMap(8, 1); 69 | static { 70 | // standard digests from JCA specification; if we can retrieve and clone, save them 71 | for (String name : new String[] {"MD2", "MD5", "SHA-1", "SHA-256", "SHA-384", "SHA-512"}) { 72 | try { 73 | MessageDigest digest = MessageDigest.getInstance(name); 74 | digest.clone(); 75 | CLONEABLE_DIGESTS.put(name, digest); 76 | } 77 | catch (Exception e) { 78 | logger().debug(name + " not clonable", e); 79 | } 80 | } 81 | } 82 | 83 | private static Logger logger() { return LoggerFactory.getLogger(RubyDigest.class); } 84 | 85 | private static final String PROVIDER = "org.bouncycastle.jce.provider.BouncyCastleProvider"; 86 | private static Provider provider = null; 87 | 88 | public static void createDigest(Ruby runtime) { 89 | try { 90 | provider = (Provider) Class.forName(PROVIDER).getConstructor().newInstance(); 91 | } 92 | catch (Throwable t) { /* provider is not available */ } 93 | 94 | RubyModule mDigest = runtime.defineModule("Digest"); 95 | mDigest.defineAnnotatedMethods(RubyDigest.class); 96 | RubyModule mDigestInstance = mDigest.defineModuleUnder("Instance"); 97 | mDigestInstance.defineAnnotatedMethods(DigestInstance.class); 98 | RubyClass cDigestClass = mDigest.defineClassUnder("Class", runtime.getObject(), DigestClass::new); 99 | cDigestClass.defineAnnotatedMethods(DigestClass.class); 100 | cDigestClass.includeModule(mDigestInstance); 101 | RubyClass cDigestBase = mDigest.defineClassUnder("Base", cDigestClass, DigestBase::new); 102 | cDigestBase.defineAnnotatedMethods(DigestBase.class); 103 | } 104 | 105 | private static MessageDigest createMessageDigest(final String name) throws NoSuchAlgorithmException { 106 | MessageDigest cloneable = CLONEABLE_DIGESTS.get(name); 107 | if (cloneable != null) { 108 | try { 109 | return (MessageDigest) cloneable.clone(); 110 | } 111 | catch (CloneNotSupportedException e) { 112 | // should never happen, since we tested it in static init 113 | } 114 | } 115 | 116 | // fall back on JCA mechanisms for getting a digest 117 | if (provider != null) { 118 | try { 119 | return MessageDigest.getInstance(name, provider); 120 | } 121 | catch (NoSuchAlgorithmException e) { 122 | // bouncy castle doesn't support algorithm 123 | } 124 | } 125 | 126 | // fall back to default JCA providers 127 | return MessageDigest.getInstance(name); 128 | } 129 | 130 | private final static byte[] digits = { 131 | '0', '1', '2', '3', '4', '5', 132 | '6', '7', '8', '9', 'a', 'b', 133 | 'c', 'd', 'e', 'f', 'g', 'h', 134 | 'i', 'j', 'k', 'l', 'm', 'n', 135 | 'o', 'p', 'q', 'r', 's', 't', 136 | 'u', 'v', 'w', 'x', 'y', 'z' 137 | }; 138 | 139 | private static ByteList toHex(byte[] val) { 140 | ByteList byteList = new ByteList(val.length * 2); 141 | for (int i = 0, j = val.length; i < j; i++) { 142 | int b = val[i] & 0xFF; 143 | byteList.append(digits[b >> 4]); 144 | byteList.append(digits[b & 0xF]); 145 | } 146 | return byteList; 147 | } 148 | 149 | private static RubyString toHexString(Ruby runtime, byte[] val) { 150 | return RubyString.newStringNoCopy(runtime, new ByteList(ByteList.plain(toHex(val)), USASCIIEncoding.INSTANCE)); 151 | } 152 | 153 | @JRubyMethod(name = "hexencode", required = 1, meta = true) 154 | public static RubyString hexencode(IRubyObject self, IRubyObject arg) { 155 | return toHexString(self.getRuntime(), arg.convertToString().getBytes()); 156 | } 157 | 158 | @JRubyMethod(name = "bubblebabble", required = 1, meta = true) 159 | public static RubyString bubblebabble(IRubyObject recv, IRubyObject arg) { 160 | final ByteList bytes = arg.convertToString().getByteList(); 161 | return RubyString.newString(recv.getRuntime(), BubbleBabble.bubblebabble(bytes.unsafeBytes(), bytes.begin(), bytes.length())); 162 | } 163 | 164 | private static class Metadata { 165 | 166 | private final String name; 167 | private final int blockLength; 168 | 169 | Metadata(String name, int blockLength) { 170 | this.name = name; 171 | this.blockLength = blockLength; 172 | } 173 | 174 | String getName() { 175 | return name; 176 | } 177 | 178 | int getBlockLength() { 179 | return blockLength; 180 | } 181 | } 182 | 183 | 184 | @JRubyClass(name="Digest::MD5", parent="Digest::Base") 185 | public static class MD5 {} 186 | @JRubyClass(name="Digest::RMD160", parent="Digest::Base") 187 | public static class RMD160 {} 188 | @JRubyClass(name="Digest::SHA1", parent="Digest::Base") 189 | public static class SHA1 {} 190 | @JRubyClass(name="Digest::SHA256", parent="Digest::Base") 191 | public static class SHA256 {} 192 | @JRubyClass(name="Digest::SHA384", parent="Digest::Base") 193 | public static class SHA384 {} 194 | @JRubyClass(name="Digest::SHA512", parent="Digest::Base") 195 | public static class SHA512 {} 196 | 197 | public static void createDigestMD5(Ruby runtime) { 198 | runtime.getLoadService().require("digest"); 199 | RubyModule Digest = runtime.getModule("Digest"); 200 | RubyClass Base = Digest.getClass("Base"); 201 | RubyClass MD5 = Digest.defineClassUnder("MD5", Base, Base.getAllocator()); 202 | MD5.setInternalVariable("metadata", new Metadata("MD5", 64)); 203 | } 204 | 205 | public static void createDigestRMD160(Ruby runtime) { 206 | runtime.getLoadService().require("digest"); 207 | if(provider == null) { 208 | throw runtime.newLoadError("RMD160 not supported without BouncyCastle"); 209 | } 210 | RubyModule Digest = runtime.getModule("Digest"); 211 | RubyClass Base = Digest.getClass("Base"); 212 | RubyClass RMD160 = Digest.defineClassUnder("RMD160", Base, Base.getAllocator()); 213 | RMD160.setInternalVariable("metadata", new Metadata("RIPEMD160", 64)); 214 | } 215 | 216 | public static void createDigestSHA1(Ruby runtime) { 217 | runtime.getLoadService().require("digest"); 218 | RubyModule Digest = runtime.getModule("Digest"); 219 | RubyClass Base = Digest.getClass("Base"); 220 | RubyClass SHA1 = Digest.defineClassUnder("SHA1", Base, Base.getAllocator()); 221 | SHA1.setInternalVariable("metadata", new Metadata("SHA1", 64)); 222 | } 223 | 224 | public static void createDigestSHA2(Ruby runtime) { 225 | runtime.getLoadService().require("digest"); 226 | try { 227 | createMessageDigest("SHA-256"); 228 | } 229 | catch (NoSuchAlgorithmException e) { 230 | RaiseException ex = runtime.newLoadError("SHA2 not supported"); 231 | ex.initCause(e); 232 | throw ex; 233 | } 234 | final RubyModule Digest = runtime.getModule("Digest"); 235 | final RubyClass Base = Digest.getClass("Base"); 236 | RubyClass SHA256 = Digest.defineClassUnder("SHA256", Base, Base.getAllocator()); 237 | SHA256.setInternalVariable("metadata", new Metadata("SHA-256", 64)); 238 | RubyClass SHA384 = Digest.defineClassUnder("SHA384", Base, Base.getAllocator()); 239 | SHA384.setInternalVariable("metadata", new Metadata("SHA-384", 128)); 240 | RubyClass SHA512 = Digest.defineClassUnder("SHA512", Base, Base.getAllocator()); 241 | SHA512.setInternalVariable("metadata", new Metadata("SHA-512", 128)); 242 | } 243 | 244 | public static void createDigestBubbleBabble(Ruby runtime) { 245 | runtime.getLoadService().require("digest"); 246 | RubyModule Digest = runtime.getModule("Digest"); 247 | RubyClass Base = Digest.getClass("Base"); 248 | RubyClass MD5 = Digest.defineClassUnder("BubbleBabble", Base, Base.getAllocator()); 249 | MD5.setInternalVariable("metadata", new Metadata("BubbleBabble", 64)); 250 | } 251 | 252 | @JRubyModule(name = "Digest::Instance") 253 | public static class DigestInstance { 254 | 255 | private static IRubyObject throwUnimplError(IRubyObject self, String name) { 256 | throw self.getRuntime().newRuntimeError(String.format("%s does not implement %s()", self.getMetaClass().getRealClass().getName(), name)); 257 | } 258 | 259 | /* instance methods that should be overridden */ 260 | @JRubyMethod(name = {"update", "<<"}, required = 1) 261 | public static IRubyObject update(ThreadContext context, IRubyObject self, IRubyObject arg) { 262 | return throwUnimplError(self, "update"); 263 | } 264 | 265 | @JRubyMethod() 266 | public static IRubyObject finish(ThreadContext context, IRubyObject self) { 267 | return throwUnimplError(self, "finish"); 268 | } 269 | 270 | @JRubyMethod() 271 | public static IRubyObject reset(ThreadContext context, IRubyObject self) { 272 | return throwUnimplError(self, "reset"); 273 | } 274 | 275 | @JRubyMethod() 276 | public static IRubyObject digest_length(ThreadContext context, IRubyObject self) { 277 | return digest(context, self, null).convertToString().bytesize(); 278 | } 279 | 280 | @JRubyMethod() 281 | public static IRubyObject block_length(ThreadContext context, IRubyObject self) { 282 | return throwUnimplError(self, "block_length"); 283 | } 284 | 285 | /* instance methods that may be overridden */ 286 | @JRubyMethod(name = "==", required = 1) 287 | public static IRubyObject op_equal(ThreadContext context, IRubyObject self, IRubyObject oth) { 288 | if(oth.isNil()) return context.fals; 289 | 290 | RubyString str1, str2; 291 | RubyModule instance = (RubyModule)context.runtime.getModule("Digest").getConstantAt("Instance"); 292 | if (oth.getMetaClass().getRealClass().hasModuleInHierarchy(instance)) { 293 | str1 = digest(context, self, null).convertToString(); 294 | str2 = digest(context, oth, null).convertToString(); 295 | } else { 296 | str1 = to_s(context, self).convertToString(); 297 | str2 = oth.convertToString(); 298 | } 299 | boolean ret = str1.bytesize().eql(str2.bytesize()) && (str1.eql(str2)); 300 | return ret ? context.tru : context.fals; 301 | } 302 | 303 | @JRubyMethod() 304 | public static IRubyObject inspect(ThreadContext context, IRubyObject self) { 305 | return RubyString.newStringNoCopy(self.getRuntime(), ByteList.plain("#<" + self.getMetaClass().getRealClass().getName() + ": " + hexdigest(context, self, null) + ">")); 306 | } 307 | 308 | /* instance methods that need not usually be overridden */ 309 | @JRubyMethod(name = "new") 310 | public static IRubyObject newObject(ThreadContext context, IRubyObject self) { 311 | return self.rbClone().callMethod(context, "reset"); 312 | } 313 | 314 | @JRubyMethod(optional = 1) 315 | public static IRubyObject digest(ThreadContext context, IRubyObject self, IRubyObject[] args) { 316 | final IRubyObject value; 317 | if (args != null && args.length > 0) { 318 | self.callMethod(context, "reset"); 319 | self.callMethod(context, "update", args[0]); 320 | value = self.callMethod(context, "finish"); 321 | self.callMethod(context, "reset"); 322 | } else { 323 | IRubyObject clone = self.rbClone(); 324 | value = clone.callMethod(context, "finish"); 325 | clone.callMethod(context, "reset"); 326 | } 327 | return value; 328 | } 329 | 330 | @JRubyMethod(name = "digest!") 331 | public static IRubyObject digest_bang(ThreadContext context, IRubyObject self) { 332 | IRubyObject value = self.callMethod(context, "finish"); 333 | self.callMethod(context, "reset"); 334 | return value; 335 | } 336 | 337 | @JRubyMethod(optional = 1) 338 | public static IRubyObject hexdigest(ThreadContext context, IRubyObject self, IRubyObject[] args) { 339 | return toHexString(context.runtime, digest(context, self, args).convertToString().getBytes()); 340 | } 341 | 342 | @JRubyMethod(name = "hexdigest!") 343 | public static IRubyObject hexdigest_bang(ThreadContext context, IRubyObject self) { 344 | return toHexString(context.runtime, digest_bang(context, self).convertToString().getBytes()); 345 | } 346 | 347 | @JRubyMethod(name = "bubblebabble", required = 1, optional = 1, meta = true) 348 | public static IRubyObject bubblebabble(ThreadContext context, IRubyObject recv, IRubyObject[] args, Block unusedBlock) { 349 | byte[] digest = recv.callMethod(context, "digest", args, Block.NULL_BLOCK).convertToString().getBytes(); 350 | return RubyString.newString(recv.getRuntime(), BubbleBabble.bubblebabble(digest, 0, digest.length)); 351 | } 352 | 353 | @JRubyMethod() 354 | public static IRubyObject to_s(ThreadContext context, IRubyObject self) { 355 | return self.callMethod(context, "hexdigest"); 356 | } 357 | 358 | @JRubyMethod(name = {"length", "size"}) 359 | public static IRubyObject length(ThreadContext context, IRubyObject self) { 360 | return self.callMethod(context, "digest_length"); 361 | } 362 | } 363 | 364 | 365 | @JRubyClass(name="Digest::Class") 366 | public static class DigestClass extends RubyObject { 367 | public DigestClass(Ruby runtime, RubyClass type) { 368 | super(runtime, type); 369 | } 370 | 371 | @JRubyMethod(name = "digest", required = 1, rest = true, meta = true) 372 | public static IRubyObject s_digest(ThreadContext context, IRubyObject recv, IRubyObject[] args, Block unusedBlock) { 373 | final Ruby runtime = context.runtime; 374 | if (args.length < 1) { 375 | throw runtime.newArgumentError("no data given"); 376 | } 377 | RubyString str = args[0].convertToString(); 378 | args = ArraySupport.newCopy(args, 1, args.length - 1); // skip first arg 379 | IRubyObject obj = ((RubyClass) recv).newInstance(context, args, Block.NULL_BLOCK); 380 | return obj.callMethod(context, "digest", str); 381 | } 382 | 383 | @JRubyMethod(name = "hexdigest", required = 1, optional = 1, meta = true) 384 | public static IRubyObject s_hexdigest(ThreadContext context, IRubyObject recv, IRubyObject[] args, Block unusedBlock) { 385 | Ruby runtime = recv.getRuntime(); 386 | byte[] digest = recv.callMethod(context, "digest", args, Block.NULL_BLOCK).convertToString().getBytes(); 387 | return RubyDigest.toHexString(runtime, digest); 388 | } 389 | 390 | @JRubyMethod(name = "bubblebabble", required = 1, meta = true) 391 | public static RubyString bubblebabble(IRubyObject recv, IRubyObject arg) { 392 | byte[] digest = recv.callMethod(recv.getRuntime().getCurrentContext(), "digest", arg).convertToString().getBytes(); 393 | return RubyString.newString(recv.getRuntime(), BubbleBabble.bubblebabble(digest, 0, digest.length)); 394 | } 395 | } 396 | 397 | 398 | @JRubyClass(name="Digest::Base") 399 | public static class DigestBase extends RubyObject { 400 | private MessageDigest algo; 401 | private int blockLength = 0; 402 | 403 | public DigestBase(Ruby runtime, RubyClass type) { 404 | super(runtime,type); 405 | 406 | if(type == runtime.getModule("Digest").getClass("Base")) { 407 | throw runtime.newNotImplementedError("Digest::Base is an abstract class"); 408 | } 409 | 410 | Metadata metadata = getMetadata(type); 411 | if(metadata == null) { 412 | throw runtime.newNotImplementedError("the " + type + "() function is unimplemented on this machine"); 413 | } 414 | 415 | try { 416 | setAlgorithm(metadata); 417 | } catch(NoSuchAlgorithmException e) { 418 | throw runtime.newNotImplementedError("the " + type + "() function is unimplemented on this machine"); 419 | } 420 | 421 | } 422 | 423 | // if subclass extends particular digest we need to walk to find it...we should rearchitect digest to avoid walking type systems 424 | private Metadata getMetadata(RubyModule type) { 425 | for (RubyModule current = type; current != null; current = current.getSuperClass()) { 426 | Metadata metadata = (Metadata) current.getInternalVariable("metadata"); 427 | 428 | if (metadata != null) return metadata; 429 | } 430 | 431 | return null; 432 | } 433 | 434 | @JRubyMethod(required = 1, visibility = Visibility.PRIVATE) 435 | @Override 436 | public IRubyObject initialize_copy(IRubyObject obj) { 437 | if (this == obj) return this; 438 | 439 | DigestBase from = (DigestBase) obj; 440 | from.checkFrozen(); 441 | 442 | try { 443 | this.algo = (MessageDigest) from.algo.clone(); 444 | } 445 | catch (CloneNotSupportedException e) { 446 | String name = from.algo.getAlgorithm(); 447 | throw getRuntime().newTypeError("Could not initialize copy of digest (" + name + ")"); 448 | } 449 | return this; 450 | } 451 | 452 | @JRubyMethod(name = {"update", "<<"}, required = 1) 453 | public IRubyObject update(IRubyObject obj) { 454 | ByteList bytes = obj.convertToString().getByteList(); 455 | algo.update(bytes.getUnsafeBytes(), bytes.getBegin(), bytes.getRealSize()); 456 | return this; 457 | } 458 | 459 | @JRubyMethod() 460 | public IRubyObject finish() { 461 | IRubyObject digest = RubyString.newStringNoCopy(getRuntime(), algo.digest()); 462 | algo.reset(); 463 | return digest; 464 | } 465 | 466 | @JRubyMethod() 467 | public IRubyObject digest_length() { 468 | return RubyFixnum.newFixnum(getRuntime(), algo.getDigestLength()); 469 | } 470 | 471 | @JRubyMethod() 472 | public IRubyObject block_length() { 473 | if (blockLength == 0) { 474 | throw getRuntime().newRuntimeError( 475 | this.getMetaClass() + " doesn't implement block_length()"); 476 | } 477 | return RubyFixnum.newFixnum(getRuntime(), blockLength); 478 | } 479 | 480 | @JRubyMethod() 481 | public IRubyObject reset() { 482 | algo.reset(); 483 | return this; 484 | } 485 | 486 | @JRubyMethod() 487 | public IRubyObject bubblebabble(ThreadContext context) { 488 | final byte[] digest = algo.digest(); 489 | return RubyString.newString(context.runtime, BubbleBabble.bubblebabble(digest, 0, digest.length)); 490 | } 491 | 492 | private void setAlgorithm(Metadata metadata) throws NoSuchAlgorithmException { 493 | this.algo = createMessageDigest(metadata.getName()); 494 | this.blockLength = metadata.getBlockLength(); 495 | } 496 | 497 | } 498 | }// RubyDigest 499 | -------------------------------------------------------------------------------- /ext/java/org/jruby/ext/digest/SHA1.java: -------------------------------------------------------------------------------- 1 | /* 2 | **** BEGIN LICENSE BLOCK ***** 3 | * BSD 2-Clause License 4 | * 5 | * Copyright (c) 2010, Charles Oliver Nutter 6 | * All rights reserved. 7 | * 8 | * Redistribution and use in source and binary forms, with or without 9 | * modification, are permitted provided that the following conditions are met: 10 | * 11 | * 1. Redistributions of source code must retain the above copyright notice, this 12 | * list of conditions and the following disclaimer. 13 | * 14 | * 2. Redistributions in binary form must reproduce the above copyright notice, 15 | * this list of conditions and the following disclaimer in the documentation 16 | * and/or other materials provided with the distribution. 17 | * 18 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 19 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 20 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 21 | * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 22 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 23 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 24 | * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 25 | * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 26 | * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 27 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 | ***** END LICENSE BLOCK *****/ 29 | 30 | package org.jruby.ext.digest; 31 | 32 | import java.io.IOException; 33 | import org.jruby.Ruby; 34 | import org.jruby.runtime.load.Library; 35 | 36 | public class SHA1 implements Library { 37 | 38 | public void load(final Ruby runtime, boolean wrap) throws IOException { 39 | org.jruby.ext.digest.RubyDigest.createDigestSHA1(runtime); 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /ext/java/org/jruby/ext/digest/SHA2.java: -------------------------------------------------------------------------------- 1 | /* 2 | **** BEGIN LICENSE BLOCK ***** 3 | * BSD 2-Clause License 4 | * 5 | * Copyright (c) 2010, Charles Oliver Nutter 6 | * All rights reserved. 7 | * 8 | * Redistribution and use in source and binary forms, with or without 9 | * modification, are permitted provided that the following conditions are met: 10 | * 11 | * 1. Redistributions of source code must retain the above copyright notice, this 12 | * list of conditions and the following disclaimer. 13 | * 14 | * 2. Redistributions in binary form must reproduce the above copyright notice, 15 | * this list of conditions and the following disclaimer in the documentation 16 | * and/or other materials provided with the distribution. 17 | * 18 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 19 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 20 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 21 | * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 22 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 23 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 24 | * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 25 | * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 26 | * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 27 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 | ***** END LICENSE BLOCK *****/ 29 | 30 | package org.jruby.ext.digest; 31 | 32 | import java.io.IOException; 33 | import org.jruby.Ruby; 34 | import org.jruby.runtime.load.Library; 35 | 36 | public class SHA2 implements Library { 37 | 38 | public void load(final Ruby runtime, boolean wrap) throws IOException { 39 | org.jruby.ext.digest.RubyDigest.createDigestSHA2(runtime); 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /ext/java/org/jruby/ext/digest/lib/digest/bubblebabble.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | JRuby::Util.load_ext("org.jruby.ext.digest.BubbleBabble") 4 | -------------------------------------------------------------------------------- /ext/java/org/jruby/ext/digest/lib/digest/loader.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | JRuby::Util.load_ext('org.jruby.ext.digest.DigestLibrary') 4 | -------------------------------------------------------------------------------- /ext/java/org/jruby/ext/digest/lib/digest/md5.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | JRuby::Util.load_ext("org.jruby.ext.digest.MD5") 4 | -------------------------------------------------------------------------------- /ext/java/org/jruby/ext/digest/lib/digest/rmd160.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | JRuby::Util.load_ext("org.jruby.ext.digest.RMD160") 4 | -------------------------------------------------------------------------------- /ext/java/org/jruby/ext/digest/lib/digest/sha1.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | JRuby::Util.load_ext("org.jruby.ext.digest.SHA1") 4 | -------------------------------------------------------------------------------- /ext/java/org/jruby/ext/digest/lib/digest/sha2/loader.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | JRuby::Util.load_ext('org.jruby.ext.digest.SHA2') 4 | -------------------------------------------------------------------------------- /lib/digest.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: false 2 | 3 | if defined?(Digest) && 4 | /\A(?:2\.|3\.0\.[0-2]\z)/.match?(RUBY_VERSION) && 5 | caller_locations.any? { |l| 6 | %r{/(rubygems/gem_runner|bundler/cli)\.rb}.match?(l.path) 7 | } 8 | # Before Ruby 3.0.3/3.1.0, the gem and bundle commands used to load 9 | # the digest library before loading additionally installed gems, so 10 | # you will get constant redefinition warnings and unexpected 11 | # implementation overwriting if we proceed here. Avoid that. 12 | return 13 | end 14 | 15 | require 'digest/version' 16 | require 'digest/loader' 17 | 18 | module Digest 19 | # A mutex for Digest(). 20 | REQUIRE_MUTEX = Thread::Mutex.new 21 | 22 | def self.const_missing(name) # :nodoc: 23 | case name 24 | when :SHA256, :SHA384, :SHA512 25 | lib = 'digest/sha2' 26 | else 27 | lib = File.join('digest', name.to_s.downcase) 28 | end 29 | 30 | begin 31 | require lib 32 | rescue LoadError 33 | raise LoadError, "library not found for class Digest::#{name} -- #{lib}", caller(1) 34 | end 35 | unless Digest.const_defined?(name) 36 | raise NameError, "uninitialized constant Digest::#{name}", caller(1) 37 | end 38 | Digest.const_get(name) 39 | end 40 | 41 | class ::Digest::Class 42 | # Creates a digest object and reads a given file, _name_. 43 | # Optional arguments are passed to the constructor of the digest 44 | # class. 45 | # 46 | # p Digest::SHA256.file("X11R6.8.2-src.tar.bz2").hexdigest 47 | # # => "f02e3c85572dc9ad7cb77c2a638e3be24cc1b5bea9fdbb0b0299c9668475c534" 48 | def self.file(name, *args) 49 | new(*args).file(name) 50 | end 51 | 52 | # Returns the base64 encoded hash value of a given _string_. The 53 | # return value is properly padded with '=' and contains no line 54 | # feeds. 55 | def self.base64digest(str, *args) 56 | [digest(str, *args)].pack('m0') 57 | end 58 | end 59 | 60 | module Instance 61 | # Updates the digest with the contents of a given file _name_ and 62 | # returns self. 63 | def file(name) 64 | File.open(name, "rb") {|f| 65 | buf = "" 66 | while f.read(16384, buf) 67 | update buf 68 | end 69 | } 70 | self 71 | end 72 | 73 | # If none is given, returns the resulting hash value of the digest 74 | # in a base64 encoded form, keeping the digest's state. 75 | # 76 | # If a +string+ is given, returns the hash value for the given 77 | # +string+ in a base64 encoded form, resetting the digest to the 78 | # initial state before and after the process. 79 | # 80 | # In either case, the return value is properly padded with '=' and 81 | # contains no line feeds. 82 | def base64digest(str = nil) 83 | [str ? digest(str) : digest].pack('m0') 84 | end 85 | 86 | # Returns the resulting hash value and resets the digest to the 87 | # initial state. 88 | def base64digest! 89 | [digest!].pack('m0') 90 | end 91 | end 92 | end 93 | 94 | # call-seq: 95 | # Digest(name) -> digest_subclass 96 | # 97 | # Returns a Digest subclass by +name+ in a thread-safe manner even 98 | # when on-demand loading is involved. 99 | # 100 | # require 'digest' 101 | # 102 | # Digest("MD5") 103 | # # => Digest::MD5 104 | # 105 | # Digest(:SHA256) 106 | # # => Digest::SHA256 107 | # 108 | # Digest(:Foo) 109 | # # => LoadError: library not found for class Digest::Foo -- digest/foo 110 | def Digest(name) 111 | const = name.to_sym 112 | Digest::REQUIRE_MUTEX.synchronize { 113 | # Ignore autoload's because it is void when we have #const_missing 114 | Digest.const_missing(const) 115 | } 116 | rescue LoadError 117 | # Constants do not necessarily rely on digest/*. 118 | if Digest.const_defined?(const) 119 | Digest.const_get(const) 120 | else 121 | raise 122 | end 123 | end 124 | -------------------------------------------------------------------------------- /lib/digest/sha2.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: false 2 | #-- 3 | # sha2.rb - defines Digest::SHA2 class which wraps up the SHA256, 4 | # SHA384, and SHA512 classes. 5 | #++ 6 | # Copyright (c) 2006 Akinori MUSHA 7 | # 8 | # All rights reserved. You can redistribute and/or modify it under the same 9 | # terms as Ruby. 10 | # 11 | # $Id$ 12 | 13 | require 'digest' 14 | require 'digest/sha2/loader' 15 | 16 | module Digest 17 | # 18 | # A meta digest provider class for SHA256, SHA384 and SHA512. 19 | # 20 | # FIPS 180-2 describes SHA2 family of digest algorithms. It defines 21 | # three algorithms: 22 | # * one which works on chunks of 512 bits and returns a 256-bit 23 | # digest (SHA256), 24 | # * one which works on chunks of 1024 bits and returns a 384-bit 25 | # digest (SHA384), 26 | # * and one which works on chunks of 1024 bits and returns a 512-bit 27 | # digest (SHA512). 28 | # 29 | # ==Examples 30 | # require 'digest' 31 | # 32 | # # Compute a complete digest 33 | # Digest::SHA2.hexdigest 'abc' # => "ba7816bf8..." 34 | # Digest::SHA2.new(256).hexdigest 'abc' # => "ba7816bf8..." 35 | # Digest::SHA256.hexdigest 'abc' # => "ba7816bf8..." 36 | # 37 | # Digest::SHA2.new(384).hexdigest 'abc' # => "cb00753f4..." 38 | # Digest::SHA384.hexdigest 'abc' # => "cb00753f4..." 39 | # 40 | # Digest::SHA2.new(512).hexdigest 'abc' # => "ddaf35a19..." 41 | # Digest::SHA512.hexdigest 'abc' # => "ddaf35a19..." 42 | # 43 | # # Compute digest by chunks 44 | # sha2 = Digest::SHA2.new # =># 45 | # sha2.update "ab" 46 | # sha2 << "c" # alias for #update 47 | # sha2.hexdigest # => "ba7816bf8..." 48 | # 49 | # # Use the same object to compute another digest 50 | # sha2.reset 51 | # sha2 << "message" 52 | # sha2.hexdigest # => "ab530a13e..." 53 | # 54 | class SHA2 < Digest::Class 55 | # call-seq: 56 | # Digest::SHA2.new(bitlen = 256) -> digest_obj 57 | # 58 | # Create a new SHA2 hash object with a given bit length. 59 | # 60 | # Valid bit lengths are 256, 384 and 512. 61 | def initialize(bitlen = 256) 62 | case bitlen 63 | when 256 64 | @sha2 = Digest::SHA256.new 65 | when 384 66 | @sha2 = Digest::SHA384.new 67 | when 512 68 | @sha2 = Digest::SHA512.new 69 | else 70 | raise ArgumentError, "unsupported bit length: %s" % bitlen.inspect 71 | end 72 | @bitlen = bitlen 73 | end 74 | 75 | # call-seq: 76 | # digest_obj.reset -> digest_obj 77 | # 78 | # Reset the digest to the initial state and return self. 79 | def reset 80 | @sha2.reset 81 | self 82 | end 83 | 84 | # call-seq: 85 | # digest_obj.update(string) -> digest_obj 86 | # digest_obj << string -> digest_obj 87 | # 88 | # Update the digest using a given _string_ and return self. 89 | def update(str) 90 | @sha2.update(str) 91 | self 92 | end 93 | alias << update 94 | 95 | def finish # :nodoc: 96 | @sha2.digest! 97 | end 98 | private :finish 99 | 100 | 101 | # call-seq: 102 | # digest_obj.block_length -> Integer 103 | # 104 | # Return the block length of the digest in bytes. 105 | # 106 | # Digest::SHA256.new.block_length * 8 107 | # # => 512 108 | # Digest::SHA384.new.block_length * 8 109 | # # => 1024 110 | # Digest::SHA512.new.block_length * 8 111 | # # => 1024 112 | def block_length 113 | @sha2.block_length 114 | end 115 | 116 | # call-seq: 117 | # digest_obj.digest_length -> Integer 118 | # 119 | # Return the length of the hash value (the digest) in bytes. 120 | # 121 | # Digest::SHA256.new.digest_length * 8 122 | # # => 256 123 | # Digest::SHA384.new.digest_length * 8 124 | # # => 384 125 | # Digest::SHA512.new.digest_length * 8 126 | # # => 512 127 | # 128 | # For example, digests produced by Digest::SHA256 will always be 32 bytes 129 | # (256 bits) in size. 130 | def digest_length 131 | @sha2.digest_length 132 | end 133 | 134 | def initialize_copy(other) # :nodoc: 135 | @sha2 = other.instance_eval { @sha2.clone } 136 | end 137 | 138 | def inspect # :nodoc: 139 | "#<%s:%d %s>" % [self.class.name, @bitlen, hexdigest] 140 | end 141 | end 142 | end 143 | -------------------------------------------------------------------------------- /lib/digest/version.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | module Digest 4 | VERSION = "3.2.0" 5 | end 6 | -------------------------------------------------------------------------------- /rakelib/epoch.rake: -------------------------------------------------------------------------------- 1 | task "build" => "date_epoch" 2 | 3 | task "date_epoch" do 4 | ENV["SOURCE_DATE_EPOCH"] = IO.popen(%W[git -C #{__dir__} log -1 --format=%ct], &:read).chomp 5 | end 6 | -------------------------------------------------------------------------------- /test/digest/digest/foo.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: false 2 | module Digest 3 | Foo = nil 4 | 5 | sleep 0.2 6 | 7 | remove_const(:Foo) 8 | 9 | class Foo < Class 10 | end 11 | end 12 | -------------------------------------------------------------------------------- /test/digest/test_digest.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: false 2 | # $RoughId: test.rb,v 1.4 2001/07/13 15:38:27 knu Exp $ 3 | # $Id$ 4 | 5 | require 'test/unit' 6 | require 'tempfile' 7 | 8 | require 'digest' 9 | %w[digest/md5 digest/rmd160 digest/sha1 digest/sha2 digest/bubblebabble].each do |lib| 10 | begin 11 | require lib 12 | rescue LoadError 13 | end 14 | end 15 | 16 | module TestDigest 17 | Data1 = "abc" 18 | Data2 = "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq" 19 | 20 | def test_s_new 21 | self.class::DATA.each do |str, hexdigest| 22 | assert_raise(ArgumentError) { self.class::ALGO.new("") } 23 | end 24 | end 25 | 26 | def test_s_hexdigest 27 | self.class::DATA.each do |str, hexdigest| 28 | actual = self.class::ALGO.hexdigest(str) 29 | assert_equal(hexdigest, actual) 30 | assert_equal(Encoding::US_ASCII, actual.encoding) 31 | end 32 | end 33 | 34 | def test_s_base64digest 35 | self.class::DATA.each do |str, hexdigest| 36 | digest = [hexdigest].pack("H*") 37 | actual = self.class::ALGO.base64digest(str) 38 | assert_equal([digest].pack("m0"), actual) 39 | assert_equal(Encoding::US_ASCII, actual.encoding) 40 | end 41 | end 42 | 43 | def test_s_digest 44 | self.class::DATA.each do |str, hexdigest| 45 | digest = [hexdigest].pack("H*") 46 | actual = self.class::ALGO.digest(str) 47 | assert_equal(digest, actual) 48 | assert_equal(Encoding::BINARY, actual.encoding) 49 | end 50 | end 51 | 52 | def test_update 53 | # This test is also for digest() and hexdigest() 54 | 55 | str = "ABC" 56 | 57 | md = self.class::ALGO.new 58 | md.update str 59 | assert_equal(self.class::ALGO.hexdigest(str), md.hexdigest) 60 | assert_equal(self.class::ALGO.digest(str), md.digest) 61 | end 62 | 63 | def test_eq 64 | # This test is also for clone() 65 | 66 | md1 = self.class::ALGO.new 67 | md1 << "ABC" 68 | 69 | assert_equal(md1, md1.clone, self.class::ALGO) 70 | 71 | bug9913 = '[ruby-core:62967] [Bug #9913]' 72 | assert_not_equal(md1, nil, bug9913) 73 | 74 | md2 = self.class::ALGO.new 75 | md2 << "A" 76 | 77 | assert_not_equal(md1, md2, self.class::ALGO) 78 | 79 | md2 << "BC" 80 | 81 | assert_equal(md1, md2, self.class::ALGO) 82 | end 83 | 84 | def test_s_file 85 | Tempfile.create("test_digest_file", mode: File::BINARY) { |tmpfile| 86 | str = "hello, world.\r\n" 87 | tmpfile.print str 88 | tmpfile.close 89 | 90 | assert_equal self.class::ALGO.new.update(str), self.class::ALGO.file(tmpfile.path) 91 | } 92 | end 93 | 94 | def test_instance_eval 95 | assert_nothing_raised { 96 | self.class::ALGO.new.instance_eval { update "a" } 97 | } 98 | end 99 | 100 | def test_alignment 101 | md = self.class::ALGO.new 102 | assert_nothing_raised('#4320') { 103 | md.update('a' * 97) 104 | md.update('a' * 97) 105 | md.hexdigest 106 | } 107 | end 108 | 109 | def test_bubblebabble 110 | expected = "xirek-hasol-fumik-lanax" 111 | assert_equal expected, Digest.bubblebabble('message') 112 | end 113 | 114 | def test_bubblebabble_class 115 | expected = "xopoh-fedac-fenyh-nehon-mopel-nivor-lumiz-rypon-gyfot-cosyz-rimez-lolyv-pekyz-rosud-ricob-surac-toxox" 116 | assert_equal expected, Digest::SHA256.bubblebabble('message') 117 | end 118 | 119 | def test_bubblebabble_instance 120 | expected = "xumor-boceg-dakuz-sulic-gukoz-rutas-mekek-zovud-gunap-vabov-genin-rygyg-sanun-hykac-ruvah-dovah-huxex" 121 | 122 | hash = Digest::SHA256.new 123 | assert_equal expected, hash.bubblebabble 124 | end 125 | 126 | class TestMD5 < Test::Unit::TestCase 127 | include TestDigest 128 | ALGO = Digest::MD5 129 | DATA = { 130 | Data1 => "900150983cd24fb0d6963f7d28e17f72", 131 | Data2 => "8215ef0796a20bcaaae116d3876c664a", 132 | } 133 | end if defined?(Digest::MD5) 134 | 135 | class TestSHA1 < Test::Unit::TestCase 136 | include TestDigest 137 | ALGO = Digest::SHA1 138 | DATA = { 139 | Data1 => "a9993e364706816aba3e25717850c26c9cd0d89d", 140 | Data2 => "84983e441c3bd26ebaae4aa1f95129e5e54670f1", 141 | } 142 | end if defined?(Digest::SHA1) 143 | 144 | class TestSHA256 < Test::Unit::TestCase 145 | include TestDigest 146 | ALGO = Digest::SHA256 147 | DATA = { 148 | Data1 => "ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad", 149 | Data2 => "248d6a61d20638b8e5c026930c3e6039a33ce45964ff2167f6ecedd419db06c1", 150 | } 151 | end if defined?(Digest::SHA256) 152 | 153 | class TestSHA384 < Test::Unit::TestCase 154 | include TestDigest 155 | ALGO = Digest::SHA384 156 | DATA = { 157 | Data1 => "cb00753f45a35e8bb5a03d699ac65007272c32ab0eded1631a8b605a43ff5bed"\ 158 | "8086072ba1e7cc2358baeca134c825a7", 159 | Data2 => "3391fdddfc8dc7393707a65b1b4709397cf8b1d162af05abfe8f450de5f36bc6"\ 160 | "b0455a8520bc4e6f5fe95b1fe3c8452b", 161 | } 162 | end if defined?(Digest::SHA384) 163 | 164 | class TestSHA512 < Test::Unit::TestCase 165 | include TestDigest 166 | ALGO = Digest::SHA512 167 | DATA = { 168 | Data1 => "ddaf35a193617abacc417349ae20413112e6fa4e89a97ea20a9eeee64b55d39a"\ 169 | "2192992a274fc1a836ba3c23a3feebbd454d4423643ce80e2a9ac94fa54ca49f", 170 | Data2 => "204a8fc6dda82f0a0ced7beb8e08a41657c16ef468b228a8279be331a703c335"\ 171 | "96fd15c13b1b07f9aa1d3bea57789ca031ad85c7a71dd70354ec631238ca3445", 172 | } 173 | end if defined?(Digest::SHA512) 174 | 175 | class TestSHA2 < Test::Unit::TestCase 176 | 177 | def test_s_file 178 | Tempfile.create("test_digest_file") { |tmpfile| 179 | str = Data1 180 | tmpfile.print str 181 | tmpfile.close 182 | 183 | assert_equal "cb00753f45a35e8bb5a03d699ac65007272c32ab0eded1631a8b605a43ff5bed"\ 184 | "8086072ba1e7cc2358baeca134c825a7", 185 | Digest::SHA2.file(tmpfile.path, 384).hexdigest 186 | } 187 | end 188 | 189 | end if defined?(Digest::SHA2) 190 | 191 | class TestRMD160 < Test::Unit::TestCase 192 | include TestDigest 193 | ALGO = Digest::RMD160 194 | DATA = { 195 | Data1 => "8eb208f7e05d987a9b044a8e98c6b087f15a0bfc", 196 | Data2 => "12a053384a9c0c88e405a06c27dcf49ada62eb2b", 197 | } 198 | end if defined?(Digest::RMD160) 199 | 200 | class TestBase < Test::Unit::TestCase 201 | def test_base 202 | bug3810 = '[ruby-core:32231]' 203 | assert_raise(NotImplementedError, bug3810) {Digest::Base.new} 204 | end 205 | end 206 | 207 | class TestInitCopy < Test::Unit::TestCase 208 | if defined?(Digest::MD5) and defined?(Digest::RMD160) 209 | def test_initialize_copy_md5_rmd160 210 | assert_separately(%w[-rdigest], <<-'end;') 211 | md5 = Digest::MD5.allocate 212 | rmd160 = Digest::RMD160.allocate 213 | assert_raise(TypeError) {md5.__send__(:initialize_copy, rmd160)} 214 | end; 215 | end 216 | end 217 | end 218 | 219 | class TestDigestParen < Test::Unit::TestCase 220 | def test_sha2 221 | assert_separately(%w[-rdigest], <<-'end;') 222 | assert_nothing_raised { 223 | Digest(:SHA256).new 224 | Digest(:SHA384).new 225 | Digest(:SHA512).new 226 | } 227 | end; 228 | end 229 | 230 | def test_no_lib 231 | assert_separately(%w[-rdigest], <<-'end;') 232 | class Digest::Nolib < Digest::Class 233 | end 234 | 235 | assert_nothing_raised { 236 | Digest(:Nolib).new 237 | } 238 | end; 239 | end 240 | 241 | def test_no_lib_no_def 242 | assert_separately(%w[-rdigest], <<-'end;') 243 | assert_raise(LoadError) { 244 | Digest(:Nodef).new 245 | } 246 | end; 247 | end 248 | 249 | def test_race 250 | assert_separately(['-rdigest', "-I#{File.dirname(__FILE__)}"], <<-"end;") 251 | assert_nothing_raised { 252 | t = Thread.start { 253 | sleep #{ EnvUtil.apply_timeout_scale(0.1) } 254 | Digest(:Foo).new 255 | } 256 | Digest(:Foo).new 257 | t.join 258 | } 259 | end; 260 | end 261 | 262 | def test_race_mixed 263 | assert_separately(['-rdigest', "-I#{File.dirname(__FILE__)}"], <<-"end;") 264 | assert_nothing_raised { 265 | t = Thread.start { 266 | sleep #{ EnvUtil.apply_timeout_scale(0.1) } 267 | Thread.current.report_on_exception = false 268 | Digest::Foo.new 269 | } 270 | Digest(:Foo).new 271 | begin 272 | t.join 273 | rescue NoMethodError, NameError 274 | # NoMethodError is highly likely; NameError is listed just in case 275 | end 276 | } 277 | end; 278 | end 279 | end 280 | end 281 | -------------------------------------------------------------------------------- /test/digest/test_digest_extend.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: false 2 | require 'test/unit' 3 | require 'digest' 4 | require_relative '../lib/with_different_ofs' 5 | 6 | class TestDigestExtend < Test::Unit::TestCase 7 | extend DifferentOFS 8 | 9 | TEST_DIGEST = %w[SHA1024 SHA512 SHA384 SHA256 SHA1].find do |n| 10 | break Digest.const_get(n) 11 | rescue LoadError 12 | end 13 | 14 | class MyDigest < Digest::Class 15 | def initialize(*arg) 16 | super 17 | @buf = [] 18 | end 19 | 20 | def initialize_copy(org) 21 | @buf = org.buf.dup 22 | end 23 | 24 | def update(arg) 25 | @buf << arg 26 | self 27 | end 28 | 29 | alias << update 30 | 31 | def finish 32 | (@buf.join('').length % 256).chr 33 | end 34 | 35 | def reset 36 | @buf.clear 37 | self 38 | end 39 | 40 | protected 41 | 42 | def buf 43 | @buf 44 | end 45 | end 46 | 47 | def setup 48 | @MyDigest = Class.new(MyDigest) 49 | end 50 | 51 | def test_digest_s_hexencode 52 | assert_equal('', Digest.hexencode('')) 53 | assert_equal('0102', Digest.hexencode("\1\2")) 54 | assert_equal( 55 | (0..0xff).to_a.map { |c| sprintf("%02x", c ) }.join(''), 56 | Digest.hexencode((0..0xff).to_a.map { |c| c.chr }.join('')) 57 | ) 58 | assert_equal(Encoding::US_ASCII, Digest.hexencode("\1\2").encoding) 59 | end 60 | 61 | def test_class_reset 62 | a = TEST_DIGEST.new 63 | base = a.to_s 64 | assert_equal(base, a.reset.to_s) 65 | b = a.new 66 | assert_equal(base, b.to_s) 67 | b.update('1') 68 | assert_not_equal(base, b.to_s) 69 | assert_equal(base, b.reset.to_s) 70 | end if TEST_DIGEST 71 | 72 | def test_digest 73 | assert_equal("\3", MyDigest.digest("foo")) 74 | end 75 | 76 | def test_hexdigest 77 | assert_equal("03", @MyDigest.hexdigest("foo")) 78 | end 79 | 80 | def test_context 81 | digester = @MyDigest.new 82 | digester.update("foo") 83 | assert_equal("\3", digester.digest) 84 | digester.update("foobar") 85 | assert_equal("\t", digester.digest) 86 | digester.update("foo") 87 | assert_equal("\f", digester.digest) 88 | end 89 | 90 | def test_new 91 | a = TEST_DIGEST.new 92 | b = a.new 93 | obj = a.to_s 94 | assert_equal(obj, a.to_s) 95 | assert_equal(obj, b.to_s) 96 | a.update('1') 97 | assert_not_equal(obj, a.to_s) 98 | assert_equal(obj, b.to_s) 99 | end if TEST_DIGEST 100 | 101 | def test_digest_hexdigest 102 | [:digest, :hexdigest].each do |m| 103 | exp_1st = "\3"; exp_1st = Digest.hexencode(exp_1st) if m == :hexdigest 104 | exp_2nd = "\6"; exp_2nd = Digest.hexencode(exp_2nd) if m == :hexdigest 105 | digester = @MyDigest.new 106 | digester.update("foo") 107 | obj = digester.send(m) 108 | # digest w/o param does not reset the org digester. 109 | assert_equal(exp_1st, obj) 110 | digester.update("bar") 111 | obj = digester.send(m) 112 | assert_equal(exp_2nd, obj) 113 | obj = digester.send(m, "baz") 114 | # digest with param resets the org digester. 115 | assert_equal(exp_1st, obj) 116 | end 117 | end 118 | 119 | def test_digest_hexdigest_bang 120 | [:digest!, :hexdigest!].each do |m| 121 | exp_1st = "\3"; exp_1st = Digest.hexencode(exp_1st) if m == :hexdigest! 122 | digester = @MyDigest.new 123 | digester.update("foo") 124 | obj = digester.send(m) # digest! always resets the org digester. 125 | assert_equal(exp_1st, obj) 126 | digester.update("bar") 127 | obj = digester.send(m) 128 | assert_equal(exp_1st, obj) 129 | end 130 | end 131 | 132 | def test_to_s 133 | digester = @MyDigest.new 134 | digester.update("foo") 135 | assert_equal("03", digester.to_s) 136 | end 137 | 138 | def test_length 139 | @MyDigest.class_eval do 140 | def digest_length 141 | 2 142 | end 143 | end 144 | digester = @MyDigest.new 145 | assert_equal(2, digester.length) 146 | assert_equal(2, digester.size) 147 | end 148 | 149 | def test_digest_length # breaks @MyDigest#digest_length 150 | assert_equal(1, @MyDigest.new.digest_length) 151 | @MyDigest.class_eval do 152 | def digest_length 153 | 2 154 | end 155 | end 156 | assert_equal(2, @MyDigest.new.digest_length) 157 | end 158 | 159 | def test_block_length 160 | assert_raise(RuntimeError) do 161 | @MyDigest.new.block_length 162 | end 163 | end 164 | end 165 | -------------------------------------------------------------------------------- /test/digest/test_ractor.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | require 'test/unit' 3 | 4 | require 'digest' 5 | %w[digest/md5 digest/rmd160 digest/sha1 digest/sha2 digest/bubblebabble].each do |lib| 6 | begin 7 | require lib 8 | rescue LoadError 9 | end 10 | end 11 | 12 | module TestDigestRactor 13 | Data1 = "abc" 14 | Data2 = "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq" 15 | 16 | def test_s_hexdigest 17 | assert_in_out_err([], <<-"end;", ["true", "true"], []) 18 | class Ractor 19 | alias value take 20 | end unless Ractor.method_defined? :value # compat with Ruby 3.4 and olders 21 | 22 | $VERBOSE = nil 23 | require "digest" 24 | require "#{self.class::LIB}" 25 | DATA = #{self.class::DATA.inspect} 26 | rs = DATA.map do |str, hexdigest| 27 | r = Ractor.new str do |x| 28 | #{self.class::ALGO}.hexdigest(x) 29 | end 30 | [r, hexdigest] 31 | end 32 | rs.each do |r, hexdigest| 33 | puts r.value == hexdigest 34 | end 35 | end; 36 | end 37 | 38 | class TestMD5Ractor < Test::Unit::TestCase 39 | include TestDigestRactor 40 | LIB = "digest/md5" 41 | ALGO = Digest::MD5 42 | DATA = { 43 | Data1 => "900150983cd24fb0d6963f7d28e17f72", 44 | Data2 => "8215ef0796a20bcaaae116d3876c664a", 45 | } 46 | end if defined?(Digest::MD5) 47 | 48 | class TestSHA1Ractor < Test::Unit::TestCase 49 | include TestDigestRactor 50 | LIB = "digest/sha1" 51 | ALGO = Digest::SHA1 52 | DATA = { 53 | Data1 => "a9993e364706816aba3e25717850c26c9cd0d89d", 54 | Data2 => "84983e441c3bd26ebaae4aa1f95129e5e54670f1", 55 | } 56 | end if defined?(Digest::SHA1) 57 | 58 | class TestSHA256Ractor < Test::Unit::TestCase 59 | include TestDigestRactor 60 | LIB = "digest/sha2" 61 | ALGO = Digest::SHA256 62 | DATA = { 63 | Data1 => "ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad", 64 | Data2 => "248d6a61d20638b8e5c026930c3e6039a33ce45964ff2167f6ecedd419db06c1", 65 | } 66 | end if defined?(Digest::SHA256) 67 | 68 | class TestSHA384Ractor < Test::Unit::TestCase 69 | include TestDigestRactor 70 | LIB = "digest/sha2" 71 | ALGO = Digest::SHA384 72 | DATA = { 73 | Data1 => "cb00753f45a35e8bb5a03d699ac65007272c32ab0eded1631a8b605a43ff5bed"\ 74 | "8086072ba1e7cc2358baeca134c825a7", 75 | Data2 => "3391fdddfc8dc7393707a65b1b4709397cf8b1d162af05abfe8f450de5f36bc6"\ 76 | "b0455a8520bc4e6f5fe95b1fe3c8452b", 77 | } 78 | end if defined?(Digest::SHA384) 79 | 80 | class TestSHA512Ractor < Test::Unit::TestCase 81 | include TestDigestRactor 82 | LIB = "digest/sha2" 83 | ALGO = Digest::SHA512 84 | DATA = { 85 | Data1 => "ddaf35a193617abacc417349ae20413112e6fa4e89a97ea20a9eeee64b55d39a"\ 86 | "2192992a274fc1a836ba3c23a3feebbd454d4423643ce80e2a9ac94fa54ca49f", 87 | Data2 => "204a8fc6dda82f0a0ced7beb8e08a41657c16ef468b228a8279be331a703c335"\ 88 | "96fd15c13b1b07f9aa1d3bea57789ca031ad85c7a71dd70354ec631238ca3445", 89 | } 90 | end if defined?(Digest::SHA512) 91 | 92 | class TestRMD160Ractor < Test::Unit::TestCase 93 | include TestDigestRactor 94 | LIB = "digest/rmd160" 95 | ALGO = Digest::RMD160 96 | DATA = { 97 | Data1 => "8eb208f7e05d987a9b044a8e98c6b087f15a0bfc", 98 | Data2 => "12a053384a9c0c88e405a06c27dcf49ada62eb2b", 99 | } 100 | end if defined?(Digest::RMD160) 101 | end if defined?(Ractor) 102 | -------------------------------------------------------------------------------- /test/lib/helper.rb: -------------------------------------------------------------------------------- 1 | require "test/unit" 2 | require "core_assertions" 3 | 4 | Test::Unit::TestCase.include Test::Unit::CoreAssertions 5 | -------------------------------------------------------------------------------- /test/lib/with_different_ofs.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | module DifferentOFS 3 | module WithDifferentOFS 4 | def setup 5 | super 6 | verbose, $VERBOSE = $VERBOSE, nil 7 | @ofs, $, = $,, "-" 8 | $VERBOSE = verbose 9 | end 10 | def teardown 11 | verbose, $VERBOSE = $VERBOSE, nil 12 | $, = @ofs 13 | $VERBOSE = verbose 14 | super 15 | end 16 | end 17 | 18 | def self.extended(klass) 19 | super(klass) 20 | c = klass.const_set(:DifferentOFS, Class.new(klass).class_eval {include WithDifferentOFS}) 21 | c.is_a?(Array) ? c[0].name : c.name 22 | end 23 | end 24 | --------------------------------------------------------------------------------