git ssb

0+

dangerousbeans / %aPBe2k3ugtjBr4rrsU1…



Tree: 2ec9dacebb3345a9db2541e7dc7e7bea00147661

Files: 2ec9dacebb3345a9db2541e7dc7e7bea00147661 / lib / bcrypt / engine.rb

3600 bytesRaw
1module 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 = 10
6 # The minimum cost supported by the algorithm.
7 MIN_COST = 4
8 # Maximum possible size of bcrypt() salts.
9 MAX_SALT_LENGTH = 16
10
11 if RUBY_PLATFORM != "java"
12 # C-level routines which, if they don't get the right input, will crash the
13 # hell out of the Ruby process.
14 private_class_method :__bc_salt
15 private_class_method :__bc_crypt
16 end
17
18 @cost = nil
19
20 # Returns the cost factor that will be used if one is not specified when
21 # creating a password hash. Defaults to DEFAULT_COST if not set.
22 def self.cost
23 @cost || DEFAULT_COST
24 end
25
26 # Set a default cost factor that will be used if one is not specified when
27 # creating a password hash.
28 #
29 # Example:
30 #
31 # BCrypt::Engine::DEFAULT_COST #=> 10
32 # BCrypt::Password.create('secret').cost #=> 10
33 #
34 # BCrypt::Engine.cost = 8
35 # BCrypt::Password.create('secret').cost #=> 8
36 #
37 # # cost can still be overridden as needed
38 # BCrypt::Password.create('secret', :cost => 6).cost #=> 6
39 def self.cost=(cost)
40 @cost = cost
41 end
42
43 # Given a secret and a valid salt (see BCrypt::Engine.generate_salt) calculates
44 # a bcrypt() password hash.
45 def self.hash_secret(secret, salt, _ = nil)
46 if valid_secret?(secret)
47 if valid_salt?(salt)
48 if RUBY_PLATFORM == "java"
49 Java.bcrypt_jruby.BCrypt.hashpw(secret.to_s, salt.to_s)
50 else
51 __bc_crypt(secret.to_s, salt)
52 end
53 else
54 raise Errors::InvalidSalt.new("invalid salt")
55 end
56 else
57 raise Errors::InvalidSecret.new("invalid secret")
58 end
59 end
60
61 # Generates a random salt with a given computational cost.
62 def self.generate_salt(cost = self.cost)
63 cost = cost.to_i
64 if cost > 0
65 if cost < MIN_COST
66 cost = MIN_COST
67 end
68 if RUBY_PLATFORM == "java"
69 Java.bcrypt_jruby.BCrypt.gensalt(cost)
70 else
71 prefix = "$2a$05$CCCCCCCCCCCCCCCCCCCCC.E5YPO9kmyuRGyh0XouQYb4YMJKvyOeW"
72 __bc_salt(prefix, cost, OpenSSL::Random.random_bytes(MAX_SALT_LENGTH))
73 end
74 else
75 raise Errors::InvalidCost.new("cost must be numeric and > 0")
76 end
77 end
78
79 # Returns true if +salt+ is a valid bcrypt() salt, false if not.
80 def self.valid_salt?(salt)
81 !!(salt =~ /^\$[0-9a-z]{2,}\$[0-9]{2,}\$[A-Za-z0-9\.\/]{22,}$/)
82 end
83
84 # Returns true if +secret+ is a valid bcrypt() secret, false if not.
85 def self.valid_secret?(secret)
86 secret.respond_to?(:to_s)
87 end
88
89 # Returns the cost factor which will result in computation times less than +upper_time_limit_in_ms+.
90 #
91 # Example:
92 #
93 # BCrypt::Engine.calibrate(200) #=> 10
94 # BCrypt::Engine.calibrate(1000) #=> 12
95 #
96 # # should take less than 200ms
97 # BCrypt::Password.create("woo", :cost => 10)
98 #
99 # # should take less than 1000ms
100 # BCrypt::Password.create("woo", :cost => 12)
101 def self.calibrate(upper_time_limit_in_ms)
102 40.times do |i|
103 start_time = Time.now
104 Password.create("testing testing", :cost => i+1)
105 end_time = Time.now - start_time
106 return i if end_time * 1_000 > upper_time_limit_in_ms
107 end
108 end
109
110 # Autodetects the cost from the salt string.
111 def self.autodetect_cost(salt)
112 salt[4..5].to_i
113 end
114 end
115
116end
117

Built with git-ssb-web