bcrypt 3.1.13 → 3.1.18

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 8d5e2ce3f7df5807725e03678a1d8d60d24d710aefa7a3c2636c4c71d7602911
4
- data.tar.gz: 98bcb12a01f59e508d9d523dd031bab988d453abaddde47847c34e7919b67c23
3
+ metadata.gz: ba8b7b14c18d5ad7f8dcd58b2e719925695a8af445b232d50fc21695b3cd4200
4
+ data.tar.gz: a3a566bb869dcc9001dbeae8041595152444596253d152c9a374ce9c1503d817
5
5
  SHA512:
6
- metadata.gz: 2f3bc43174cdb2f8298c81c7853c973e33f745aa1ea5ddb69121ebd953b086494005dce8a9c1861e818f38a1084c301df302ee8821ae975be2186ddbc7b07c80
7
- data.tar.gz: 9380402fbc0260e1b0590e846795324144c6d8b70c16c8a8ff3edbb93297387ee452bd1cbcd0b66126f48e99d11433ad958c1ddb4b801e586752684ad52d523f
6
+ metadata.gz: 9e21ae566338f46280af6576c42b54d6dfe9e75619c35a72b87f6401bef689be8526b3385a556f332c28d9a939ca7cd4f2104ef1483f4cc24d144ba837b69af4
7
+ data.tar.gz: 1c2e714911083b8aa457d9d16c5dd084acd6610e67a4f2c489ec137b1c503f2753d4a2c98e06446bc7771caec176b7b24a207f7395541e32c31268c8d8773551
@@ -0,0 +1,59 @@
1
+ name: Test Suite
2
+
3
+ # Run against all commits and pull requests.
4
+ on: [ push, pull_request ]
5
+
6
+ jobs:
7
+ test_matrix:
8
+
9
+ strategy:
10
+ fail-fast: false
11
+ matrix:
12
+ os:
13
+ - ubuntu
14
+ - macos
15
+ - windows
16
+ ruby:
17
+ - 2.1
18
+ - 2.2
19
+ - 2.3
20
+ - 2.4
21
+ - 2.5
22
+ - 2.6
23
+ - 2.7
24
+ - '3.0'
25
+ - 3.1
26
+ - head
27
+ - jruby
28
+ - jruby-head
29
+ - truffleruby
30
+ - truffleruby-head
31
+ - mingw
32
+ exclude:
33
+ - { os: ubuntu, ruby: mingw }
34
+ - { os: macos, ruby: mingw }
35
+ - { os: windows, ruby: truffleruby }
36
+ - { os: windows, ruby: truffleruby-head }
37
+
38
+ runs-on: ${{ matrix.os }}-latest
39
+
40
+ steps:
41
+ - uses: actions/checkout@v2
42
+ - name: Set up Ruby
43
+ uses: ruby/setup-ruby@v1
44
+ with:
45
+ ruby-version: ${{ matrix.ruby }}
46
+ bundler-cache: true
47
+ env:
48
+ JAVA_OPTS: -Djdk.io.File.enableADS=true
49
+ - name: Run tests
50
+ run: bundle exec rake default
51
+ env:
52
+ JAVA_OPTS: -Djdk.io.File.enableADS=true
53
+
54
+ finish:
55
+ runs-on: ubuntu-latest
56
+ needs: [ test_matrix ]
57
+ steps:
58
+ - name: Wait for status checks
59
+ run: echo "All Green!"
data/.gitignore CHANGED
@@ -7,3 +7,4 @@ tmp
7
7
  *.jar
8
8
  .DS_Store
9
9
  .rbenv-gemsets
10
+ Gemfile.lock
data/CHANGELOG CHANGED
@@ -1,94 +1,113 @@
1
- 1.0.0 Feb 27 2007
2
- - Initial release.
1
+ 3.1.18 May 16 2022
2
+ - Unlock GVL when calculating hashes and salts [GH #260]
3
+ - Fix compilation warnings in `ext/mri/bcrypt_ext.c` [GH #261]
3
4
 
4
- 2.0.0 Mar 07 2007
5
- - Removed BCrypt::Password#exactly_equals -- use BCrypt::Password#eql? instead.
6
- - Added BCrypt::Password#is_password?.
7
- - Refactored out BCrypt::Internals into more useful BCrypt::Engine.
8
- - Added validation of secrets -- nil is not healthy.
5
+ 3.1.17 Mar 14 2022
6
+ - Fix regex in validators to use \A and \z instead of ^ and $ [GH #121]
7
+ - Truncate secrets greater than 72 bytes in hash_secret [GH #255]
8
+ - Assorted test and doc improvements
9
9
 
10
- 2.0.1 Mar 09 2007
11
- - Fixed load path issues
12
- - Fixed crashes when hashing weird values (e.g., false, etc.)
10
+ 3.1.16 Sep 3 2020
11
+ - Fix compilation on FreeBSD. [GH #234]
13
12
 
14
- 2.0.2 Jun 06 2007
15
- - Fixed example code in the README [Winson]
16
- - Fixed Solaris compatibility [Jeremy LaTrasse, Twitter crew]
13
+ 3.1.15 July 21 2020
14
+ - Remove GVL optimization. Apparently it breaks things [GH #230]
17
15
 
18
- 2.0.3 May 07 2008
19
- - Made exception classes descend from StandardError, not Exception [Dan42]
20
- - Changed BCrypt::Engine.hash to BCrypt::Engine.hash_secret to avoid Merb
21
- sorting issues. [Lee Pope]
16
+ 3.1.14 July 21 2020
17
+ - Start calibration from the minimum cost supported by the algorithm [GH #206 by @sergey-alekseev]
22
18
 
23
- 2.0.4 Mar 09 2009
24
- - Added Ruby 1.9 compatibility. [Genki Takiuchi]
25
- - Fixed segfaults on some different types of empty strings. [Mike Pomraning]
19
+ 3.1.13 May 31 2019
20
+ - No longer include compiled binaries for Windows. See GH #173.
21
+ - Update C and Java implementations to latest versions [GH #182 by @fonica]
22
+ - Bump default cost to 12 [GH #181 by @bdewater]
23
+ - Remove explicit support for Rubies 1.8 and 1.9
24
+ - Define SKIP_GNU token when building extension (Fixes FreeBSD >= 12) [GH #189 by @adam12]
26
25
 
27
- 2.0.5 Mar 11 2009
28
- - Fixed Ruby 1.8.5 compatibility. [Mike Pomraning]
26
+ 3.1.12 May 16 2018
27
+ - Add support for Ruby 2.3, 2.4, and 2.5 in compiled Windows binaries
28
+ - Fix compatibility with libxcrypt - Fixes hash errors in Fedora 28 and Ubuntu 20 [GH #164 by @besser82]
29
29
 
30
- 2.1.0 Aug 12 2009
31
- - Improved code coverage, unit tests, and build chain. [Hongli Lai]
32
- - Ruby 1.9 compatibility fixes. [Hongli Lai]
33
- - JRuby support, using Damien Miller's jBCrypt. [Hongli Lai]
34
- - Ruby 1.9 GIL releasing for high-cost hashes. [Hongli Lai]
30
+ 3.1.11 Mar 06 2016
31
+ - Add support for Ruby 2.2 in compiled Windows binaries
35
32
 
36
- 2.1.1 Aug 14 2009
37
- - JVM 1.4/1.5 compatibility [Hongli Lai]
33
+ 3.1.10 Jan 28 2015
34
+ - Fix issue with dumping a BCrypt::Password instance to YAML in Ruby 2.2 [GH #107 by @mattwildig]
38
35
 
39
- 2.1.2 Sep 16 2009
40
- - Fixed support for Solaris, OpenSolaris.
36
+ 3.1.9 Oct 23 2014
37
+ - Rebuild corrupt binaries
41
38
 
42
- 3.0.0 Aug 24 2011
43
- - Bcrypt C implementation replaced with a public domain implementation.
44
- - License changed to MIT
39
+ 3.1.8 Oct 23 2014
40
+ - Add support for Ruby 2.1 in compiled Windows binaries [GH #102]
45
41
 
46
- 3.0.1 Sep 12 2011
47
- - create raises an exception if the cost is higher than 31. GH #27
42
+ 3.1.7 Feb 24 2014
43
+ - Rebuild corrupt Java binary version of gem [GH #90]
44
+ - The 2.1 support for Windows binaries alleged in 3.1.3 was a lie -- documentation removed
45
+
46
+ 3.1.6 Feb 21 2014
47
+ - Dummy version of "bcrypt-ruby" needed a couple version bumps to fix some
48
+ bugs. It felt wrong to have that at a higher version than the real gem, so
49
+ the real gem is getting bumped to 3.1.6.
50
+
51
+ 3.1.3 Feb 21 2014
52
+ - Add support for Ruby 2.1 in compiled Windows binaries
53
+ - Rename gem from "bcrypt-ruby" to just "bcrypt". [GH #86 by @sferik]
54
+
55
+ 3.1.2 Aug 26 2013
56
+ - Add support for Ruby 1.8 and 2.0 (in addition to 1.9) in compiled Windows binaries
57
+ - Add support for 64-bit Windows
58
+
59
+ 3.1.1 Jul 10 2013
60
+ - Remove support for Ruby 1.8 in compiled win32 binaries
48
61
 
49
62
  3.1.0 May 07 2013
50
63
  - Add BCrypt::Password.valid_hash?(str) to check if a string is a valid bcrypt password hash
51
64
  - BCrypt::Password cost should be set to DEFAULT_COST if nil
52
65
  - Add BCrypt::Engine.cost attribute for getting/setting a default cost externally
53
66
 
54
- 3.1.1 Jul 10 2013
55
- - Remove support for Ruby 1.8 in compiled win32 binaries
67
+ 3.0.1 Sep 12 2011
68
+ - create raises an exception if the cost is higher than 31. GH #27
56
69
 
57
- 3.1.2 Aug 26 2013
58
- - Add support for Ruby 1.8 and 2.0 (in addition to 1.9) in compiled Windows binaries
59
- - Add support for 64-bit Windows
70
+ 3.0.0 Aug 24 2011
71
+ - Bcrypt C implementation replaced with a public domain implementation.
72
+ - License changed to MIT
60
73
 
61
- 3.1.3 Feb 21 2014
62
- - Add support for Ruby 2.1 in compiled Windows binaries
63
- - Rename gem from "bcrypt-ruby" to just "bcrypt". [GH #86 by @sferik]
74
+ 2.1.2 Sep 16 2009
75
+ - Fixed support for Solaris, OpenSolaris.
64
76
 
65
- 3.1.6 Feb 21 2014
66
- - Dummy version of "bcrypt-ruby" needed a couple version bumps to fix some
67
- bugs. It felt wrong to have that at a higher version than the real gem, so
68
- the real gem is getting bumped to 3.1.6.
77
+ 2.1.1 Aug 14 2009
78
+ - JVM 1.4/1.5 compatibility [Hongli Lai]
69
79
 
70
- 3.1.7 Feb 24 2014
71
- - Rebuild corrupt Java binary version of gem [GH #90]
72
- - The 2.1 support for Windows binaries alleged in 3.1.3 was a lie -- documentation removed
80
+ 2.1.0 Aug 12 2009
81
+ - Improved code coverage, unit tests, and build chain. [Hongli Lai]
82
+ - Ruby 1.9 compatibility fixes. [Hongli Lai]
83
+ - JRuby support, using Damien Miller's jBCrypt. [Hongli Lai]
84
+ - Ruby 1.9 GIL releasing for high-cost hashes. [Hongli Lai]
73
85
 
74
- 3.1.8 Oct 23 2014
75
- - Add support for Ruby 2.1 in compiled Windows binaries [GH #102]
86
+ 2.0.5 Mar 11 2009
87
+ - Fixed Ruby 1.8.5 compatibility. [Mike Pomraning]
76
88
 
77
- 3.1.9 Oct 23 2014
78
- - Rebuild corrupt binaries
89
+ 2.0.4 Mar 09 2009
90
+ - Added Ruby 1.9 compatibility. [Genki Takiuchi]
91
+ - Fixed segfaults on some different types of empty strings. [Mike Pomraning]
79
92
 
80
- 3.1.10 Jan 28 2015
81
- - Fix issue with dumping a BCrypt::Password instance to YAML in Ruby 2.2 [GH #107 by @mattwildig]
93
+ 2.0.3 May 07 2008
94
+ - Made exception classes descend from StandardError, not Exception [Dan42]
95
+ - Changed BCrypt::Engine.hash to BCrypt::Engine.hash_secret to avoid Merb
96
+ sorting issues. [Lee Pope]
82
97
 
83
- 3.1.11 Mar 06 2016
84
- - Add support for Ruby 2.2 in compiled Windows binaries
98
+ 2.0.2 Jun 06 2007
99
+ - Fixed example code in the README [Winson]
100
+ - Fixed Solaris compatibility [Jeremy LaTrasse, Twitter crew]
85
101
 
86
- 3.1.12 May 16 2018
87
- - Add support for Ruby 2.3, 2.4, and 2.5 in compiled Windows binaries
88
- - Fix compatibility with libxcrypt [GH #164 by @besser82]
102
+ 2.0.1 Mar 09 2007
103
+ - Fixed load path issues
104
+ - Fixed crashes when hashing weird values (e.g., false, etc.)
89
105
 
90
- [DRAFT] 4.0.0 MMM DD YYYY
91
- - No longer include compiled binaries for Windows. See GH #173.
92
- - Update C and Java implementations to latest versions [GH #182 by @fonica]
93
- - Bump default cost to 12 [GH #181 by @bdewater]
94
- - Remove explicit support for Rubies 1.8 and 1.9
106
+ 2.0.0 Mar 07 2007
107
+ - Removed BCrypt::Password#exactly_equals -- use BCrypt::Password#eql? instead.
108
+ - Added BCrypt::Password#is_password?.
109
+ - Refactored out BCrypt::Internals into more useful BCrypt::Engine.
110
+ - Added validation of secrets -- nil is not healthy.
111
+
112
+ 1.0.0 Feb 27 2007
113
+ - Initial release.
data/README.md CHANGED
@@ -2,11 +2,9 @@
2
2
 
3
3
  An easy way to keep your users' passwords secure.
4
4
 
5
- * https://github.com/codahale/bcrypt-ruby/tree/master
6
-
7
- [![Travis Build Status](https://travis-ci.org/codahale/bcrypt-ruby.svg?branch=master)](https://travis-ci.org/codahale/bcrypt-ruby)
8
- [![AppVeyor Build Status](https://ci.appveyor.com/api/projects/status/6fplerx9lnaf0hyo?svg=true)](https://ci.appveyor.com/project/TJSchuck35975/bcrypt-ruby)
5
+ * https://github.com/bcrypt-ruby/bcrypt-ruby/tree/master
9
6
 
7
+ [![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)
10
8
 
11
9
  ## Why you should use `bcrypt()`
12
10
 
@@ -32,8 +30,8 @@ re-hash those passwords. This vulnerability only affected the JRuby gem.
32
30
  The bcrypt gem is available on the following Ruby platforms:
33
31
 
34
32
  * JRuby
35
- * RubyInstaller 2.0 – 2.5 builds on Windows with the DevKit
36
- * Any 2.0 – 2.5 Ruby on a BSD/OS X/Linux system with a compiler
33
+ * RubyInstaller 2.0 – 3.0 builds on Windows with the DevKit
34
+ * Any 2.0 – 3.0 Ruby on a BSD/OS X/Linux system with a compiler
37
35
 
38
36
  ## How to use `bcrypt()` in your Rails application
39
37
 
data/Rakefile CHANGED
@@ -50,6 +50,8 @@ end
50
50
  if RUBY_PLATFORM =~ /java/
51
51
  Rake::JavaExtensionTask.new('bcrypt_ext', GEMSPEC) do |ext|
52
52
  ext.ext_dir = 'ext/jruby'
53
+ ext.source_version = "1.7"
54
+ ext.target_version = "1.7"
53
55
  end
54
56
  else
55
57
  Rake::ExtensionTask.new("bcrypt_ext", GEMSPEC) do |ext|
data/bcrypt.gemspec CHANGED
@@ -1,6 +1,6 @@
1
1
  Gem::Specification.new do |s|
2
2
  s.name = 'bcrypt'
3
- s.version = '3.1.13'
3
+ s.version = '3.1.18'
4
4
 
5
5
  s.summary = "OpenBSD's bcrypt() password hashing algorithm."
6
6
  s.description = <<-EOF
@@ -12,7 +12,7 @@ Gem::Specification.new do |s|
12
12
  s.files = `git ls-files`.split("\n")
13
13
  s.require_path = 'lib'
14
14
 
15
- s.add_development_dependency 'rake-compiler', '~> 0.9.2'
15
+ s.add_development_dependency 'rake-compiler', '~> 1.2.0'
16
16
  s.add_development_dependency 'rspec', '>= 3'
17
17
 
18
18
  s.rdoc_options += ['--title', 'bcrypt-ruby', '--line-numbers', '--inline-source', '--main', 'README.md']
@@ -22,6 +22,6 @@ Gem::Specification.new do |s|
22
22
 
23
23
  s.authors = ["Coda Hale"]
24
24
  s.email = "coda.hale@gmail.com"
25
- s.homepage = "https://github.com/codahale/bcrypt-ruby"
25
+ s.homepage = "https://github.com/bcrypt-ruby/bcrypt-ruby"
26
26
  s.license = "MIT"
27
27
  end
data/ext/mri/bcrypt_ext.c CHANGED
@@ -1,53 +1,105 @@
1
1
  #include <ruby.h>
2
2
  #include <ow-crypt.h>
3
3
 
4
+ #ifdef HAVE_RUBY_THREAD_H
5
+ #include <ruby/thread.h>
6
+ #endif
7
+
4
8
  static VALUE mBCrypt;
5
9
  static VALUE cBCryptEngine;
6
10
 
11
+ struct bc_salt_args {
12
+ const char * prefix;
13
+ unsigned long count;
14
+ const char * input;
15
+ int size;
16
+ };
17
+
18
+ static void * bc_salt_nogvl(void * ptr) {
19
+ struct bc_salt_args * args = ptr;
20
+
21
+ return crypt_gensalt_ra(args->prefix, args->count, args->input, args->size);
22
+ }
23
+
7
24
  /* Given a logarithmic cost parameter, generates a salt for use with +bc_crypt+.
8
25
  */
9
26
  static VALUE bc_salt(VALUE self, VALUE prefix, VALUE count, VALUE input) {
10
27
  char * salt;
11
28
  VALUE str_salt;
12
-
13
- salt = crypt_gensalt_ra(
14
- StringValuePtr(prefix),
15
- NUM2ULONG(count),
16
- NIL_P(input) ? NULL : StringValuePtr(input),
17
- NIL_P(input) ? 0 : RSTRING_LEN(input));
29
+ struct bc_salt_args args;
30
+
31
+ /* duplicate the parameters for thread safety. If another thread has a
32
+ * reference to the parameters and mutates them while we are working,
33
+ * that would be very bad. Duping the strings means that the reference
34
+ * isn't shared. */
35
+ prefix = rb_str_new_frozen(prefix);
36
+ input = rb_str_new_frozen(input);
37
+
38
+ args.prefix = StringValueCStr(prefix);
39
+ args.count = NUM2ULONG(count);
40
+ args.input = NIL_P(input) ? NULL : StringValuePtr(input);
41
+ args.size = NIL_P(input) ? 0 : RSTRING_LEN(input);
42
+
43
+ #ifdef HAVE_RUBY_THREAD_H
44
+ salt = rb_thread_call_without_gvl(bc_salt_nogvl, &args, NULL, NULL);
45
+ #else
46
+ salt = bc_salt_nogvl((void *)&args);
47
+ #endif
18
48
 
19
49
  if(!salt) return Qnil;
20
50
 
21
51
  str_salt = rb_str_new2(salt);
22
- xfree(salt);
52
+ free(salt);
23
53
 
24
54
  return str_salt;
25
55
  }
26
56
 
57
+ struct bc_crypt_args {
58
+ const char * key;
59
+ const char * setting;
60
+ void * data;
61
+ int size;
62
+ };
63
+
64
+ static void * bc_crypt_nogvl(void * ptr) {
65
+ struct bc_crypt_args * args = ptr;
66
+
67
+ return crypt_ra(args->key, args->setting, &args->data, &args->size);
68
+ }
69
+
27
70
  /* Given a secret and a salt, generates a salted hash (which you can then store safely).
28
71
  */
29
72
  static VALUE bc_crypt(VALUE self, VALUE key, VALUE setting) {
30
73
  char * value;
31
- void * data;
32
- int size;
33
74
  VALUE out;
34
75
 
35
- data = NULL;
36
- size = 0xDEADBEEF;
76
+ struct bc_crypt_args args;
37
77
 
38
78
  if(NIL_P(key) || NIL_P(setting)) return Qnil;
39
79
 
40
- value = crypt_ra(
41
- NIL_P(key) ? NULL : StringValuePtr(key),
42
- NIL_P(setting) ? NULL : StringValuePtr(setting),
43
- &data,
44
- &size);
80
+ /* duplicate the parameters for thread safety. If another thread has a
81
+ * reference to the parameters and mutates them while we are working,
82
+ * that would be very bad. Duping the strings means that the reference
83
+ * isn't shared. */
84
+ key = rb_str_new_frozen(key);
85
+ setting = rb_str_new_frozen(setting);
86
+
87
+ args.data = NULL;
88
+ args.size = 0xDEADBEEF;
89
+ args.key = NIL_P(key) ? NULL : StringValueCStr(key);
90
+ args.setting = NIL_P(setting) ? NULL : StringValueCStr(setting);
91
+
92
+ #ifdef HAVE_RUBY_THREAD_H
93
+ value = rb_thread_call_without_gvl(bc_crypt_nogvl, &args, NULL, NULL);
94
+ #else
95
+ value = bc_crypt_nogvl((void *)&args);
96
+ #endif
45
97
 
46
- if(!value) return Qnil;
98
+ if(!value || !args.data) return Qnil;
47
99
 
48
100
  out = rb_str_new2(value);
49
101
 
50
- xfree(data);
102
+ free(args.data);
51
103
 
52
104
  return out;
53
105
  }
@@ -361,7 +361,7 @@ static BF_ctx BF_init_state = {
361
361
  }
362
362
  };
363
363
 
364
- static unsigned char BF_itoa64[64 + 1] =
364
+ static const unsigned char BF_itoa64[64 + 1] =
365
365
  "./ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
366
366
 
367
367
  static unsigned char BF_atoi64[0x60] = {
@@ -387,9 +387,8 @@ static int BF_decode(BF_word *dst, const char *src, int size)
387
387
  unsigned char *dptr = (unsigned char *)dst;
388
388
  unsigned char *end = dptr + size;
389
389
  const unsigned char *sptr = (const unsigned char *)src;
390
- unsigned int tmp, c1, c2, c3, c4;
391
-
392
390
  do {
391
+ unsigned int tmp, c1, c2, c3, c4;
393
392
  BF_safe_atoi64(c1, *sptr++);
394
393
  BF_safe_atoi64(c2, *sptr++);
395
394
  *dptr++ = (c1 << 2) | ((c2 & 0x30) >> 4);
@@ -402,7 +401,6 @@ static int BF_decode(BF_word *dst, const char *src, int size)
402
401
  BF_safe_atoi64(c4, *sptr++);
403
402
  *dptr++ = ((c3 & 0x03) << 6) | c4;
404
403
  } while (dptr < end);
405
-
406
404
  return 0;
407
405
  }
408
406
 
@@ -411,9 +409,8 @@ static void BF_encode(char *dst, const BF_word *src, int size)
411
409
  const unsigned char *sptr = (const unsigned char *)src;
412
410
  const unsigned char *end = sptr + size;
413
411
  unsigned char *dptr = (unsigned char *)dst;
414
- unsigned int c1, c2;
415
-
416
412
  do {
413
+ unsigned int c1, c2;
417
414
  c1 = *sptr++;
418
415
  *dptr++ = BF_itoa64[c1 >> 2];
419
416
  c1 = (c1 & 0x03) << 4;
@@ -442,10 +439,9 @@ static void BF_swap(BF_word *x, int count)
442
439
  {
443
440
  static int endianness_check = 1;
444
441
  char *is_little_endian = (char *)&endianness_check;
445
- BF_word tmp;
446
-
447
442
  if (*is_little_endian)
448
443
  do {
444
+ BF_word tmp;
449
445
  tmp = *x;
450
446
  tmp = (tmp << 16) | (tmp >> 16);
451
447
  *x++ = ((tmp & 0x00FF00FF) << 8) | ((tmp >> 8) & 0x00FF00FF);
@@ -517,7 +513,7 @@ static void BF_swap(BF_word *x, int count)
517
513
  R = L; \
518
514
  L = tmp4 ^ data.ctx.P[BF_N + 1];
519
515
 
520
- #if BF_ASM
516
+ #if BF_ASM == 1
521
517
  #define BF_body() \
522
518
  _BF_body_r(&data.ctx);
523
519
  #else
@@ -650,7 +646,7 @@ static char *BF_crypt(const char *key, const char *setting,
650
646
  char *output, int size,
651
647
  BF_word min)
652
648
  {
653
- #if BF_ASM
649
+ #if BF_ASM == 1
654
650
  extern void _BF_body_r(BF_ctx *ctx);
655
651
  #endif
656
652
  struct {
@@ -28,7 +28,7 @@
28
28
  /* Just to make sure the prototypes match the actual definitions */
29
29
  #include "crypt_gensalt.h"
30
30
 
31
- unsigned char _crypt_itoa64[64 + 1] =
31
+ const unsigned char _crypt_itoa64[64 + 1] =
32
32
  "./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
33
33
 
34
34
  char *_crypt_gensalt_traditional_rn(const char *prefix, unsigned long count,
@@ -17,7 +17,7 @@
17
17
  #ifndef _CRYPT_GENSALT_H
18
18
  #define _CRYPT_GENSALT_H
19
19
 
20
- extern unsigned char _crypt_itoa64[];
20
+ extern const unsigned char _crypt_itoa64[];
21
21
  extern char *_crypt_gensalt_traditional_rn(const char *prefix,
22
22
  unsigned long count,
23
23
  const char *input, int size, char *output, int output_size);
data/ext/mri/wrapper.c CHANGED
@@ -17,6 +17,9 @@
17
17
  #include <stdlib.h>
18
18
  #include <string.h>
19
19
 
20
+ /* Redefine strdup to ruby_strdup in case string.h doesn't export it. */
21
+ #include <ruby/util.h>
22
+
20
23
  #include <errno.h>
21
24
  #ifndef __set_errno
22
25
  #define __set_errno(val) errno = (val)
@@ -176,7 +179,7 @@ char *crypt_ra(const char *key, const char *setting,
176
179
  return _crypt_blowfish_rn(key, setting, (char *)*data, *size);
177
180
  }
178
181
 
179
- char *crypt_r(const char *key, const char *setting, void *data)
182
+ char *crypt_r(const char *key, const char *setting, struct crypt_data *data)
180
183
  {
181
184
  return _crypt_retval_magic(
182
185
  crypt_rn(key, setting, data, CRYPT_OUTPUT_SIZE),
data/ext/mri/x86.S CHANGED
@@ -199,5 +199,5 @@ BF_die:
199
199
  #endif
200
200
 
201
201
  #if defined(__ELF__) && defined(__linux__)
202
- .section .note.GNU-stack,"",@progbits
202
+ .section .note.GNU-stack,"",%progbits
203
203
  #endif
data/lib/bcrypt/engine.rb CHANGED
@@ -5,6 +5,16 @@ module BCrypt
5
5
  DEFAULT_COST = 12
6
6
  # The minimum cost supported by the algorithm.
7
7
  MIN_COST = 4
8
+ # The maximum cost supported by the algorithm.
9
+ MAX_COST = 31
10
+ # Maximum possible size of bcrypt() secrets.
11
+ # Older versions of the bcrypt library would truncate passwords longer
12
+ # than 72 bytes, but newer ones do not. We truncate like the old library for
13
+ # forward compatibility. This way users upgrading from Ubuntu 18.04 to 20.04
14
+ # will not have their user passwords invalidated, for example.
15
+ # A max secret length greater than 255 leads to bcrypt returning nil.
16
+ # https://github.com/bcrypt-ruby/bcrypt-ruby/issues/225#issuecomment-875908425
17
+ MAX_SECRET_BYTESIZE = 72
8
18
  # Maximum possible size of bcrypt() salts.
9
19
  MAX_SALT_LENGTH = 16
10
20
 
@@ -41,14 +51,16 @@ module BCrypt
41
51
  end
42
52
 
43
53
  # Given a secret and a valid salt (see BCrypt::Engine.generate_salt) calculates
44
- # a bcrypt() password hash.
54
+ # a bcrypt() password hash. Secrets longer than 72 bytes are truncated.
45
55
  def self.hash_secret(secret, salt, _ = nil)
46
56
  if valid_secret?(secret)
47
57
  if valid_salt?(salt)
48
58
  if RUBY_PLATFORM == "java"
49
59
  Java.bcrypt_jruby.BCrypt.hashpw(secret.to_s.to_java_bytes, salt.to_s)
50
60
  else
51
- __bc_crypt(secret.to_s, salt)
61
+ secret = secret.to_s
62
+ secret = secret.byteslice(0, MAX_SECRET_BYTESIZE) if secret && secret.bytesize > MAX_SECRET_BYTESIZE
63
+ __bc_crypt(secret, salt)
52
64
  end
53
65
  else
54
66
  raise Errors::InvalidSalt.new("invalid salt")
@@ -68,8 +80,7 @@ module BCrypt
68
80
  if RUBY_PLATFORM == "java"
69
81
  Java.bcrypt_jruby.BCrypt.gensalt(cost)
70
82
  else
71
- prefix = "$2a$05$CCCCCCCCCCCCCCCCCCCCC.E5YPO9kmyuRGyh0XouQYb4YMJKvyOeW"
72
- __bc_salt(prefix, cost, OpenSSL::Random.random_bytes(MAX_SALT_LENGTH))
83
+ __bc_salt("$2a$", cost, OpenSSL::Random.random_bytes(MAX_SALT_LENGTH))
73
84
  end
74
85
  else
75
86
  raise Errors::InvalidCost.new("cost must be numeric and > 0")
@@ -78,7 +89,7 @@ module BCrypt
78
89
 
79
90
  # Returns true if +salt+ is a valid bcrypt() salt, false if not.
80
91
  def self.valid_salt?(salt)
81
- !!(salt =~ /^\$[0-9a-z]{2,}\$[0-9]{2,}\$[A-Za-z0-9\.\/]{22,}$/)
92
+ !!(salt =~ /\A\$[0-9a-z]{2,}\$[0-9]{2,}\$[A-Za-z0-9\.\/]{22,}\z/)
82
93
  end
83
94
 
84
95
  # Returns true if +secret+ is a valid bcrypt() secret, false if not.
@@ -99,7 +110,7 @@ module BCrypt
99
110
  # # should take less than 1000ms
100
111
  # BCrypt::Password.create("woo", :cost => 12)
101
112
  def self.calibrate(upper_time_limit_in_ms)
102
- 40.times do |i|
113
+ (BCrypt::Engine::MIN_COST..BCrypt::Engine::MAX_COST-1).each do |i|
103
114
  start_time = Time.now
104
115
  Password.create("testing testing", :cost => i+1)
105
116
  end_time = Time.now - start_time
@@ -42,12 +42,12 @@ module BCrypt
42
42
  # @password = BCrypt::Password.create("my secret", :cost => 13)
43
43
  def create(secret, options = {})
44
44
  cost = options[:cost] || BCrypt::Engine.cost
45
- raise ArgumentError if cost > 31
45
+ raise ArgumentError if cost > BCrypt::Engine::MAX_COST
46
46
  Password.new(BCrypt::Engine.hash_secret(secret, BCrypt::Engine.generate_salt(cost)))
47
47
  end
48
48
 
49
49
  def valid_hash?(h)
50
- h =~ /^\$[0-9a-z]{2}\$[0-9]{2}\$[A-Za-z0-9\.\/]{53}$/
50
+ /\A\$[0-9a-z]{2}\$[0-9]{2}\$[A-Za-z0-9\.\/]{53}\z/ === h
51
51
  end
52
52
  end
53
53
 
@@ -62,6 +62,17 @@ module BCrypt
62
62
  end
63
63
 
64
64
  # Compares a potential secret against the hash. Returns true if the secret is the original secret, false otherwise.
65
+ #
66
+ # Comparison edge case/gotcha:
67
+ #
68
+ # secret = "my secret"
69
+ # @password = BCrypt::Password.create(secret)
70
+ #
71
+ # @password == secret # => True
72
+ # @password == @password # => False
73
+ # @password == @password.to_s # => False
74
+ # @password.to_s == @password # => True
75
+ # @password.to_s == @password.to_s # => True
65
76
  def ==(secret)
66
77
  super(BCrypt::Engine.hash_secret(secret, @salt))
67
78
  end
@@ -83,5 +94,4 @@ module BCrypt
83
94
  return v.to_str, c.to_i, h[0, 29].to_str, mash[-31, 31].to_str
84
95
  end
85
96
  end
86
-
87
97
  end
@@ -1,9 +1,23 @@
1
1
  require File.expand_path(File.join(File.dirname(__FILE__), "..", "spec_helper"))
2
+ require 'securerandom'
3
+
4
+ describe 'BCrypt::Engine' do
5
+ describe '.calibrate(upper_time_limit_in_ms)' do
6
+ context 'a tiny upper time limit provided' do
7
+ it 'returns a minimum cost supported by the algorithm' do
8
+ expect(BCrypt::Engine.calibrate(0.001)).to eq(4)
9
+ end
10
+ end
11
+ end
12
+ end
2
13
 
3
14
  describe "The BCrypt engine" do
4
15
  specify "should calculate the optimal cost factor to fit in a specific time" do
5
- first = BCrypt::Engine.calibrate(100)
6
- second = BCrypt::Engine.calibrate(400)
16
+ start_time = Time.now
17
+ BCrypt::Password.create("testing testing", :cost => BCrypt::Engine::MIN_COST + 1)
18
+ min_time_ms = (Time.now - start_time) * 1000
19
+ first = BCrypt::Engine.calibrate(min_time_ms)
20
+ second = BCrypt::Engine.calibrate(min_time_ms * 4)
7
21
  expect(second).to be > first
8
22
  end
9
23
  end
@@ -144,4 +158,19 @@ describe "Generating BCrypt hashes" do
144
158
  expect(BCrypt::Engine.hash_secret(secret, salt)).to eql(test_vector)
145
159
  end
146
160
  end
161
+
162
+ specify "should truncate long 1-byte character secrets to 72 bytes" do
163
+ # 'b' as a base triggers the failure at 256 characters, but 'a' does not.
164
+ too_long_secret = 'b'*(BCrypt::Engine::MAX_SECRET_BYTESIZE + 1)
165
+ just_right_secret = 'b'*BCrypt::Engine::MAX_SECRET_BYTESIZE
166
+ expect(BCrypt::Engine.hash_secret(too_long_secret, @salt)).to eq(BCrypt::Engine.hash_secret(just_right_secret, @salt))
167
+ end
168
+
169
+ specify "should truncate long multi-byte character secrets to 72 bytes" do
170
+ # 256 times causes bcrypt to return nil for libxcrypt > 4.4.18-4.
171
+ too_long_secret = '𐐷'*256
172
+ # 𐐷 takes 4 bytes in UTF-8. 18 times is 72 bytes
173
+ just_right_secret = '𐐷'*18
174
+ expect(BCrypt::Engine.hash_secret(too_long_secret, @salt)).to eq(BCrypt::Engine.hash_secret(just_right_secret, @salt))
175
+ end
147
176
  end
@@ -1,4 +1,5 @@
1
1
  require File.expand_path(File.join(File.dirname(__FILE__), "..", "spec_helper"))
2
+ require 'securerandom'
2
3
 
3
4
  describe "Creating a hashed password" do
4
5
 
@@ -26,6 +27,10 @@ describe "Creating a hashed password" do
26
27
  expect { BCrypt::Password.create( "" ) }.not_to raise_error
27
28
  expect { BCrypt::Password.create( String.new ) }.not_to raise_error
28
29
  end
30
+
31
+ specify "should tolerate very long string secrets" do
32
+ expect { BCrypt::Password.create("abcd"*1024) }.not_to raise_error
33
+ end
29
34
  end
30
35
 
31
36
  describe "Reading a hashed password" do
@@ -108,6 +113,7 @@ end
108
113
  describe "Validating a generated salt" do
109
114
  specify "should not accept an invalid salt" do
110
115
  expect(BCrypt::Engine.valid_salt?("invalid")).to eq(false)
116
+ expect(BCrypt::Engine.valid_salt?("invalid\n#{BCrypt::Engine.generate_salt}\ninvalid")).to eq(false)
111
117
  end
112
118
  specify "should accept a valid salt" do
113
119
  expect(BCrypt::Engine.valid_salt?(BCrypt::Engine.generate_salt)).to eq(true)
@@ -116,9 +122,10 @@ end
116
122
 
117
123
  describe "Validating a password hash" do
118
124
  specify "should not accept an invalid password" do
119
- expect(BCrypt::Password.valid_hash?("i_am_so_not_valid")).to be_falsey
125
+ expect(BCrypt::Password.valid_hash?("i_am_so_not_valid")).to be(false)
126
+ expect(BCrypt::Password.valid_hash?("invalid\n#{BCrypt::Password.create "i_am_so_valid"}\ninvalid")).to be(false)
120
127
  end
121
128
  specify "should accept a valid password" do
122
- expect(BCrypt::Password.valid_hash?(BCrypt::Password.create "i_am_so_valid")).to be_truthy
129
+ expect(BCrypt::Password.valid_hash?(BCrypt::Password.create "i_am_so_valid")).to be(true)
123
130
  end
124
131
  end
metadata CHANGED
@@ -1,38 +1,38 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: bcrypt
3
3
  version: !ruby/object:Gem::Version
4
- version: 3.1.13
4
+ version: 3.1.18
5
5
  platform: ruby
6
6
  authors:
7
7
  - Coda Hale
8
- autorequire:
8
+ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2019-05-31 00:00:00.000000000 Z
11
+ date: 2022-05-16 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
+ name: rake-compiler
14
15
  requirement: !ruby/object:Gem::Requirement
15
16
  requirements:
16
17
  - - "~>"
17
18
  - !ruby/object:Gem::Version
18
- version: 0.9.2
19
- name: rake-compiler
20
- prerelease: false
19
+ version: 1.2.0
21
20
  type: :development
21
+ prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
24
  - - "~>"
25
25
  - !ruby/object:Gem::Version
26
- version: 0.9.2
26
+ version: 1.2.0
27
27
  - !ruby/object:Gem::Dependency
28
+ name: rspec
28
29
  requirement: !ruby/object:Gem::Requirement
29
30
  requirements:
30
31
  - - ">="
31
32
  - !ruby/object:Gem::Version
32
33
  version: '3'
33
- name: rspec
34
- prerelease: false
35
34
  type: :development
35
+ prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
38
  - - ">="
@@ -50,21 +50,19 @@ extra_rdoc_files:
50
50
  - README.md
51
51
  - COPYING
52
52
  - CHANGELOG
53
- - lib/bcrypt.rb
54
53
  - lib/bcrypt/password.rb
55
54
  - lib/bcrypt/engine.rb
56
55
  - lib/bcrypt/error.rb
56
+ - lib/bcrypt.rb
57
57
  files:
58
+ - ".github/workflows/ruby.yml"
58
59
  - ".gitignore"
59
60
  - ".rspec"
60
- - ".travis.yml"
61
61
  - CHANGELOG
62
62
  - COPYING
63
63
  - Gemfile
64
- - Gemfile.lock
65
64
  - README.md
66
65
  - Rakefile
67
- - appveyor.yml
68
66
  - bcrypt.gemspec
69
67
  - ext/jruby/bcrypt_jruby/BCrypt.java
70
68
  - ext/mri/bcrypt_ext.c
@@ -87,11 +85,11 @@ files:
87
85
  - spec/bcrypt/error_spec.rb
88
86
  - spec/bcrypt/password_spec.rb
89
87
  - spec/spec_helper.rb
90
- homepage: https://github.com/codahale/bcrypt-ruby
88
+ homepage: https://github.com/bcrypt-ruby/bcrypt-ruby
91
89
  licenses:
92
90
  - MIT
93
91
  metadata: {}
94
- post_install_message:
92
+ post_install_message:
95
93
  rdoc_options:
96
94
  - "--title"
97
95
  - bcrypt-ruby
@@ -112,9 +110,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
112
110
  - !ruby/object:Gem::Version
113
111
  version: '0'
114
112
  requirements: []
115
- rubyforge_project:
116
- rubygems_version: 2.7.6
117
- signing_key:
113
+ rubygems_version: 3.1.4
114
+ signing_key:
118
115
  specification_version: 4
119
116
  summary: OpenBSD's bcrypt() password hashing algorithm.
120
117
  test_files: []
data/.travis.yml DELETED
@@ -1,17 +0,0 @@
1
- language: ruby
2
- before_install:
3
- - "echo 'gem: --no-rdoc --no-ri' > ~/.gemrc"
4
- - gem update --system 2.7.8
5
- - gem install bundler -v 1.17.3
6
- rvm:
7
- - 2.0
8
- - 2.1
9
- - 2.2
10
- - 2.3
11
- - 2.4
12
- - 2.5
13
- - 2.6
14
- - ruby-head
15
- - jruby-head
16
- - rbx-3
17
- script: bundle exec rake
data/Gemfile.lock DELETED
@@ -1,37 +0,0 @@
1
- PATH
2
- remote: .
3
- specs:
4
- bcrypt (3.1.13)
5
-
6
- GEM
7
- remote: https://rubygems.org/
8
- specs:
9
- diff-lcs (1.3)
10
- rake (12.3.2)
11
- rake-compiler (0.9.9)
12
- rake
13
- rspec (3.8.0)
14
- rspec-core (~> 3.8.0)
15
- rspec-expectations (~> 3.8.0)
16
- rspec-mocks (~> 3.8.0)
17
- rspec-core (3.8.0)
18
- rspec-support (~> 3.8.0)
19
- rspec-expectations (3.8.3)
20
- diff-lcs (>= 1.2.0, < 2.0)
21
- rspec-support (~> 3.8.0)
22
- rspec-mocks (3.8.0)
23
- diff-lcs (>= 1.2.0, < 2.0)
24
- rspec-support (~> 3.8.0)
25
- rspec-support (3.8.0)
26
-
27
- PLATFORMS
28
- java
29
- ruby
30
-
31
- DEPENDENCIES
32
- bcrypt!
33
- rake-compiler (~> 0.9.2)
34
- rspec (>= 3)
35
-
36
- BUNDLED WITH
37
- 1.16.1
data/appveyor.yml DELETED
@@ -1,50 +0,0 @@
1
- version: "{branch}-{build}"
2
- build: off
3
- clone_depth: 1
4
-
5
- init:
6
- # Install Ruby head
7
- - if %RUBY_VERSION%==head (
8
- appveyor DownloadFile https://github.com/oneclick/rubyinstaller2/releases/download/rubyinstaller-head/rubyinstaller-head-x86.exe -FileName C:\head_x86.exe &
9
- C:\head_x86.exe /verysilent /dir=C:\Ruby%RUBY_VERSION%
10
- )
11
- - if %RUBY_VERSION%==head-x64 (
12
- appveyor DownloadFile https://github.com/oneclick/rubyinstaller2/releases/download/rubyinstaller-head/rubyinstaller-head-x64.exe -FileName C:\head_x64.exe &
13
- C:\head_x64.exe /verysilent /dir=C:\Ruby%RUBY_VERSION%
14
- )
15
-
16
- # Add Ruby to the path
17
- - set PATH=C:\Ruby%RUBY_VERSION%\bin;%PATH%
18
-
19
- environment:
20
- matrix:
21
- - RUBY_VERSION: "head"
22
- - RUBY_VERSION: "head-x64"
23
- - RUBY_VERSION: "25"
24
- - RUBY_VERSION: "25-x64"
25
- - RUBY_VERSION: "24"
26
- - RUBY_VERSION: "24-x64"
27
- - RUBY_VERSION: "23"
28
- - RUBY_VERSION: "23-x64"
29
- - RUBY_VERSION: "22"
30
- - RUBY_VERSION: "22-x64"
31
- - RUBY_VERSION: "21"
32
- - RUBY_VERSION: "21-x64"
33
- - RUBY_VERSION: "200"
34
- - RUBY_VERSION: "200-x64"
35
-
36
- install:
37
- - ps: "Set-Content -Value 'gem: --no-ri --no-rdoc ' -Path C:\\ProgramData\\gemrc"
38
- - if %RUBY_VERSION%==head ( gem install bundler -v'< 2' )
39
- - if %RUBY_VERSION%==head-x64 ( gem install bundler -v'< 2' )
40
- - bundle install
41
-
42
- before_build:
43
- - ruby -v
44
- - gem -v
45
-
46
- build_script:
47
- - bundle exec rake compile -rdevkit
48
-
49
- test_script:
50
- - bundle exec rake spec