bcrypt 3.1.14-java

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,203 @@
1
+ /*
2
+ * Written by Solar Designer <solar at openwall.com> in 1998-2010.
3
+ * No copyright is claimed, and the software is hereby placed in the public
4
+ * domain. In case this attempt to disclaim copyright and place the software
5
+ * in the public domain is deemed null and void, then the software is
6
+ * Copyright (c) 1998-2010 Solar Designer and it is hereby released to the
7
+ * general public under the following terms:
8
+ *
9
+ * Redistribution and use in source and binary forms, with or without
10
+ * modification, are permitted.
11
+ *
12
+ * There's ABSOLUTELY NO WARRANTY, express or implied.
13
+ *
14
+ * See crypt_blowfish.c for more information.
15
+ */
16
+
17
+ #ifdef __i386__
18
+
19
+ #if defined(__OpenBSD__) && !defined(__ELF__)
20
+ #define UNDERSCORES
21
+ #define ALIGN_LOG
22
+ #endif
23
+
24
+ #if defined(__CYGWIN32__) || defined(__MINGW32__)
25
+ #define UNDERSCORES
26
+ #endif
27
+
28
+ #ifdef __DJGPP__
29
+ #define UNDERSCORES
30
+ #define ALIGN_LOG
31
+ #endif
32
+
33
+ #ifdef UNDERSCORES
34
+ #define _BF_body_r __BF_body_r
35
+ #endif
36
+
37
+ #ifdef ALIGN_LOG
38
+ #define DO_ALIGN(log) .align (log)
39
+ #elif defined(DUMBAS)
40
+ #define DO_ALIGN(log) .align 1 << log
41
+ #else
42
+ #define DO_ALIGN(log) .align (1 << (log))
43
+ #endif
44
+
45
+ #define BF_FRAME 0x200
46
+ #define ctx %esp
47
+
48
+ #define BF_ptr (ctx)
49
+
50
+ #define S(N, r) N+BF_FRAME(ctx,r,4)
51
+ #ifdef DUMBAS
52
+ #define P(N) 0x1000+N+N+N+N+BF_FRAME(ctx)
53
+ #else
54
+ #define P(N) 0x1000+4*N+BF_FRAME(ctx)
55
+ #endif
56
+
57
+ /*
58
+ * This version of the assembly code is optimized primarily for the original
59
+ * Intel Pentium but is also careful to avoid partial register stalls on the
60
+ * Pentium Pro family of processors (tested up to Pentium III Coppermine).
61
+ *
62
+ * It is possible to do 15% faster on the Pentium Pro family and probably on
63
+ * many non-Intel x86 processors, but, unfortunately, that would make things
64
+ * twice slower for the original Pentium.
65
+ *
66
+ * An additional 2% speedup may be achieved with non-reentrant code.
67
+ */
68
+
69
+ #define L %esi
70
+ #define R %edi
71
+ #define tmp1 %eax
72
+ #define tmp1_lo %al
73
+ #define tmp2 %ecx
74
+ #define tmp2_hi %ch
75
+ #define tmp3 %edx
76
+ #define tmp3_lo %dl
77
+ #define tmp4 %ebx
78
+ #define tmp4_hi %bh
79
+ #define tmp5 %ebp
80
+
81
+ .text
82
+
83
+ #define BF_ROUND(L, R, N) \
84
+ xorl L,tmp2; \
85
+ xorl tmp1,tmp1; \
86
+ movl tmp2,L; \
87
+ shrl $16,tmp2; \
88
+ movl L,tmp4; \
89
+ movb tmp2_hi,tmp1_lo; \
90
+ andl $0xFF,tmp2; \
91
+ movb tmp4_hi,tmp3_lo; \
92
+ andl $0xFF,tmp4; \
93
+ movl S(0,tmp1),tmp1; \
94
+ movl S(0x400,tmp2),tmp5; \
95
+ addl tmp5,tmp1; \
96
+ movl S(0x800,tmp3),tmp5; \
97
+ xorl tmp5,tmp1; \
98
+ movl S(0xC00,tmp4),tmp5; \
99
+ addl tmp1,tmp5; \
100
+ movl 4+P(N),tmp2; \
101
+ xorl tmp5,R
102
+
103
+ #define BF_ENCRYPT_START \
104
+ BF_ROUND(L, R, 0); \
105
+ BF_ROUND(R, L, 1); \
106
+ BF_ROUND(L, R, 2); \
107
+ BF_ROUND(R, L, 3); \
108
+ BF_ROUND(L, R, 4); \
109
+ BF_ROUND(R, L, 5); \
110
+ BF_ROUND(L, R, 6); \
111
+ BF_ROUND(R, L, 7); \
112
+ BF_ROUND(L, R, 8); \
113
+ BF_ROUND(R, L, 9); \
114
+ BF_ROUND(L, R, 10); \
115
+ BF_ROUND(R, L, 11); \
116
+ BF_ROUND(L, R, 12); \
117
+ BF_ROUND(R, L, 13); \
118
+ BF_ROUND(L, R, 14); \
119
+ BF_ROUND(R, L, 15); \
120
+ movl BF_ptr,tmp5; \
121
+ xorl L,tmp2; \
122
+ movl P(17),L
123
+
124
+ #define BF_ENCRYPT_END \
125
+ xorl R,L; \
126
+ movl tmp2,R
127
+
128
+ DO_ALIGN(5)
129
+ .globl _BF_body_r
130
+ _BF_body_r:
131
+ movl 4(%esp),%eax
132
+ pushl %ebp
133
+ pushl %ebx
134
+ pushl %esi
135
+ pushl %edi
136
+ subl $BF_FRAME-8,%eax
137
+ xorl L,L
138
+ cmpl %esp,%eax
139
+ ja BF_die
140
+ xchgl %eax,%esp
141
+ xorl R,R
142
+ pushl %eax
143
+ leal 0x1000+BF_FRAME-4(ctx),%eax
144
+ movl 0x1000+BF_FRAME-4(ctx),tmp2
145
+ pushl %eax
146
+ xorl tmp3,tmp3
147
+ BF_loop_P:
148
+ BF_ENCRYPT_START
149
+ addl $8,tmp5
150
+ BF_ENCRYPT_END
151
+ leal 0x1000+18*4+BF_FRAME(ctx),tmp1
152
+ movl tmp5,BF_ptr
153
+ cmpl tmp5,tmp1
154
+ movl L,-8(tmp5)
155
+ movl R,-4(tmp5)
156
+ movl P(0),tmp2
157
+ ja BF_loop_P
158
+ leal BF_FRAME(ctx),tmp5
159
+ xorl tmp3,tmp3
160
+ movl tmp5,BF_ptr
161
+ BF_loop_S:
162
+ BF_ENCRYPT_START
163
+ BF_ENCRYPT_END
164
+ movl P(0),tmp2
165
+ movl L,(tmp5)
166
+ movl R,4(tmp5)
167
+ BF_ENCRYPT_START
168
+ BF_ENCRYPT_END
169
+ movl P(0),tmp2
170
+ movl L,8(tmp5)
171
+ movl R,12(tmp5)
172
+ BF_ENCRYPT_START
173
+ BF_ENCRYPT_END
174
+ movl P(0),tmp2
175
+ movl L,16(tmp5)
176
+ movl R,20(tmp5)
177
+ BF_ENCRYPT_START
178
+ addl $32,tmp5
179
+ BF_ENCRYPT_END
180
+ leal 0x1000+BF_FRAME(ctx),tmp1
181
+ movl tmp5,BF_ptr
182
+ cmpl tmp5,tmp1
183
+ movl P(0),tmp2
184
+ movl L,-8(tmp5)
185
+ movl R,-4(tmp5)
186
+ ja BF_loop_S
187
+ movl 4(%esp),%esp
188
+ popl %edi
189
+ popl %esi
190
+ popl %ebx
191
+ popl %ebp
192
+ ret
193
+
194
+ BF_die:
195
+ /* Oops, need to re-compile with a larger BF_FRAME. */
196
+ hlt
197
+ jmp BF_die
198
+
199
+ #endif
200
+
201
+ #if defined(__ELF__) && defined(__linux__)
202
+ .section .note.GNU-stack,"",%progbits
203
+ #endif
@@ -0,0 +1,16 @@
1
+ # A Ruby library implementing OpenBSD's bcrypt()/crypt_blowfish algorithm for
2
+ # hashing passwords.
3
+ module BCrypt
4
+ end
5
+
6
+ if RUBY_PLATFORM == "java"
7
+ require 'java'
8
+ else
9
+ require "openssl"
10
+ end
11
+
12
+ require "bcrypt_ext"
13
+
14
+ require 'bcrypt/error'
15
+ require 'bcrypt/engine'
16
+ require 'bcrypt/password'
@@ -0,0 +1,118 @@
1
+ module BCrypt
2
+ # A Ruby wrapper for the bcrypt() C extension calls and the Java calls.
3
+ class Engine
4
+ # The default computational expense parameter.
5
+ DEFAULT_COST = 12
6
+ # The minimum cost supported by the algorithm.
7
+ MIN_COST = 4
8
+ # The maximum cost supported by the algorithm.
9
+ MAX_COST = 31
10
+ # Maximum possible size of bcrypt() salts.
11
+ MAX_SALT_LENGTH = 16
12
+
13
+ if RUBY_PLATFORM != "java"
14
+ # C-level routines which, if they don't get the right input, will crash the
15
+ # hell out of the Ruby process.
16
+ private_class_method :__bc_salt
17
+ private_class_method :__bc_crypt
18
+ end
19
+
20
+ @cost = nil
21
+
22
+ # Returns the cost factor that will be used if one is not specified when
23
+ # creating a password hash. Defaults to DEFAULT_COST if not set.
24
+ def self.cost
25
+ @cost || DEFAULT_COST
26
+ end
27
+
28
+ # Set a default cost factor that will be used if one is not specified when
29
+ # creating a password hash.
30
+ #
31
+ # Example:
32
+ #
33
+ # BCrypt::Engine::DEFAULT_COST #=> 12
34
+ # BCrypt::Password.create('secret').cost #=> 12
35
+ #
36
+ # BCrypt::Engine.cost = 8
37
+ # BCrypt::Password.create('secret').cost #=> 8
38
+ #
39
+ # # cost can still be overridden as needed
40
+ # BCrypt::Password.create('secret', :cost => 6).cost #=> 6
41
+ def self.cost=(cost)
42
+ @cost = cost
43
+ end
44
+
45
+ # Given a secret and a valid salt (see BCrypt::Engine.generate_salt) calculates
46
+ # a bcrypt() password hash.
47
+ def self.hash_secret(secret, salt, _ = nil)
48
+ if valid_secret?(secret)
49
+ if valid_salt?(salt)
50
+ if RUBY_PLATFORM == "java"
51
+ Java.bcrypt_jruby.BCrypt.hashpw(secret.to_s.to_java_bytes, salt.to_s)
52
+ else
53
+ __bc_crypt(secret.to_s, salt)
54
+ end
55
+ else
56
+ raise Errors::InvalidSalt.new("invalid salt")
57
+ end
58
+ else
59
+ raise Errors::InvalidSecret.new("invalid secret")
60
+ end
61
+ end
62
+
63
+ # Generates a random salt with a given computational cost.
64
+ def self.generate_salt(cost = self.cost)
65
+ cost = cost.to_i
66
+ if cost > 0
67
+ if cost < MIN_COST
68
+ cost = MIN_COST
69
+ end
70
+ if RUBY_PLATFORM == "java"
71
+ Java.bcrypt_jruby.BCrypt.gensalt(cost)
72
+ else
73
+ prefix = "$2a$05$CCCCCCCCCCCCCCCCCCCCC.E5YPO9kmyuRGyh0XouQYb4YMJKvyOeW"
74
+ __bc_salt(prefix, cost, OpenSSL::Random.random_bytes(MAX_SALT_LENGTH))
75
+ end
76
+ else
77
+ raise Errors::InvalidCost.new("cost must be numeric and > 0")
78
+ end
79
+ end
80
+
81
+ # Returns true if +salt+ is a valid bcrypt() salt, false if not.
82
+ def self.valid_salt?(salt)
83
+ !!(salt =~ /^\$[0-9a-z]{2,}\$[0-9]{2,}\$[A-Za-z0-9\.\/]{22,}$/)
84
+ end
85
+
86
+ # Returns true if +secret+ is a valid bcrypt() secret, false if not.
87
+ def self.valid_secret?(secret)
88
+ secret.respond_to?(:to_s)
89
+ end
90
+
91
+ # Returns the cost factor which will result in computation times less than +upper_time_limit_in_ms+.
92
+ #
93
+ # Example:
94
+ #
95
+ # BCrypt::Engine.calibrate(200) #=> 10
96
+ # BCrypt::Engine.calibrate(1000) #=> 12
97
+ #
98
+ # # should take less than 200ms
99
+ # BCrypt::Password.create("woo", :cost => 10)
100
+ #
101
+ # # should take less than 1000ms
102
+ # BCrypt::Password.create("woo", :cost => 12)
103
+ def self.calibrate(upper_time_limit_in_ms)
104
+ (BCrypt::Engine::MIN_COST..BCrypt::Engine::MAX_COST-1).each do |i|
105
+ start_time = Time.now
106
+ Password.create("testing testing", :cost => i+1)
107
+ end_time = Time.now - start_time
108
+ return i if end_time * 1_000 > upper_time_limit_in_ms
109
+ end
110
+ end
111
+
112
+ # Autodetects the cost from the salt string.
113
+ def self.autodetect_cost(salt)
114
+ salt[4..5].to_i
115
+ end
116
+ end
117
+
118
+ end
@@ -0,0 +1,22 @@
1
+ module BCrypt
2
+
3
+ class Error < StandardError # :nodoc:
4
+ end
5
+
6
+ module Errors # :nodoc:
7
+
8
+ # The salt parameter provided to bcrypt() is invalid.
9
+ class InvalidSalt < BCrypt::Error; end
10
+
11
+ # The hash parameter provided to bcrypt() is invalid.
12
+ class InvalidHash < BCrypt::Error; end
13
+
14
+ # The cost parameter provided to bcrypt() is invalid.
15
+ class InvalidCost < BCrypt::Error; end
16
+
17
+ # The secret parameter provided to bcrypt() is invalid.
18
+ class InvalidSecret < BCrypt::Error; end
19
+
20
+ end
21
+
22
+ end
@@ -0,0 +1,87 @@
1
+ module BCrypt
2
+ # A password management class which allows you to safely store users' passwords and compare them.
3
+ #
4
+ # Example usage:
5
+ #
6
+ # include BCrypt
7
+ #
8
+ # # hash a user's password
9
+ # @password = Password.create("my grand secret")
10
+ # @password #=> "$2a$12$C5.FIvVDS9W4AYZ/Ib37YuWd/7ozp1UaMhU28UKrfSxp2oDchbi3K"
11
+ #
12
+ # # store it safely
13
+ # @user.update_attribute(:password, @password)
14
+ #
15
+ # # read it back
16
+ # @user.reload!
17
+ # @db_password = Password.new(@user.password)
18
+ #
19
+ # # compare it after retrieval
20
+ # @db_password == "my grand secret" #=> true
21
+ # @db_password == "a paltry guess" #=> false
22
+ #
23
+ class Password < String
24
+ # The hash portion of the stored password hash.
25
+ attr_reader :checksum
26
+ # The salt of the store password hash (including version and cost).
27
+ attr_reader :salt
28
+ # The version of the bcrypt() algorithm used to create the hash.
29
+ attr_reader :version
30
+ # The cost factor used to create the hash.
31
+ attr_reader :cost
32
+
33
+ class << self
34
+ # Hashes a secret, returning a BCrypt::Password instance. Takes an optional <tt>:cost</tt> option, which is a
35
+ # logarithmic variable which determines how computational expensive the hash is to calculate (a <tt>:cost</tt> of
36
+ # 4 is twice as much work as a <tt>:cost</tt> of 3). The higher the <tt>:cost</tt> the harder it becomes for
37
+ # attackers to try to guess passwords (even if a copy of your database is stolen), but the slower it is to check
38
+ # users' passwords.
39
+ #
40
+ # Example:
41
+ #
42
+ # @password = BCrypt::Password.create("my secret", :cost => 13)
43
+ def create(secret, options = {})
44
+ cost = options[:cost] || BCrypt::Engine.cost
45
+ raise ArgumentError if cost > BCrypt::Engine::MAX_COST
46
+ Password.new(BCrypt::Engine.hash_secret(secret, BCrypt::Engine.generate_salt(cost)))
47
+ end
48
+
49
+ def valid_hash?(h)
50
+ h =~ /^\$[0-9a-z]{2}\$[0-9]{2}\$[A-Za-z0-9\.\/]{53}$/
51
+ end
52
+ end
53
+
54
+ # Initializes a BCrypt::Password instance with the data from a stored hash.
55
+ def initialize(raw_hash)
56
+ if valid_hash?(raw_hash)
57
+ self.replace(raw_hash)
58
+ @version, @cost, @salt, @checksum = split_hash(self)
59
+ else
60
+ raise Errors::InvalidHash.new("invalid hash")
61
+ end
62
+ end
63
+
64
+ # Compares a potential secret against the hash. Returns true if the secret is the original secret, false otherwise.
65
+ def ==(secret)
66
+ super(BCrypt::Engine.hash_secret(secret, @salt))
67
+ end
68
+ alias_method :is_password?, :==
69
+
70
+ private
71
+
72
+ # Returns true if +h+ is a valid hash.
73
+ def valid_hash?(h)
74
+ self.class.valid_hash?(h)
75
+ end
76
+
77
+ # call-seq:
78
+ # split_hash(raw_hash) -> version, cost, salt, hash
79
+ #
80
+ # Splits +h+ into version, cost, salt, and hash and returns them in that order.
81
+ def split_hash(h)
82
+ _, v, c, mash = h.split('$')
83
+ return v.to_str, c.to_i, h[0, 29].to_str, mash[-31, 31].to_str
84
+ end
85
+ end
86
+
87
+ end