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(':')}.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 fields.join(','), text.hmac(key).base64 end end require 'uri' module URI PCHAR = /[^\w!$'():@\/]/ class HTTP def add_param(name, value) @query ? @query+='&' : @query='' @query += URI::escape(name,PCHAR) + '=' + URI::escape(value,PCHAR) 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