1. 程式人生 > >GO語言DES加密解密

GO語言DES加密解密

概念理解

DES是以64位元的明文為一個單位來進行加密,並生成64位元的密文。由於它每次只能處理特定長度的一塊資料,所以DES屬於分組密碼演算法。cypto/des包提供了有關des加密的功能。

模式

由於分組密碼演算法只能加密固定長度的分組,所以當加密的明文超過分組密碼的長度時,就需要對分組密碼演算法進行迭代,而迭代的方法就稱為分組密碼的模式。模式主要有ECB(電子密碼本)、CBC(密碼分組連結模式)、CTR(計數器模式)、OFB(輸出反饋模式)、CFB(密碼反饋模式)五種。下面簡單介紹下前兩種: 1. ECB(electronic code book)是最簡單的方式,它將明文分組加密後的結果直接成為密文分組。 優缺點:模式操作簡單;明文中的重複內容將在密文中表現出來,特別對於影象資料和明文變化較少的資料;適於短報文的加密傳遞。這裡寫圖片描述

2. CBC(cipher block chaining)的原理是加密演算法的輸入是當前的明文分組和前一密文分組的異或,第一個明文分組和一個初始向量進行異或,這樣同一個明文分組重複出現時會產生不同的密文分組。 特點:同一個明文分組重複出現時產生不同的密文分組;加密函式的輸入是當前的明文分組和前一個密文分組的異或;每個明文分組的加密函式的輸入與明文分組之間不再有固定的關係;適合加密長訊息。這裡寫圖片描述

填充方式

在按8個位元組對DES進行加密或解密時,如果最後一段位元組不足8位,就需要對資料進行補位。即使加密或解密的資料剛好是8的倍數時,也會再補8位。舉個栗子,如果末尾剛好出現1,這時你就無法判斷這個1是原來資料,還是經過補位得到的1。因此,可以再補8位進行標識。填充方式主要有以下幾種:pkcs7padding、pkcs5padding、zeropadding、iso10126、ansix923。 1. pkcs7padding和pkcs5padding的填充方式相同,填充位元組的值都等於填充位元組的個數。例如需要填充4個位元組,則填充的值為”4 4 4 4”。 2. zeropadding填充位元組的值都為0。

密碼

DES的金鑰長度是64位元,但由於每隔7個位元會設定一個用於錯誤檢測的位元,因此其實質金鑰長度為56位元。

偏移量

上面模式中,例如CBC,再加密第一個明文分組時,由於不存在“前一個密文分組”,因此需要事先準備一個長度為一個分組的位元序列來代替“前一個密文分組”,這個位元序列成為初始化向量,也稱偏移量,通常縮寫為IV。一般來說,每次加密時都會隨機產生一個不同的位元序列來作為初始化向量。偏移量的長度必須和塊的大小相同。

輸出

加密後的位元組在顯示時可以進行hex和base64編碼,hex是十六進位制編碼,base64是一種基於64個可列印字元來標識二進位制資料的方法。

package main

import (
	"bytes"
	"crypto/des"
	"crypto/cipher"
	"fmt"
)

//填充字串(末尾)
func PaddingText(str []byte, blockSize int) []byte {
	//需要填充的資料長度
	paddingCount := blockSize - len(str)%blockSize
	//填充資料為:paddingCount ,填充的值為:paddingCount
	paddingStr := bytes.Repeat([]byte{byte(paddingCount)}, paddingCount)
	newPaddingStr := append(str, paddingStr...)
	//fmt.Println(newPaddingStr)
	return newPaddingStr
}

//去掉字元(末尾)
func UnPaddingText(str []byte) []byte {
	n := len(str)
	count := int(str[n-1])
	newPaddingText := str[:n-count]
	return newPaddingText
}
//---------------DES加密  解密--------------------
func EncyptogDES(src, key []byte) []byte {
	//1、建立並返回一個使用DES演算法的cipher.Block介面
	block, _ := des.NewCipher(key)
	//2、對資料進行填充
	src1 := PaddingText(src, block.BlockSize())

	//3.建立一個密碼分組為連結模式,底層使用des加密的blockmode介面
	iv := []byte("aaaabbbb")
	blockMode := cipher.NewCBCEncrypter(block, iv)
	//4加密連續的資料塊
	desc := make([]byte, len(src1))
	blockMode.CryptBlocks(desc, src1)
	return desc
}
func DecrptogDES(src,key[]byte) []byte {
	//建立一個block的介面
	block,_:=des.NewCipher(key)
	iv := []byte("aaaabbbb")
	//連結模式,建立blockMode介面
	blockeMode:=cipher.NewCBCDecrypter(block,iv)
	//解密
	blockeMode.CryptBlocks(src,src)
	//去掉填充
	newText:=UnPaddingText(src)
	return newText
}
//---------------DES加密  解密--------------------
func Encyptog3DES(src, key []byte) []byte {
	//des包下的三次加密介面
	block,_:=des.NewTripleDESCipher(key)
	src=PaddingText(src,block.BlockSize())
	blockMode:=cipher.NewCBCEncrypter(block,key[:block.BlockSize()])
	blockMode.CryptBlocks(src,src)
	return src
}
func Decrptog3DES(src,key[]byte) []byte {
	block,_:=des.NewTripleDESCipher(key)
	blockMode:=cipher.NewCBCDecrypter(block,key[:block.BlockSize()])
	blockMode.CryptBlocks(src,src)
	src=UnPaddingText(src)
	return src
}
func main() {
	fmt.Println("---------------DES加解密----------------------")
	str:=[]byte("江洲。。。")
	fmt.Println("加密之前的資料為:",string(str))
	key:=[]byte("12345678")
	src:=EncyptogDES(str,key)
	src=DecrptogDES(src,key)
	fmt.Println("解密之後的資料為:",string(src))

	fmt.Println("---------------3DES加解密----------------------")
	str1:=[]byte("海記憶體知己天涯若比鄰")
	fmt.Println("加密之前的資料為:",string(str1))
	key1:=[]byte("12345678abcdefgh98765432")
	src1:=Encyptog3DES(str1,key1)
	src1=Decrptog3DES(src1,key1)
	fmt.Println("解密之後的資料為:",string(src1))

}