Class: Passlib::Password Abstract
- Inherits:
-
Object
- Object
- Passlib::Password
- Extended by:
- Internal::DSL
- Defined in:
- lib/passlib/password.rb
Overview
Subclass and implement the private #create method (and optionally #load and/or #verify) to add a new algorithm.
Abstract base class for all password hash implementations.
Concrete subclasses (e.g. BCrypt, PBKDF2, SHA2Crypt) each implement a specific algorithm. The public interface is identical across all of them: use Password.load to parse a stored hash, Password.create to generate a new one, and #verify to verify a plaintext secret.
Instances are immutable value objects. The underlying hash string is accessible via #to_s/#to_str and is always frozen.
Direct Known Subclasses
Argon2, BCrypt, Balloon, BcryptSHA256, LdapDigest, MD5Crypt, PBKDF2, PHPass, SCrypt, SHA1Crypt, SHA2Crypt, Yescrypt
Constant Summary
Constants included from Internal::DSL
Instance Attribute Summary collapse
-
#config ⇒ Configuration
(also: #configuration)
readonly
The configuration used when this instance was created or loaded.
-
#string ⇒ String
(also: #to_str, #to_s)
readonly
The frozen hash string, e.g.
Class Method Summary collapse
-
.available? ⇒ Boolean
Returns whether this algorithm’s dependency gem is installed and available.
-
.create(secret, config = nil) ⇒ Password
Creates a new password hash for the given secret.
-
.load(string, config = nil) ⇒ Password
Parses a stored hash string and returns a Password instance.
Instance Method Summary collapse
-
#create_comparable(secret) ⇒ Password
abstract
Re-hashes
secretusing the same parameters (salt, rounds, etc.). -
#initialize(config, method) ⇒ Password
constructor
private
A new instance of Password.
-
#inspect ⇒ String
private
Returns a human-readable representation including the class name and hash string.
-
#pretty_print(pp) ⇒ void
private
Pretty-print support for
pp. -
#upgrade? ⇒ Boolean
Returns whether this hash should be re-hashed with the current configuration.
-
#verify(secret) ⇒ Boolean
(also: #match?)
Verifies that
secretmatches this password hash.
Methods included from Internal::DSL
Constructor Details
#initialize(config, method) ⇒ Password
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
Returns a new instance of Password.
99 100 101 102 103 104 105 |
# File 'lib/passlib/password.rb', line 99 def initialize(config, method, ...) super() @config = config result = send(method, ...) @string ||= result.to_str @string = @string.frozen? ? @string : @string.dup.freeze end |
Instance Attribute Details
#config ⇒ Configuration (readonly) Also known as: configuration
The configuration used when this instance was created or loaded.
89 90 91 |
# File 'lib/passlib/password.rb', line 89 def config @config end |
#string ⇒ String (readonly) Also known as: to_str, to_s
The frozen hash string, e.g. “$2a$12$…” or “{SSHA}…” .
94 95 96 |
# File 'lib/passlib/password.rb', line 94 def string @string end |
Class Method Details
.available? ⇒ Boolean
Returns whether this algorithm’s dependency gem is installed and available.
83 |
# File 'lib/passlib/password.rb', line 83 def self.available? = true |
.create(secret, config = nil) ⇒ Password
Creates a new password hash for the given secret.
When called on a concrete subclass the algorithm is fixed. When called on Passlib::Password directly, the algorithm is selected from the configuration: set preferred_scheme (a single identifier) or preferred_schemes (an ordered list) in the supplied Configuration::Passlib and the first available algorithm in the list is used. Raises UnsupportedAlgorithm when no usable scheme can be found.
72 73 74 75 76 77 78 79 |
# File 'lib/passlib/password.rb', line 72 def self.create(secret, config = nil, **) config = config(config, **) return new(config, :create, secret) if self != Password scheme = config.preferred_scheme return ::Passlib[scheme].create(secret, config) if scheme raise UnsupportedAlgorithm, "no preferred schemes configured" if config.preferred_schemes.empty? raise UnsupportedAlgorithm, "no available preferred schemes: #{config.preferred_schemes.join(", ")}" end |
.load(string, config = nil) ⇒ Password
Parses a stored hash string and returns a Passlib::Password instance.
When called on Passlib::Password directly (rather than a concrete subclass), the algorithm is auto-detected from the hash format. When called on a subclass, the string must be a valid hash for that algorithm.
41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 |
# File 'lib/passlib/password.rb', line 41 def self.load(string, config = nil, **) return new(config(config, **), :load, string) if self != Password case string when /\A\$([\w-]+)/ then klass = Internal::Register::MFC_IDS[$1] || Internal::Register::MFC_IDS[$1[/\A\w+/]] when /\A{([\w-]+)(?:,[^}]*)?}/ then klass = Internal::Register::LDAP_IDS[$1.upcase] else classes = Set.new Internal::Register::PATTERNS.each do |pattern, candidate| classes << candidate if pattern === string end klass = classes.first if classes.size == 1 end return klass.load(string, config, **) if klass raise ArgumentError, "unknown password hash format: #{string.inspect}" end |
Instance Method Details
#create_comparable(secret) ⇒ Password
Re-hashes secret using the same parameters (salt, rounds, etc.).
Not all subclasses define it, use respond_to?(:create_comparable) to check.
|
|
# File 'lib/passlib/password.rb', line 107
|
#inspect ⇒ String
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
Returns a human-readable representation including the class name and hash string.
140 |
# File 'lib/passlib/password.rb', line 140 def inspect = "#<#{self.class.name} #{string.inspect}>" |
#pretty_print(pp) ⇒ void
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
This method returns an undefined value.
Pretty-print support for pp.
146 147 148 149 150 151 |
# File 'lib/passlib/password.rb', line 146 def pretty_print(pp) pp.object_group(self) do pp.breakable pp.pp string end end |
#upgrade? ⇒ Boolean
Returns whether this hash should be re-hashed with the current configuration.
Called by Configuration::Context#upgrade? after confirming the hash already uses the preferred algorithm. Returns true if any parameter (cost, rounds, etc.) does not exactly match the active configuration, including when stored costs are higher than configured (allowing a downgrade when parameters were set too high).
162 |
# File 'lib/passlib/password.rb', line 162 def upgrade? = raise NotImplementedError, "subclass must implement #upgrade?" |
#verify(secret) ⇒ Boolean Also known as: match?
Verifies that secret matches this password hash.
Uses constant-time comparison via Passlib#secure_compare to prevent timing attacks.
123 124 125 126 127 128 |
# File 'lib/passlib/password.rb', line 123 def verify(secret) Passlib.secure_compare(self, create_comparable(secret)) rescue NameError => error raise error unless error.name == :create_comparable raise NotImplementedError, "subclass must implement #verify or #create_comparable" end |