日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

Go加密解密之DES

發布時間:2025/7/25 编程问答 32 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Go加密解密之DES 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

一、DES簡介

DES(Data Encryption Standard)是對稱加密算法,也就是加密和解密用相同的密鑰。其入口參數有三個:key、data、mode。key為加密解密使用的密鑰,data為加密解密的數據,mode為其工作模式。當模式為加密模式時,明文按照64位進行分組,形成明文組,key用于對數據加密,當模式為解密模式時,key用于對數據解密。實際運用中,密鑰只用到了64位中的56位,這樣才具有高的安全性。DES 的常見變體是三重 DES,使用 168 位的密鑰對資料進行三次加密的一種機制;它通常(但非始終)提供極其強大的安全性。如果三個 56 位的子元素都相同,則三重 DES 向后兼容 DES。

DES加密,涉及到加密模式和填充方式,所以,和其他語言加解密時,應該約定好加密模式和填充方式。(模式定義了Cipher如何應用加密算法。改變模式可以容許一個塊加密程序變為流加密程序。)

關于分組加密:分組密碼每次加密一個數據分組,這個分組的位數可以是隨意的,一般選擇64或者128位。另一方面,流加密程序每次可以加密或解密一個字節的數據,這就使它比流加密的應用程序更為有用。

在用DES加密解密時,經常會涉及到一個概念:塊(block,也叫分組),模式(比如cbc),初始向量(iv),填充方式(padding,包括none,用’\0′填充,pkcs5padding或pkcs7padding)。多語言加密解密交互時,需要確定好這些。比如這么定:

采用3DES、CBC模式、pkcs5padding,初始向量用key充當;另外,對于zero padding,還得約定好,對于數據長度剛好是block size的整數倍時,是否需要額外填充。

二、Go DES加密解密

1、crypto/des包

Go中crypto/des包實現了 Data Encryption Standard (DES) and the Triple Data Encryption Algorithm (TDEA)。查看該包文檔,發現相當簡單:
定義了DES塊大小(8bytes),定義了一個KeySizeError。另外定義了兩個我們需要特別關注的函數,即

1func NewCipher(key []byte) (cipher.Block, error)
2func NewTripleDESCipher(key []byte) (cipher.Block, error)

他們都是用來獲得一個cipher.Block。從名字可以很容易知道,DES使用NewCipher,3DES使用NewTripleDESCipher。參數都是密鑰(key)

2、crypto/cipher包

那么,cipher這個包是干嘛用的呢?它實現了標準的塊加密模式。我們看一下cipher.Block

1type Block interface {
2????// BlockSize returns the cipher's block size.
3????BlockSize() int
4?
5????// Encrypt encrypts the first block in src into dst.
6????// Dst and src may point at the same memory.
7????Encrypt(dst, src []byte)
8?
9????// Decrypt decrypts the first block in src into dst.
10????// Dst and src may point at the same memory.
11????Decrypt(dst, src []byte)
12}

這是一個接口

對稱加密,按塊方式,我們經常見到CBC、ECB之類的,這些是加密模式。可以參考:DES加密模式詳解 http://linux.bokee.com/6956594.html
Go中定義了一個接口BlockMode代表各種模式

1type BlockMode interface {
2????// BlockSize returns the mode's block size.
3????BlockSize() int
4?
5????// CryptBlocks encrypts or decrypts a number of blocks. The length of
6????// src must be a multiple of the block size. Dst and src may point to
7????// the same memory.
8????CryptBlocks(dst, src []byte)
9}

該包還提供了獲取BlockMode實例的兩個方法

1func NewCBCDecrypter(b Block, iv []byte) BlockMode
2func NewCBCEncrypter(b Block, iv []byte) BlockMode

即一個CBC加密,一個CBC解密

對于按流方式加密的,定義了一個接口:

1type Stream interface {
2????// XORKeyStream XORs each byte in the given slice with a byte from the
3????// cipher's key stream. Dst and src may point to the same memory.
4????XORKeyStream(dst, src []byte)
5}

同樣也提供了獲取實現該接口的實例

這里,我們只討論CBC模式

3、加密解密

1)DES
DES加密代碼如下:

1func DesEncrypt(origData, key []byte) ([]byte, error) {
2?????block, err := des.NewCipher(key)
3?????if err != nil {
4??????????return nil, err
5?????}
6?????origData = PKCS5Padding(origData, block.BlockSize())
7?????// origData = ZeroPadding(origData, block.BlockSize())
8?????blockMode := cipher.NewCBCEncrypter(block, key)
9?????crypted := make([]byte, len(origData))
10??????// 根據CryptBlocks方法的說明,如下方式初始化crypted也可以
11?????// crypted := origData
12?????blockMode.CryptBlocks(crypted, origData)
13?????return crypted, nil
14}

以上代碼使用DES加密(des.NewCipher),加密模式為CBC(cipher.NewCBCEncrypter(block, key)),填充方式PKCS5Padding,該函數的代碼如下:

1func PKCS5Padding(ciphertext []byte, blockSize int) []byte {
2?????padding := blockSize - len(ciphertext)%blockSize
3?????padtext := bytes.Repeat([]byte{byte(padding)}, padding)
4?????return append(ciphertext, padtext...)
5}

可見,數據長度剛好是block size的整數倍時,也進行了填充,如果不進行填充,unpadding會搞不定。
另外,為了方便,初始向量直接使用key充當了(實際項目中,最好別這么做)。

DES解密代碼如下:

1func DesDecrypt(crypted, key []byte) ([]byte, error) {
2?????block, err := des.NewCipher(key)
3?????if err != nil {
4??????????return nil, err
5?????}
6?????blockMode := cipher.NewCBCDecrypter(block, key)
7?????origData := make([]byte, len(crypted))
8?????// origData := crypted
9?????blockMode.CryptBlocks(origData, crypted)
10?????origData = PKCS5UnPadding(origData)
11?????// origData = ZeroUnPadding(origData)
12?????return origData, nil
13}

可見,解密無非是調用cipher.NewCBCDecrypter,最后unpadding,其他跟加密幾乎一樣。相應的PKCS5UnPadding:

1func PKCS5UnPadding(origData []byte) []byte {
2????length := len(origData)
3????// 去掉最后一個字節 unpadding 次
4????unpadding := int(origData[length-1])
5????return origData[:(length - unpadding)]
6}

2)、3DES

加密代碼:

1// 3DES加密
2func TripleDesEncrypt(origData, key []byte) ([]byte, error) {
3?????block, err := des.NewTripleDESCipher(key)
4?????if err != nil {
5??????????return nil, err
6?????}
7?????origData = PKCS5Padding(origData, block.BlockSize())
8?????// origData = ZeroPadding(origData, block.BlockSize())
9?????blockMode := cipher.NewCBCEncrypter(block, key[:8])
10?????crypted := make([]byte, len(origData))
11?????blockMode.CryptBlocks(crypted, origData)
12?????return crypted, nil
13}

對比DES,發現只是換了NewTripleDESCipher。不過,需要注意的是,密鑰長度必須24byte,否則直接返回錯誤。關于這一點,PHP中卻不是這樣的,只要是8byte以上就行;而Java中,要求必須是24byte以上,內部會取前24byte(相當于就是24byte)。

另外,初始化向量長度是8byte(目前各個語言都是如此,不是8byte會有問題)。然而,如果你用的Go是1.0.3(或以下),iv可以不等于8byte。其實,在cipher.NewCBCEncrypter方法中有注釋:
The length of iv must be the same as the Block’s block size.
可是代碼中的實現卻沒有做判斷。不過,go tips中修正了這個問題,如果iv不等于block size(des為8),則直接panic。所以,對于加解密,一定要測試,保證iv等于block size,否則可能會panic:

1func NewCBCDecrypter(b Block, iv []byte) BlockMode {
2?????if len(iv) != b.BlockSize() {
3??????????panic("cipher.NewCBCDecrypter: IV length must equal block size")
4?????}
5?????return (*cbcDecrypter)(newCBC(b, iv))
6}

此處之所有用panic而不是返回error,個人猜測,是由于目前發布的版本,該方法沒有返回error,修改方法簽名會導致兼容性問題,因此用panic了。

解密代碼:

1// 3DES解密
2func TripleDesDecrypt(crypted, key []byte) ([]byte, error) {
3?????block, err := des.NewTripleDESCipher(key)
4?????if err != nil {
5??????????return nil, err
6?????}
7?????blockMode := cipher.NewCBCDecrypter(block, key[:8])
8?????origData := make([]byte, len(crypted))
9?????// origData := crypted
10?????blockMode.CryptBlocks(origData, crypted)
11?????origData = PKCS5UnPadding(origData)
12?????// origData = ZeroUnPadding(origData)
13?????return origData, nil
14}

三、和其他語言交互:加解密

這次,我寫了PHP、Java的版本,具體代碼放在github上。這里說明一下,Java中,默認模式是ECB,且沒有用”\0″填充的情況,只有NoPadding和PKCS5Padding;而PHP中(mcrypt擴展),默認填充方式是”\0″,而且,當數據長度剛好是block size的整數倍時,默認不會填充”\0″,這樣,如果數據剛好是block size的整數倍且結尾字符是”\0″,會有問題。

綜上,跨語言加密解密,應該使用PKCS5Padding填充。

轉載于:https://www.cnblogs.com/mafeng/p/6208296.html

總結

以上是生活随笔為你收集整理的Go加密解密之DES的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。