class TypeKey

This class handles TypeKey logins.

Attributes

base_url[RW]
key_cache_path[RW]
key_cache_timeout[RW]
key_url[RW]
login_timeout[RW]

Public Class Methods

new(token, version = '1.1') click to toggle source
# File vendor/qwik/lib/qwik/typekey.rb, line 52
def initialize(token, version = '1.1')
  @token = token
  @version = version

  # Base url for generating login and logout urls.
  @base_url = 'https://www.typekey.com/t/typekey/'

  # Url used to download the public key.
  @key_url = 'http://www.typekey.com/extras/regkeys.txt'

  # Location for caching the public key.
  @key_cache_path = '/tmp/tk_key_cache'

  # Length of time to wait before refreshing the public key cache, in seconds.
  # Defaults to two days.
  @key_cache_timeout = 60 * 60 * 24 * 2

  # Length of time logins remain valid, in seconds.
  # Defaults to five minutes.
  @login_timeout = 60 * 5
end

Public Instance Methods

dsa_verify(message, sig, key) click to toggle source

Verify a DSA signature

# File vendor/qwik/lib/qwik/typekey.rb, line 145
def dsa_verify(message, sig, key)
  r_sig, s_sig = sig.split(':')
  r_sig = Base64.decode64(r_sig).unpack('H*')[0].hex
  s_sig = Base64.decode64(s_sig).unpack('H*')[0].hex
  sign = OpenSSL::ASN1::Sequence.new([OpenSSL::ASN1::Integer.new(r_sig),
                                       OpenSSL::ASN1::Integer.new(s_sig)]
                                     ).to_der
  dsa = OpenSSL::PKey::DSA.new
  dsa.p = key['p']
  dsa.q = key['q']
  dsa.g = key['g']
  dsa.pub_key = key['pub_key']
  dss1 = OpenSSL::Digest::DSS1.new
  return dsa.verify(dss1, sign, message)
end
get_key(url = nil) click to toggle source

Return the TypeKey public keys, cache results unless a url is passed

# File vendor/qwik/lib/qwik/typekey.rb, line 107
def get_key(url = nil)
  if url.nil?
    begin
      mod_time = File.mtime(@key_cache_path).to_i
    rescue SystemCallError
      mod_time = 0
    end

    if @key_cache_timeout < (Time.now.to_i - mod_time) ||
        ! File.exist?(@key_cache_path)
      open(@key_url) {|fh| # using open-uri
        @key_string = fh.read
      }
      File.open(@key_cache_path, 'w') {|fh|
        fh.puts(@key_string)
      }
    else
      File.open(@key_cache_path, 'r') {|fh|
        @key_string = fh.read
      }
    end
  else
    open(url) {|fh|
      @key_string = fh.read
    }
  end

  tk_key = Hash.new

  for pair in @key_string.strip.split(' ')
    key, value = pair.split('=')
    tk_key[key] = value.to_i
  end

  return tk_key
end
get_login_url(return_url, email = false) click to toggle source

Return a URL to login to TypeKey

# File vendor/qwik/lib/qwik/typekey.rb, line 92
def get_login_url(return_url, email = false)
  url  = @base_url
  url += "login?t=#{@token}"
  url += (email ? '&need_email=1' : '')
  url += "&_return=#{URI.escape(return_url)}"
  url += "&v=#{@version}"
  return url
end
get_logout_url(return_url) click to toggle source

Return a URL to logout of TypeKey

# File vendor/qwik/lib/qwik/typekey.rb, line 102
def get_logout_url(return_url)
  return @base_url + 'logout?_return=' + URI.escape(return_url)
end
verify(email, name, nick, ts, sig, key = nil) click to toggle source

Verify a typekey login

# File vendor/qwik/lib/qwik/typekey.rb, line 77
def verify(email, name, nick, ts, sig, key = nil)
  sig.gsub!(/ /, '+') # sig isn't urlencoded.

  key = get_key if key.nil?

  message_ar = [email, name, nick, ts.to_s]
  message_ar << @token if @version == '1.1'
  message = message_ar.join('::')

  raise VerifyFailed if ! dsa_verify(message, sig, key)
  raise TimeOutError if (Time.now.to_i - ts.to_i) > @login_timeout
  return true
end