This is a creation in Article, where the information may have evolved or changed.
Recently due to the need for work, the implementation of a go Blowfish algorithm is required. In fact, go itself has a cryptographic algorithm library crypto, which has blowfish. But the algorithm differs from my needs in many details, resulting in a wide variety of final encryption results.
Blowfish algorithm
Blowfish is one of the symmetric cryptographic algorithms. In many scenarios, an alternative to des appears. Blowfish does not encrypt the data directly with the key we specify, but first preprocess the key and then encrypts the data with the result of the processing. The decryption process is the same.
The Blowfish algorithm contains two source keys: Pbox and sbox,pbox18 bit arrays, sbox4 256-bit arrays. The algorithm uses a lot of displacement and logical bit operations in two boxes when encrypting and decrypting. Details of the specific algorithm Baidu/Google, this article is not detailed.
Go implementation
1. Generate Pbox and Sbox
A few important variable declarations
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) //第四个盒子)
Generate Pbox and Sbox
The source string of the 2 boxes is Pencs and Sencs, each byte is shifted to the right by a certain number of digits, resulting in an intermediate array pinit and Sinit
func Initparam () {var poff int32 = Plen: = Len (Penc) for I, J: = 0, 0; j < Plen; F j = = plen-1 {Pinit[i] |= UInt32 (penc[j]) >> UInt32 (-poff)} else if Poff < 0 {Pi Nit[i] |= UInt32 (penc[j]) >> UInt32 (-poff) i++ Poff + = Pinit[i] |= uint32 (penc[j ]) << UInt32 (Poff)} else {Pinit[i] |= UInt32 (penc[j]) << UInt32 (Poff)} Poff -= 7} var soff int32 = 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 + = Sinit[i] |= UInt32 (Senc[j]) << UInt32 (Soff)} else {Sinit[i] |= UInt32 (senc[j]) << UInt32 (Soff) } Soff-= 7}}
2. Key preprocessing
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 + = $ Lenth: = Len (key) LL: = 0 for I, j: = UInt32 (0), uint 32 (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, UInt32, Stemp[0], 0) for J: = (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 < N, 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[le FT&255] i++ Right ^= temp ^ ppp[i] temp = (sss0[right>>24&255] + SSS1[RIGHT>>16&A MP;255] ^ sss2[right>>8&255]) + sss3[right&255] Left ^= temp ^ ppp[i+1]} Out[outoff] = right ^ PPP[17] outoff++ Out[outoff] = left}
3. Encryption
Func Encrypt (encryptable []uint8) []uint8 {blocks: = Len (encryptable)/+ REM: = Len (encryptable)% length: = blocks * + 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 [Out[outoff] = Uint8 (right >> & 255) out[outoff+1] = Uint8 (right >> + & 255) Out[outo FF+2] = uint8 (right >> 8 & 255) out[outoff+3] = Uint8 (right & 255) out[outoff+4] = Uint8 (left >> (& 255) out[outoff+5] = Uint8 (left >> 255) out[outoff+6] = Uint8 (left >> 8 & 255) OUT[OUTOFF+7] = Uint8 (left & 255)}