From bb0c1da8c977734642585c73ade132f5a30d09e1 Mon Sep 17 00:00:00 2001 From: Brandon Fish Date: Tue, 31 Mar 2020 10:42:50 -0500 Subject: [PATCH 01/66] Add TruffleRuby to CI --- .travis.yml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.travis.yml b/.travis.yml index 94e234e..1cecdb2 100644 --- a/.travis.yml +++ b/.travis.yml @@ -14,10 +14,14 @@ rvm: - ruby-head - jruby-head - rbx-3 + - truffleruby + - truffleruby-head matrix: allow_failures: - rvm: ruby-head - rvm: jruby-head - rvm: rbx-3 + - rvm: truffleruby + - rvm: truffleruby-head fast_finish: true script: bundle exec rake From 919d58472b63f276eb2c63797d784cb27f0191e2 Mon Sep 17 00:00:00 2001 From: Brandon Fish Date: Tue, 14 Apr 2020 11:48:55 -0500 Subject: [PATCH 02/66] Calculate minimum calibration time variably --- spec/bcrypt/engine_spec.rb | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/spec/bcrypt/engine_spec.rb b/spec/bcrypt/engine_spec.rb index 90a681e..7c6d6f3 100644 --- a/spec/bcrypt/engine_spec.rb +++ b/spec/bcrypt/engine_spec.rb @@ -12,8 +12,11 @@ describe "The BCrypt engine" do specify "should calculate the optimal cost factor to fit in a specific time" do - first = BCrypt::Engine.calibrate(100) - second = BCrypt::Engine.calibrate(400) + start_time = Time.now + BCrypt::Password.create("testing testing", :cost => BCrypt::Engine::MIN_COST + 1) + min_time_ms = (Time.now - start_time) * 1000 + first = BCrypt::Engine.calibrate(min_time_ms) + second = BCrypt::Engine.calibrate(min_time_ms * 2) expect(second).to be > first end end From 5fba8e4ef4151ba2763da395ef2f58838c127bba Mon Sep 17 00:00:00 2001 From: Michael McCarthy Date: Tue, 29 Sep 2020 22:26:37 -0400 Subject: [PATCH 03/66] additional changelog comment --- CHANGELOG | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG b/CHANGELOG index 6c2b465..dd7ba1c 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -16,7 +16,7 @@ 3.1.12 May 16 2018 - Add support for Ruby 2.3, 2.4, and 2.5 in compiled Windows binaries - - Fix compatibility with libxcrypt [GH #164 by @besser82] + - Fix compatibility with libxcrypt - Fixes hash errors in Fedora 28 and Ubuntu 20 [GH #164 by @besser82] 3.1.11 Mar 06 2016 - Add support for Ruby 2.2 in compiled Windows binaries From fc652e5248a4132af2c5f5c0b61eeceff02f4316 Mon Sep 17 00:00:00 2001 From: "T.J. Schuck" Date: Mon, 5 Oct 2020 12:34:29 -0400 Subject: [PATCH 04/66] Make min time difference still x4 https://github.com/codahale/bcrypt-ruby/pull/223/files updated this test and also made the time diff x2 instead of x4. This made it start failing on Windows. Bump back to x4. --- spec/bcrypt/engine_spec.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spec/bcrypt/engine_spec.rb b/spec/bcrypt/engine_spec.rb index 7c6d6f3..ad9a7e8 100644 --- a/spec/bcrypt/engine_spec.rb +++ b/spec/bcrypt/engine_spec.rb @@ -16,7 +16,7 @@ BCrypt::Password.create("testing testing", :cost => BCrypt::Engine::MIN_COST + 1) min_time_ms = (Time.now - start_time) * 1000 first = BCrypt::Engine.calibrate(min_time_ms) - second = BCrypt::Engine.calibrate(min_time_ms * 2) + second = BCrypt::Engine.calibrate(min_time_ms * 4) expect(second).to be > first end end From ac8fd5ef14364ddac1fe9257229b7e2ac6d23f3d Mon Sep 17 00:00:00 2001 From: timcraft Date: Wed, 6 Jan 2021 14:42:10 +0000 Subject: [PATCH 05/66] Test on ruby 3.0 --- .travis.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.travis.yml b/.travis.yml index 9842f8d..5cb4461 100644 --- a/.travis.yml +++ b/.travis.yml @@ -10,6 +10,7 @@ rvm: - 2.5 - 2.6 - 2.7 + - 3.0 - ruby-head - jruby-head - rbx-3 From 770faeaa884cb0e4dd3a34f82c25f62a980ae8fe Mon Sep 17 00:00:00 2001 From: shmokmt <32533860+shmokmt@users.noreply.github.com> Date: Fri, 12 Feb 2021 18:03:04 +0900 Subject: [PATCH 06/66] Update version --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 9bbc739..fff49a3 100644 --- a/README.md +++ b/README.md @@ -32,8 +32,8 @@ re-hash those passwords. This vulnerability only affected the JRuby gem. The bcrypt gem is available on the following Ruby platforms: * JRuby -* RubyInstaller 2.0 – 2.5 builds on Windows with the DevKit -* Any 2.0 – 2.5 Ruby on a BSD/OS X/Linux system with a compiler +* RubyInstaller 2.0 – 3.0 builds on Windows with the DevKit +* Any 2.0 – 3.0 Ruby on a BSD/OS X/Linux system with a compiler ## How to use `bcrypt()` in your Rails application From beb3e2938af1fd6609d2098207f1046b21ebc97e Mon Sep 17 00:00:00 2001 From: Kenichi Kamiya Date: Tue, 2 Mar 2021 15:42:54 +0900 Subject: [PATCH 07/66] Ignore Gemfile.lock in git --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index 3c40c7f..633ad7c 100644 --- a/.gitignore +++ b/.gitignore @@ -7,3 +7,4 @@ tmp *.jar .DS_Store .rbenv-gemsets +Gemfile.lock From acd74603685c351b5135742c875963727ed51576 Mon Sep 17 00:00:00 2001 From: Kenichi Kamiya Date: Sat, 26 Sep 2015 01:41:41 +0900 Subject: [PATCH 08/66] Fix a regex in Bcrypt::Password.valid_hash? and Bcrypt::Engine.valid_salt? --- lib/bcrypt/engine.rb | 2 +- lib/bcrypt/password.rb | 2 +- spec/bcrypt/password_spec.rb | 2 ++ 3 files changed, 4 insertions(+), 2 deletions(-) diff --git a/lib/bcrypt/engine.rb b/lib/bcrypt/engine.rb index 2204843..ca57da0 100644 --- a/lib/bcrypt/engine.rb +++ b/lib/bcrypt/engine.rb @@ -80,7 +80,7 @@ def self.generate_salt(cost = self.cost) # Returns true if +salt+ is a valid bcrypt() salt, false if not. def self.valid_salt?(salt) - !!(salt =~ /^\$[0-9a-z]{2,}\$[0-9]{2,}\$[A-Za-z0-9\.\/]{22,}$/) + !!(salt =~ /\A\$[0-9a-z]{2,}\$[0-9]{2,}\$[A-Za-z0-9\.\/]{22,}\z/) end # Returns true if +secret+ is a valid bcrypt() secret, false if not. diff --git a/lib/bcrypt/password.rb b/lib/bcrypt/password.rb index 554967c..94bccb2 100644 --- a/lib/bcrypt/password.rb +++ b/lib/bcrypt/password.rb @@ -47,7 +47,7 @@ def create(secret, options = {}) end def valid_hash?(h) - /^\$[0-9a-z]{2}\$[0-9]{2}\$[A-Za-z0-9\.\/]{53}$/ === h + /\A\$[0-9a-z]{2}\$[0-9]{2}\$[A-Za-z0-9\.\/]{53}\z/ === h end end diff --git a/spec/bcrypt/password_spec.rb b/spec/bcrypt/password_spec.rb index f880f1c..a818a7b 100644 --- a/spec/bcrypt/password_spec.rb +++ b/spec/bcrypt/password_spec.rb @@ -108,6 +108,7 @@ describe "Validating a generated salt" do specify "should not accept an invalid salt" do expect(BCrypt::Engine.valid_salt?("invalid")).to eq(false) + expect(BCrypt::Engine.valid_salt?("invalid\n#{BCrypt::Engine.generate_salt}\ninvalid")).to eq(false) end specify "should accept a valid salt" do expect(BCrypt::Engine.valid_salt?(BCrypt::Engine.generate_salt)).to eq(true) @@ -117,6 +118,7 @@ describe "Validating a password hash" do specify "should not accept an invalid password" do expect(BCrypt::Password.valid_hash?("i_am_so_not_valid")).to be(false) + expect(BCrypt::Password.valid_hash?("invalid\n#{BCrypt::Password.create "i_am_so_valid"}\ninvalid")).to be(false) end specify "should accept a valid password" do expect(BCrypt::Password.valid_hash?(BCrypt::Password.create "i_am_so_valid")).to be(true) From 637a0dbb63d42c8a8c214959d17f38fd43ab2b1b Mon Sep 17 00:00:00 2001 From: Josh Cheek Date: Thu, 18 Mar 2021 11:18:14 -0500 Subject: [PATCH 09/66] Make the prefix less sus --- lib/bcrypt/engine.rb | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/lib/bcrypt/engine.rb b/lib/bcrypt/engine.rb index ca57da0..c2b78f8 100644 --- a/lib/bcrypt/engine.rb +++ b/lib/bcrypt/engine.rb @@ -70,8 +70,7 @@ def self.generate_salt(cost = self.cost) if RUBY_PLATFORM == "java" Java.bcrypt_jruby.BCrypt.gensalt(cost) else - prefix = "$2a$05$CCCCCCCCCCCCCCCCCCCCC.E5YPO9kmyuRGyh0XouQYb4YMJKvyOeW" - __bc_salt(prefix, cost, OpenSSL::Random.random_bytes(MAX_SALT_LENGTH)) + __bc_salt("$2a$", cost, OpenSSL::Random.random_bytes(MAX_SALT_LENGTH)) end else raise Errors::InvalidCost.new("cost must be numeric and > 0") From 34e59955f1e18d8c04e4d0ce15e75d2530e4bb66 Mon Sep 17 00:00:00 2001 From: Josh Buker Date: Mon, 29 Mar 2021 08:38:19 -0700 Subject: [PATCH 10/66] Document BCrypt::Password#== edge case/gotcha --- lib/bcrypt/password.rb | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/lib/bcrypt/password.rb b/lib/bcrypt/password.rb index 94bccb2..6902aba 100644 --- a/lib/bcrypt/password.rb +++ b/lib/bcrypt/password.rb @@ -62,6 +62,15 @@ def initialize(raw_hash) end # Compares a potential secret against the hash. Returns true if the secret is the original secret, false otherwise. + # + # Comparison edge case/gotcha: + # + # secret = "my secret" + # @password = BCrypt::Password.create(secret) + # + # @password == secret # => True + # @password == @password.to_s # => False + # @password.to_s == @password.to_s # => True def ==(secret) super(BCrypt::Engine.hash_secret(secret, @salt)) end From cf9bae41c926ab83e7aa6fa8669f9d0552727f78 Mon Sep 17 00:00:00 2001 From: Josh Buker Date: Mon, 29 Mar 2021 08:47:05 -0700 Subject: [PATCH 11/66] Document all possible permutations --- lib/bcrypt/password.rb | 2 ++ 1 file changed, 2 insertions(+) diff --git a/lib/bcrypt/password.rb b/lib/bcrypt/password.rb index 6902aba..1f902d2 100644 --- a/lib/bcrypt/password.rb +++ b/lib/bcrypt/password.rb @@ -69,7 +69,9 @@ def initialize(raw_hash) # @password = BCrypt::Password.create(secret) # # @password == secret # => True + # @password == @password # => False # @password == @password.to_s # => False + # @password.to_s == @password # => True # @password.to_s == @password.to_s # => True def ==(secret) super(BCrypt::Engine.hash_secret(secret, @salt)) From a0d528f12c41df121ab211f97885b397f42f2e40 Mon Sep 17 00:00:00 2001 From: "T.J. Schuck" Date: Mon, 29 Mar 2021 18:12:46 -0400 Subject: [PATCH 12/66] Some URL updates now that this has moved to an org --- README.md | 4 ++-- bcrypt.gemspec | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index fff49a3..6e2088b 100644 --- a/README.md +++ b/README.md @@ -2,9 +2,9 @@ An easy way to keep your users' passwords secure. -* https://github.com/codahale/bcrypt-ruby/tree/master +* https://github.com/bcrypt-ruby/bcrypt-ruby/tree/master -[![Travis Build Status](https://travis-ci.org/codahale/bcrypt-ruby.svg?branch=master)](https://travis-ci.org/codahale/bcrypt-ruby) +[![Travis Build Status](https://travis-ci.org/bcrypt-ruby/bcrypt-ruby.svg?branch=master)](https://travis-ci.org/bcrypt-ruby/bcrypt-ruby) [![AppVeyor Build Status](https://ci.appveyor.com/api/projects/status/6fplerx9lnaf0hyo?svg=true)](https://ci.appveyor.com/project/TJSchuck35975/bcrypt-ruby) diff --git a/bcrypt.gemspec b/bcrypt.gemspec index b32cd08..29ef18c 100644 --- a/bcrypt.gemspec +++ b/bcrypt.gemspec @@ -22,6 +22,6 @@ Gem::Specification.new do |s| s.authors = ["Coda Hale"] s.email = "coda.hale@gmail.com" - s.homepage = "https://github.com/codahale/bcrypt-ruby" + s.homepage = "https://github.com/bcrypt-ruby/bcrypt-ruby" s.license = "MIT" end From 2b4abfc130e90c1a8a6a05658ce6352efd140a95 Mon Sep 17 00:00:00 2001 From: Josh Buker Date: Tue, 6 Apr 2021 20:51:31 -0700 Subject: [PATCH 13/66] Add Github Action --- .github/workflows/ruby.yml | 47 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 47 insertions(+) create mode 100644 .github/workflows/ruby.yml diff --git a/.github/workflows/ruby.yml b/.github/workflows/ruby.yml new file mode 100644 index 0000000..1441a9a --- /dev/null +++ b/.github/workflows/ruby.yml @@ -0,0 +1,47 @@ +name: Test Suite + +# Run against all commits and pull requests. +on: [ push, pull_request ] + +jobs: + test_matrix: + + strategy: + fail-fast: false + matrix: + os: + - ubuntu-latest + - macos-latest + ruby: + - 2.1 + - 2.2 + - 2.3 + - 2.4 + - 2.5 + - 2.6 + - 2.7 + - 3.0 + - head + - jruby + - jruby-head + - truffleruby + - truffleruby-head + + runs-on: ${{ matrix.os }} + + steps: + - uses: actions/checkout@v2 + - name: Set up Ruby + uses: ruby/setup-ruby@v1.68.0 + with: + ruby-version: ${{ matrix.ruby }} + bundler-cache: true + - name: Run tests + run: bundle exec rake spec + + finish: + runs-on: ubuntu-latest + needs: [ test_matrix ] + steps: + - name: Wait for status checks + run: echo "All Green!" From 579b83021b8cfeda237781f44fc6ff7846424488 Mon Sep 17 00:00:00 2001 From: Josh Buker Date: Tue, 6 Apr 2021 20:57:20 -0700 Subject: [PATCH 14/66] Use default rake task --- .github/workflows/ruby.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ruby.yml b/.github/workflows/ruby.yml index 1441a9a..16bf217 100644 --- a/.github/workflows/ruby.yml +++ b/.github/workflows/ruby.yml @@ -37,7 +37,7 @@ jobs: ruby-version: ${{ matrix.ruby }} bundler-cache: true - name: Run tests - run: bundle exec rake spec + run: bundle exec rake finish: runs-on: ubuntu-latest From 5c08123c1e252205cc088e4c0782b043f677fe9c Mon Sep 17 00:00:00 2001 From: Josh Buker Date: Tue, 6 Apr 2021 21:12:11 -0700 Subject: [PATCH 15/66] Use latest setup-ruby and add mingw/mswin --- .github/workflows/ruby.yml | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/.github/workflows/ruby.yml b/.github/workflows/ruby.yml index 16bf217..569b480 100644 --- a/.github/workflows/ruby.yml +++ b/.github/workflows/ruby.yml @@ -10,8 +10,8 @@ jobs: fail-fast: false matrix: os: - - ubuntu-latest - - macos-latest + - ubuntu + - macos ruby: - 2.1 - 2.2 @@ -26,18 +26,20 @@ jobs: - jruby-head - truffleruby - truffleruby-head + - mingw + - mswin - runs-on: ${{ matrix.os }} + runs-on: ${{ matrix.os }}-latest steps: - uses: actions/checkout@v2 - name: Set up Ruby - uses: ruby/setup-ruby@v1.68.0 + uses: ruby/setup-ruby@v1 with: ruby-version: ${{ matrix.ruby }} bundler-cache: true - name: Run tests - run: bundle exec rake + run: bundle exec rake default finish: runs-on: ubuntu-latest From 9acc2ee6fc6cbea38d2b2860a9ff38be64d4951d Mon Sep 17 00:00:00 2001 From: Josh Buker Date: Tue, 6 Apr 2021 21:17:39 -0700 Subject: [PATCH 16/66] Add windows to github action and remove jruby from ubuntu matrix --- .github/workflows/ruby.yml | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/.github/workflows/ruby.yml b/.github/workflows/ruby.yml index 569b480..169a2e6 100644 --- a/.github/workflows/ruby.yml +++ b/.github/workflows/ruby.yml @@ -12,6 +12,7 @@ jobs: os: - ubuntu - macos + - windows ruby: - 2.1 - 2.2 @@ -28,6 +29,13 @@ jobs: - truffleruby-head - mingw - mswin + include: + - { os: windows, ruby: mingw } + - { os: windows, ruby: mswin } + # It appears Ubuntu doesn't support jruby + exclude: + - { os: ubuntu, ruby: jruby } + - { os: ubuntu, ruby: jruby-head } runs-on: ${{ matrix.os }}-latest From 242467320efcdad9a3ded982c7bfa39c2db1e376 Mon Sep 17 00:00:00 2001 From: Josh Buker Date: Tue, 6 Apr 2021 21:24:12 -0700 Subject: [PATCH 17/66] Fine tune exclusions --- .github/workflows/ruby.yml | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/.github/workflows/ruby.yml b/.github/workflows/ruby.yml index 169a2e6..1f64d22 100644 --- a/.github/workflows/ruby.yml +++ b/.github/workflows/ruby.yml @@ -29,13 +29,15 @@ jobs: - truffleruby-head - mingw - mswin - include: - - { os: windows, ruby: mingw } - - { os: windows, ruby: mswin } - # It appears Ubuntu doesn't support jruby exclude: - { os: ubuntu, ruby: jruby } - { os: ubuntu, ruby: jruby-head } + - { os: ubuntu, ruby: mingw } + - { os: ubuntu, ruby: mswin } + - { os: macos, ruby: mingw } + - { os: macos, ruby: mswin } + - { os: windows, ruby: truffleruby } + - { os: windows, ruby: truffleruby-head } runs-on: ${{ matrix.os }}-latest From 9ce55a00714d6c1517db1919e54e3fbf97f2f160 Mon Sep 17 00:00:00 2001 From: Josh Buker Date: Tue, 6 Apr 2021 21:54:33 -0700 Subject: [PATCH 18/66] Remove mswin and try using include instead of exclude for mingw --- .github/workflows/ruby.yml | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/.github/workflows/ruby.yml b/.github/workflows/ruby.yml index 1f64d22..f227058 100644 --- a/.github/workflows/ruby.yml +++ b/.github/workflows/ruby.yml @@ -28,14 +28,11 @@ jobs: - truffleruby - truffleruby-head - mingw - - mswin + include: + - { os: windows, ruby: mingw } exclude: - { os: ubuntu, ruby: jruby } - { os: ubuntu, ruby: jruby-head } - - { os: ubuntu, ruby: mingw } - - { os: ubuntu, ruby: mswin } - - { os: macos, ruby: mingw } - - { os: macos, ruby: mswin } - { os: windows, ruby: truffleruby } - { os: windows, ruby: truffleruby-head } From ebae2e36402aec015f66ea0b11fa9b3a64aeeb8b Mon Sep 17 00:00:00 2001 From: Josh Buker Date: Tue, 6 Apr 2021 21:56:06 -0700 Subject: [PATCH 19/66] Include doesn't work as expected --- .github/workflows/ruby.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/ruby.yml b/.github/workflows/ruby.yml index f227058..618ac97 100644 --- a/.github/workflows/ruby.yml +++ b/.github/workflows/ruby.yml @@ -28,11 +28,11 @@ jobs: - truffleruby - truffleruby-head - mingw - include: - - { os: windows, ruby: mingw } exclude: - - { os: ubuntu, ruby: jruby } - - { os: ubuntu, ruby: jruby-head } + - { os: ubuntu, ruby: jruby } + - { os: ubuntu, ruby: jruby-head } + - { os: ubuntu, ruby: mingw } + - { os: macos, ruby: mingw } - { os: windows, ruby: truffleruby } - { os: windows, ruby: truffleruby-head } From 96698e8c48c2fd903a654d8392c151895a51c489 Mon Sep 17 00:00:00 2001 From: Josh Buker Date: Wed, 28 Apr 2021 11:18:21 -0700 Subject: [PATCH 20/66] Minor whitespace fixes --- README.md | 1 - lib/bcrypt/password.rb | 1 - 2 files changed, 2 deletions(-) diff --git a/README.md b/README.md index 6e2088b..2362817 100644 --- a/README.md +++ b/README.md @@ -7,7 +7,6 @@ An easy way to keep your users' passwords secure. [![Travis Build Status](https://travis-ci.org/bcrypt-ruby/bcrypt-ruby.svg?branch=master)](https://travis-ci.org/bcrypt-ruby/bcrypt-ruby) [![AppVeyor Build Status](https://ci.appveyor.com/api/projects/status/6fplerx9lnaf0hyo?svg=true)](https://ci.appveyor.com/project/TJSchuck35975/bcrypt-ruby) - ## Why you should use `bcrypt()` If you store user passwords in the clear, then an attacker who steals a copy of your database has a giant list of emails diff --git a/lib/bcrypt/password.rb b/lib/bcrypt/password.rb index 1f902d2..4a2c140 100644 --- a/lib/bcrypt/password.rb +++ b/lib/bcrypt/password.rb @@ -94,5 +94,4 @@ def split_hash(h) return v.to_str, c.to_i, h[0, 29].to_str, mash[-31, 31].to_str end end - end From 81578a782bca1252827382a8502926832136a511 Mon Sep 17 00:00:00 2001 From: Josh Buker Date: Wed, 28 Apr 2021 11:18:39 -0700 Subject: [PATCH 21/66] Remove .travis.yml (unused) --- .travis.yml | 27 --------------------------- 1 file changed, 27 deletions(-) delete mode 100644 .travis.yml diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index 5cb4461..0000000 --- a/.travis.yml +++ /dev/null @@ -1,27 +0,0 @@ -language: ruby -before_install: - - "echo 'gem: --no-rdoc --no-ri' > ~/.gemrc" -rvm: - - 2.0 - - 2.1 - - 2.2 - - 2.3 - - 2.4 - - 2.5 - - 2.6 - - 2.7 - - 3.0 - - ruby-head - - jruby-head - - rbx-3 - - truffleruby - - truffleruby-head -matrix: - allow_failures: - - rvm: ruby-head - - rvm: jruby-head - - rvm: rbx-3 - - rvm: truffleruby - - rvm: truffleruby-head - fast_finish: true -script: bundle exec rake From d515706197284894814ca46ffd4f349e628126a5 Mon Sep 17 00:00:00 2001 From: Josh Buker Date: Wed, 28 Apr 2021 11:19:03 -0700 Subject: [PATCH 22/66] Update README build status badge We recently moved from TravisCI to Github Actions (GA), but forgot to update the build status badge. This replaces the build badge with its GA equivalent. --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 2362817..23a4775 100644 --- a/README.md +++ b/README.md @@ -4,7 +4,7 @@ An easy way to keep your users' passwords secure. * https://github.com/bcrypt-ruby/bcrypt-ruby/tree/master -[![Travis Build Status](https://travis-ci.org/bcrypt-ruby/bcrypt-ruby.svg?branch=master)](https://travis-ci.org/bcrypt-ruby/bcrypt-ruby) +[![Github Actions Build Status](https://github.com/bcrypt-ruby/bcrypt-ruby/actions/workflows/ruby.yml/badge.svg?branch=master)](https://github.com/bcrypt-ruby/bcrypt-ruby/actions/workflows/ruby.yml) [![AppVeyor Build Status](https://ci.appveyor.com/api/projects/status/6fplerx9lnaf0hyo?svg=true)](https://ci.appveyor.com/project/TJSchuck35975/bcrypt-ruby) ## Why you should use `bcrypt()` From 2cb53822f0b3e9ec978dd53b5ed414bdcd49d6a6 Mon Sep 17 00:00:00 2001 From: Alan Savage Date: Wed, 7 Jul 2021 13:00:03 -0700 Subject: [PATCH 23/66] Add a test demonstrating passwords >255 chars fail --- spec/bcrypt/password_spec.rb | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/spec/bcrypt/password_spec.rb b/spec/bcrypt/password_spec.rb index a818a7b..c841568 100644 --- a/spec/bcrypt/password_spec.rb +++ b/spec/bcrypt/password_spec.rb @@ -1,4 +1,5 @@ require File.expand_path(File.join(File.dirname(__FILE__), "..", "spec_helper")) +require 'securerandom' describe "Creating a hashed password" do @@ -26,6 +27,28 @@ expect { BCrypt::Password.create( "" ) }.not_to raise_error expect { BCrypt::Password.create( String.new ) }.not_to raise_error end + + context 'with a 256 character password' do + before :each do + @secret = SecureRandom.hex(256) + @password = BCrypt::Password.create(@secret, :cost => 4) + end + + specify "should return a BCrypt::Password" do + expect(@password).to be_an_instance_of(BCrypt::Password) + end + end + + context 'with a 255 character password' do + before :each do + @secret = SecureRandom.hex(255) + @password = BCrypt::Password.create(@secret, :cost => 4) + end + + specify "should return a BCrypt::Password" do + expect(@password).to be_an_instance_of(BCrypt::Password) + end + end end describe "Reading a hashed password" do From 2649bd72a48b83821f2754de6fb8273574e7addc Mon Sep 17 00:00:00 2001 From: Alan Savage Date: Wed, 7 Jul 2021 13:26:05 -0700 Subject: [PATCH 24/66] Truncate secrets greater than 255 chars in hash_secret --- lib/bcrypt/engine.rb | 7 ++++++- spec/bcrypt/engine_spec.rb | 8 ++++++++ 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/lib/bcrypt/engine.rb b/lib/bcrypt/engine.rb index ca57da0..e8fcfcf 100644 --- a/lib/bcrypt/engine.rb +++ b/lib/bcrypt/engine.rb @@ -7,6 +7,9 @@ class Engine MIN_COST = 4 # The maximum cost supported by the algorithm. MAX_COST = 31 + # Maximum possible size of bcrypt() secrets. + # https://github.com/bcrypt-ruby/bcrypt-ruby/issues/225#issuecomment-875908425 + MAX_SECRET_LENGTH = 255 # Maximum possible size of bcrypt() salts. MAX_SALT_LENGTH = 16 @@ -50,7 +53,9 @@ def self.hash_secret(secret, salt, _ = nil) if RUBY_PLATFORM == "java" Java.bcrypt_jruby.BCrypt.hashpw(secret.to_s.to_java_bytes, salt.to_s) else - __bc_crypt(secret.to_s, salt) + secret = secret.to_s + secret = secret[0..(MAX_SECRET_LENGTH-1)] if secret && secret.length > MAX_SECRET_LENGTH + __bc_crypt(secret, salt) end else raise Errors::InvalidSalt.new("invalid salt") diff --git a/spec/bcrypt/engine_spec.rb b/spec/bcrypt/engine_spec.rb index ad9a7e8..e9723d5 100644 --- a/spec/bcrypt/engine_spec.rb +++ b/spec/bcrypt/engine_spec.rb @@ -1,4 +1,5 @@ require File.expand_path(File.join(File.dirname(__FILE__), "..", "spec_helper")) +require 'securerandom' describe 'BCrypt::Engine' do describe '.calibrate(upper_time_limit_in_ms)' do @@ -157,4 +158,11 @@ class MyInvalidSecret expect(BCrypt::Engine.hash_secret(secret, salt)).to eql(test_vector) end end + + specify "should truncate secrets that are greater than the maximum length" do + # 'b' as a base triggers the failure at 256 characters, but 'a' does not. + too_long_secret = 'b'*(BCrypt::Engine::MAX_SECRET_LENGTH + 1) + just_right_secret = 'b'*BCrypt::Engine::MAX_SECRET_LENGTH + expect(BCrypt::Engine.hash_secret(too_long_secret, @salt)).to eq(BCrypt::Engine.hash_secret(just_right_secret, @salt)) + end end From c31d9cdec03496ca2e1f49e8c7cc838e0f95cfec Mon Sep 17 00:00:00 2001 From: Alan Savage Date: Wed, 7 Jul 2021 14:07:52 -0700 Subject: [PATCH 25/66] Switch from 255 char max to 72 --- lib/bcrypt/engine.rb | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/lib/bcrypt/engine.rb b/lib/bcrypt/engine.rb index e8fcfcf..9891ee6 100644 --- a/lib/bcrypt/engine.rb +++ b/lib/bcrypt/engine.rb @@ -8,8 +8,13 @@ class Engine # The maximum cost supported by the algorithm. MAX_COST = 31 # Maximum possible size of bcrypt() secrets. + # Older versions of the bcrypt library would truncate passwords longer + # than 72, but newer ones do not. We truncate like the old library for + # forward compatibility. This way users upgrading from Ubuntu 18.04 to 20.04 + # will not have their user passwords invalidated, for example. + # A max secret length greater than 255 leads to bcrypt returning nil. # https://github.com/bcrypt-ruby/bcrypt-ruby/issues/225#issuecomment-875908425 - MAX_SECRET_LENGTH = 255 + MAX_SECRET_LENGTH = 72 # Maximum possible size of bcrypt() salts. MAX_SALT_LENGTH = 16 From a848abb2523764ba8c114fcd6079b17cf5d1fdeb Mon Sep 17 00:00:00 2001 From: Alan Savage Date: Wed, 7 Jul 2021 18:02:02 -0700 Subject: [PATCH 26/66] Truncate based on bytesize instead of number of chars --- lib/bcrypt/engine.rb | 8 ++++---- spec/bcrypt/engine_spec.rb | 14 +++++++++++--- 2 files changed, 15 insertions(+), 7 deletions(-) diff --git a/lib/bcrypt/engine.rb b/lib/bcrypt/engine.rb index 9891ee6..f6a6ba7 100644 --- a/lib/bcrypt/engine.rb +++ b/lib/bcrypt/engine.rb @@ -9,12 +9,12 @@ class Engine MAX_COST = 31 # Maximum possible size of bcrypt() secrets. # Older versions of the bcrypt library would truncate passwords longer - # than 72, but newer ones do not. We truncate like the old library for + # than 72 bytes, but newer ones do not. We truncate like the old library for # forward compatibility. This way users upgrading from Ubuntu 18.04 to 20.04 # will not have their user passwords invalidated, for example. # A max secret length greater than 255 leads to bcrypt returning nil. # https://github.com/bcrypt-ruby/bcrypt-ruby/issues/225#issuecomment-875908425 - MAX_SECRET_LENGTH = 72 + MAX_SECRET_BYTESIZE = 72 # Maximum possible size of bcrypt() salts. MAX_SALT_LENGTH = 16 @@ -51,7 +51,7 @@ def self.cost=(cost) end # Given a secret and a valid salt (see BCrypt::Engine.generate_salt) calculates - # a bcrypt() password hash. + # a bcrypt() password hash. Secrets longer than 72 bytes are truncated. def self.hash_secret(secret, salt, _ = nil) if valid_secret?(secret) if valid_salt?(salt) @@ -59,7 +59,7 @@ def self.hash_secret(secret, salt, _ = nil) Java.bcrypt_jruby.BCrypt.hashpw(secret.to_s.to_java_bytes, salt.to_s) else secret = secret.to_s - secret = secret[0..(MAX_SECRET_LENGTH-1)] if secret && secret.length > MAX_SECRET_LENGTH + secret = secret.byteslice(0, MAX_SECRET_BYTESIZE) if secret && secret.bytesize > MAX_SECRET_BYTESIZE __bc_crypt(secret, salt) end else diff --git a/spec/bcrypt/engine_spec.rb b/spec/bcrypt/engine_spec.rb index e9723d5..a4c4056 100644 --- a/spec/bcrypt/engine_spec.rb +++ b/spec/bcrypt/engine_spec.rb @@ -159,10 +159,18 @@ class MyInvalidSecret end end - specify "should truncate secrets that are greater than the maximum length" do + specify "should truncate 1-byte character secrets to 72 bytes" do # 'b' as a base triggers the failure at 256 characters, but 'a' does not. - too_long_secret = 'b'*(BCrypt::Engine::MAX_SECRET_LENGTH + 1) - just_right_secret = 'b'*BCrypt::Engine::MAX_SECRET_LENGTH + too_long_secret = 'b'*(BCrypt::Engine::MAX_SECRET_BYTESIZE + 1) + just_right_secret = 'b'*BCrypt::Engine::MAX_SECRET_BYTESIZE + expect(BCrypt::Engine.hash_secret(too_long_secret, @salt)).to eq(BCrypt::Engine.hash_secret(just_right_secret, @salt)) + end + + specify "should truncate multi-byte character secrets to 72 bytes" do + # 256 times causes bcrypt to return nil for libxcrypt > 4.4.18-4. + too_long_secret = '𐐷'*256 + # 𐐷 takes 4 bytes in UTF-8. 18 times is 72 bytes + just_right_secret = '𐐷'*18 expect(BCrypt::Engine.hash_secret(too_long_secret, @salt)).to eq(BCrypt::Engine.hash_secret(just_right_secret, @salt)) end end From 7a411eea3942579675a0075d91e77f4184b44c29 Mon Sep 17 00:00:00 2001 From: Alan Savage Date: Thu, 8 Jul 2021 15:22:54 -0700 Subject: [PATCH 27/66] test: Reword hash_secret specs for clarity --- spec/bcrypt/engine_spec.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/spec/bcrypt/engine_spec.rb b/spec/bcrypt/engine_spec.rb index a4c4056..b527a6b 100644 --- a/spec/bcrypt/engine_spec.rb +++ b/spec/bcrypt/engine_spec.rb @@ -159,14 +159,14 @@ class MyInvalidSecret end end - specify "should truncate 1-byte character secrets to 72 bytes" do + specify "should truncate long 1-byte character secrets to 72 bytes" do # 'b' as a base triggers the failure at 256 characters, but 'a' does not. too_long_secret = 'b'*(BCrypt::Engine::MAX_SECRET_BYTESIZE + 1) just_right_secret = 'b'*BCrypt::Engine::MAX_SECRET_BYTESIZE expect(BCrypt::Engine.hash_secret(too_long_secret, @salt)).to eq(BCrypt::Engine.hash_secret(just_right_secret, @salt)) end - specify "should truncate multi-byte character secrets to 72 bytes" do + specify "should truncate long multi-byte character secrets to 72 bytes" do # 256 times causes bcrypt to return nil for libxcrypt > 4.4.18-4. too_long_secret = '𐐷'*256 # 𐐷 takes 4 bytes in UTF-8. 18 times is 72 bytes From 7ed2fa8c69c7b9555e0e8be6aac14d52f2b0befd Mon Sep 17 00:00:00 2001 From: Alan Savage Date: Thu, 8 Jul 2021 15:23:47 -0700 Subject: [PATCH 28/66] test: Simplify password create tests for long secrets --- spec/bcrypt/password_spec.rb | 22 ++-------------------- 1 file changed, 2 insertions(+), 20 deletions(-) diff --git a/spec/bcrypt/password_spec.rb b/spec/bcrypt/password_spec.rb index c841568..1899221 100644 --- a/spec/bcrypt/password_spec.rb +++ b/spec/bcrypt/password_spec.rb @@ -28,26 +28,8 @@ expect { BCrypt::Password.create( String.new ) }.not_to raise_error end - context 'with a 256 character password' do - before :each do - @secret = SecureRandom.hex(256) - @password = BCrypt::Password.create(@secret, :cost => 4) - end - - specify "should return a BCrypt::Password" do - expect(@password).to be_an_instance_of(BCrypt::Password) - end - end - - context 'with a 255 character password' do - before :each do - @secret = SecureRandom.hex(255) - @password = BCrypt::Password.create(@secret, :cost => 4) - end - - specify "should return a BCrypt::Password" do - expect(@password).to be_an_instance_of(BCrypt::Password) - end + specify "should tolerate very long string secrets" do + expect { BCrypt::Password.create("abcd"*1024) }.not_to raise_error end end From d83b916219145893dbac5106e8a77edd05af74ac Mon Sep 17 00:00:00 2001 From: Peter Goldstein Date: Mon, 24 Jan 2022 11:25:02 -0800 Subject: [PATCH 29/66] Add Ruby 3.1 to CI --- .github/workflows/ruby.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/ruby.yml b/.github/workflows/ruby.yml index 618ac97..54a1561 100644 --- a/.github/workflows/ruby.yml +++ b/.github/workflows/ruby.yml @@ -21,7 +21,8 @@ jobs: - 2.5 - 2.6 - 2.7 - - 3.0 + - '3.0' + - 3.1 - head - jruby - jruby-head From 5bf36393d330947e055af635687b32719a8df668 Mon Sep 17 00:00:00 2001 From: "T.J. Schuck" Date: Mon, 14 Mar 2022 15:11:18 -0400 Subject: [PATCH 30/66] Update for release --- CHANGELOG | 5 +++++ bcrypt.gemspec | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/CHANGELOG b/CHANGELOG index dd7ba1c..dbc2d82 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,3 +1,8 @@ +3.1.17 Mar 14 2022 +- Fix regex in validators to use \A and \z instead of ^ and $ [GH #121] +- Truncate secrets greater than 72 bytes in hash_secret [GH #255] +- Assorted test and doc improvements + 3.1.16 Sep 3 2020 - Fix compilation on FreeBSD. [GH #234] diff --git a/bcrypt.gemspec b/bcrypt.gemspec index 29ef18c..5971af1 100644 --- a/bcrypt.gemspec +++ b/bcrypt.gemspec @@ -1,6 +1,6 @@ Gem::Specification.new do |s| s.name = 'bcrypt' - s.version = '3.1.16' + s.version = '3.1.17' s.summary = "OpenBSD's bcrypt() password hashing algorithm." s.description = <<-EOF From 49161d9f68b90211661838f28fe2d5cf128a8b96 Mon Sep 17 00:00:00 2001 From: Nate Smith Date: Fri, 29 Apr 2022 14:08:00 -0400 Subject: [PATCH 31/66] Use `free` instead of `xfree` This was clobbered in the revert. --- ext/mri/bcrypt_ext.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ext/mri/bcrypt_ext.c b/ext/mri/bcrypt_ext.c index c8db933..189e0e8 100644 --- a/ext/mri/bcrypt_ext.c +++ b/ext/mri/bcrypt_ext.c @@ -47,7 +47,7 @@ static VALUE bc_crypt(VALUE self, VALUE key, VALUE setting) { out = rb_str_new2(value); - xfree(data); + free(data); return out; } From aec1265e6c0ff8622085fd6c40fbd4d039e992ef Mon Sep 17 00:00:00 2001 From: Nate Smith Date: Fri, 29 Apr 2022 11:17:10 -0400 Subject: [PATCH 32/66] Re-introduce GVL unlock Re-introduce the change from e1320b0 but with a fix for the bug causing bad hashes on Linux. The original patch was incorrectly copying the `data` struct into the string returned by the function. --- ext/mri/bcrypt_ext.c | 84 ++++++++++++++++++++++++++++++++++++-------- 1 file changed, 69 insertions(+), 15 deletions(-) diff --git a/ext/mri/bcrypt_ext.c b/ext/mri/bcrypt_ext.c index 189e0e8..6c68504 100644 --- a/ext/mri/bcrypt_ext.c +++ b/ext/mri/bcrypt_ext.c @@ -1,20 +1,50 @@ #include #include +#ifdef HAVE_RUBY_THREAD_H +#include +#endif + static VALUE mBCrypt; static VALUE cBCryptEngine; +struct bc_salt_args { + const char * prefix; + unsigned long count; + const char * input; + int size; +}; + +static void * bc_salt_nogvl(void * ptr) { + struct bc_salt_args * args = ptr; + + return crypt_gensalt_ra(args->prefix, args->count, args->input, args->size); +} + /* Given a logarithmic cost parameter, generates a salt for use with +bc_crypt+. */ static VALUE bc_salt(VALUE self, VALUE prefix, VALUE count, VALUE input) { char * salt; VALUE str_salt; - - salt = crypt_gensalt_ra( - StringValuePtr(prefix), - NUM2ULONG(count), - NIL_P(input) ? NULL : StringValuePtr(input), - NIL_P(input) ? 0 : RSTRING_LEN(input)); + struct bc_salt_args args; + + /* duplicate the parameters for thread safety. If another thread has a + * reference to the parameters and mutates them while we are working, + * that would be very bad. Duping the strings means that the reference + * isn't shared. */ + prefix = rb_str_new_frozen(prefix); + input = rb_str_new_frozen(input); + + args.prefix = StringValueCStr(prefix); + args.count = NUM2ULONG(count); + args.input = NIL_P(input) ? NULL : StringValuePtr(input); + args.size = NIL_P(input) ? 0 : RSTRING_LEN(input); + +#ifdef HAVE_RUBY_THREAD_H + salt = rb_thread_call_without_gvl(bc_salt_nogvl, &args, NULL, NULL); +#else + salt = bc_salt_nogvl((void *)&args); +#endif if(!salt) return Qnil; @@ -24,6 +54,19 @@ static VALUE bc_salt(VALUE self, VALUE prefix, VALUE count, VALUE input) { return str_salt; } +struct bc_crypt_args { + const char * key; + const char * setting; + void * data; + int size; +}; + +static void * bc_crypt_nogvl(void * ptr) { + struct bc_crypt_args * args = ptr; + + return crypt_ra(args->key, args->setting, &args->data, &args->size); +} + /* Given a secret and a salt, generates a salted hash (which you can then store safely). */ static VALUE bc_crypt(VALUE self, VALUE key, VALUE setting) { @@ -32,22 +75,33 @@ static VALUE bc_crypt(VALUE self, VALUE key, VALUE setting) { int size; VALUE out; - data = NULL; - size = 0xDEADBEEF; + struct bc_crypt_args args; if(NIL_P(key) || NIL_P(setting)) return Qnil; - value = crypt_ra( - NIL_P(key) ? NULL : StringValuePtr(key), - NIL_P(setting) ? NULL : StringValuePtr(setting), - &data, - &size); + /* duplicate the parameters for thread safety. If another thread has a + * reference to the parameters and mutates them while we are working, + * that would be very bad. Duping the strings means that the reference + * isn't shared. */ + key = rb_str_new_frozen(key); + setting = rb_str_new_frozen(setting); + + args.data = NULL; + args.size = 0xDEADBEEF; + args.key = NIL_P(key) ? NULL : StringValueCStr(key); + args.setting = NIL_P(setting) ? NULL : StringValueCStr(setting); + +#ifdef HAVE_RUBY_THREAD_H + value = rb_thread_call_without_gvl(bc_crypt_nogvl, &args, NULL, NULL); +#else + value = bc_crypt_nogvl((void *)&args); +#endif - if(!value || !data) return Qnil; + if(!value || !args.data) return Qnil; out = rb_str_new2(value); - free(data); + free(args.data); return out; } From f78b1763505d435f349a0d6dc8be18dc09418aac Mon Sep 17 00:00:00 2001 From: Nate Smith Date: Mon, 16 May 2022 12:19:28 -0400 Subject: [PATCH 33/66] Work around bug in JDK for JRuby tests --- .github/workflows/ruby.yml | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ruby.yml b/.github/workflows/ruby.yml index 54a1561..47a6651 100644 --- a/.github/workflows/ruby.yml +++ b/.github/workflows/ruby.yml @@ -30,8 +30,6 @@ jobs: - truffleruby-head - mingw exclude: - - { os: ubuntu, ruby: jruby } - - { os: ubuntu, ruby: jruby-head } - { os: ubuntu, ruby: mingw } - { os: macos, ruby: mingw } - { os: windows, ruby: truffleruby } @@ -46,8 +44,12 @@ jobs: with: ruby-version: ${{ matrix.ruby }} bundler-cache: true + env: + JAVA_OPTS: -Djdk.io.File.enableADS=true - name: Run tests run: bundle exec rake default + env: + JAVA_OPTS: -Djdk.io.File.enableADS=true finish: runs-on: ubuntu-latest From cc28f9efdc40316467e8d82095f9f8def7d0dfc2 Mon Sep 17 00:00:00 2001 From: Nate Smith Date: Mon, 16 May 2022 12:25:52 -0400 Subject: [PATCH 34/66] Update rake-compiler --- bcrypt.gemspec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bcrypt.gemspec b/bcrypt.gemspec index 5971af1..3a4487e 100644 --- a/bcrypt.gemspec +++ b/bcrypt.gemspec @@ -12,7 +12,7 @@ Gem::Specification.new do |s| s.files = `git ls-files`.split("\n") s.require_path = 'lib' - s.add_development_dependency 'rake-compiler', '~> 0.9.2' + s.add_development_dependency 'rake-compiler', '~> 1.2.0' s.add_development_dependency 'rspec', '>= 3' s.rdoc_options += ['--title', 'bcrypt-ruby', '--line-numbers', '--inline-source', '--main', 'README.md'] From 6d051de5ac04f08cc1e681e045c582dc61555c2a Mon Sep 17 00:00:00 2001 From: Nate Smith Date: Mon, 16 May 2022 14:19:03 -0400 Subject: [PATCH 35/66] Fix compiler warnings --- ext/mri/bcrypt_ext.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/ext/mri/bcrypt_ext.c b/ext/mri/bcrypt_ext.c index 6c68504..2366185 100644 --- a/ext/mri/bcrypt_ext.c +++ b/ext/mri/bcrypt_ext.c @@ -71,8 +71,6 @@ static void * bc_crypt_nogvl(void * ptr) { */ static VALUE bc_crypt(VALUE self, VALUE key, VALUE setting) { char * value; - void * data; - int size; VALUE out; struct bc_crypt_args args; From 87f132256456eb7cb3d403ffba245e9906bd9531 Mon Sep 17 00:00:00 2001 From: Nate Smith Date: Mon, 16 May 2022 16:20:41 -0400 Subject: [PATCH 36/66] Remove AppVeyor configuration --- README.md | 1 - appveyor.yml | 50 -------------------------------------------------- 2 files changed, 51 deletions(-) delete mode 100644 appveyor.yml diff --git a/README.md b/README.md index 23a4775..dd55971 100644 --- a/README.md +++ b/README.md @@ -5,7 +5,6 @@ An easy way to keep your users' passwords secure. * https://github.com/bcrypt-ruby/bcrypt-ruby/tree/master [![Github Actions Build Status](https://github.com/bcrypt-ruby/bcrypt-ruby/actions/workflows/ruby.yml/badge.svg?branch=master)](https://github.com/bcrypt-ruby/bcrypt-ruby/actions/workflows/ruby.yml) -[![AppVeyor Build Status](https://ci.appveyor.com/api/projects/status/6fplerx9lnaf0hyo?svg=true)](https://ci.appveyor.com/project/TJSchuck35975/bcrypt-ruby) ## Why you should use `bcrypt()` diff --git a/appveyor.yml b/appveyor.yml deleted file mode 100644 index e832e22..0000000 --- a/appveyor.yml +++ /dev/null @@ -1,50 +0,0 @@ -version: "{branch}-{build}" -build: off -clone_depth: 1 - -init: - # Install Ruby head - - if %RUBY_VERSION%==head ( - appveyor DownloadFile https://github.com/oneclick/rubyinstaller2/releases/download/rubyinstaller-head/rubyinstaller-head-x86.exe -FileName C:\head_x86.exe & - C:\head_x86.exe /verysilent /dir=C:\Ruby%RUBY_VERSION% - ) - - if %RUBY_VERSION%==head-x64 ( - appveyor DownloadFile https://github.com/oneclick/rubyinstaller2/releases/download/rubyinstaller-head/rubyinstaller-head-x64.exe -FileName C:\head_x64.exe & - C:\head_x64.exe /verysilent /dir=C:\Ruby%RUBY_VERSION% - ) - - # Add Ruby to the path - - set PATH=C:\Ruby%RUBY_VERSION%\bin;%PATH% - -environment: - matrix: - - RUBY_VERSION: "head" - - RUBY_VERSION: "head-x64" - - RUBY_VERSION: "25" - - RUBY_VERSION: "25-x64" - - RUBY_VERSION: "24" - - RUBY_VERSION: "24-x64" - - RUBY_VERSION: "23" - - RUBY_VERSION: "23-x64" - - RUBY_VERSION: "22" - - RUBY_VERSION: "22-x64" - - RUBY_VERSION: "21" - - RUBY_VERSION: "21-x64" - - RUBY_VERSION: "200" - - RUBY_VERSION: "200-x64" - -install: - - ps: "Set-Content -Value 'gem: --no-ri --no-rdoc ' -Path C:\\ProgramData\\gemrc" - - if %RUBY_VERSION%==head ( gem install bundler -v'< 2' ) - - if %RUBY_VERSION%==head-x64 ( gem install bundler -v'< 2' ) - - bundle install - -before_build: - - ruby -v - - gem -v - -build_script: - - bundle exec rake compile -rdevkit - -test_script: - - bundle exec rake spec From e799c279b0575e87940026100c3217d0b008ab1c Mon Sep 17 00:00:00 2001 From: Nate Smith Date: Mon, 16 May 2022 16:26:10 -0400 Subject: [PATCH 37/66] Update for release --- CHANGELOG | 4 ++++ bcrypt.gemspec | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/CHANGELOG b/CHANGELOG index dbc2d82..dc03826 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,3 +1,7 @@ +3.1.18 May 16 2022 + - Unlock GVL when calculating hashes and salts [GH #260] + - Fix compilation warnings in `ext/mri/bcrypt_ext.c` [GH #261] + 3.1.17 Mar 14 2022 - Fix regex in validators to use \A and \z instead of ^ and $ [GH #121] - Truncate secrets greater than 72 bytes in hash_secret [GH #255] diff --git a/bcrypt.gemspec b/bcrypt.gemspec index 5971af1..3c63b5d 100644 --- a/bcrypt.gemspec +++ b/bcrypt.gemspec @@ -1,6 +1,6 @@ Gem::Specification.new do |s| s.name = 'bcrypt' - s.version = '3.1.17' + s.version = '3.1.18' s.summary = "OpenBSD's bcrypt() password hashing algorithm." s.description = <<-EOF From df27ee50c9c9d639c8eb30536fcbecf371a7b484 Mon Sep 17 00:00:00 2001 From: Sergey Alekseev Date: Sat, 6 Jul 2019 13:10:09 +0300 Subject: [PATCH 38/66] deprecate passing the third argument to `BCrypt::Engine.hash_secret` Re https://github.com/codahale/bcrypt-ruby/pull/74#issuecomment-492277126. --- CHANGELOG | 3 +++ lib/bcrypt/engine.rb | 7 +++++++ 2 files changed, 10 insertions(+) diff --git a/CHANGELOG b/CHANGELOG index dc03826..d2bf07d 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,3 +1,6 @@ +Unreleased: + - Deprecate passing the third argument to `BCrypt::Engine.hash_secret` [GH #207 by @sergey-alekseev] + 3.1.18 May 16 2022 - Unlock GVL when calculating hashes and salts [GH #260] - Fix compilation warnings in `ext/mri/bcrypt_ext.c` [GH #261] diff --git a/lib/bcrypt/engine.rb b/lib/bcrypt/engine.rb index 552b7b0..1a253b3 100644 --- a/lib/bcrypt/engine.rb +++ b/lib/bcrypt/engine.rb @@ -53,6 +53,13 @@ def self.cost=(cost) # Given a secret and a valid salt (see BCrypt::Engine.generate_salt) calculates # a bcrypt() password hash. Secrets longer than 72 bytes are truncated. def self.hash_secret(secret, salt, _ = nil) + unless _.nil? + warn "[DEPRECATION] Passing the third argument to " \ + "`BCrypt::Engine.hash_secret` is deprecated. " \ + "Please do not pass the third argument which " \ + "is currently not used." + end + if valid_secret?(secret) if valid_salt?(salt) if RUBY_PLATFORM == "java" From 477f290b0893a87d2d5183e473f1995c2aa05c7f Mon Sep 17 00:00:00 2001 From: Aaron Patterson Date: Wed, 4 Jan 2023 17:05:42 -0800 Subject: [PATCH 39/66] Add a test for passwords with null bytes Raise an exception when passwords contain null bytes. This was already fixed (inadvertently I think?) in aec1265e. StringValueCStr will raise an exception if the string buffer it's unwrapping contains null bytes. Fixes #115 Fixes #114 --- spec/bcrypt/password_spec.rb | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/spec/bcrypt/password_spec.rb b/spec/bcrypt/password_spec.rb index 1899221..5a93cbd 100644 --- a/spec/bcrypt/password_spec.rb +++ b/spec/bcrypt/password_spec.rb @@ -31,6 +31,12 @@ specify "should tolerate very long string secrets" do expect { BCrypt::Password.create("abcd"*1024) }.not_to raise_error end + + specify "blows up when null bytes are in the string" do + # JRuby can handle the null bytes + skip if RUBY_ENGINE == 'jruby' + expect { BCrypt::Password.create( "foo\0bar".chop ) }.to raise_error + end end describe "Reading a hashed password" do From 53ec1e1bea1fa75c847b9af468ca937b83d1b417 Mon Sep 17 00:00:00 2001 From: Peter Arato Date: Thu, 22 Jun 2023 09:53:58 -0400 Subject: [PATCH 40/66] Fixing a rare bug when calling BCrypt::Engine#hash_secret - which produces nil accidentally 1 out of 500 cases in TruffleRuby. Co-authored-by: Benoit Daloze Co-authored-by: Peter Arato --- ext/mri/bcrypt_ext.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/ext/mri/bcrypt_ext.c b/ext/mri/bcrypt_ext.c index 2366185..757b068 100644 --- a/ext/mri/bcrypt_ext.c +++ b/ext/mri/bcrypt_ext.c @@ -49,6 +49,9 @@ static VALUE bc_salt(VALUE self, VALUE prefix, VALUE count, VALUE input) { if(!salt) return Qnil; str_salt = rb_str_new2(salt); + + RB_GC_GUARD(prefix); + RB_GC_GUARD(input); free(salt); return str_salt; @@ -99,6 +102,8 @@ static VALUE bc_crypt(VALUE self, VALUE key, VALUE setting) { out = rb_str_new2(value); + RB_GC_GUARD(key); + RB_GC_GUARD(setting); free(args.data); return out; From 31458e76f6975aad88dcd09f533fff23bb54c4f6 Mon Sep 17 00:00:00 2001 From: Aaron Patterson Date: Thu, 22 Jun 2023 09:46:43 -0700 Subject: [PATCH 41/66] bumping version / updating changelog --- CHANGELOG | 3 ++- bcrypt.gemspec | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index d2bf07d..9f3e624 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,5 +1,6 @@ -Unreleased: +3.1.19 June 22 2023 - Deprecate passing the third argument to `BCrypt::Engine.hash_secret` [GH #207 by @sergey-alekseev] + - Add GC guards so the C compiler won't optimize out references [GH #270] 3.1.18 May 16 2022 - Unlock GVL when calculating hashes and salts [GH #260] diff --git a/bcrypt.gemspec b/bcrypt.gemspec index 7dc6abf..506d8bf 100644 --- a/bcrypt.gemspec +++ b/bcrypt.gemspec @@ -1,6 +1,6 @@ Gem::Specification.new do |s| s.name = 'bcrypt' - s.version = '3.1.18' + s.version = '3.1.19' s.summary = "OpenBSD's bcrypt() password hashing algorithm." s.description = <<-EOF From 863cfbd80451af0521217bfbb92c80d7a9b824a0 Mon Sep 17 00:00:00 2001 From: Aaron Patterson Date: Thu, 22 Jun 2023 11:39:05 -0700 Subject: [PATCH 42/66] bumping Java version https://github.com/rake-compiler/rake-compiler/pull/172 --- Rakefile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Rakefile b/Rakefile index a47ce55..58b51fe 100644 --- a/Rakefile +++ b/Rakefile @@ -50,8 +50,8 @@ end if RUBY_PLATFORM =~ /java/ Rake::JavaExtensionTask.new('bcrypt_ext', GEMSPEC) do |ext| ext.ext_dir = 'ext/jruby' - ext.source_version = "1.7" - ext.target_version = "1.7" + ext.source_version = "1.8" + ext.target_version = "1.8" end else Rake::ExtensionTask.new("bcrypt_ext", GEMSPEC) do |ext| From d9ed4e21c95ba13239593250ed4cd1b225117173 Mon Sep 17 00:00:00 2001 From: Piotr Usewicz Date: Fri, 17 Nov 2023 10:08:37 +0100 Subject: [PATCH 43/66] Limit packaged files Limit files included in the gem to the ones that are necessary. This skips shipping the gem with directories such as `.github`, `spec` and other files that are not normally accessible and arguably should be skipped. This saves us some bytes in transfer and disk space on all the computers these gems are downloaded to. --- bcrypt.gemspec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bcrypt.gemspec b/bcrypt.gemspec index 506d8bf..01db5e1 100644 --- a/bcrypt.gemspec +++ b/bcrypt.gemspec @@ -9,7 +9,7 @@ Gem::Specification.new do |s| passwords. EOF - s.files = `git ls-files`.split("\n") + s.files = Dir['CHANGELOG', 'COPYING', 'README.md', 'lib/**/*.rb', 'ext/**/*.*'] s.require_path = 'lib' s.add_development_dependency 'rake-compiler', '~> 1.2.0' From b8dbc8524fa598503fd06b94a8a95ff2ba3525ec Mon Sep 17 00:00:00 2001 From: "T.J. Schuck" Date: Fri, 17 Nov 2023 11:02:01 -0500 Subject: [PATCH 44/66] Add 3.2 to the test matrix --- .github/workflows/ruby.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/ruby.yml b/.github/workflows/ruby.yml index 47a6651..2f06236 100644 --- a/.github/workflows/ruby.yml +++ b/.github/workflows/ruby.yml @@ -23,6 +23,7 @@ jobs: - 2.7 - '3.0' - 3.1 + - 3.2 - head - jruby - jruby-head From b23e4bd8b64ea8424d9d68f6df5f04e46f4ba0d7 Mon Sep 17 00:00:00 2001 From: "T.J. Schuck" Date: Fri, 17 Nov 2023 11:37:38 -0500 Subject: [PATCH 45/66] Run old rubies on Ubuntu 20.04 See https://github.com/ruby/setup-ruby/issues/496 --- .github/workflows/ruby.yml | 23 ++++++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) diff --git a/.github/workflows/ruby.yml b/.github/workflows/ruby.yml index 2f06236..82c49b3 100644 --- a/.github/workflows/ruby.yml +++ b/.github/workflows/ruby.yml @@ -5,7 +5,6 @@ on: [ push, pull_request ] jobs: test_matrix: - strategy: fail-fast: false matrix: @@ -31,6 +30,8 @@ jobs: - truffleruby-head - mingw exclude: + - { os: ubuntu, ruby: 2.1 } + - { os: ubuntu, ruby: 2.2 } - { os: ubuntu, ruby: mingw } - { os: macos, ruby: mingw } - { os: windows, ruby: truffleruby } @@ -52,6 +53,26 @@ jobs: env: JAVA_OPTS: -Djdk.io.File.enableADS=true + test_matrix_old_rubies: + strategy: + fail-fast: false + matrix: + ruby: + - 2.1 + - 2.2 + + runs-on: ubuntu-20.04 + + steps: + - uses: actions/checkout@v2 + - name: Set up Ruby + uses: ruby/setup-ruby@v1 + with: + ruby-version: ${{ matrix.ruby }} + bundler-cache: true + - name: Run tests + run: bundle exec rake default + finish: runs-on: ubuntu-latest needs: [ test_matrix ] From 58f8afd33d8813e84706b938815bb1aa08d0b470 Mon Sep 17 00:00:00 2001 From: "T.J. Schuck" Date: Fri, 17 Nov 2023 11:58:28 -0500 Subject: [PATCH 46/66] Bump version/changelog --- CHANGELOG | 3 +++ bcrypt.gemspec | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/CHANGELOG b/CHANGELOG index 9f3e624..92a8114 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,3 +1,6 @@ +3.1.20 Nov 17 2023 + - Limit packaged files -- decrease gem filesize by ~28% [GH #272 by @pusewicz] + 3.1.19 June 22 2023 - Deprecate passing the third argument to `BCrypt::Engine.hash_secret` [GH #207 by @sergey-alekseev] - Add GC guards so the C compiler won't optimize out references [GH #270] diff --git a/bcrypt.gemspec b/bcrypt.gemspec index 01db5e1..68a31ea 100644 --- a/bcrypt.gemspec +++ b/bcrypt.gemspec @@ -1,6 +1,6 @@ Gem::Specification.new do |s| s.name = 'bcrypt' - s.version = '3.1.19' + s.version = '3.1.20' s.summary = "OpenBSD's bcrypt() password hashing algorithm." s.description = <<-EOF From 49f935c57d16dce78efd54518d6522174ab1d1f7 Mon Sep 17 00:00:00 2001 From: Mark Young Date: Wed, 20 Dec 2023 14:14:48 +0000 Subject: [PATCH 47/66] Provide a 'Changelog' link on rubygems.org/gems/bcrypt By providing a 'changelog_uri' in the metadata of the gemspec a 'Changelog' link will be shown on https://rubygems.org/gems/bcrypt which makes it quick and easy for someone to check on the changes introduced with a new version. --- bcrypt.gemspec | 2 ++ 1 file changed, 2 insertions(+) diff --git a/bcrypt.gemspec b/bcrypt.gemspec index 68a31ea..c425529 100644 --- a/bcrypt.gemspec +++ b/bcrypt.gemspec @@ -24,4 +24,6 @@ Gem::Specification.new do |s| s.email = "coda.hale@gmail.com" s.homepage = "https://github.com/bcrypt-ruby/bcrypt-ruby" s.license = "MIT" + + s.metadata["changelog_uri"] = s.homepage + "/blob/master/CHANGELOG" end From 985e6d0579eba5cb534ac388179916fdab5adb9b Mon Sep 17 00:00:00 2001 From: m-nakamura145 Date: Tue, 21 May 2024 22:48:40 +0900 Subject: [PATCH 48/66] Support ruby 3.3 and 3.4.0-preview1 --- .github/workflows/ruby.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/ruby.yml b/.github/workflows/ruby.yml index 82c49b3..a93f979 100644 --- a/.github/workflows/ruby.yml +++ b/.github/workflows/ruby.yml @@ -23,6 +23,8 @@ jobs: - '3.0' - 3.1 - 3.2 + - 3.3 + - 3.4.0-preview1 - head - jruby - jruby-head From 9a3a85ca9de4557b22aa8836bc7c1b9c387c024b Mon Sep 17 00:00:00 2001 From: "T.J. Schuck" Date: Tue, 21 May 2024 09:58:48 -0400 Subject: [PATCH 49/66] Update README to remove specific Ruby version mentions So we don't have to update this in lockstep with the CI matrix --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index dd55971..88598ad 100644 --- a/README.md +++ b/README.md @@ -30,8 +30,8 @@ re-hash those passwords. This vulnerability only affected the JRuby gem. The bcrypt gem is available on the following Ruby platforms: * JRuby -* RubyInstaller 2.0 – 3.0 builds on Windows with the DevKit -* Any 2.0 – 3.0 Ruby on a BSD/OS X/Linux system with a compiler +* RubyInstaller builds on Windows with the DevKit +* Any modern Ruby on a BSD/OS X/Linux system with a compiler ## How to use `bcrypt()` in your Rails application From a75cc698c4733a79c213c8a9609563abedc450bc Mon Sep 17 00:00:00 2001 From: "T.J. Schuck" Date: Wed, 22 May 2024 17:08:30 -0400 Subject: [PATCH 50/66] Ruby 3.4.0.-preview1 is not available on Windows See https://github.com/ruby/setup-ruby and https://github.com/ruby/setup-ruby/blob/master/windows-versions.json --- .github/workflows/ruby.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/ruby.yml b/.github/workflows/ruby.yml index a93f979..9111c87 100644 --- a/.github/workflows/ruby.yml +++ b/.github/workflows/ruby.yml @@ -38,6 +38,7 @@ jobs: - { os: macos, ruby: mingw } - { os: windows, ruby: truffleruby } - { os: windows, ruby: truffleruby-head } + - { os: windows, ruby: 3.4.0-preview1 } runs-on: ${{ matrix.os }}-latest From b8a167ab23959d1f37983b9228e9f01c03c726fd Mon Sep 17 00:00:00 2001 From: "T.J. Schuck" Date: Wed, 22 May 2024 17:18:47 -0400 Subject: [PATCH 51/66] Test old Rubies on older x64 macOS --- .github/workflows/ruby.yml | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/.github/workflows/ruby.yml b/.github/workflows/ruby.yml index 9111c87..e940a81 100644 --- a/.github/workflows/ruby.yml +++ b/.github/workflows/ruby.yml @@ -36,6 +36,11 @@ jobs: - { os: ubuntu, ruby: 2.2 } - { os: ubuntu, ruby: mingw } - { os: macos, ruby: mingw } + - { os: macos, ruby: 2.1 } + - { os: macos, ruby: 2.2 } + - { os: macos, ruby: 2.3 } + - { os: macos, ruby: 2.4 } + - { os: macos, ruby: 2.5 } - { os: windows, ruby: truffleruby } - { os: windows, ruby: truffleruby-head } - { os: windows, ruby: 3.4.0-preview1 } @@ -60,11 +65,17 @@ jobs: strategy: fail-fast: false matrix: + os: + - ubuntu-20.04 + - macos-13 ruby: - 2.1 - 2.2 + - 2.3 + - 2.4 + - 2.5 - runs-on: ubuntu-20.04 + runs-on: ${{ matrix.os }} steps: - uses: actions/checkout@v2 From ff9084a3f5e993b1ba9609e2326494fd97db61dc Mon Sep 17 00:00:00 2001 From: Federico Date: Sat, 13 Jul 2024 22:15:49 -0300 Subject: [PATCH 52/66] Add == gotcha that can be unintuitive at first --- lib/bcrypt/password.rb | 2 ++ 1 file changed, 2 insertions(+) diff --git a/lib/bcrypt/password.rb b/lib/bcrypt/password.rb index 4a2c140..3160c9b 100644 --- a/lib/bcrypt/password.rb +++ b/lib/bcrypt/password.rb @@ -73,6 +73,8 @@ def initialize(raw_hash) # @password == @password.to_s # => False # @password.to_s == @password # => True # @password.to_s == @password.to_s # => True + # + # secret == @password # => probably False, because the secret is not a BCrypt::Password instance. def ==(secret) super(BCrypt::Engine.hash_secret(secret, @salt)) end From 7277821447a7f40e605d9ff17a6b3b2b68e5c286 Mon Sep 17 00:00:00 2001 From: Mohamed Hafez Date: Wed, 18 Sep 2024 17:02:41 +0200 Subject: [PATCH 53/66] Mark as ractor-safe --- ext/mri/bcrypt_ext.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/ext/mri/bcrypt_ext.c b/ext/mri/bcrypt_ext.c index 757b068..3e5ac1c 100644 --- a/ext/mri/bcrypt_ext.c +++ b/ext/mri/bcrypt_ext.c @@ -111,6 +111,10 @@ static VALUE bc_crypt(VALUE self, VALUE key, VALUE setting) { /* Create the BCrypt and BCrypt::Engine modules, and populate them with methods. */ void Init_bcrypt_ext(){ +#ifdef HAVE_RB_EXT_RACTOR_SAFE + rb_ext_ractor_safe(true); +#endif + mBCrypt = rb_define_module("BCrypt"); cBCryptEngine = rb_define_class_under(mBCrypt, "Engine", rb_cObject); From 9597533827b5274a1947da56000728c20af397e7 Mon Sep 17 00:00:00 2001 From: Griffin Smith Date: Thu, 6 Aug 2015 14:06:03 -0400 Subject: [PATCH 54/66] Use a constant-time secure comparison for passwords Use a constant-time byte-by-byte secure comparison to compare potential password hashes rather than `String#==`, which uses strcmp under the hood and stops as soon as there's an unmatched byte. --- lib/bcrypt/password.rb | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/lib/bcrypt/password.rb b/lib/bcrypt/password.rb index 3160c9b..db09009 100644 --- a/lib/bcrypt/password.rb +++ b/lib/bcrypt/password.rb @@ -76,7 +76,14 @@ def initialize(raw_hash) # # secret == @password # => probably False, because the secret is not a BCrypt::Password instance. def ==(secret) - super(BCrypt::Engine.hash_secret(secret, @salt)) + hash = BCrypt::Engine.hash_secret(secret, @salt) + + return false if hash.strip.empty? || strip.empty? || hash.bytesize != bytesize + l = hash.unpack "C#{hash.bytesize}" + + res = 0 + each_byte { |byte| res |= byte ^ l.shift } + res == 0 end alias_method :is_password?, :== From a7a868e12d80c6e0a75d81acdfdc3c4a763a622b Mon Sep 17 00:00:00 2001 From: Aaron Patterson Date: Tue, 29 Oct 2024 16:04:46 -0700 Subject: [PATCH 55/66] Lets not allocate anything --- lib/bcrypt/password.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/bcrypt/password.rb b/lib/bcrypt/password.rb index db09009..0c432d6 100644 --- a/lib/bcrypt/password.rb +++ b/lib/bcrypt/password.rb @@ -79,10 +79,10 @@ def ==(secret) hash = BCrypt::Engine.hash_secret(secret, @salt) return false if hash.strip.empty? || strip.empty? || hash.bytesize != bytesize - l = hash.unpack "C#{hash.bytesize}" + # Constant time comparison so they can't tell the length. res = 0 - each_byte { |byte| res |= byte ^ l.shift } + bytesize.times { |i| res |= getbyte(i) ^ hash.getbyte(i) } res == 0 end alias_method :is_password?, :== From 27dbab3080c2dbd22ae0652b36fd37eba69dda30 Mon Sep 17 00:00:00 2001 From: Aaron Patterson Date: Wed, 31 Dec 2025 10:14:07 -0800 Subject: [PATCH 56/66] Declare development dependencies --- bcrypt.gemspec | 2 ++ 1 file changed, 2 insertions(+) diff --git a/bcrypt.gemspec b/bcrypt.gemspec index c425529..bae0473 100644 --- a/bcrypt.gemspec +++ b/bcrypt.gemspec @@ -14,6 +14,8 @@ Gem::Specification.new do |s| s.add_development_dependency 'rake-compiler', '~> 1.2.0' s.add_development_dependency 'rspec', '>= 3' + s.add_development_dependency 'rdoc', '>= 7.0.3' + s.add_development_dependency 'benchmark', '>= 0.5.0' s.rdoc_options += ['--title', 'bcrypt-ruby', '--line-numbers', '--inline-source', '--main', 'README.md'] s.extra_rdoc_files += ['README.md', 'COPYING', 'CHANGELOG', *Dir['lib/**/*.rb']] From c1562549b901349c79fb5e96d16c32e25caa7938 Mon Sep 17 00:00:00 2001 From: Aaron Patterson Date: Wed, 31 Dec 2025 10:14:19 -0800 Subject: [PATCH 57/66] Modernize CI --- .github/workflows/ruby.yml | 111 ++++++++++++------------------------- 1 file changed, 34 insertions(+), 77 deletions(-) diff --git a/.github/workflows/ruby.yml b/.github/workflows/ruby.yml index e940a81..c5fb94b 100644 --- a/.github/workflows/ruby.yml +++ b/.github/workflows/ruby.yml @@ -3,93 +3,50 @@ name: Test Suite # Run against all commits and pull requests. on: [ push, pull_request ] +env: + JAVA_OPTS: '-Xms60M -Xmx1G' + jobs: - test_matrix: + ruby-versions: + uses: ruby/actions/.github/workflows/ruby_versions.yml@master + with: + engine: cruby + min_version: 3.1 + + test: + needs: ruby-versions + runs-on: ${{ matrix.os }} strategy: fail-fast: false matrix: - os: - - ubuntu - - macos - - windows - ruby: - - 2.1 - - 2.2 - - 2.3 - - 2.4 - - 2.5 - - 2.6 - - 2.7 - - '3.0' - - 3.1 - - 3.2 - - 3.3 - - 3.4.0-preview1 - - head - - jruby - - jruby-head - - truffleruby - - truffleruby-head - - mingw - exclude: - - { os: ubuntu, ruby: 2.1 } - - { os: ubuntu, ruby: 2.2 } - - { os: ubuntu, ruby: mingw } - - { os: macos, ruby: mingw } - - { os: macos, ruby: 2.1 } - - { os: macos, ruby: 2.2 } - - { os: macos, ruby: 2.3 } - - { os: macos, ruby: 2.4 } - - { os: macos, ruby: 2.5 } - - { os: windows, ruby: truffleruby } - - { os: windows, ruby: truffleruby-head } - - { os: windows, ruby: 3.4.0-preview1 } - - runs-on: ${{ matrix.os }}-latest + ruby: ${{ fromJson(needs.ruby-versions.outputs.versions) }} + os: [ ubuntu-latest, macos-latest, windows-latest ] + include: + - { os: windows-latest, ruby: jruby-head } + - { os: macos-latest, ruby: jruby-head } + - { os: ubuntu-latest, ruby: jruby-head } + - { os: windows-latest, ruby: ucrt } + - { os: windows-latest, ruby: mingw } steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v4 + - name: Set up Ruby - uses: ruby/setup-ruby@v1 + uses: ruby/setup-ruby-pkgs@v1 with: ruby-version: ${{ matrix.ruby }} - bundler-cache: true - env: - JAVA_OPTS: -Djdk.io.File.enableADS=true - - name: Run tests - run: bundle exec rake default - env: - JAVA_OPTS: -Djdk.io.File.enableADS=true + apt-get: "haveged libyaml-dev" + brew: libyaml + vcpkg: libyaml - test_matrix_old_rubies: - strategy: - fail-fast: false - matrix: - os: - - ubuntu-20.04 - - macos-13 - ruby: - - 2.1 - - 2.2 - - 2.3 - - 2.4 - - 2.5 + - name: Set JRuby ENV vars + run: | + echo 'JAVA_OPTS=-Xmx1g' >> $GITHUB_ENV + if: ${{ ! startsWith(matrix.ruby, 'jruby') }} - runs-on: ${{ matrix.os }} + - name: Install dependencies + run: bundle install --jobs 1 - steps: - - uses: actions/checkout@v2 - - name: Set up Ruby - uses: ruby/setup-ruby@v1 - with: - ruby-version: ${{ matrix.ruby }} - bundler-cache: true - name: Run tests - run: bundle exec rake default - - finish: - runs-on: ubuntu-latest - needs: [ test_matrix ] - steps: - - name: Wait for status checks - run: echo "All Green!" + run: bundle exec rake + continue-on-error: ${{ matrix.ruby == 'jruby-head' }} From d94041a0d2972f4dba1d831a9ebdefad398fe604 Mon Sep 17 00:00:00 2001 From: Aaron Patterson Date: Wed, 31 Dec 2025 10:39:17 -0800 Subject: [PATCH 58/66] Try to deal with flaky tests We have a test that tries to test the "calibration" function in BCrypt. This function is supposed to return a "cost" based on some number of milliseconds passed in. We're trying to make the cost relative to some beginning cost (MIN_COST + 1), time that, then use it as the "relative time". The problem is that the time this takes in CI is not constant, so even `min_time_ms * 4` may fit inside the same "cost" as the original. I'm bumping the factor to `5` to hopefully reduce the flakiness. It seems like we just want to test that "some time deadline" returns a greater cost than a different time deadline, so I think bumping the factor to 5 is a legit fix --- spec/bcrypt/engine_spec.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spec/bcrypt/engine_spec.rb b/spec/bcrypt/engine_spec.rb index b527a6b..8abbe9f 100644 --- a/spec/bcrypt/engine_spec.rb +++ b/spec/bcrypt/engine_spec.rb @@ -17,7 +17,7 @@ BCrypt::Password.create("testing testing", :cost => BCrypt::Engine::MIN_COST + 1) min_time_ms = (Time.now - start_time) * 1000 first = BCrypt::Engine.calibrate(min_time_ms) - second = BCrypt::Engine.calibrate(min_time_ms * 4) + second = BCrypt::Engine.calibrate(min_time_ms * 5) expect(second).to be > first end end From 344ca599eed0fc311e3a5be80441ddb85540f34f Mon Sep 17 00:00:00 2001 From: Aaron Patterson Date: Wed, 31 Dec 2025 11:33:52 -0800 Subject: [PATCH 59/66] Configure trusted publishing This way we can just push a tag and let GitHub actions do the release --- .github/workflows/release.yml | 62 +++++++++++++++++++++++++++++++++++ 1 file changed, 62 insertions(+) create mode 100644 .github/workflows/release.yml diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 0000000..1325988 --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,62 @@ +name: Publish gem to rubygems.org + +on: + push: + tags: + - 'v*' + +permissions: + contents: read + +jobs: + push: + if: github.repository == 'bcrypt-ruby/bcrypt-ruby' + runs-on: ubuntu-latest + + environment: + name: rubygems.org + url: https://rubygems.org/gems/bcrypt-ruby + + permissions: + contents: write + id-token: write + + strategy: + matrix: + ruby: ["ruby", "jruby"] + + steps: + - name: Harden Runner + uses: step-security/harden-runner@v2 + with: + egress-policy: audit + + - uses: actions/checkout@v4 + + - name: Set up Ruby + uses: ruby/setup-ruby@v1 + with: + ruby-version: ${{ matrix.ruby }} + + # https://github.com/rubygems/rubygems/issues/5882 + - name: Install dependencies and build for JRuby + run: | + sudo apt install default-jdk maven + gem update --system + gem install ruby-maven rake-compiler --no-document + rake compile + if: matrix.ruby == 'jruby' + + - name: Install dependencies + run: bundle install --jobs 4 --retry 3 + + - name: Publish to RubyGems + uses: rubygems/release-gem@v1 + + - name: Create GitHub release + run: | + tag_name="$(git describe --tags --abbrev=0)" + gh release create "${tag_name}" --verify-tag --generate-notes + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + if: matrix.ruby != 'jruby' From 64605fc1de894ba125de6a7eb61dd8cceb9bc65d Mon Sep 17 00:00:00 2001 From: Aaron Patterson Date: Wed, 31 Dec 2025 11:39:38 -0800 Subject: [PATCH 60/66] bump version --- CHANGELOG | 4 ++++ bcrypt.gemspec | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/CHANGELOG b/CHANGELOG index 92a8114..1682923 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,3 +1,7 @@ +3.1.21 Dec 31 2025 + - Use constant time comparisons + - Mark as Ractor safe + 3.1.20 Nov 17 2023 - Limit packaged files -- decrease gem filesize by ~28% [GH #272 by @pusewicz] diff --git a/bcrypt.gemspec b/bcrypt.gemspec index bae0473..e35a402 100644 --- a/bcrypt.gemspec +++ b/bcrypt.gemspec @@ -1,6 +1,6 @@ Gem::Specification.new do |s| s.name = 'bcrypt' - s.version = '3.1.20' + s.version = '3.1.21' s.summary = "OpenBSD's bcrypt() password hashing algorithm." s.description = <<-EOF From 4b1fc736c0f4f66d5e2dd4a5c28bd4f3f51aea93 Mon Sep 17 00:00:00 2001 From: Aaron Patterson Date: Wed, 31 Dec 2025 11:41:44 -0800 Subject: [PATCH 61/66] add bundler tasks --- Rakefile | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Rakefile b/Rakefile index 58b51fe..95e22a5 100644 --- a/Rakefile +++ b/Rakefile @@ -5,6 +5,8 @@ require 'rake/javaextensiontask' require 'rake/clean' require 'rdoc/task' require 'benchmark' +require "bundler" +Bundler::GemHelper.install_tasks CLEAN.include( "tmp", From 01cc68835f0bcdd7ef16de477471c112adb417da Mon Sep 17 00:00:00 2001 From: Aaron Patterson Date: Wed, 31 Dec 2025 12:02:49 -0800 Subject: [PATCH 62/66] Move compilation after bundle install The Rakefile depends on gems being installed. Hopefully this will fix JRuby releases on trusted publishing --- .github/workflows/release.yml | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 1325988..10d91ed 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -44,12 +44,16 @@ jobs: sudo apt install default-jdk maven gem update --system gem install ruby-maven rake-compiler --no-document - rake compile if: matrix.ruby == 'jruby' - name: Install dependencies run: bundle install --jobs 4 --retry 3 + - name: Compile on JRuby + run: | + rake compile + if: matrix.ruby == 'jruby' + - name: Publish to RubyGems uses: rubygems/release-gem@v1 From 4d1d95b8ec624d0cf8ed1099402a7edd2f308da2 Mon Sep 17 00:00:00 2001 From: "T.J. Schuck" Date: Thu, 29 Jan 2026 10:12:24 -0500 Subject: [PATCH 63/66] Add TruffleRuby in CI Co-authored-by: Benoit Daloze --- .github/workflows/ruby.yml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.github/workflows/ruby.yml b/.github/workflows/ruby.yml index c5fb94b..176faa0 100644 --- a/.github/workflows/ruby.yml +++ b/.github/workflows/ruby.yml @@ -27,6 +27,10 @@ jobs: - { os: ubuntu-latest, ruby: jruby-head } - { os: windows-latest, ruby: ucrt } - { os: windows-latest, ruby: mingw } + - { os: macos-latest, ruby: truffleruby } + - { os: ubuntu-latest, ruby: truffleruby } + - { os: macos-latest, ruby: truffleruby-head } + - { os: ubuntu-latest, ruby: truffleruby-head } steps: - uses: actions/checkout@v4 From 01f947a66ad8c5e20d8c89d9adbc7e3bd49afb70 Mon Sep 17 00:00:00 2001 From: Aaron Patterson Date: Wed, 18 Mar 2026 13:07:19 -0700 Subject: [PATCH 64/66] fix env url --- .github/workflows/release.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 10d91ed..3389e52 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -15,7 +15,7 @@ jobs: environment: name: rubygems.org - url: https://rubygems.org/gems/bcrypt-ruby + url: https://rubygems.org/gems/bcrypt permissions: contents: write From 5faa2748331d3edc661c127ef2fbb3afcb6b02a4 Mon Sep 17 00:00:00 2001 From: Kevin Farrell Date: Wed, 18 Mar 2026 16:43:13 +0000 Subject: [PATCH 65/66] Fix integer overflow in JRuby BCrypt rounds calculation [CVE-2026-33306] --- ext/jruby/bcrypt_jruby/BCrypt.java | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/ext/jruby/bcrypt_jruby/BCrypt.java b/ext/jruby/bcrypt_jruby/BCrypt.java index 86db91b..bf987d9 100644 --- a/ext/jruby/bcrypt_jruby/BCrypt.java +++ b/ext/jruby/bcrypt_jruby/BCrypt.java @@ -688,20 +688,21 @@ static long roundsForLogRounds(int log_rounds) { */ private byte[] crypt_raw(byte password[], byte salt[], int log_rounds, boolean sign_ext_bug, int safety) { - int rounds, i, j; + long rounds; + int i, j; int cdata[] = bf_crypt_ciphertext.clone(); int clen = cdata.length; byte ret[]; if (log_rounds < 4 || log_rounds > 31) throw new IllegalArgumentException ("Bad number of rounds"); - rounds = 1 << log_rounds; + rounds = roundsForLogRounds(log_rounds); if (salt.length != BCRYPT_SALT_LEN) throw new IllegalArgumentException ("Bad salt length"); init_key(); ekskey(salt, password, sign_ext_bug, safety); - for (i = 0; i < rounds; i++) { + for (long r = 0; r < rounds; r++) { key(password, sign_ext_bug, safety); key(salt, false, safety); } From 32e687ec5f62baad01a62e4634e41d97f8432a61 Mon Sep 17 00:00:00 2001 From: Aaron Patterson Date: Wed, 18 Mar 2026 15:42:34 -0700 Subject: [PATCH 66/66] bump version update changelog --- CHANGELOG | 3 +++ bcrypt.gemspec | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/CHANGELOG b/CHANGELOG index 1682923..a2c9982 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,3 +1,6 @@ +3.1.22 Mar 18 2026 + - [CVE-2026-33306] Fix integer overflow in Java extension + 3.1.21 Dec 31 2025 - Use constant time comparisons - Mark as Ractor safe diff --git a/bcrypt.gemspec b/bcrypt.gemspec index e35a402..b848c01 100644 --- a/bcrypt.gemspec +++ b/bcrypt.gemspec @@ -1,6 +1,6 @@ Gem::Specification.new do |s| s.name = 'bcrypt' - s.version = '3.1.21' + s.version = '3.1.22' s.summary = "OpenBSD's bcrypt() password hashing algorithm." s.description = <<-EOF