module Pwned::PasswordBase
This class represents a password. It does all the work of talking to the Pwned
Passwords API to find out if the password has been pwned. @see haveibeenpwned.com/API/v2#PwnedPasswords
Constants
- API_URL
The base URL for the
Pwned
Passwords API- DEFAULT_REQUEST_HEADERS
The default request headers that are used to make HTTP requests to the API. A user agent is provided as requested in the documentation. @see haveibeenpwned.com/API/v2#UserAgent
- HASH_PREFIX_LENGTH
The number of characters from the start of the hash of the password that are used to search for the range of passwords.
- SHA1_LENGTH
The total length of a SHA1 hash
Attributes
Returns the full SHA1 hash of the given password in uppercase. @return [String] The full SHA1 hash of the given password. @since 1.0.0
Public Instance Methods
@example
password = Pwned::Password.new("password") password.pwned? #=> true password.pwned? #=> true
@return [Boolean] true
when the password has been pwned. @raise [Pwned::Error] if there are errors with the HTTP request. @raise [Pwned::TimeoutError] if the HTTP request times out. @since 1.0.0
# File lib/pwned/password_base.rb, line 43 def pwned? pwned_count > 0 end
@example
password = Pwned::Password.new("password") password.pwned_count #=> 3303003
@return [Integer] the number of times the password has been pwned. @raise [Pwned::Error] if there are errors with the HTTP request. @raise [Pwned::TimeoutError] if the HTTP request times out. @since 1.0.0
# File lib/pwned/password_base.rb, line 56 def pwned_count @pwned_count ||= fetch_pwned_count end
Private Instance Methods
# File lib/pwned/password_base.rb, line 70 def fetch_pwned_count for_each_response_line do |line| next unless line.start_with?(hashed_password_suffix) # Count starts after the suffix, followed by a colon return line[(SHA1_LENGTH-HASH_PREFIX_LENGTH+1)..-1].to_i end # The hash was not found, we can assume the password is not pwned [yet] 0 end
# File lib/pwned/password_base.rb, line 81 def for_each_response_line(&block) begin with_http_response "#{API_URL}#{hashed_password_prefix}" do |response| response.value # raise if request was unsuccessful stream_response_lines(response, &block) end rescue Timeout::Error => e raise Pwned::TimeoutError, e.message rescue => e raise Pwned::Error, e.message end end
# File lib/pwned/password_base.rb, line 94 def hashed_password_prefix @hashed_password[0...HASH_PREFIX_LENGTH] end
# File lib/pwned/password_base.rb, line 98 def hashed_password_suffix @hashed_password[HASH_PREFIX_LENGTH..-1] end
Stream a Net::HTTPResponse by line, handling lines that cross chunks.
# File lib/pwned/password_base.rb, line 127 def stream_response_lines(response, &block) last_line = "" response.read_body do |chunk| chunk_lines = (last_line + chunk).lines # This could end with half a line, so save it for next time. If # chunk_lines is empty, pop returns nil, so this also ensures last_line # is always a string. last_line = chunk_lines.pop || "" chunk_lines.each(&block) end yield last_line unless last_line.empty? end
Make a HTTP GET request given the url and headers. Yields a `Net::HTTPResponse`.
# File lib/pwned/password_base.rb, line 104 def with_http_response(url, &block) uri = URI(url) request = Net::HTTP::Get.new(uri) request.initialize_http_header(request_headers) request_options[:use_ssl] = true environment_proxy = ignore_env_proxy ? nil : :ENV Net::HTTP.start( uri.host, uri.port, request_proxy&.host || environment_proxy, request_proxy&.port, request_proxy&.user, request_proxy&.password, request_options ) do |http| http.request(request, &block) end end