ucenter auth加解算法for ruby.authcode.rb

jerry 2015年11月18日 收藏
thinkphp与其它语言用户互通,采用了PHP+Ucenter,其它项目中的ruby需要相应的uc_authcode加解密,公司同事写了一段,在公司的项目中测试通过。
  1. #coding: utf-8
  2. require 'digest/md5'
  3. require 'base64'
  4. require 'cgi'
  5. class Authcode
  6.    
  7.   def authcode(auth_key, string, operation = '', expiry = 0)
  8.     ckey_length = 4
  9.     key = md5(auth_key)
  10.     keya = md5(key[0, 16])
  11.     keyb = md5(key[16, 16])
  12.     keyc = ckey_length > 0 ? (operation == 'DECODE' ? string[0, ckey_length] : (md5(microtime()))[-ckey_length..-1]) : ''
  13.     cryptkey = keya + md5(keya+keyc)
  14.     key_length = cryptkey.size
  15.     string = operation == 'DECODE' ? base64_url_decode(string[ckey_length..-1]) : sprintf('%010d', expiry>0 ? expiry + Time.now.to_i : 0)+ (md5(string+keyb))[0, 16] + string
  16.     string_ords = ords(string)
  17.     string_length = string_ords.size
  18.     result = ''
  19.     box = (0..255).to_a
  20.  
  21.     rndkey = []
  22.  
  23.     0.upto(255) do |i|
  24.       rndkey[i] = (cryptkey[% key_length]).ord
  25.     end
  26.  
  27.     j = i = 0
  28.     while i < 256 do
  29.       j = (+ box[i] + rndkey[i]) % 256
  30.       box[i], box[j] = box[j], box[i]
  31.       i +=1
  32.     end
  33.  
  34.     a = j = i = 0
  35.     while i < string_length
  36.       a = (+ 1) % 256
  37.       j = (+ box[a]) % 256
  38.       box[a], box[j] = box[j], box[a]
  39.       result += (string_ords[i] ^ (box[(box[a] + box[j]) % 256])).chr
  40.       i +=1
  41.     end
  42.  
  43.     if operation == 'DECODE' then
  44.       if ( result[0,10] == '0'*10 || (result[0, 10]).to_i - Time.now.to_i  >  0 ) and
  45.          result[10, 16] == (md5(result[26..-1] + keyb))[0, 16] then
  46.         return result[26..-1]
  47.       else
  48.         return ''
  49.       end
  50.     else
  51.       keyc + (Base64.encode64(result)).gsub(/=/, '')
  52.     end
  53.   end
  54.    
  55.    
  56.   def md5(s)
  57.     Digest::MD5.hexdigest(s)
  58.   end
  59.  
  60.   def base64_url_decode(str)
  61.     str += '=' * (4 - str.length.modulo(4))
  62.     Base64.decode64(str.tr('-_','+/'))
  63.   end
  64.  
  65.   def microtime
  66.     epoch_mirco = Time.now.to_f
  67.     epoch_full = Time.now.to_i
  68.     epoch_fraction = epoch_mirco - epoch_full
  69.     epoch_fraction.to_s + ' ' + epoch_full.to_s
  70.   end
  71.  
  72.   def ords(s)
  73.     s.bytes.to_a
  74.   end
  75.    
  76. end
  77.  
  78. # 测试代码,和discuz的调用方法并不完全相同,第一个参数是加密解密算子,第二个才是字符串值
  79.   
  80.  
  81. # code = "b384r5HiERJ+kEbb25t9jbtDXULGnCnR++1EK9xlmG74OKkd3hfjC4+dUJePocsJHts2JeO4/Po"
  82. # key = "Y426x6Basctda9f94e49h3B6OeofcdX0J8Ua2a37P1M9Jd00he28o3t5ocq707U5"
  83. # y = (Authcode.new).authcode(key,code,'DECODE')
  84. # puts " ----- #{y}"
  85. # #action=synlogin&username=homey0&uid=713627&password=10c308db89f5cf6bd6d011de005c25d2&time=1344610064