bcrypt 3.1.16 → 3.1.22

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: 24a80205a939e463319b4dd986b58cd5a4d43e66e864818e0c7efa7767e25cdc
4
- data.tar.gz: 964599e45299ac4964773f2ede8e6a20eab2511910fecac3512e284bfff09a1b
3
+ metadata.gz: 521c5039d4a683bdf17faa98c3fddc47318f415597bd7575615c1f309ba65a4d
4
+ data.tar.gz: 9abdb8766bcfdc8cfeacbe41eb66fd0a8436ad5b1e9ff67b18239019387be3a1
5
5
  SHA512:
6
- metadata.gz: 87542a66be75234db706e7f2995d4bee03e0b19611bb9bfa19e21c923656d863dfa5fadee6829e779b726a4370351734f92315f29ef8facbe89b90c930202d19
7
- data.tar.gz: 6d4cd84d8e2bda4067c3816a339503257662c6f0eafcaffc7ba4aa05dacb76d4cd3d39e6c6f51951caf7f5d2ea325a81dcce374982aa3fdf57624d534b3c2ae5
6
+ metadata.gz: 6ce98e4f36915b8fb3dc2cc5a0dadb7624914bbfabd8d5e804ac1c945c8fe23794c1a3652841634766c5fe8876cd06ccb04b737c84f54e6b4bca82701d529c07
7
+ data.tar.gz: 9a2eddcb94fa016dfae3e46901df0cd5f9afd30c63789eb4682cf9fc7b55cc3348e1822663a4c4cff9f277d26a6f907ba139d2578fb1510b58559ee76d58d2ce
data/CHANGELOG CHANGED
@@ -1,3 +1,26 @@
1
+ 3.1.22 Mar 18 2026
2
+ - [CVE-2026-33306] Fix integer overflow in Java extension
3
+
4
+ 3.1.21 Dec 31 2025
5
+ - Use constant time comparisons
6
+ - Mark as Ractor safe
7
+
8
+ 3.1.20 Nov 17 2023
9
+ - Limit packaged files -- decrease gem filesize by ~28% [GH #272 by @pusewicz]
10
+
11
+ 3.1.19 June 22 2023
12
+ - Deprecate passing the third argument to `BCrypt::Engine.hash_secret` [GH #207 by @sergey-alekseev]
13
+ - Add GC guards so the C compiler won't optimize out references [GH #270]
14
+
15
+ 3.1.18 May 16 2022
16
+ - Unlock GVL when calculating hashes and salts [GH #260]
17
+ - Fix compilation warnings in `ext/mri/bcrypt_ext.c` [GH #261]
18
+
19
+ 3.1.17 Mar 14 2022
20
+ - Fix regex in validators to use \A and \z instead of ^ and $ [GH #121]
21
+ - Truncate secrets greater than 72 bytes in hash_secret [GH #255]
22
+ - Assorted test and doc improvements
23
+
1
24
  3.1.16 Sep 3 2020
2
25
  - Fix compilation on FreeBSD. [GH #234]
3
26
 
@@ -16,7 +39,7 @@
16
39
 
17
40
  3.1.12 May 16 2018
18
41
  - Add support for Ruby 2.3, 2.4, and 2.5 in compiled Windows binaries
19
- - Fix compatibility with libxcrypt [GH #164 by @besser82]
42
+ - Fix compatibility with libxcrypt - Fixes hash errors in Fedora 28 and Ubuntu 20 [GH #164 by @besser82]
20
43
 
21
44
  3.1.11 Mar 06 2016
22
45
  - Add support for Ruby 2.2 in compiled Windows binaries
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 builds on Windows with the DevKit
34
+ * Any modern 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
 
@@ -688,20 +688,21 @@ public class BCrypt {
688
688
  */
689
689
  private byte[] crypt_raw(byte password[], byte salt[], int log_rounds,
690
690
  boolean sign_ext_bug, int safety) {
691
- int rounds, i, j;
691
+ long rounds;
692
+ int i, j;
692
693
  int cdata[] = bf_crypt_ciphertext.clone();
693
694
  int clen = cdata.length;
694
695
  byte ret[];
695
696
 
696
697
  if (log_rounds < 4 || log_rounds > 31)
697
698
  throw new IllegalArgumentException ("Bad number of rounds");
698
- rounds = 1 << log_rounds;
699
+ rounds = roundsForLogRounds(log_rounds);
699
700
  if (salt.length != BCRYPT_SALT_LEN)
700
701
  throw new IllegalArgumentException ("Bad salt length");
701
702
 
702
703
  init_key();
703
704
  ekskey(salt, password, sign_ext_bug, safety);
704
- for (i = 0; i < rounds; i++) {
705
+ for (long r = 0; r < rounds; r++) {
705
706
  key(password, sign_ext_bug, safety);
706
707
  key(salt, false, safety);
707
708
  }
data/ext/mri/bcrypt_ext.c CHANGED
@@ -1,59 +1,120 @@
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);
52
+
53
+ RB_GC_GUARD(prefix);
54
+ RB_GC_GUARD(input);
22
55
  free(salt);
23
56
 
24
57
  return str_salt;
25
58
  }
26
59
 
60
+ struct bc_crypt_args {
61
+ const char * key;
62
+ const char * setting;
63
+ void * data;
64
+ int size;
65
+ };
66
+
67
+ static void * bc_crypt_nogvl(void * ptr) {
68
+ struct bc_crypt_args * args = ptr;
69
+
70
+ return crypt_ra(args->key, args->setting, &args->data, &args->size);
71
+ }
72
+
27
73
  /* Given a secret and a salt, generates a salted hash (which you can then store safely).
28
74
  */
29
75
  static VALUE bc_crypt(VALUE self, VALUE key, VALUE setting) {
30
76
  char * value;
31
- void * data;
32
- int size;
33
77
  VALUE out;
34
78
 
35
- data = NULL;
36
- size = 0xDEADBEEF;
79
+ struct bc_crypt_args args;
37
80
 
38
81
  if(NIL_P(key) || NIL_P(setting)) return Qnil;
39
82
 
40
- value = crypt_ra(
41
- NIL_P(key) ? NULL : StringValuePtr(key),
42
- NIL_P(setting) ? NULL : StringValuePtr(setting),
43
- &data,
44
- &size);
83
+ /* duplicate the parameters for thread safety. If another thread has a
84
+ * reference to the parameters and mutates them while we are working,
85
+ * that would be very bad. Duping the strings means that the reference
86
+ * isn't shared. */
87
+ key = rb_str_new_frozen(key);
88
+ setting = rb_str_new_frozen(setting);
89
+
90
+ args.data = NULL;
91
+ args.size = 0xDEADBEEF;
92
+ args.key = NIL_P(key) ? NULL : StringValueCStr(key);
93
+ args.setting = NIL_P(setting) ? NULL : StringValueCStr(setting);
94
+
95
+ #ifdef HAVE_RUBY_THREAD_H
96
+ value = rb_thread_call_without_gvl(bc_crypt_nogvl, &args, NULL, NULL);
97
+ #else
98
+ value = bc_crypt_nogvl((void *)&args);
99
+ #endif
45
100
 
46
- if(!value || !data) return Qnil;
101
+ if(!value || !args.data) return Qnil;
47
102
 
48
103
  out = rb_str_new2(value);
49
104
 
50
- xfree(data);
105
+ RB_GC_GUARD(key);
106
+ RB_GC_GUARD(setting);
107
+ free(args.data);
51
108
 
52
109
  return out;
53
110
  }
54
111
 
55
112
  /* Create the BCrypt and BCrypt::Engine modules, and populate them with methods. */
56
113
  void Init_bcrypt_ext(){
114
+ #ifdef HAVE_RB_EXT_RACTOR_SAFE
115
+ rb_ext_ractor_safe(true);
116
+ #endif
117
+
57
118
  mBCrypt = rb_define_module("BCrypt");
58
119
  cBCryptEngine = rb_define_class_under(mBCrypt, "Engine", rb_cObject);
59
120
 
data/lib/bcrypt/engine.rb CHANGED
@@ -7,6 +7,14 @@ module BCrypt
7
7
  MIN_COST = 4
8
8
  # The maximum cost supported by the algorithm.
9
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
10
18
  # Maximum possible size of bcrypt() salts.
11
19
  MAX_SALT_LENGTH = 16
12
20
 
@@ -43,14 +51,23 @@ module BCrypt
43
51
  end
44
52
 
45
53
  # Given a secret and a valid salt (see BCrypt::Engine.generate_salt) calculates
46
- # a bcrypt() password hash.
54
+ # a bcrypt() password hash. Secrets longer than 72 bytes are truncated.
47
55
  def self.hash_secret(secret, salt, _ = nil)
56
+ unless _.nil?
57
+ warn "[DEPRECATION] Passing the third argument to " \
58
+ "`BCrypt::Engine.hash_secret` is deprecated. " \
59
+ "Please do not pass the third argument which " \
60
+ "is currently not used."
61
+ end
62
+
48
63
  if valid_secret?(secret)
49
64
  if valid_salt?(salt)
50
65
  if RUBY_PLATFORM == "java"
51
66
  Java.bcrypt_jruby.BCrypt.hashpw(secret.to_s.to_java_bytes, salt.to_s)
52
67
  else
53
- __bc_crypt(secret.to_s, salt)
68
+ secret = secret.to_s
69
+ secret = secret.byteslice(0, MAX_SECRET_BYTESIZE) if secret && secret.bytesize > MAX_SECRET_BYTESIZE
70
+ __bc_crypt(secret, salt)
54
71
  end
55
72
  else
56
73
  raise Errors::InvalidSalt.new("invalid salt")
@@ -70,8 +87,7 @@ module BCrypt
70
87
  if RUBY_PLATFORM == "java"
71
88
  Java.bcrypt_jruby.BCrypt.gensalt(cost)
72
89
  else
73
- prefix = "$2a$05$CCCCCCCCCCCCCCCCCCCCC.E5YPO9kmyuRGyh0XouQYb4YMJKvyOeW"
74
- __bc_salt(prefix, cost, OpenSSL::Random.random_bytes(MAX_SALT_LENGTH))
90
+ __bc_salt("$2a$", cost, OpenSSL::Random.random_bytes(MAX_SALT_LENGTH))
75
91
  end
76
92
  else
77
93
  raise Errors::InvalidCost.new("cost must be numeric and > 0")
@@ -80,7 +96,7 @@ module BCrypt
80
96
 
81
97
  # Returns true if +salt+ is a valid bcrypt() salt, false if not.
82
98
  def self.valid_salt?(salt)
83
- !!(salt =~ /^\$[0-9a-z]{2,}\$[0-9]{2,}\$[A-Za-z0-9\.\/]{22,}$/)
99
+ !!(salt =~ /\A\$[0-9a-z]{2,}\$[0-9]{2,}\$[A-Za-z0-9\.\/]{22,}\z/)
84
100
  end
85
101
 
86
102
  # Returns true if +secret+ is a valid bcrypt() secret, false if not.
@@ -47,7 +47,7 @@ module BCrypt
47
47
  end
48
48
 
49
49
  def valid_hash?(h)
50
- /^\$[0-9a-z]{2}\$[0-9]{2}\$[A-Za-z0-9\.\/]{53}$/ === h
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,8 +62,28 @@ 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
76
+ #
77
+ # secret == @password # => probably False, because the secret is not a BCrypt::Password instance.
65
78
  def ==(secret)
66
- super(BCrypt::Engine.hash_secret(secret, @salt))
79
+ hash = BCrypt::Engine.hash_secret(secret, @salt)
80
+
81
+ return false if hash.strip.empty? || strip.empty? || hash.bytesize != bytesize
82
+
83
+ # Constant time comparison so they can't tell the length.
84
+ res = 0
85
+ bytesize.times { |i| res |= getbyte(i) ^ hash.getbyte(i) }
86
+ res == 0
67
87
  end
68
88
  alias_method :is_password?, :==
69
89
 
@@ -83,5 +103,4 @@ module BCrypt
83
103
  return v.to_str, c.to_i, h[0, 29].to_str, mash[-31, 31].to_str
84
104
  end
85
105
  end
86
-
87
106
  end
metadata CHANGED
@@ -1,36 +1,35 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: bcrypt
3
3
  version: !ruby/object:Gem::Version
4
- version: 3.1.16
4
+ version: 3.1.22
5
5
  platform: ruby
6
6
  authors:
7
7
  - Coda Hale
8
- autorequire:
9
8
  bindir: bin
10
9
  cert_chain: []
11
- date: 2020-09-03 00:00:00.000000000 Z
10
+ date: 1980-01-02 00:00:00.000000000 Z
12
11
  dependencies:
13
12
  - !ruby/object:Gem::Dependency
13
+ name: rake-compiler
14
14
  requirement: !ruby/object:Gem::Requirement
15
15
  requirements:
16
16
  - - "~>"
17
17
  - !ruby/object:Gem::Version
18
- version: 0.9.2
19
- name: rake-compiler
18
+ version: 1.2.0
20
19
  type: :development
21
20
  prerelease: false
22
21
  version_requirements: !ruby/object:Gem::Requirement
23
22
  requirements:
24
23
  - - "~>"
25
24
  - !ruby/object:Gem::Version
26
- version: 0.9.2
25
+ version: 1.2.0
27
26
  - !ruby/object:Gem::Dependency
27
+ name: rspec
28
28
  requirement: !ruby/object:Gem::Requirement
29
29
  requirements:
30
30
  - - ">="
31
31
  - !ruby/object:Gem::Version
32
32
  version: '3'
33
- name: rspec
34
33
  type: :development
35
34
  prerelease: false
36
35
  version_requirements: !ruby/object:Gem::Requirement
@@ -38,6 +37,34 @@ dependencies:
38
37
  - - ">="
39
38
  - !ruby/object:Gem::Version
40
39
  version: '3'
40
+ - !ruby/object:Gem::Dependency
41
+ name: rdoc
42
+ requirement: !ruby/object:Gem::Requirement
43
+ requirements:
44
+ - - ">="
45
+ - !ruby/object:Gem::Version
46
+ version: 7.0.3
47
+ type: :development
48
+ prerelease: false
49
+ version_requirements: !ruby/object:Gem::Requirement
50
+ requirements:
51
+ - - ">="
52
+ - !ruby/object:Gem::Version
53
+ version: 7.0.3
54
+ - !ruby/object:Gem::Dependency
55
+ name: benchmark
56
+ requirement: !ruby/object:Gem::Requirement
57
+ requirements:
58
+ - - ">="
59
+ - !ruby/object:Gem::Version
60
+ version: 0.5.0
61
+ type: :development
62
+ prerelease: false
63
+ version_requirements: !ruby/object:Gem::Requirement
64
+ requirements:
65
+ - - ">="
66
+ - !ruby/object:Gem::Version
67
+ version: 0.5.0
41
68
  description: |2
42
69
  bcrypt() is a sophisticated and secure hash algorithm designed by The OpenBSD project
43
70
  for hashing passwords. The bcrypt Ruby gem provides a simple wrapper for safely handling
@@ -47,24 +74,17 @@ executables: []
47
74
  extensions:
48
75
  - ext/mri/extconf.rb
49
76
  extra_rdoc_files:
50
- - README.md
51
- - COPYING
52
77
  - CHANGELOG
78
+ - COPYING
79
+ - README.md
53
80
  - lib/bcrypt.rb
54
- - lib/bcrypt/password.rb
55
81
  - lib/bcrypt/engine.rb
56
82
  - lib/bcrypt/error.rb
83
+ - lib/bcrypt/password.rb
57
84
  files:
58
- - ".gitignore"
59
- - ".rspec"
60
- - ".travis.yml"
61
85
  - CHANGELOG
62
86
  - COPYING
63
- - Gemfile
64
87
  - README.md
65
- - Rakefile
66
- - appveyor.yml
67
- - bcrypt.gemspec
68
88
  - ext/jruby/bcrypt_jruby/BCrypt.java
69
89
  - ext/mri/bcrypt_ext.c
70
90
  - ext/mri/crypt.c
@@ -81,16 +101,11 @@ files:
81
101
  - lib/bcrypt/engine.rb
82
102
  - lib/bcrypt/error.rb
83
103
  - lib/bcrypt/password.rb
84
- - spec/TestBCrypt.java
85
- - spec/bcrypt/engine_spec.rb
86
- - spec/bcrypt/error_spec.rb
87
- - spec/bcrypt/password_spec.rb
88
- - spec/spec_helper.rb
89
- homepage: https://github.com/codahale/bcrypt-ruby
104
+ homepage: https://github.com/bcrypt-ruby/bcrypt-ruby
90
105
  licenses:
91
106
  - MIT
92
- metadata: {}
93
- post_install_message:
107
+ metadata:
108
+ changelog_uri: https://github.com/bcrypt-ruby/bcrypt-ruby/blob/master/CHANGELOG
94
109
  rdoc_options:
95
110
  - "--title"
96
111
  - bcrypt-ruby
@@ -111,8 +126,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
111
126
  - !ruby/object:Gem::Version
112
127
  version: '0'
113
128
  requirements: []
114
- rubygems_version: 3.0.6
115
- signing_key:
129
+ rubygems_version: 4.0.6
116
130
  specification_version: 4
117
131
  summary: OpenBSD's bcrypt() password hashing algorithm.
118
132
  test_files: []
data/.gitignore DELETED
@@ -1,9 +0,0 @@
1
- doc
2
- pkg
3
- tmp
4
- *.o
5
- *.bundle
6
- *.so
7
- *.jar
8
- .DS_Store
9
- .rbenv-gemsets
data/.rspec DELETED
@@ -1,3 +0,0 @@
1
- --color
2
- --backtrace
3
- --format documentation
data/.travis.yml DELETED
@@ -1,22 +0,0 @@
1
- language: ruby
2
- before_install:
3
- - "echo 'gem: --no-rdoc --no-ri' > ~/.gemrc"
4
- rvm:
5
- - 2.0
6
- - 2.1
7
- - 2.2
8
- - 2.3
9
- - 2.4
10
- - 2.5
11
- - 2.6
12
- - 2.7
13
- - ruby-head
14
- - jruby-head
15
- - rbx-3
16
- matrix:
17
- allow_failures:
18
- - rvm: ruby-head
19
- - rvm: jruby-head
20
- - rvm: rbx-3
21
- fast_finish: true
22
- script: bundle exec rake
data/Gemfile DELETED
@@ -1,2 +0,0 @@
1
- source 'https://rubygems.org'
2
- gemspec
data/Rakefile DELETED
@@ -1,72 +0,0 @@
1
- require 'rspec/core/rake_task'
2
- require 'rubygems/package_task'
3
- require 'rake/extensiontask'
4
- require 'rake/javaextensiontask'
5
- require 'rake/clean'
6
- require 'rdoc/task'
7
- require 'benchmark'
8
-
9
- CLEAN.include(
10
- "tmp",
11
- "lib/bcrypt_ext.jar",
12
- "lib/bcrypt_ext.so"
13
- )
14
- CLOBBER.include(
15
- "doc",
16
- "pkg"
17
- )
18
-
19
- GEMSPEC = Gem::Specification.load("bcrypt.gemspec")
20
-
21
- task :default => [:compile, :spec]
22
-
23
- desc "Run all specs"
24
- RSpec::Core::RakeTask.new do |t|
25
- t.pattern = 'spec/**/*_spec.rb'
26
- t.ruby_opts = '-w'
27
- end
28
-
29
- desc "Run all specs, with coverage testing"
30
- RSpec::Core::RakeTask.new(:rcov) do |t|
31
- t.pattern = 'spec/**/*_spec.rb'
32
- t.rcov = true
33
- t.rcov_path = 'doc/coverage'
34
- t.rcov_opts = ['--exclude', 'rspec,diff-lcs,rcov,_spec,_helper']
35
- end
36
-
37
- desc 'Generate RDoc'
38
- RDoc::Task.new do |rdoc|
39
- rdoc.rdoc_dir = 'doc/rdoc'
40
- rdoc.options += GEMSPEC.rdoc_options
41
- rdoc.template = ENV['TEMPLATE'] if ENV['TEMPLATE']
42
- rdoc.rdoc_files.include(*GEMSPEC.extra_rdoc_files)
43
- end
44
-
45
- Gem::PackageTask.new(GEMSPEC) do |pkg|
46
- pkg.need_zip = true
47
- pkg.need_tar = true
48
- end
49
-
50
- if RUBY_PLATFORM =~ /java/
51
- Rake::JavaExtensionTask.new('bcrypt_ext', GEMSPEC) do |ext|
52
- ext.ext_dir = 'ext/jruby'
53
- ext.source_version = "1.7"
54
- ext.target_version = "1.7"
55
- end
56
- else
57
- Rake::ExtensionTask.new("bcrypt_ext", GEMSPEC) do |ext|
58
- ext.ext_dir = 'ext/mri'
59
- end
60
- end
61
-
62
- desc "Run a set of benchmarks on the compiled extension."
63
- task :benchmark do
64
- TESTS = 100
65
- TEST_PWD = "this is a test"
66
- require File.expand_path(File.join(File.dirname(__FILE__), "lib", "bcrypt"))
67
- Benchmark.bmbm do |results|
68
- 4.upto(10) do |n|
69
- results.report("cost #{n}:") { TESTS.times { BCrypt::Password.create(TEST_PWD, :cost => n) } }
70
- end
71
- end
72
- end
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
data/bcrypt.gemspec DELETED
@@ -1,27 +0,0 @@
1
- Gem::Specification.new do |s|
2
- s.name = 'bcrypt'
3
- s.version = '3.1.16'
4
-
5
- s.summary = "OpenBSD's bcrypt() password hashing algorithm."
6
- s.description = <<-EOF
7
- bcrypt() is a sophisticated and secure hash algorithm designed by The OpenBSD project
8
- for hashing passwords. The bcrypt Ruby gem provides a simple wrapper for safely handling
9
- passwords.
10
- EOF
11
-
12
- s.files = `git ls-files`.split("\n")
13
- s.require_path = 'lib'
14
-
15
- s.add_development_dependency 'rake-compiler', '~> 0.9.2'
16
- s.add_development_dependency 'rspec', '>= 3'
17
-
18
- s.rdoc_options += ['--title', 'bcrypt-ruby', '--line-numbers', '--inline-source', '--main', 'README.md']
19
- s.extra_rdoc_files += ['README.md', 'COPYING', 'CHANGELOG', *Dir['lib/**/*.rb']]
20
-
21
- s.extensions = 'ext/mri/extconf.rb'
22
-
23
- s.authors = ["Coda Hale"]
24
- s.email = "coda.hale@gmail.com"
25
- s.homepage = "https://github.com/codahale/bcrypt-ruby"
26
- s.license = "MIT"
27
- end
data/spec/TestBCrypt.java DELETED
@@ -1,194 +0,0 @@
1
- // Copyright (c) 2006 Damien Miller <djm@mindrot.org>
2
- //
3
- // Permission to use, copy, modify, and distribute this software for any
4
- // purpose with or without fee is hereby granted, provided that the above
5
- // copyright notice and this permission notice appear in all copies.
6
- //
7
- // THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
8
- // WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
9
- // MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
10
- // ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
11
- // WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
12
- // ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
13
- // OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
14
-
15
- import junit.framework.TestCase;
16
-
17
- /**
18
- * JUnit unit tests for BCrypt routines
19
- * @author Damien Miller
20
- * @version 0.2
21
- */
22
- public class TestBCrypt extends TestCase {
23
- String test_vectors[][] = {
24
- { "",
25
- "$2a$06$DCq7YPn5Rq63x1Lad4cll.",
26
- "$2a$06$DCq7YPn5Rq63x1Lad4cll.TV4S6ytwfsfvkgY8jIucDrjc8deX1s." },
27
- { "",
28
- "$2a$08$HqWuK6/Ng6sg9gQzbLrgb.",
29
- "$2a$08$HqWuK6/Ng6sg9gQzbLrgb.Tl.ZHfXLhvt/SgVyWhQqgqcZ7ZuUtye" },
30
- { "",
31
- "$2a$10$k1wbIrmNyFAPwPVPSVa/ze",
32
- "$2a$10$k1wbIrmNyFAPwPVPSVa/zecw2BCEnBwVS2GbrmgzxFUOqW9dk4TCW" },
33
- { "",
34
- "$2a$12$k42ZFHFWqBp3vWli.nIn8u",
35
- "$2a$12$k42ZFHFWqBp3vWli.nIn8uYyIkbvYRvodzbfbK18SSsY.CsIQPlxO" },
36
- { "a",
37
- "$2a$06$m0CrhHm10qJ3lXRY.5zDGO",
38
- "$2a$06$m0CrhHm10qJ3lXRY.5zDGO3rS2KdeeWLuGmsfGlMfOxih58VYVfxe" },
39
- { "a",
40
- "$2a$08$cfcvVd2aQ8CMvoMpP2EBfe",
41
- "$2a$08$cfcvVd2aQ8CMvoMpP2EBfeodLEkkFJ9umNEfPD18.hUF62qqlC/V." },
42
- { "a",
43
- "$2a$10$k87L/MF28Q673VKh8/cPi.",
44
- "$2a$10$k87L/MF28Q673VKh8/cPi.SUl7MU/rWuSiIDDFayrKk/1tBsSQu4u" },
45
- { "a",
46
- "$2a$12$8NJH3LsPrANStV6XtBakCe",
47
- "$2a$12$8NJH3LsPrANStV6XtBakCez0cKHXVxmvxIlcz785vxAIZrihHZpeS" },
48
- { "abc",
49
- "$2a$06$If6bvum7DFjUnE9p2uDeDu",
50
- "$2a$06$If6bvum7DFjUnE9p2uDeDu0YHzrHM6tf.iqN8.yx.jNN1ILEf7h0i" },
51
- { "abc",
52
- "$2a$08$Ro0CUfOqk6cXEKf3dyaM7O",
53
- "$2a$08$Ro0CUfOqk6cXEKf3dyaM7OhSCvnwM9s4wIX9JeLapehKK5YdLxKcm" },
54
- { "abc",
55
- "$2a$10$WvvTPHKwdBJ3uk0Z37EMR.",
56
- "$2a$10$WvvTPHKwdBJ3uk0Z37EMR.hLA2W6N9AEBhEgrAOljy2Ae5MtaSIUi" },
57
- { "abc",
58
- "$2a$12$EXRkfkdmXn2gzds2SSitu.",
59
- "$2a$12$EXRkfkdmXn2gzds2SSitu.MW9.gAVqa9eLS1//RYtYCmB1eLHg.9q" },
60
- { "abcdefghijklmnopqrstuvwxyz",
61
- "$2a$06$.rCVZVOThsIa97pEDOxvGu",
62
- "$2a$06$.rCVZVOThsIa97pEDOxvGuRRgzG64bvtJ0938xuqzv18d3ZpQhstC" },
63
- { "abcdefghijklmnopqrstuvwxyz",
64
- "$2a$08$aTsUwsyowQuzRrDqFflhge",
65
- "$2a$08$aTsUwsyowQuzRrDqFflhgekJ8d9/7Z3GV3UcgvzQW3J5zMyrTvlz." },
66
- { "abcdefghijklmnopqrstuvwxyz",
67
- "$2a$10$fVH8e28OQRj9tqiDXs1e1u",
68
- "$2a$10$fVH8e28OQRj9tqiDXs1e1uxpsjN0c7II7YPKXua2NAKYvM6iQk7dq" },
69
- { "abcdefghijklmnopqrstuvwxyz",
70
- "$2a$12$D4G5f18o7aMMfwasBL7Gpu",
71
- "$2a$12$D4G5f18o7aMMfwasBL7GpuQWuP3pkrZrOAnqP.bmezbMng.QwJ/pG" },
72
- { "~!@#$%^&*() ~!@#$%^&*()PNBFRD",
73
- "$2a$06$fPIsBO8qRqkjj273rfaOI.",
74
- "$2a$06$fPIsBO8qRqkjj273rfaOI.HtSV9jLDpTbZn782DC6/t7qT67P6FfO" },
75
- { "~!@#$%^&*() ~!@#$%^&*()PNBFRD",
76
- "$2a$08$Eq2r4G/76Wv39MzSX262hu",
77
- "$2a$08$Eq2r4G/76Wv39MzSX262huzPz612MZiYHVUJe/OcOql2jo4.9UxTW" },
78
- { "~!@#$%^&*() ~!@#$%^&*()PNBFRD",
79
- "$2a$10$LgfYWkbzEvQ4JakH7rOvHe",
80
- "$2a$10$LgfYWkbzEvQ4JakH7rOvHe0y8pHKF9OaFgwUZ2q7W2FFZmZzJYlfS" },
81
- { "~!@#$%^&*() ~!@#$%^&*()PNBFRD",
82
- "$2a$12$WApznUOJfkEGSmYRfnkrPO",
83
- "$2a$12$WApznUOJfkEGSmYRfnkrPOr466oFDCaj4b6HY3EXGvfxm43seyhgC" },
84
- };
85
-
86
- /**
87
- * Entry point for unit tests
88
- * @param args unused
89
- */
90
- public static void main(String[] args) {
91
- junit.textui.TestRunner.run(TestBCrypt.class);
92
- }
93
-
94
- /**
95
- * Test method for 'BCrypt.hashpw(String, String)'
96
- */
97
- public void testHashpw() {
98
- System.out.print("BCrypt.hashpw(): ");
99
- for (int i = 0; i < test_vectors.length; i++) {
100
- String plain = test_vectors[i][0];
101
- String salt = test_vectors[i][1];
102
- String expected = test_vectors[i][2];
103
- String hashed = BCrypt.hashpw(plain, salt);
104
- assertEquals(hashed, expected);
105
- System.out.print(".");
106
- }
107
- System.out.println("");
108
- }
109
-
110
- /**
111
- * Test method for 'BCrypt.gensalt(int)'
112
- */
113
- public void testGensaltInt() {
114
- System.out.print("BCrypt.gensalt(log_rounds):");
115
- for (int i = 4; i <= 12; i++) {
116
- System.out.print(" " + Integer.toString(i) + ":");
117
- for (int j = 0; j < test_vectors.length; j += 4) {
118
- String plain = test_vectors[j][0];
119
- String salt = BCrypt.gensalt(i);
120
- String hashed1 = BCrypt.hashpw(plain, salt);
121
- String hashed2 = BCrypt.hashpw(plain, hashed1);
122
- assertEquals(hashed1, hashed2);
123
- System.out.print(".");
124
- }
125
- }
126
- System.out.println("");
127
- }
128
-
129
- /**
130
- * Test method for 'BCrypt.gensalt()'
131
- */
132
- public void testGensalt() {
133
- System.out.print("BCrypt.gensalt(): ");
134
- for (int i = 0; i < test_vectors.length; i += 4) {
135
- String plain = test_vectors[i][0];
136
- String salt = BCrypt.gensalt();
137
- String hashed1 = BCrypt.hashpw(plain, salt);
138
- String hashed2 = BCrypt.hashpw(plain, hashed1);
139
- assertEquals(hashed1, hashed2);
140
- System.out.print(".");
141
- }
142
- System.out.println("");
143
- }
144
-
145
- /**
146
- * Test method for 'BCrypt.checkpw(String, String)'
147
- * expecting success
148
- */
149
- public void testCheckpw_success() {
150
- System.out.print("BCrypt.checkpw w/ good passwords: ");
151
- for (int i = 0; i < test_vectors.length; i++) {
152
- String plain = test_vectors[i][0];
153
- String expected = test_vectors[i][2];
154
- assertTrue(BCrypt.checkpw(plain, expected));
155
- System.out.print(".");
156
- }
157
- System.out.println("");
158
- }
159
-
160
- /**
161
- * Test method for 'BCrypt.checkpw(String, String)'
162
- * expecting failure
163
- */
164
- public void testCheckpw_failure() {
165
- System.out.print("BCrypt.checkpw w/ bad passwords: ");
166
- for (int i = 0; i < test_vectors.length; i++) {
167
- int broken_index = (i + 4) % test_vectors.length;
168
- String plain = test_vectors[i][0];
169
- String expected = test_vectors[broken_index][2];
170
- assertFalse(BCrypt.checkpw(plain, expected));
171
- System.out.print(".");
172
- }
173
- System.out.println("");
174
- }
175
-
176
- /**
177
- * Test for correct hashing of non-US-ASCII passwords
178
- */
179
- public void testInternationalChars() {
180
- System.out.print("BCrypt.hashpw w/ international chars: ");
181
- String pw1 = "ππππππππ";
182
- String pw2 = "????????";
183
-
184
- String h1 = BCrypt.hashpw(pw1, BCrypt.gensalt());
185
- assertFalse(BCrypt.checkpw(pw2, h1));
186
- System.out.print(".");
187
-
188
- String h2 = BCrypt.hashpw(pw2, BCrypt.gensalt());
189
- assertFalse(BCrypt.checkpw(pw1, h2));
190
- System.out.print(".");
191
- System.out.println("");
192
- }
193
-
194
- }
@@ -1,157 +0,0 @@
1
- require File.expand_path(File.join(File.dirname(__FILE__), "..", "spec_helper"))
2
-
3
- describe 'BCrypt::Engine' do
4
- describe '.calibrate(upper_time_limit_in_ms)' do
5
- context 'a tiny upper time limit provided' do
6
- it 'returns a minimum cost supported by the algorithm' do
7
- expect(BCrypt::Engine.calibrate(0.001)).to eq(4)
8
- end
9
- end
10
- end
11
- end
12
-
13
- describe "The BCrypt engine" do
14
- specify "should calculate the optimal cost factor to fit in a specific time" do
15
- first = BCrypt::Engine.calibrate(100)
16
- second = BCrypt::Engine.calibrate(400)
17
- expect(second).to be > first
18
- end
19
- end
20
-
21
- describe "Generating BCrypt salts" do
22
-
23
- specify "should produce strings" do
24
- expect(BCrypt::Engine.generate_salt).to be_an_instance_of(String)
25
- end
26
-
27
- specify "should produce random data" do
28
- expect(BCrypt::Engine.generate_salt).to_not equal(BCrypt::Engine.generate_salt)
29
- end
30
-
31
- specify "should raise a InvalidCostError if the cost parameter isn't numeric" do
32
- expect { BCrypt::Engine.generate_salt('woo') }.to raise_error(BCrypt::Errors::InvalidCost)
33
- end
34
-
35
- specify "should raise a InvalidCostError if the cost parameter isn't greater than 0" do
36
- expect { BCrypt::Engine.generate_salt(-1) }.to raise_error(BCrypt::Errors::InvalidCost)
37
- end
38
- end
39
-
40
- describe "Autodetecting of salt cost" do
41
-
42
- specify "should work" do
43
- expect(BCrypt::Engine.autodetect_cost("$2a$08$hRx2IVeHNsTSYYtUWn61Ou")).to eq 8
44
- expect(BCrypt::Engine.autodetect_cost("$2a$05$XKd1bMnLgUnc87qvbAaCUu")).to eq 5
45
- expect(BCrypt::Engine.autodetect_cost("$2a$13$Lni.CZ6z5A7344POTFBBV.")).to eq 13
46
- end
47
-
48
- end
49
-
50
- describe "Generating BCrypt hashes" do
51
-
52
- class MyInvalidSecret
53
- undef to_s
54
- end
55
-
56
- before :each do
57
- @salt = BCrypt::Engine.generate_salt(4)
58
- @password = "woo"
59
- end
60
-
61
- specify "should produce a string" do
62
- expect(BCrypt::Engine.hash_secret(@password, @salt)).to be_an_instance_of(String)
63
- end
64
-
65
- specify "should raise an InvalidSalt error if the salt is invalid" do
66
- expect { BCrypt::Engine.hash_secret(@password, 'nino') }.to raise_error(BCrypt::Errors::InvalidSalt)
67
- end
68
-
69
- specify "should raise an InvalidSecret error if the secret is invalid" do
70
- expect { BCrypt::Engine.hash_secret(MyInvalidSecret.new, @salt) }.to raise_error(BCrypt::Errors::InvalidSecret)
71
- expect { BCrypt::Engine.hash_secret(nil, @salt) }.not_to raise_error
72
- expect { BCrypt::Engine.hash_secret(false, @salt) }.not_to raise_error
73
- end
74
-
75
- specify "should call #to_s on the secret and use the return value as the actual secret data" do
76
- expect(BCrypt::Engine.hash_secret(false, @salt)).to eq BCrypt::Engine.hash_secret("false", @salt)
77
- end
78
-
79
- specify "should be interoperable with other implementations" do
80
- test_vectors = [
81
- # test vectors from the OpenWall implementation <https://www.openwall.com/crypt/>, found in wrapper.c
82
- ["U*U", "$2a$05$CCCCCCCCCCCCCCCCCCCCC.", "$2a$05$CCCCCCCCCCCCCCCCCCCCC.E5YPO9kmyuRGyh0XouQYb4YMJKvyOeW"],
83
- ["U*U*", "$2a$05$CCCCCCCCCCCCCCCCCCCCC.", "$2a$05$CCCCCCCCCCCCCCCCCCCCC.VGOzA784oUp/Z0DY336zx7pLYAy0lwK"],
84
- ["U*U*U", "$2a$05$XXXXXXXXXXXXXXXXXXXXXO", "$2a$05$XXXXXXXXXXXXXXXXXXXXXOAcXxm9kjPGEMsLznoKqmqw7tc8WCx4a"],
85
- ["0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789chars after 72 are ignored", "$2a$05$abcdefghijklmnopqrstuu", "$2a$05$abcdefghijklmnopqrstuu5s2v8.iXieOjg/.AySBTTZIIVFJeBui"],
86
- ["\xa3", "$2x$05$/OK.fbVrR/bpIqNJ5ianF.", "$2x$05$/OK.fbVrR/bpIqNJ5ianF.CE5elHaaO4EbggVDjb8P19RukzXSM3e"],
87
- ["\xff\xff\xa3", "$2x$05$/OK.fbVrR/bpIqNJ5ianF.", "$2x$05$/OK.fbVrR/bpIqNJ5ianF.CE5elHaaO4EbggVDjb8P19RukzXSM3e"],
88
- ["\xff\xff\xa3", "$2y$05$/OK.fbVrR/bpIqNJ5ianF.", "$2y$05$/OK.fbVrR/bpIqNJ5ianF.CE5elHaaO4EbggVDjb8P19RukzXSM3e"],
89
- ["\xff\xff\xa3", "$2a$05$/OK.fbVrR/bpIqNJ5ianF.", "$2a$05$/OK.fbVrR/bpIqNJ5ianF.nqd1wy.pTMdcvrRWxyiGL2eMz.2a85."],
90
- ["\xff\xff\xa3", "$2b$05$/OK.fbVrR/bpIqNJ5ianF.", "$2b$05$/OK.fbVrR/bpIqNJ5ianF.CE5elHaaO4EbggVDjb8P19RukzXSM3e"],
91
- ["\xa3", "$2y$05$/OK.fbVrR/bpIqNJ5ianF.", "$2y$05$/OK.fbVrR/bpIqNJ5ianF.Sa7shbm4.OzKpvFnX1pQLmQW96oUlCq"],
92
- ["\xa3", "$2a$05$/OK.fbVrR/bpIqNJ5ianF.", "$2a$05$/OK.fbVrR/bpIqNJ5ianF.Sa7shbm4.OzKpvFnX1pQLmQW96oUlCq"],
93
- ["\xa3", "$2b$05$/OK.fbVrR/bpIqNJ5ianF.", "$2b$05$/OK.fbVrR/bpIqNJ5ianF.Sa7shbm4.OzKpvFnX1pQLmQW96oUlCq"],
94
- ["1\xa3" "345", "$2x$05$/OK.fbVrR/bpIqNJ5ianF.", "$2x$05$/OK.fbVrR/bpIqNJ5ianF.o./n25XVfn6oAPaUvHe.Csk4zRfsYPi"],
95
- ["\xff\xa3" "345", "$2x$05$/OK.fbVrR/bpIqNJ5ianF.", "$2x$05$/OK.fbVrR/bpIqNJ5ianF.o./n25XVfn6oAPaUvHe.Csk4zRfsYPi"],
96
- ["\xff\xa3" "34" "\xff\xff\xff\xa3" "345", "$2x$05$/OK.fbVrR/bpIqNJ5ianF.", "$2x$05$/OK.fbVrR/bpIqNJ5ianF.o./n25XVfn6oAPaUvHe.Csk4zRfsYPi"],
97
- ["\xff\xa3" "34" "\xff\xff\xff\xa3" "345", "$2y$05$/OK.fbVrR/bpIqNJ5ianF.", "$2y$05$/OK.fbVrR/bpIqNJ5ianF.o./n25XVfn6oAPaUvHe.Csk4zRfsYPi"],
98
- ["\xff\xa3" "34" "\xff\xff\xff\xa3" "345", "$2a$05$/OK.fbVrR/bpIqNJ5ianF.", "$2a$05$/OK.fbVrR/bpIqNJ5ianF.ZC1JEJ8Z4gPfpe1JOr/oyPXTWl9EFd."],
99
- ["\xff\xa3" "345", "$2y$05$/OK.fbVrR/bpIqNJ5ianF.", "$2y$05$/OK.fbVrR/bpIqNJ5ianF.nRht2l/HRhr6zmCp9vYUvvsqynflf9e"],
100
- ["\xff\xa3" "345", "$2a$05$/OK.fbVrR/bpIqNJ5ianF.", "$2a$05$/OK.fbVrR/bpIqNJ5ianF.nRht2l/HRhr6zmCp9vYUvvsqynflf9e"],
101
- ["\xa3" "ab", "$2a$05$/OK.fbVrR/bpIqNJ5ianF.", "$2a$05$/OK.fbVrR/bpIqNJ5ianF.6IflQkJytoRVc1yuaNtHfiuq.FRlSIS"],
102
- ["\xa3" "ab", "$2x$05$/OK.fbVrR/bpIqNJ5ianF.", "$2x$05$/OK.fbVrR/bpIqNJ5ianF.6IflQkJytoRVc1yuaNtHfiuq.FRlSIS"],
103
- ["\xa3" "ab", "$2y$05$/OK.fbVrR/bpIqNJ5ianF.", "$2y$05$/OK.fbVrR/bpIqNJ5ianF.6IflQkJytoRVc1yuaNtHfiuq.FRlSIS"],
104
- ["\xd1\x91", "$2x$05$6bNw2HLQYeqHYyBfLMsv/O", "$2x$05$6bNw2HLQYeqHYyBfLMsv/OiwqTymGIGzFsA4hOTWebfehXHNprcAS"],
105
- ["\xd0\xc1\xd2\xcf\xcc\xd8", "$2x$05$6bNw2HLQYeqHYyBfLMsv/O", "$2x$05$6bNw2HLQYeqHYyBfLMsv/O9LIGgn8OMzuDoHfof8AQimSGfcSWxnS"],
106
- ["\xaa"*72+"chars after 72 are ignored as usual", "$2a$05$/OK.fbVrR/bpIqNJ5ianF.", "$2a$05$/OK.fbVrR/bpIqNJ5ianF.swQOIzjOiJ9GHEPuhEkvqrUyvWhEMx6"],
107
- ["\xaa\x55"*36, "$2a$05$/OK.fbVrR/bpIqNJ5ianF.", "$2a$05$/OK.fbVrR/bpIqNJ5ianF.R9xrDjiycxMbQE2bp.vgqlYpW5wx2yy"],
108
- ["\x55\xaa\xff"*24, "$2a$05$/OK.fbVrR/bpIqNJ5ianF.", "$2a$05$/OK.fbVrR/bpIqNJ5ianF.9tQZzcJfm3uj2NvJ/n5xkhpqLrMpWCe"],
109
- ["", "$2a$05$CCCCCCCCCCCCCCCCCCCCC.", "$2a$05$CCCCCCCCCCCCCCCCCCCCC.7uG0VCzI2bS7j6ymqJi9CdcdxiRTWNy"],
110
-
111
- # test vectors from the Java implementation, found in https://github.com/spring-projects/spring-security/blob/master/crypto/src/test/java/org/springframework/security/crypto/bcrypt/BCryptTests.java
112
- ["", "$2a$06$DCq7YPn5Rq63x1Lad4cll.", "$2a$06$DCq7YPn5Rq63x1Lad4cll.TV4S6ytwfsfvkgY8jIucDrjc8deX1s."],
113
- ["", "$2a$08$HqWuK6/Ng6sg9gQzbLrgb.", "$2a$08$HqWuK6/Ng6sg9gQzbLrgb.Tl.ZHfXLhvt/SgVyWhQqgqcZ7ZuUtye"],
114
- ["", "$2a$10$k1wbIrmNyFAPwPVPSVa/ze", "$2a$10$k1wbIrmNyFAPwPVPSVa/zecw2BCEnBwVS2GbrmgzxFUOqW9dk4TCW"],
115
- ["", "$2a$12$k42ZFHFWqBp3vWli.nIn8u", "$2a$12$k42ZFHFWqBp3vWli.nIn8uYyIkbvYRvodzbfbK18SSsY.CsIQPlxO"],
116
- ["", "$2b$06$8eVN9RiU8Yki430X.wBvN.", "$2b$06$8eVN9RiU8Yki430X.wBvN.LWaqh2962emLVSVXVZIXJvDYLsV0oFu"],
117
- ["", "$2b$06$NlgfNgpIc6GlHciCkMEW8u", "$2b$06$NlgfNgpIc6GlHciCkMEW8uKOBsyvAp7QwlHpysOlKdtyEw50WQua2"],
118
- ["", "$2y$06$mFDtkz6UN7B3GZ2qi2hhaO", "$2y$06$mFDtkz6UN7B3GZ2qi2hhaO3OFWzNEdcY84ELw6iHCPruuQfSAXBLK"],
119
- ["", "$2y$06$88kSqVttBx.e9iXTPCLa5u", "$2y$06$88kSqVttBx.e9iXTPCLa5uFPrVFjfLH4D.KcO6pBiAmvUkvdg0EYy"],
120
- ["a", "$2a$06$m0CrhHm10qJ3lXRY.5zDGO", "$2a$06$m0CrhHm10qJ3lXRY.5zDGO3rS2KdeeWLuGmsfGlMfOxih58VYVfxe"],
121
- ["a", "$2a$08$cfcvVd2aQ8CMvoMpP2EBfe", "$2a$08$cfcvVd2aQ8CMvoMpP2EBfeodLEkkFJ9umNEfPD18.hUF62qqlC/V."],
122
- ["a", "$2a$10$k87L/MF28Q673VKh8/cPi.", "$2a$10$k87L/MF28Q673VKh8/cPi.SUl7MU/rWuSiIDDFayrKk/1tBsSQu4u"],
123
- ["a", "$2a$12$8NJH3LsPrANStV6XtBakCe", "$2a$12$8NJH3LsPrANStV6XtBakCez0cKHXVxmvxIlcz785vxAIZrihHZpeS"],
124
- ["a", "$2b$06$ehKGYiS4wt2HAr7KQXS5z.", "$2b$06$ehKGYiS4wt2HAr7KQXS5z.OaRjB4jHO7rBHJKlGXbqEH3QVJfO7iO"],
125
- ["a", "$2b$06$PWxFFHA3HiCD46TNOZh30e", "$2b$06$PWxFFHA3HiCD46TNOZh30eNto1hg5uM9tHBlI4q/b03SW/gGKUYk6"],
126
- ["a", "$2y$06$LUdD6/aD0e/UbnxVAVbvGu", "$2y$06$LUdD6/aD0e/UbnxVAVbvGuUmIoJ3l/OK94ThhadpMWwKC34LrGEey"],
127
- ["a", "$2y$06$eqgY.T2yloESMZxgp76deO", "$2y$06$eqgY.T2yloESMZxgp76deOROa7nzXDxbO0k.PJvuClTa.Vu1AuemG"],
128
- ["abc", "$2a$06$If6bvum7DFjUnE9p2uDeDu", "$2a$06$If6bvum7DFjUnE9p2uDeDu0YHzrHM6tf.iqN8.yx.jNN1ILEf7h0i"],
129
- ["abc", "$2a$08$Ro0CUfOqk6cXEKf3dyaM7O", "$2a$08$Ro0CUfOqk6cXEKf3dyaM7OhSCvnwM9s4wIX9JeLapehKK5YdLxKcm"],
130
- ["abc", "$2a$10$WvvTPHKwdBJ3uk0Z37EMR.", "$2a$10$WvvTPHKwdBJ3uk0Z37EMR.hLA2W6N9AEBhEgrAOljy2Ae5MtaSIUi"],
131
- ["abc", "$2a$12$EXRkfkdmXn2gzds2SSitu.", "$2a$12$EXRkfkdmXn2gzds2SSitu.MW9.gAVqa9eLS1//RYtYCmB1eLHg.9q"],
132
- ["abc", "$2b$06$5FyQoicpbox1xSHFfhhdXu", "$2b$06$5FyQoicpbox1xSHFfhhdXuR2oxLpO1rYsQh5RTkI/9.RIjtoF0/ta"],
133
- ["abc", "$2b$06$1kJyuho8MCVP3HHsjnRMkO", "$2b$06$1kJyuho8MCVP3HHsjnRMkO1nvCOaKTqLnjG2TX1lyMFbXH/aOkgc."],
134
- ["abc", "$2y$06$ACfku9dT6.H8VjdKb8nhlu", "$2y$06$ACfku9dT6.H8VjdKb8nhluaoBmhJyK7GfoNScEfOfrJffUxoUeCjK"],
135
- ["abc", "$2y$06$9JujYcoWPmifvFA3RUP90e", "$2y$06$9JujYcoWPmifvFA3RUP90e5rSEHAb5Ye6iv3.G9ikiHNv5cxjNEse"],
136
- ["abcdefghijklmnopqrstuvwxyz", "$2a$06$.rCVZVOThsIa97pEDOxvGu", "$2a$06$.rCVZVOThsIa97pEDOxvGuRRgzG64bvtJ0938xuqzv18d3ZpQhstC"],
137
- ["abcdefghijklmnopqrstuvwxyz", "$2a$08$aTsUwsyowQuzRrDqFflhge", "$2a$08$aTsUwsyowQuzRrDqFflhgekJ8d9/7Z3GV3UcgvzQW3J5zMyrTvlz."],
138
- ["abcdefghijklmnopqrstuvwxyz", "$2a$10$fVH8e28OQRj9tqiDXs1e1u", "$2a$10$fVH8e28OQRj9tqiDXs1e1uxpsjN0c7II7YPKXua2NAKYvM6iQk7dq"],
139
- ["abcdefghijklmnopqrstuvwxyz", "$2a$12$D4G5f18o7aMMfwasBL7Gpu", "$2a$12$D4G5f18o7aMMfwasBL7GpuQWuP3pkrZrOAnqP.bmezbMng.QwJ/pG"],
140
- ["abcdefghijklmnopqrstuvwxyz", "$2b$06$O8E89AQPj1zJQA05YvIAU.", "$2b$06$O8E89AQPj1zJQA05YvIAU.hMpj25BXri1bupl/Q7CJMlpLwZDNBoO"],
141
- ["abcdefghijklmnopqrstuvwxyz", "$2b$06$PDqIWr./o/P3EE/P.Q0A/u", "$2b$06$PDqIWr./o/P3EE/P.Q0A/uFg86WL/PXTbaW267TDALEwDylqk00Z."],
142
- ["abcdefghijklmnopqrstuvwxyz", "$2y$06$34MG90ZLah8/ZNr3ltlHCu", "$2y$06$34MG90ZLah8/ZNr3ltlHCuz6bachF8/3S5jTuzF1h2qg2cUk11sFW"],
143
- ["abcdefghijklmnopqrstuvwxyz", "$2y$06$AK.hSLfMyw706iEW24i68u", "$2y$06$AK.hSLfMyw706iEW24i68uKAc2yorPTrB0cimvjJHEBUrPkOq7VvG"],
144
- ["~!@#$%^&*() ~!@#$%^&*()PNBFRD", "$2a$06$fPIsBO8qRqkjj273rfaOI.", "$2a$06$fPIsBO8qRqkjj273rfaOI.HtSV9jLDpTbZn782DC6/t7qT67P6FfO"],
145
- ["~!@#$%^&*() ~!@#$%^&*()PNBFRD", "$2a$08$Eq2r4G/76Wv39MzSX262hu", "$2a$08$Eq2r4G/76Wv39MzSX262huzPz612MZiYHVUJe/OcOql2jo4.9UxTW"],
146
- ["~!@#$%^&*() ~!@#$%^&*()PNBFRD", "$2a$10$LgfYWkbzEvQ4JakH7rOvHe", "$2a$10$LgfYWkbzEvQ4JakH7rOvHe0y8pHKF9OaFgwUZ2q7W2FFZmZzJYlfS"],
147
- ["~!@#$%^&*() ~!@#$%^&*()PNBFRD", "$2a$12$WApznUOJfkEGSmYRfnkrPO", "$2a$12$WApznUOJfkEGSmYRfnkrPOr466oFDCaj4b6HY3EXGvfxm43seyhgC"],
148
- ["~!@#$%^&*() ~!@#$%^&*()PNBFRD", "$2b$06$FGWA8OlY6RtQhXBXuCJ8Wu", "$2b$06$FGWA8OlY6RtQhXBXuCJ8WusVipRI15cWOgJK8MYpBHEkktMfbHRIG"],
149
- ["~!@#$%^&*() ~!@#$%^&*()PNBFRD", "$2b$06$G6aYU7UhUEUDJBdTgq3CRe", "$2b$06$G6aYU7UhUEUDJBdTgq3CRekiopCN4O4sNitFXrf5NUscsVZj3a2r6"],
150
- ["~!@#$%^&*() ~!@#$%^&*()PNBFRD", "$2y$06$sYDFHqOcXTjBgOsqC0WCKe", "$2y$06$sYDFHqOcXTjBgOsqC0WCKeMd3T1UhHuWQSxncLGtXDLMrcE6vFDti"],
151
- ["~!@#$%^&*() ~!@#$%^&*()PNBFRD", "$2y$06$6Xm0gCw4g7ZNDCEp4yTise", "$2y$06$6Xm0gCw4g7ZNDCEp4yTisez0kSdpXEl66MvdxGidnmChIe8dFmMnq"]
152
- ]
153
- for secret, salt, test_vector in test_vectors
154
- expect(BCrypt::Engine.hash_secret(secret, salt)).to eql(test_vector)
155
- end
156
- end
157
- end
@@ -1,37 +0,0 @@
1
- require File.expand_path(File.join(File.dirname(__FILE__), "..", "spec_helper"))
2
-
3
- describe "Errors" do
4
-
5
- shared_examples "descends from StandardError" do
6
- it "can be rescued as a StandardError" do
7
- expect(described_class).to be < StandardError
8
- end
9
- end
10
-
11
- shared_examples "descends from BCrypt::Error" do
12
- it "can be rescued as a BCrypt::Error" do
13
- expect(described_class).to be < BCrypt::Error
14
- end
15
- end
16
-
17
- describe BCrypt::Error do
18
- include_examples "descends from StandardError"
19
- end
20
-
21
- describe BCrypt::Errors::InvalidCost do
22
- include_examples "descends from BCrypt::Error"
23
- end
24
-
25
- describe BCrypt::Errors::InvalidHash do
26
- include_examples "descends from BCrypt::Error"
27
- end
28
-
29
- describe BCrypt::Errors::InvalidSalt do
30
- include_examples "descends from BCrypt::Error"
31
- end
32
-
33
- describe BCrypt::Errors::InvalidSecret do
34
- include_examples "descends from BCrypt::Error"
35
- end
36
-
37
- end
@@ -1,124 +0,0 @@
1
- require File.expand_path(File.join(File.dirname(__FILE__), "..", "spec_helper"))
2
-
3
- describe "Creating a hashed password" do
4
-
5
- before :each do
6
- @secret = "wheedle"
7
- @password = BCrypt::Password.create(@secret, :cost => 4)
8
- end
9
-
10
- specify "should return a BCrypt::Password" do
11
- expect(@password).to be_an_instance_of(BCrypt::Password)
12
- end
13
-
14
- specify "should return a valid bcrypt password" do
15
- expect { BCrypt::Password.new(@password) }.not_to raise_error
16
- end
17
-
18
- specify "should behave normally if the secret is not a string" do
19
- expect { BCrypt::Password.create(nil) }.not_to raise_error
20
- expect { BCrypt::Password.create({:woo => "yeah"}) }.not_to raise_error
21
- expect { BCrypt::Password.create(false) }.not_to raise_error
22
- end
23
-
24
- specify "should tolerate empty string secrets" do
25
- expect { BCrypt::Password.create( "\n".chop ) }.not_to raise_error
26
- expect { BCrypt::Password.create( "" ) }.not_to raise_error
27
- expect { BCrypt::Password.create( String.new ) }.not_to raise_error
28
- end
29
- end
30
-
31
- describe "Reading a hashed password" do
32
- before :each do
33
- @secret = "U*U"
34
- @hash = "$2a$05$CCCCCCCCCCCCCCCCCCCCC.E5YPO9kmyuRGyh0XouQYb4YMJKvyOeW"
35
- end
36
-
37
- specify "the cost is too damn high" do
38
- expect {
39
- BCrypt::Password.create("hello", :cost => 32)
40
- }.to raise_error(ArgumentError)
41
- end
42
-
43
- specify "the cost should be set to the default if nil" do
44
- expect(BCrypt::Password.create("hello", :cost => nil).cost).to equal(BCrypt::Engine::DEFAULT_COST)
45
- end
46
-
47
- specify "the cost should be set to the default if empty hash" do
48
- expect(BCrypt::Password.create("hello", {}).cost).to equal(BCrypt::Engine::DEFAULT_COST)
49
- end
50
-
51
- specify "the cost should be set to the passed value if provided" do
52
- expect(BCrypt::Password.create("hello", :cost => 5).cost).to equal(5)
53
- end
54
-
55
- specify "the cost should be set to the global value if set" do
56
- BCrypt::Engine.cost = 5
57
- expect(BCrypt::Password.create("hello").cost).to equal(5)
58
- # unset the global value to not affect other tests
59
- BCrypt::Engine.cost = nil
60
- end
61
-
62
- specify "the cost should be set to an overridden constant for backwards compatibility" do
63
- # suppress "already initialized constant" warning
64
- old_verbose, $VERBOSE = $VERBOSE, nil
65
- old_default_cost = BCrypt::Engine::DEFAULT_COST
66
-
67
- BCrypt::Engine::DEFAULT_COST = 5
68
- expect(BCrypt::Password.create("hello").cost).to equal(5)
69
-
70
- # reset default to not affect other tests
71
- BCrypt::Engine::DEFAULT_COST = old_default_cost
72
- $VERBOSE = old_verbose
73
- end
74
-
75
- specify "should read the version, cost, salt, and hash" do
76
- password = BCrypt::Password.new(@hash)
77
- expect(password.version).to eql("2a")
78
- expect(password.version.class).to eq String
79
- expect(password.cost).to equal(5)
80
- expect(password.salt).to eql("$2a$05$CCCCCCCCCCCCCCCCCCCCC.")
81
- expect(password.salt.class).to eq String
82
- expect(password.checksum).to eq("E5YPO9kmyuRGyh0XouQYb4YMJKvyOeW")
83
- expect(password.checksum.class).to eq String
84
- expect(password.to_s).to eql(@hash)
85
- end
86
-
87
- specify "should raise an InvalidHashError when given an invalid hash" do
88
- expect { BCrypt::Password.new('weedle') }.to raise_error(BCrypt::Errors::InvalidHash)
89
- end
90
- end
91
-
92
- describe "Comparing a hashed password with a secret" do
93
- before :each do
94
- @secret = "U*U"
95
- @hash = "$2a$05$CCCCCCCCCCCCCCCCCCCCC.E5YPO9kmyuRGyh0XouQYb4YMJKvyOeW"
96
- @password = BCrypt::Password.create(@secret)
97
- end
98
-
99
- specify "should compare successfully to the original secret" do
100
- expect((@password == @secret)).to be(true)
101
- end
102
-
103
- specify "should compare unsuccessfully to anything besides original secret" do
104
- expect((@password == "@secret")).to be(false)
105
- end
106
- end
107
-
108
- describe "Validating a generated salt" do
109
- specify "should not accept an invalid salt" do
110
- expect(BCrypt::Engine.valid_salt?("invalid")).to eq(false)
111
- end
112
- specify "should accept a valid salt" do
113
- expect(BCrypt::Engine.valid_salt?(BCrypt::Engine.generate_salt)).to eq(true)
114
- end
115
- end
116
-
117
- describe "Validating a password hash" do
118
- specify "should not accept an invalid password" do
119
- expect(BCrypt::Password.valid_hash?("i_am_so_not_valid")).to be(false)
120
- end
121
- specify "should accept a valid password" do
122
- expect(BCrypt::Password.valid_hash?(BCrypt::Password.create "i_am_so_valid")).to be(true)
123
- end
124
- end
data/spec/spec_helper.rb DELETED
@@ -1,2 +0,0 @@
1
- $:.unshift File.expand_path('../../lib', __FILE__)
2
- require 'bcrypt'