|版權聲明:本文爲博主原創文章,未經博主允許不得轉載。博客地址: https://blog.csdn.net/sgsgy5
具體封裝的所有函數的加密包github地址:https://github.com/wumansgy/goEncrypt
CTR 模式
CTR模式的全稱是CounTeR模式(計數器模式)。CTR摸式是一種通過將逐次累加的計數器進行加密來生成密鑰流的流密碼(下圖)。
CTR模式中,每個分組對應一個逐次累加的計數器,並通過對計數器進行加密來生成密鑰流。也就是說,最終的密文分組是通過將計數器加密得到的比特序列,與明文分組進行XOR而得到的。
這裏我們就簡單介紹一下AES的CTR模式的實現。
計數器的生成方法
每次加密時都會生成一個不同的值(nonce)來作爲計數器的初始值。當分組長度爲128比特(16字節)時,計數器的初始值可能是像下面這樣的形式。
其中前8個字節爲nonce(隨機數),這個值在每次加密時必須都是不同的,後8個字節爲分組序號,這個部分是會逐次累加的。在加密的過程中,計數器的值會產生如下變化:
按照上述生成方法,可以保證計數器的值每次都不同。由於計數器的值每次都不同,因此每個分組中將計數器進行加密所得到的密鑰流也是不同的。也是說,這種方法就是用分組密碼來模擬生成隨機的比特序列。
OFB模式與CTR模式對比
CTR模式和OFB模式一樣,都屬於流密碼。如果我們將單個分組的加密過程拿出來,那麼OFB模式和CTR模式之間的差異還是很容易理解的(下圖)。OFB模式是將加密的輸出反憒到輸入,而CTR模式則是將計數器的值用作輸入。
CTR模式的特點
CTR模式的加密和解密使用了完全相同的結構,因此在程序實現上比較容易。這一特點和同爲流密碼的OFB模式是一樣的。
此外,CTR模式中可以以任意順序對分組進行加密和解密,因此在加密和解密時需要用到的“計數器"的值可以由nonce和分組序號直接計算出來。這一性質是OFB模式所不具備的。
能夠以任意順序處理分組,就意味着能夠實現並行計算。在支持並行計算的系統中,CTR模式的速度是非常快的。
幾種模式的對比總結
AES的CTR模式代碼實現
func AesCTR_Encrypt(plainText,key[]byte)[]byte{
//判斷用戶傳過來的key是否符合16字節,如果不符合16字節加以處理
keylen:=len(key)
if keylen==0{ //如果用戶傳入的密鑰爲空那麼就用默認密鑰
key=[]byte("wumansgygoaescbc") //默認密鑰
}else if keylen>0&&keylen<16{ //如果密鑰長度在0到16之間,那麼用0補齊剩餘的
key=append(key,bytes.Repeat([]byte{0},(16-keylen))...)
}else if keylen>16{
key=key[:16]
}
//1.指定使用的加密aes算法
block, err := aes.NewCipher(key)
if err!=nil{
panic(err)
}
//2.不需要填充,直接獲取ctr分組模式的stream
// 返回一個計數器模式的、底層採用block生成key流的Stream接口,初始向量iv的長度必須等於block的塊尺寸。
iv := []byte("wumansgygoaesctr")
stream := cipher.NewCTR(block, iv)
//3.加密操作
cipherText := make([]byte,len(plainText))
stream.XORKeyStream(cipherText,plainText)
return cipherText
}
func AesCTR_Decrypt(cipherText,key []byte)[]byte{
//判斷用戶傳過來的key是否符合16字節,如果不符合16字節加以處理
keylen:=len(key)
if keylen==0{ //如果用戶傳入的密鑰爲空那麼就用默認密鑰
key=[]byte("wumansgygoaescbc") //默認密鑰
}else if keylen>0&&keylen<16{ //如果密鑰長度在0到16之間,那麼用0補齊剩餘的
key=append(key,bytes.Repeat([]byte{0},(16-keylen))...)
}else if keylen>16{
key=key[:16]
}
//1.指定算法:aes
block, err:= aes.NewCipher(key)
if err!=nil{
panic(err)
}
//2.返回一個計數器模式的、底層採用block生成key流的Stream接口,初始向量iv的長度必須等於block的塊尺寸。
iv := []byte("wumansgygoaesctr")
stream := cipher.NewCTR(block, iv)
//3.解密操作
plainText := make([]byte,len(cipherText))
stream.XORKeyStream(plainText,cipherText)
return plainText
}