Class: Pwnedkeys::Request

Inherits:
Object
  • Object
show all
Defined in:
lib/pwnedkeys/request.rb

Overview

Make a query against the pwnedkeys.com API.

Defined Under Namespace

Classes: Error, VerificationError

Instance Method Summary collapse

Constructor Details

#initialize(spki) ⇒ Request

Prepare to the make a request to the pwnedkeys API.

Parameters:

  • spki (OpenSSL::X509::SPKI, OpenSSL::PKey::PKey, String)

    the public key to query for. Can be provided as a key object itself, an SPKI object (most likely derived from an X509 certificate or CSR), or a string containing a DER-encoded ‘SubjectPublicKeyInfo` ASN.1 structure.

    If in doubt, just pass in a key and we’ll take care of the rest.

Raises:



37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
# File 'lib/pwnedkeys/request.rb', line 37

def initialize(spki)
  @spki = if spki.is_a?(OpenSSL::X509::SPKI)
    spki
  elsif spki.is_a?(String)
    begin
      OpenSSL::X509::SPKI.new(spki)
    rescue OpenSSL::ASN1::ASN1Error, OpenSSL::X509::SPKIError
      raise Error,
            "Invalid SPKI ASN.1 string"
    end
  elsif spki.is_a?(OpenSSL::PKey::PKey)
    spki.to_spki
  else
    raise Error,
          "Invalid argument type passed to Pwnedkeys::Request.new (need OpenSSL::X509::SPKI, PKey, or string, got #{spki.class})"
  end

  # Verify key type is OK
  key_params
end

Instance Method Details

#pwned?Boolean

Query the pwnedkeys API and tell whether the key is exposed.

Returns:

  • (Boolean)

    whether the key embodied in this request is contained within the pwnedkeys database.

Raises:

  • (VerificationError)

    if a response was provided, but the signature on the response was not able to be verified.

  • (Error)

    if the request to the API could not be successfully completed.



69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
# File 'lib/pwnedkeys/request.rb', line 69

def pwned?
  retry_count = 10
  uri = URI(ENV["PWNEDKEYS_API_URL"] || "https://v1.pwnedkeys.com")
  uri.path += "/#{@spki.spki_fingerprint.hexdigest}"

  loop do
    res = Net::HTTP.start(uri.host, uri.port, use_ssl: uri.scheme == "https") do |http|
      req = Net::HTTP::Get.new(uri.path)
      req["User-Agent"] = "pwnedkeys-tools/0.0.0"
      http.request(req)
    end

    if res.code == "200"
      verify!(res.body)
      return true
    elsif res.code == "404"
      return false
    elsif (500..599) === res.code.to_i && retry_count > 0
      # Server-side error, let's try a few more times
      sleep 1
      retry_count -= 1
    else
      raise Error,
            "Unable to determine pwnage, error status code returned from #{uri}: #{res.code}"
    end
  end
end