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

jerry 2015年11月18日 收藏
thinkphp与其它语言用户互通,采用了PHP+Ucenter,其它项目中的ruby需要相应的uc_authcode加解密,公司同事写了一段,在公司的项目中测试通过。
#coding: utf-8
require 'digest/md5'
require 'base64'
require 'cgi'
class Authcode
   
  def authcode(auth_key, string, operation = '', expiry = 0)
    ckey_length = 4
    key = md5(auth_key)
    keya = md5(key[0, 16])
    keyb = md5(key[16, 16])
    keyc = ckey_length > 0 ? (operation == 'DECODE' ? string[0, ckey_length] : (md5(microtime()))[-ckey_length..-1]) : ''
    cryptkey = keya + md5(keya+keyc)
    key_length = cryptkey.size
    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
    string_ords = ords(string)
    string_length = string_ords.size
    result = ''
    box = (0..255).to_a
 
    rndkey = []
 
    0.upto(255) do |i|
      rndkey[i] = (cryptkey[i % key_length]).ord
    end
 
    j = i = 0
    while i < 256 do
      j = (j + box[i] + rndkey[i]) % 256
      box[i], box[j] = box[j], box[i]
      i +=1
    end
 
    a = j = i = 0
    while i < string_length
      a = (a + 1) % 256
      j = (j + box[a]) % 256
      box[a], box[j] = box[j], box[a]
      result += (string_ords[i] ^ (box[(box[a] + box[j]) % 256])).chr
      i +=1
    end
 
    if operation == 'DECODE' then
      if ( result[0,10] == '0'*10 || (result[0, 10]).to_i - Time.now.to_i  >  0 ) and
         result[10, 16] == (md5(result[26..-1] + keyb))[0, 16] then
        return result[26..-1]
      else
        return ''
      end
    else
      keyc + (Base64.encode64(result)).gsub(/=/, '')
    end
  end
   
   
  def md5(s)
    Digest::MD5.hexdigest(s)
  end
 
  def base64_url_decode(str)
    str += '=' * (4 - str.length.modulo(4))
    Base64.decode64(str.tr('-_','+/'))
  end
 
  def microtime
    epoch_mirco = Time.now.to_f
    epoch_full = Time.now.to_i
    epoch_fraction = epoch_mirco - epoch_full
    epoch_fraction.to_s + ' ' + epoch_full.to_s
  end
 
  def ords(s)
    s.bytes.to_a
  end
   
end
 
# 测试代码,和discuz的调用方法并不完全相同,第一个参数是加密解密算子,第二个才是字符串值
  
 
# code = "b384r5HiERJ+kEbb25t9jbtDXULGnCnR++1EK9xlmG74OKkd3hfjC4+dUJePocsJHts2JeO4/Po"
# key = "Y426x6Basctda9f94e49h3B6OeofcdX0J8Ua2a37P1M9Jd00he28o3t5ocq707U5"
# y = (Authcode.new).authcode(key,code,'DECODE')
# puts " ----- #{y}"
# #action=synlogin&username=homey0&uid=713627&password=10c308db89f5cf6bd6d011de005c25d2&time=1344610064