最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

golang實(shí)現(xiàn)aes-cbc-256加密解密功能

 更新時(shí)間:2023年04月28日 14:29:19   作者:啊漢  
這篇文章主要介紹了golang實(shí)現(xiàn)aes-cbc-256加密解密功能,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下

我為什么吃撐了要實(shí)現(xiàn)go的aes-cbc-256加密解密功能?

之前的項(xiàng)目是用php實(shí)現(xiàn)的,現(xiàn)在準(zhǔn)備用go重構(gòu),需要用到這個(gè)功能,這么常用的功能上網(wǎng)一搜一大把現(xiàn)成例子,于是基于go現(xiàn)有api分分鐘實(shí)現(xiàn)一對(duì)加密解密函數(shù),你想得沒錯(cuò),一跑就失敗,好了不廢話了,go的aes-cbc實(shí)現(xiàn)由兩個(gè)限制

1:面臨兩個(gè)問題1:go秘鑰長(zhǎng)度必須是16/24/32

go源碼如下,我們的秘鑰長(zhǎng)度是72,不符合啊

// NewCipher creates and returns a new cipher.Block.
// The key argument should be the AES key,
// either 16, 24, or 32 bytes to select
// AES-128, AES-192, or AES-256.
func NewCipher(key []byte) (cipher.Block, error) {
   k := len(key)
   switch k {
   default:
      return nil, KeySizeError(k)
   case 16, 24, 32:
      break
   }
   return newCipher(key)
}

2:go根本不支持256位的aes-cbc加密解密

好脾氣的我再次貼一下go的相關(guān)源碼,赫然寫著const BlockSize = 16,還他媽是個(gè)常量,也就是說go一次只能加密16*8=128位,我的php256位怎么遷移

const BlockSize = 16  //你一眼就看到這么帥的我
type aesCipherAsm struct {
   aesCipher
}
var useAsm = cipherhw.AESGCMSupport()
func newCipher(key []byte) (cipher.Block, error) {
   if !useAsm {
      return newCipherGeneric(key)
   }
   n := len(key) + 28
   c := aesCipherAsm{aesCipher{make([]uint32, n), make([]uint32, n)}}
   rounds := 10
   switch len(key) {
   case 128 / 8:
      rounds = 10
   case 192 / 8:
      rounds = 12
   case 256 / 8:
      rounds = 14
   }
   expandKeyAsm(rounds, &key[0], &c.enc[0], &c.dec[0])
   if hasGCMAsm() {
      return &aesCipherGCM{c}, nil
   }
   return &c, nil
}
func (c *aesCipherAsm) BlockSize() int { return BlockSize }
func (c *aesCipherAsm) Encrypt(dst, src []byte) {
   if len(src) < BlockSize {
      panic("crypto/aes: input not full block")
   }
   if len(dst) < BlockSize {
      panic("crypto/aes: output not full block")
   }
   encryptBlockAsm(len(c.enc)/4-1, &c.enc[0], &dst[0], &src[0])
}
func (c *aesCipherAsm) Decrypt(dst, src []byte) {
   if len(src) < BlockSize {
      panic("crypto/aes: input not full block")
   }
   if len(dst) < BlockSize {
      panic("crypto/aes: output not full block")
   }
   decryptBlockAsm(len(c.dec)/4-1, &c.dec[0], &dst[0], &src[0])
}

問題一個(gè)個(gè)擊破,想辦法看能不能繞過去,由于是在NewCipher的時(shí)候?qū)Ρ匾L(zhǎng)度做了限制,我自己new不就行了,一看傻眼了,只有接口是public,實(shí)現(xiàn)對(duì)象都是private的,要想實(shí)例化對(duì)象只能通過NewCipher,繞不過去啊,大不了我把你的源碼拷出來,自己在改改,再次沖進(jìn)go源碼,并復(fù)制了出來,給個(gè)位看看先

//加密實(shí)現(xiàn)
TEXT ·encryptBlockAsm(SB),NOSPLIT,$0
    MOVQ nr+0(FP), CX
    666...
Lenc256:
    MOVUPS 0(AX), X1
    666...
Lenc196:
    MOVUPS 0(AX), X1
    666...
Lenc128:
    MOVUPS 0(AX), X1
    666..
    RET
//解密實(shí)現(xiàn)
// func decryptBlockAsm(nr int, xk *uint32, dst, src *byte)
TEXT ·decryptBlockAsm(SB),NOSPLIT,$0
    MOVQ nr+0(FP), CX
    666...
Ldec256:
    MOVUPS 0(AX), X1
    666...
Ldec196:
    MOVUPS 0(AX), X1
    666...
Ldec128:
    MOVUPS 0(AX), X1
    666...
    RET
//通過key和iv初始化加密解密所需的數(shù)據(jù)結(jié)構(gòu)
// func expandKeyAsm(nr int, key *byte, enc, dec *uint32) {
// Note that round keys are stored in uint128 format, not uint32
TEXT ·expandKeyAsm(SB),NOSPLIT,$0
    MOVQ nr+0(FP), CX
    JE Lexp_enc196   //完全不知道是兩個(gè)什么鬼命令
    JB Lexp_enc128   //同上,所以說是兩個(gè)鬼命令
Lexp_enc256:
    MOVUPS 16(AX), X2
    666...

首長(zhǎng):同志們,跟我一起喊:源碼在手,天下我有,666...

小弟:大哥,這源碼好像有點(diǎn)不對(duì)勁啊

我去:匯編,強(qiáng)做鎮(zhèn)靜,先找一下相關(guān)資料,好久沒研究匯編的我,再次研究起了匯編,找了一些資料:https://juejin.im/entry/5a39d646f265da431a435476,資料不錯(cuò)就是看不懂

把部分代碼拷出來,試著改了一下匯編代碼,運(yùn)行了一下,沒成功

其實(shí)go也有非匯編實(shí)現(xiàn)的go代碼,但每次也是加密16字節(jié),不符合要求,我要每次處理32字節(jié)的源碼,之后還嘗試過把NewCipher出的對(duì)象包一層,讓BlockSize()返回32,自然也是不行

第一階段以失敗告終

3:想用go調(diào)PHP

人有多大膽,go調(diào)毛PHP啊,上網(wǎng)一搜還真有這么一位大膽的大神,實(shí)現(xiàn)了go調(diào)PHP:https://github.com/deuill/go-php,小弟我感覺像是找到寶了,搞過來一跑,你還別說真成功了,當(dāng)我看到go調(diào)PHP輸出hello world得那一刻,淚牛滿面,方案就這么定了:go調(diào)php實(shí)現(xiàn)aes-cbc-256加密解密

以上成功只是幻想,其實(shí)是go調(diào)c成功了,并不興奮,調(diào)php并沒有,滿電腦沒找到libphp.so,原來在編譯php的時(shí)候沒有生成這個(gè)lib庫(kù),go調(diào)php就是想把php實(shí)現(xiàn)編譯到你的程序中讓你調(diào)用,于是又開始找資料,找到這個(gè):https://github.com/taowen/go-php,好熟悉的名字,這是我們公司的大神陶師傅啊,鄭重聲明:大神可是帶我做過項(xiàng)目的。于是厚著臉皮向大神請(qǐng)教,大神說不建議用go調(diào)PHP,這條路不太靠譜,建議直接rpc調(diào)用,當(dāng)我告訴大神我的需求和go的現(xiàn)狀時(shí),大神建議:把代碼從標(biāo)準(zhǔn)庫(kù)拷出來,兩邊對(duì)照著調(diào)試,你是大神還是我是大神,讓我用go把c的aes-cbc-256從新實(shí)現(xiàn),我怎么可能做得到!當(dāng)然你是大神,我照做

4:golang實(shí)現(xiàn)aes-cbc-256加密解密正式開始

第一步看PHP源碼。按照入口一步步看下去,主要是以下幾個(gè)函數(shù)

mcrypt_module_open
mcrypt_generic_init
mcrypt_generic
mdecrypt_generic

實(shí)現(xiàn)都在PHP的擴(kuò)展模塊mcrypt中,這個(gè)模塊也是只是對(duì)另一標(biāo)準(zhǔn)庫(kù)的封裝,地址:https://sourceforge.net/projects/mcrypt/files/Libmcrypt/,于是把代碼下下來看,代碼還挺多,由于我只需要實(shí)現(xiàn)aes-cbc-256,其他的直接略過,最終發(fā)現(xiàn)我只需要關(guān)注兩個(gè)文件:modules/algorithms/rijndael-256.c,modules/modes/cbc.c,各位觀眾有沒有發(fā)現(xiàn)這個(gè)標(biāo)準(zhǔn)庫(kù)的命名很給力,幾遍下來發(fā)現(xiàn)并不復(fù)雜,總共代碼不到600+行,于是將代碼復(fù)制過來,開始將c語言翻譯成go語言,很是小心翼翼,一回兒的功夫就翻譯完了(其實(shí)用了兩個(gè)多小時(shí)),翻譯很快那是相對(duì)debug階段來說的,一加密發(fā)現(xiàn)不對(duì),也不知道錯(cuò)在哪,代碼都快看吐了,都沒發(fā)現(xiàn)問題,于是只好按照大神說的兩邊對(duì)比調(diào)試,c語言已經(jīng)兩年多沒搞了,于是安裝了Clion,簡(jiǎn)單研究了一下,由于之前是搞windows的,mac上也沒搞過,還好挺好用,開始也是編譯不過,于是簡(jiǎn)單復(fù)習(xí)了一下c語言,最后終于跑通了,由于libmcrypt的實(shí)現(xiàn)到處都是指針,很多數(shù)據(jù)都看不到,只能打印出來看,后來發(fā)現(xiàn),秘鑰長(zhǎng)度搞錯(cuò)了,我是傳的32,其實(shí)秘鑰長(zhǎng)度是這么計(jì)算的

//獲取加密key長(zhǎng)度
func getKeySize(size int) int {
   for _, val := range keySizes {
      if size <= val {
         return val
      }
   }
   return BLOCK_SIZE
}

搞了好久終于解決了加密問題,我那個(gè)喜?。牪欢彤?dāng)是方言吧),真的特別有成就感,然后就開始搞解密,發(fā)現(xiàn)不對(duì),又是半天找不到原因,在這個(gè)過程中又找了一個(gè)庫(kù):https://github.com/mfpierre/go-mcrypt,這個(gè)庫(kù)實(shí)現(xiàn)了go的各種加密解密,其實(shí)只是對(duì)c標(biāo)準(zhǔn)庫(kù)mcrypt的封裝,考慮到線上環(huán)境不一定有,或是環(huán)境不一樣,就沒考慮這個(gè)庫(kù),我他媽褲子都脫了(實(shí)現(xiàn)了一半加密),你讓我放棄。還有這個(gè)庫(kù)干嘛要對(duì)秘鑰長(zhǎng)度進(jìn)行限制,標(biāo)準(zhǔn)庫(kù)本身沒有任何限制好不好。

5:含著淚也要解決問題

實(shí)現(xiàn)完加密的時(shí)候,我就向大神吹牛說,我已經(jīng)實(shí)現(xiàn),現(xiàn)在解密沒解決,怎么辦?

又是一陣看代碼,沒發(fā)現(xiàn)任何問題,只好使出終極殺手锏:?jiǎn)尾綄?duì)比調(diào)試,其實(shí)之前已經(jīng)發(fā)現(xiàn)staticword32 rtable[256];初始化不對(duì)了,為什么加密能成解密就不行,這個(gè)變量還真是只在解密用到,同步對(duì)比調(diào)試終于發(fā)現(xiàn)了問題,一個(gè)go語言不同于c語言的問題,且看下面這個(gè)函數(shù):

//c語言實(shí)現(xiàn)
static byte bmul(byte x, byte y)
{        
   if (x && y)
      return ptab[(ltab[x] + ltab[y]) % 255];
   else
      return 0;
}
bmul(200,200) == 145
//go語言實(shí)現(xiàn)
func bmul(x, y byte) byte {
   if x > 0 && y > 0 {
      return ptab[(ltab[x]+ltab[y])%255]
   }
   return 0
}
bmul(200,200) == 144

朋友們啊,看到區(qū)別沒有,前面說了,我是把c語言直接翻譯成go語言的,但是c語言和go語言不一樣啊,兩個(gè)完全一樣的函數(shù),竟然不一樣,c語言400%255=145好理解,go怎么就變成144了呢,200+200=144,我們來看看400的二進(jìn)制表示110010000,去掉最前面的1,就是010010000,剛好144,也就是說c語言byte超過了255根本沒關(guān)系,而go超過了255就給截?cái)嗔?,說好的互聯(lián)網(wǎng)時(shí)代的c語言呢!

6:最后厚顏無恥的掛到了github.com

https://github.com/chentaihan/aesCbc

到此這篇關(guān)于golang實(shí)現(xiàn)aes-cbc-256加密解密的文章就介紹到這了,更多相關(guān)go aes加密解密內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • golang判斷net.Conn 是否已關(guān)閉的操作

    golang判斷net.Conn 是否已關(guān)閉的操作

    這篇文章主要介紹了golang判斷net.Conn 是否已關(guān)閉的操作,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧
    2020-12-12
  • go語言文件正則表達(dá)式搜索功能示例

    go語言文件正則表達(dá)式搜索功能示例

    這篇文章主要介紹了go語言文件正則表達(dá)式搜索功能,涉及Go語言文件目錄的遍歷及正則操作相關(guān)技巧,需要的朋友可以參考下
    2017-01-01
  • 詳解Golang中Requests包的使用

    詳解Golang中Requests包的使用

    Go的net/http包雖然功能強(qiáng)大、用途也廣告,但要想正確的使用請(qǐng)求的客戶端是非常繁瑣的,所以本文和大家分享一個(gè)高效的HTTP的請(qǐng)求包c(diǎn)arlmjohnson/requests的使用,需要的小伙伴可以了解一下
    2023-06-06
  • go語言數(shù)據(jù)結(jié)構(gòu)之前綴樹Trie

    go語言數(shù)據(jù)結(jié)構(gòu)之前綴樹Trie

    這篇文章主要介紹了go語言數(shù)據(jù)結(jié)構(gòu)之前綴樹Trie,文章圍繞主題展開詳細(xì)內(nèi)容介紹,具有一定得參考價(jià)值,需要的小伙伴可以參考一下
    2022-05-05
  • 一文帶你深入理解Golang中的泛型

    一文帶你深入理解Golang中的泛型

    Go?在泛型方面一直被詬病,因?yàn)樗谶@方面相對(duì)比較落后。但是,在?Go?1.18?版本中,泛型已經(jīng)被正式引入,成為了?Go?語言中一個(gè)重要的特性。本文將會(huì)詳細(xì)介紹?Go?泛型的相關(guān)概念,語法和用法,希望能夠幫助大家更好地理解和應(yīng)用這一特性
    2023-05-05
  • Go Generate 代替 Makefile使用方法詳解

    Go Generate 代替 Makefile使用方法詳解

    這篇文章主要為大家介紹了Go Generate 代替 Makefile使用方法詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-12-12
  • GoFrame?ORM原生方法操作示例

    GoFrame?ORM原生方法操作示例

    這篇文章主要為大家介紹了GoFrame?ORM原生方法操作示例,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-06-06
  • Golang學(xué)習(xí)筆記(三):控制流

    Golang學(xué)習(xí)筆記(三):控制流

    這篇文章主要介紹了Golang學(xué)習(xí)筆記(三):控制流,本文講解了IF、FOR、SWITCH、goto、break、continue等控制流語句的使用實(shí)例,需要的朋友可以參考下
    2015-05-05
  • Golang?HTTP服務(wù)超時(shí)控制實(shí)現(xiàn)原理分析

    Golang?HTTP服務(wù)超時(shí)控制實(shí)現(xiàn)原理分析

    這篇文章主要介紹了Golang?HTTP服務(wù)超時(shí)控制實(shí)現(xiàn)原理,HTTP服務(wù)的超時(shí)控制是保障服務(wù)高可用性的重要措施之一,由于HTTP服務(wù)可能會(huì)遇到網(wǎng)絡(luò)延遲,資源瓶頸等問題,因此需要對(duì)請(qǐng)求進(jìn)行超時(shí)控制,以避免服務(wù)雪崩等問題,需要的朋友可以參考下
    2023-05-05
  • Go語言pointer及switch?fallthrough實(shí)戰(zhàn)詳解

    Go語言pointer及switch?fallthrough實(shí)戰(zhàn)詳解

    這篇文章主要為大家介紹了Go語言pointer及switch?fallthrough實(shí)戰(zhàn)詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-06-06

最新評(píng)論

吉木萨尔县| 时尚| 河北区| 咸丰县| 勐海县| 正镶白旗| 嵩明县| 岳普湖县| 廊坊市| 尉犁县| 柞水县| 梁河县| 启东市| 闻喜县| 崇信县| 高密市| 阿城市| 府谷县| 万载县| 鸡东县| 比如县| 定南县| 黎城县| 丰都县| 大余县| 凉山| 田阳县| 桦甸市| 林芝县| 淮安市| 贵阳市| 正定县| 辉县市| 华宁县| 汾西县| 沂源县| 宜州市| 中宁县| 容城县| 罗源县| 淳化县|