class Integer
  def mod_exp(n,q)
    y=1
    x=self
    while n > 0
      y = (y*x) % q if n[0]==1
      n >>= 1  
      x = (x*x) % q
    end
    return y
  end

  def btwoc
    bits = [self]
    bits.unshift *bits.shift.divmod(256) until (-128..127).include? bits[0]
    bits.pack('C*')
  end
end

class String
  def ^(other)
    unpack("C*").zip(other.unpack("C*")).map {|a,b| a^b}.pack("C*")
  end

  require 'digest/sha1'
  def hmac(key, block_size=64, algorithm=Digest::SHA1)
    key = algorithm.digest(key) if key.length > block_size
    key = key.ljust(block_size,"\0").unpack('c*')

    digest = algorithm.digest(key.map {|c| c ^= 0x36}.pack('c*') + self)
    algorithm.digest(key.map {|c| c ^= 0x5c}.pack('c*') + digest)
  end

  def sha1
    Digest::SHA1.digest self
  end

  def base64
    [self].pack('m').gsub("\n",'')
  end

  def unbase64
    self.unpack('m')[0]
  end

  def unbtwoc
    self.unpack('C*').inject(self[0]<128 ? 0  : -1) {|a,b| a*256+b}
  end

  def parsekv
    Hash[*self.strip.split("\n").collect {|line| line.split(':',2)}.flatten]
  end
end

class Hash
  def to_kv
    self.collect {|key,value| "#{key}:#{value}\n"}.join
  end

  def sign key, fields
    text = fields.collect {|field| "#{field}:#{self['openid.'+field]}\n"}.join
    return text.hmac(key).base64
  end
end

require 'uri'
module URI
  PCHAR = /[^-\w\.]/

  class HTTP
    def add_params(hash)
      hash.each_pair do |name,value|
        @query ? @query+='&' : @query=''
        @query += URI::escape(name,PCHAR) + '=' + URI::escape(value,PCHAR)
      end
      self
    end

    def get_params
      Hash[*query.split('&').
        map {|p| p.split('=',2).map {|v| URI::unescape(v)}}.flatten]
    end

    def get
      Net::HTTP.start(self.host, self.port) { |http|
        http.get(self.request_uri)
      }
    end

    def post data
      Net::HTTP.start(self.host, self.port) { |http|
        data=data.map {|a,b| a.to_s+'='+CGI.escape(b)}.join('&') \
          if data.respond_to? :each_pair
        http.post(self.request_uri, data)
      }
    end
  end
end

class DiffieHellman
  attr_accessor :p, :g

  module DEFAULT
    GEN = 2
    MOD = 155172898181473697471232257763715539915724801966915404479707795314057629378541917580651227423698188993727816152646631438561595825688188889951272158842675419950341258706556549803580104870537681476726513255747040765857479291291572334510643245094715007229621094194349783925984760375594985848253359305585439638443
  end

  def initialize
    @p = DEFAULT::MOD
    @g = DEFAULT::GEN
  end

  def x
    @x ||= 1+rand(p-2)
  end

  def createKeyExchange
    g.mod_exp(x, p)
  end

  def decryptKeyExchange keyEx
    keyEx.mod_exp(x, p)
  end
end
