blob: 97e6592f44264197f5b9af7d5940e5edffbd5553 (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
|
# frozen_string_literal: true
# Support for both BCrypt and PBKDF2+SHA512 user passwords
# Meant to be used exclusively with User model but extracted
# to a concern for isolation and clarity.
module EncryptedUserPassword
extend ActiveSupport::Concern
BCRYPT_PREFIX = '$2a$'
PBKDF2_SHA512_PREFIX = '$pbkdf2-sha512$'
BCRYPT_STRATEGY = :bcrypt
PBKDF2_SHA512_STRATEGY = :pbkdf2_sha512
# Use Devise DatabaseAuthenticatable#authenticatable_salt
# unless encrypted password is PBKDF2+SHA512.
def authenticatable_salt
return super unless pbkdf2_password?
Devise::Pbkdf2Encryptable::Encryptors::Pbkdf2Sha512.split_digest(encrypted_password)[:salt]
end
# Called by Devise during database authentication.
# Also migrates the user password to the configured
# encryption type (BCrypt or PBKDF2+SHA512), if needed.
def valid_password?(password)
return false unless password_matches?(password)
migrate_password!(password)
end
def password=(new_password)
@password = new_password # rubocop:disable Gitlab/ModuleWithInstanceVariables
return unless new_password.present?
self.encrypted_password = if Gitlab::FIPS.enabled?
Devise::Pbkdf2Encryptable::Encryptors::Pbkdf2Sha512.digest(
new_password,
Devise::Pbkdf2Encryptable::Encryptors::Pbkdf2Sha512::STRETCHES,
Devise.friendly_token[0, 16])
else
Devise::Encryptor.digest(self.class, new_password)
end
end
private
def password_strategy
return BCRYPT_STRATEGY if encrypted_password.starts_with?(BCRYPT_PREFIX)
return PBKDF2_SHA512_STRATEGY if encrypted_password.starts_with?(PBKDF2_SHA512_PREFIX)
:unknown
end
def pbkdf2_password?
password_strategy == PBKDF2_SHA512_STRATEGY
end
def bcrypt_password?
password_strategy == BCRYPT_STRATEGY
end
def password_matches?(password)
if bcrypt_password?
Devise::Encryptor.compare(self.class, encrypted_password, password)
elsif pbkdf2_password?
Devise::Pbkdf2Encryptable::Encryptors::Pbkdf2Sha512.compare(encrypted_password, password)
end
end
def migrate_password!(password)
return true if password_strategy == encryptor
update_attribute(:password, password)
end
def encryptor
return BCRYPT_STRATEGY unless Gitlab::FIPS.enabled?
PBKDF2_SHA512_STRATEGY
end
end
|