go語言版本的discuz authcode函數實現

來源:互聯網
上載者:User
這是一個建立於 的文章,其中的資訊可能已經有所發展或是發生改變。

有個項目中正好需要用到一個對稱加解密函數,想起了,DZ的那個authcode函數,於是乎在網上找了哈,沒有發現,不曉得是不是我搜尋技術不夠哈,總之是沒有找到,好吧,自己動手豐衣足食。。。GO。

大概原來是秘鑰放在加密串中的,到期時間也在裡面,然後是驗證字串,解密的時候要先出去前面幾位的動態秘鑰,當然可以不用哈,那麼每次加密結果都一樣的。

key + text

text[0:10]到期時間 0:不到期

text[10:26]驗證字串

text[26:]原字串


// 加解密函數 根據dz的Authcode改寫的go版本// params[0] 加密or解密 bool true:加密 false:解密 預設false// params[1] 秘鑰// params[2] 加密:到期時間// params[3] 動態秘鑰長度 預設:4位 不能大於32位func Authcode(text string, params ...interface{}) string {l := len(params)isEncode := falsekey := ""expiry := 0cKeyLen := 4if l > 0 {isEncode = params[0].(bool)}if l > 1 {key = params[1].(string)}if l > 2 {expiry = params[2].(int)if expiry < 0 {expiry = 0}}if l > 3 {cKeyLen = params[3].(int)if cKeyLen < 0 {cKeyLen = 0}}if cKeyLen > 32 {cKeyLen = 32}timestamp := time.Now().Unix()// md5加密keymKey := Md5Sum(key)// 參與加密的keyA := Md5Sum(mKey[0:16])// 用於驗證資料有效性的keyB := Md5Sum(mKey[16:])// 動態部分var keyC stringif cKeyLen > 0 {if isEncode {// 加密的時候,動態擷取一個秘鑰keyC = Md5Sum(fmt.Sprint(timestamp))[32-cKeyLen:]} else {// 解密的時候從頭部擷取動態秘鑰部分keyC = text[0:cKeyLen]}}// 加入了動態秘鑰cryptKey := keyA + Md5Sum(keyA+keyC)// 秘鑰長度keyLen := len(cryptKey)if isEncode {// 加密 前10位是到期驗證字串 10-26位字串驗證var d int64if expiry > 0 {d = timestamp + int64(expiry)}text = fmt.Sprintf("%010d%s%s", d, Md5Sum(text + keyB)[0:16], text)} else {// 解密text = string(Base64Decode(text[cKeyLen:]))}// 字串長度textLen := len(text)if textLen <= 0 {return ""}// 密匙簿box := Range(0, 256)// 對稱演算法var rndKey []intcryptKeyB := []byte(cryptKey)for i := 0; i < 256; i++ {pos := i % keyLenrndKey = append(rndKey, int(cryptKeyB[pos]))}j := 0for i := 0; i < 256; i++ {j = (j + box[i] + rndKey[i]) % 256box[i], box[j] = box[j], box[i]}textB := []byte(text)a := 0j = 0var result []bytefor i := 0; i < textLen; i++ {a = (a + 1) % 256j = (j + box[a]) % 256box[a], box[j] = box[j], box[a]result = append(result, byte(int(textB[i])^(box[(box[a]+box[j])%256])))}if isEncode {return keyC + strings.Replace(Base64Encode(result), "=", "", -1)}// 擷取前10位,判斷到期時間d := Atoi64(string(result[0:10]), 0)if (d == 0 || d-timestamp > 0) && string(result[10:26]) == Md5Sum(string(result[26:]) + keyB)[0:16] {return string(result[26:])}return ""}
裡面有幾個自訂的相關函數,比較簡單的,需要特別說明下得是Base64Decode這個
func Base64Decode(str string) []byte {var b []bytevar err errorx := len(str) * 3 % 4switch {case x == 2:str += "=="case x == 1:str += "="}if b, err = base64.StdEncoding.DecodeString(str); err != nil {return b}return b}

因為在加密用到Base64Encode以後,替換了=為空白字串,所以這裡需要處理下,PHP裡面的base64_decode函數是可以直接處理,這裡自己卡了幾個小時去研究了下BASE64得原理,base64是說3個字元轉成4個字元的方法。因為3個字元二進位剛好24位,分成4個,那麼每個只有6位二進位,算一下剛好64,所以base64的所有字元就是64個,從A..Za..z0..9+/剛好64個。如果當轉換中,如果少了,後面補=號,所以會出現最後一個=號和兩個=號的情況。這雷根據這個原理反補了等號回去,因為GO本身的解碼函數沒有處理這個。

完整檔案包,在這裡,https://github.com/last911/utils/blob/master/tools.go

周末了,回家了。公司好像還很多人呢。

星期天要踢球,安逸。。。回家



相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.