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 +4 -4
- data/CHANGELOG +24 -1
- data/README.md +4 -6
- data/ext/jruby/bcrypt_jruby/BCrypt.java +4 -3
- data/ext/mri/bcrypt_ext.c +78 -17
- data/lib/bcrypt/engine.rb +21 -5
- data/lib/bcrypt/password.rb +22 -3
- metadata +41 -27
- data/.gitignore +0 -9
- data/.rspec +0 -3
- data/.travis.yml +0 -22
- data/Gemfile +0 -2
- data/Rakefile +0 -72
- data/appveyor.yml +0 -50
- data/bcrypt.gemspec +0 -27
- data/spec/TestBCrypt.java +0 -194
- data/spec/bcrypt/engine_spec.rb +0 -157
- data/spec/bcrypt/error_spec.rb +0 -37
- data/spec/bcrypt/password_spec.rb +0 -124
- data/spec/spec_helper.rb +0 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 521c5039d4a683bdf17faa98c3fddc47318f415597bd7575615c1f309ba65a4d
|
|
4
|
+
data.tar.gz: 9abdb8766bcfdc8cfeacbe41eb66fd0a8436ad5b1e9ff67b18239019387be3a1
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
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/
|
|
6
|
-
|
|
7
|
-
[](https://travis-ci.org/codahale/bcrypt-ruby)
|
|
8
|
-
[](https://ci.appveyor.com/project/TJSchuck35975/bcrypt-ruby)
|
|
5
|
+
* https://github.com/bcrypt-ruby/bcrypt-ruby/tree/master
|
|
9
6
|
|
|
7
|
+
[](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
|
|
36
|
-
* Any
|
|
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
|
-
|
|
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 =
|
|
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 (
|
|
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
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
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
|
-
|
|
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
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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 =~
|
|
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.
|
data/lib/bcrypt/password.rb
CHANGED
|
@@ -47,7 +47,7 @@ module BCrypt
|
|
|
47
47
|
end
|
|
48
48
|
|
|
49
49
|
def valid_hash?(h)
|
|
50
|
-
|
|
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
|
-
|
|
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.
|
|
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:
|
|
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:
|
|
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:
|
|
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
|
-
|
|
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
|
-
|
|
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:
|
|
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
data/.rspec
DELETED
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
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
|
-
}
|
data/spec/bcrypt/engine_spec.rb
DELETED
|
@@ -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
|
data/spec/bcrypt/error_spec.rb
DELETED
|
@@ -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