[golang] Blowfish演算法的go實現

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

最近由於工作的需要,需要的實現一個go的Blowfish演算法。其實go本身有一個密碼編譯演算法庫crypto,其中有Blowfish。但是該演算法在很多細節上跟我的需求不同,導致最終加密結果千差萬別。

Blowfish演算法

BlowFish是對稱式加密演算法的其中一種。在很多情境下,作為DES的替代出現。BlowFish並不是直接用我們指定的金鑰組資料加密,而是先對密鑰進行預先處理,然後用處理的結果再對資料加密。解密過程同理。

BlowFish演算法內建兩個源密鑰:pbox和sbox,pbox18位元組,sbox4個256位元組組成。演算法在加密解密時,根據兩個盒子大量使用位移運算和邏輯位元運算。具體的演算法細節自行百度/Google,本文就不詳述了。

GO實現

1. 產生pbox和sbox

幾個重要的變數聲明

var (    Pencs string = "!!!這是一個18位長度的串!!!"    Sencs string = "!!!這是一個1024位長度的串!!!"    Penc []uint8 = []uint8(Pencs)    Senc []uint8 = []uint8(Sencs)    Pinit []uint32 = make([]uint32, len(Penc)*7/32)    Sinit []uint32 = make([]uint32, len(Senc)*7/32)    PPP  []uint32 = make([]uint32, 18)  //p盒子    SSS0 []uint32 = make([]uint32, 256) //第一個盒子    SSS1 []uint32 = make([]uint32, 256) //第二個盒子    SSS2 []uint32 = make([]uint32, 256) //第三個盒子    SSS3 []uint32 = make([]uint32, 256) //第四個盒子)

產生pbox和sbox

將2個盒子的源串Pencs和Sencs,每個位元組右移一定位元,產生中間數組Pinit和Sinit

func initParam() {    var poff int32 = 25    plen := len(Penc)    for i, j := 0, 0; j < plen; j++ {        if j == plen-1 {            Pinit[i] |= uint32(Penc[j]) >> uint32(-poff)        } else if poff < 0 {            Pinit[i] |= uint32(Penc[j]) >> uint32(-poff)            i++            poff += 32            Pinit[i] |= uint32(Penc[j]) << uint32(poff)        } else {            Pinit[i] |= uint32(Penc[j]) << uint32(poff)        }        poff -= 7    }    var soff int32 = 25    slen := len(Senc)    for i, j := 0, 0; j < slen; j++ {        if j == slen-1 {            Sinit[i] |= uint32(Senc[j]) >> uint32(-soff)        } else if soff < 0 {            Sinit[i] |= uint32(Senc[j]) >> uint32(-soff)            i++            soff += 32            Sinit[i] |= uint32(Senc[j]) << uint32(soff)        } else {            Sinit[i] |= uint32(Senc[j]) << uint32(soff)        }        soff -= 7    }}
2. 密鑰預先處理
func SetKey(key []uint8) {    ptemp := []uint32{0, 0}    stemp := [][]uint32{SSS0, SSS1, SSS2, SSS3}    copy(PPP, Pinit)    for i, j := 0, 0; i < 4; i++ {        copy(stemp[i], Sinit[j:])        j += 256    }    lenth := len(key)    ll := 0    for i, j := uint32(0), uint32(0); i < 18; i++ {        for k := 0; k < 4; k++ {            ll %= lenth            j = j<<8 | uint32(key[ll])&255            ll++        }        PPP[i] ^= j    }    encryptKey(ptemp, 0, PPP, 0)    for i := uint32(0); i < 16; i += 2 {        encryptKey(PPP, i, PPP, i+2)    }    encryptKey(PPP, 16, stemp[0], 0)    for j := uint32(2); j < 256; j += 2 {        encryptKey(stemp[0], uint32(j-2), stemp[0], uint32(j))    }    k := 0    l := 254    for i := 1; i < 4; i++ {        for j := 0; j < 256; j += 2 {            encryptKey(stemp[k], uint32(l), stemp[i], uint32(j))            k = i            l = j        }    }}func encryptKey(in []uint32, inOff uint32, out []uint32, outOff uint32) {    left := in[inOff] ^ PPP[0]    inOff++    right := in[inOff]    for i := 0; i < 16; i++ {        temp := (SSS0[left>>24&255] + SSS1[left>>16&255] ^ SSS2[left>>8&255]) + SSS3[left&255]        i++        right ^= temp ^ PPP[i]        temp = (SSS0[right>>24&255] + SSS1[right>>16&255] ^ SSS2[right>>8&255]) + SSS3[right&255]        left ^= temp ^ PPP[i+1]    }    out[outOff] = right ^ PPP[17]    outOff++    out[outOff] = left}
3. 加密
func Encrypt(encryptable []uint8) []uint8 {    blocks := len(encryptable) / 64    rem := len(encryptable) % 64    length := blocks * 64    var output []uint8    if rem > 0 {        output = make([]uint8, length+64)    } else {        output = make([]uint8, length)    }    for i := 0; i < 64-rem; i++ {        encryptable = append(encryptable, 0)    }    for i := 0; i < len(encryptable); i += 8 {        encryptBytes(encryptable, uint32(i), output, uint32(i))    }    return output}func encryptBytes(in []uint8, inOff uint32, out []uint8, outOff uint32) {    left := ((uint32(in[inOff])&255)<<24 | (uint32(in[inOff+1])&255)<<16 | (uint32(in[inOff+2])&255)<<8 | (uint32(in[inOff+3]) & 255)) ^ PPP[0]    right := (uint32(in[inOff+4])&255)<<24 | (uint32(in[inOff+5])&255)<<16 | (uint32(in[inOff+6])&255)<<8 | uint32(in[inOff+7])&255    for i := 1; i < 17; i += 2 {        right ^= (SSS0[left>>24&255] + SSS1[left>>16&255] ^ SSS2[left>>8&255]) + SSS3[left&255] ^ PPP[i]        left ^= (SSS0[right>>24&255] + SSS1[right>>16&255] ^ SSS2[right>>8&255]) + SSS3[right&255] ^ PPP[i+1]    }    right ^= PPP[17]    out[outOff] = uint8(right >> 24 & 255)    out[outOff+1] = uint8(right >> 16 & 255)    out[outOff+2] = uint8(right >> 8 & 255)    out[outOff+3] = uint8(right & 255)    out[outOff+4] = uint8(left >> 24 & 255)    out[outOff+5] = uint8(left >> 16 & 255)    out[outOff+6] = uint8(left >> 8 & 255)    out[outOff+7] = uint8(left & 255)}
相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在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.