结合MD5的实现算法:
- 将网址md5后生成32位串,分4段, 每段8字节
- 对这四段循环处理,和0x3FFFFFFF与运算,即保留30位数据
- 根据字母表长度取索引值,如a-zA-Z0-9,就有62位,取0x3D (下标从0开始)
- 将前面的30位数据分成6段,每5位再和0x3D与运算,算得字母表下标,取到6位字符串 这种算法,会生成4个6位字符串。
lua版的算法如下:
local md5 = require "md5.core" function md5.sumhexa(k) k = md5.sum(k) return (string.gsub(k, ".", function (c) return string.format("%02x", string.byte(c)) end)) end local SHORT_BASE = { "a" , "b" , "c" , "d" , "e" , "f" , "g" , "h" , "i" , "j" , "k" , "l" , "m" , "n" , "o" , "p" , "q" , "r" , "s" , "t" , "u" , "v" , "w" , "x" , "y" , "z" , "0" , "1" , "2" , "3" , "4" , "5" , "6" , "7" , "8" , "9" , "A" , "B" , "C" , "D" , "E" , "F" , "G" , "H" , "I" , "J" , "K" , "L" , "M" , "N" , "O" , "P" , "Q" , "R" , "S" , "T" , "U" , "V" , "W" , "X" , "Y" , "Z" } local SHORT_PRE = "short_pre" function short_url(str) local m = md5.sumhexa(SHORT_PRE..str) local ret = {} for k=0,3 do local sub = string.sub(m, k*8+1, k*8+8) local int = 0x3fffffff & tonumber(sub, 16) local out = '' for j=1,6 do local v = ( 0x3d & int) + 1 out = out .. SHORT_BASE[v] int = int >> 5 end table.insert(ret, out) end return ret end local ret = short_url("hello world") for k,v in pairs(ret) do print("short_url", v) end
另外,再提供可让用户输入的短地址版本。就是只保留大写字母和数字,同时去掉了容易混淆的O0I1 。算法类似,可做激活码。
local md5 = require "md5.core" function md5.sumhexa(k) k = md5.sum(k) return (string.gsub(k, ".", function (c) return string.format("%02x", string.byte(c)) end)) end local SHORT_BASE = { 'A','B','C','D','E','F','G','H', 'J','K','L','M','N','P','Q','R', 'S','T','U','V','W','X','Y','Z', '2','3','4','5','6','7','8','9', } local SHORT_PRE = "short_pre" function short_url(str) local m = md5.sumhexa(SHORT_PRE..str) local ret = {} for k=0,3 do local sub = string.sub(m, k*8+1, k*8+8) local int = 0x3fffffff & tonumber(sub, 16) local out = '' for j=1,6 do local v = ( 0x1f & int) + 1 out = out .. SHORT_BASE[v] int = int >> 5 end table.insert(ret, out) end return ret end local ret = short_url("hello world") for k,v in pairs(ret) do print("short_url", v) end
评论前必须登录!
注册