一、DES算法簡(jiǎn)介
DES(Data Encryption Standard)是一種常見的分組加密算法植锉,由IBM公司在1971年提出辫樱。它是一種對(duì)稱加密算法,也就是說它使用同一個(gè)密鑰來加密和解密數(shù)據(jù)俊庇。
二狮暑、密鑰
DES使用一個(gè)56位的初始密鑰,但是這里提供的是一個(gè)64位的值辉饱,這是因?yàn)樵谟布?shí)現(xiàn)中每8位可以用于奇偶校驗(yàn)搬男。可以通過設(shè)定8位字符串彭沼,由crypto/des
庫(kù)的des.NewCipher(key)
函數(shù)生成密鑰
三缔逛、填充算法
DES分組的大小是64位,如果加密的數(shù)據(jù)長(zhǎng)度不是64位的倍數(shù),可以按照某種具體的規(guī)則來填充位褐奴。常用的填充算法有pkcs5
按脚,zero
等
pkcs5填充
//pkcs5補(bǔ)碼算法
func pkcs5Padding(ciphertext []byte, blockSize int) []byte {
padding := blockSize - len(ciphertext)%blockSize
padtext := bytes.Repeat([]byte{byte(padding)}, padding)
return append(ciphertext, padtext...)
}
//pkcs5減碼算法
func pkcs5UnPadding(origData []byte) []byte {
length := len(origData)
unpadding := int(origData[length-1])
return origData[:(length - unpadding)]
}
zero填充
//zero補(bǔ)碼算法
func zeroPadding(ciphertext []byte, blockSize int) []byte {
padding := blockSize - len(ciphertext)%blockSize
padtext := bytes.Repeat([]byte{0}, padding)
return append(ciphertext, padtext...)
}
//zero減碼算法
func zeroUnPadding(origData []byte) []byte {
return bytes.TrimFunc(origData,
func(r rune) bool {
return r == rune(0)
})
}
四、加密模式
- 密碼分組鏈接模式(Cipher Block Chaining敦冬,簡(jiǎn)稱CBC):是一種循環(huán)模式辅搬,前一個(gè)分組的密文和當(dāng)前分組的明文異或操作后再加密,這樣做的目的是增強(qiáng)破解難度脖旱。
- 電碼本模式(Electronic Codebook Book伞辛,簡(jiǎn)稱ECB):是一種基礎(chǔ)的加密方式,密文被分割成分組長(zhǎng)度相等的塊(不足補(bǔ)齊)夯缺,然后單獨(dú)一個(gè)個(gè)加密蚤氏,一個(gè)個(gè)輸出組成密文。
- 計(jì)算器模式(Counter踊兜,簡(jiǎn)稱CTR):計(jì)算器模式不常見竿滨,在CTR模式中, 有一個(gè)自增的算子捏境,這個(gè)算子用密鑰加密之后的輸出和明文異或的結(jié)果得到密文于游,相當(dāng)于一次一密。這種加密方式簡(jiǎn)單快速垫言,安全可靠贰剥,而且可以并行加密,但是在計(jì)算器不能維持很長(zhǎng)的情況下筷频,密鑰只能使用一次蚌成。
- 輸出反饋模式(Output FeedBack,簡(jiǎn)稱OFB):實(shí)際上是一種反饋模式凛捏,目的也是增強(qiáng)破解的難度担忧。
- 密碼反饋模式(Cipher FeedBack,簡(jiǎn)稱CFB):實(shí)際上是一種反饋模式坯癣,目的也是增強(qiáng)破解的難度瓶盛。
//---------------DES ECB加密--------------------
// data: 明文數(shù)據(jù)
// key: 密鑰字符串
// 返回密文數(shù)據(jù)
func DesECBEncrypt(data, key []byte) []byte {
//NewCipher創(chuàng)建一個(gè)新的加密塊
block, err := des.NewCipher(key)
if err != nil {
return nil
}
bs := block.BlockSize()
// pkcs5填充
data = pkcs5Padding(data, bs)
if len(data)%bs != 0 {
return nil
}
out := make([]byte, len(data))
dst := out
for len(data) > 0 {
//Encrypt加密第一個(gè)塊,將其結(jié)果保存到dst
block.Encrypt(dst, data[:bs])
data = data[bs:]
dst = dst[bs:]
}
return out
}
//---------------DES ECB解密--------------------
// data: 密文數(shù)據(jù)
// key: 密鑰字符串
// 返回明文數(shù)據(jù)
func DesECBDecrypter(data, key []byte) []byte {
//NewCipher創(chuàng)建一個(gè)新的加密塊
block, err := des.NewCipher(key)
if err != nil {
return nil
}
bs := block.BlockSize()
if len(data)%bs != 0 {
return nil
}
out := make([]byte, len(data))
dst := out
for len(data) > 0 {
//Encrypt加密第一個(gè)塊示罗,將其結(jié)果保存到dst
block.Decrypt(dst, data[:bs])
data = data[bs:]
dst = dst[bs:]
}
// pkcs5填充
out = pkcs5UnPadding(out)
return out
}
//---------------DES CBC加密--------------------
// data: 明文數(shù)據(jù)
// key: 密鑰字符串
// iv:iv向量
// 返回密文數(shù)據(jù)
func DesCBCEncrypt(data, key, iv []byte) []byte {
block, err := des.NewCipher(key)
if err != nil {
return nil
}
// pkcs5填充
data = pkcs5Padding(data, block.BlockSize())
cryptText := make([]byte, len(data))
blockMode := cipher.NewCBCEncrypter(block, iv)
blockMode.CryptBlocks(cryptText, data)
return cryptText
}
//---------------DES CBC解密--------------------
// data: 密文數(shù)據(jù)
// key: 密鑰字符串
// iv:iv向量
// 返回明文數(shù)據(jù)
func DesCBCDecrypter(data, key, iv []byte) []byte {
block, err := des.NewCipher(key)
if err != nil {
return nil
}
blockMode := cipher.NewCBCDecrypter(block, iv)
cryptText := make([]byte, len(data))
blockMode.CryptBlocks(cryptText, data)
// pkcs5填充
cryptText = pkcs5UnPadding(cryptText)
return cryptText
}
//---------------DES CTR加密--------------------
// data: 明文數(shù)據(jù)
// key: 密鑰字符串
// iv:iv向量
// 返回密文數(shù)據(jù)
func DesCTREncrypt(data, key, iv []byte) []byte {
block, err := des.NewCipher(key)
if err != nil {
return nil
}
// pkcs5填充
data = pkcs5Padding(data, block.BlockSize())
cryptText := make([]byte, len(data))
blockMode := cipher.NewCTR(block, iv)
blockMode.XORKeyStream(cryptText, data)
return cryptText
}
//---------------DES CTR解密--------------------
// data: 密文數(shù)據(jù)
// key: 密鑰字符串
// iv:iv向量
// 返回明文數(shù)據(jù)
func DesCTRDecrypter(data, key, iv []byte) []byte {
block, err := des.NewCipher(key)
if err != nil {
return nil
}
blockMode := cipher.NewCTR(block, iv)
cryptText := make([]byte, len(data))
blockMode.XORKeyStream(cryptText, data)
// pkcs5填充
cryptText = pkcs5UnPadding(cryptText)
return cryptText
}
//---------------DES OFB加密--------------------
// data: 明文數(shù)據(jù)
// key: 密鑰字符串
// iv:iv向量
// 返回密文數(shù)據(jù)
func DesOFBEncrypt(data, key, iv []byte) []byte {
block, err := des.NewCipher(key)
if err != nil {
return nil
}
// pkcs5填充
data = pkcs5Padding(data, block.BlockSize())
cryptText := make([]byte, len(data))
blockMode := cipher.NewOFB(block, iv)
blockMode.XORKeyStream(cryptText, data)
return cryptText
}
//---------------DES OFB解密--------------------
// data: 密文數(shù)據(jù)
// key: 密鑰字符串
// iv:iv向量
// 返回明文數(shù)據(jù)
func DesOFBDecrypter(data, key, iv []byte) []byte {
block, err := des.NewCipher(key)
if err != nil {
return nil
}
blockMode := cipher.NewOFB(block, iv)
cryptText := make([]byte, len(data))
blockMode.XORKeyStream(cryptText, data)
// pkcs5填充
cryptText = pkcs5UnPadding(cryptText)
return cryptText
}
//---------------DES CFB加密--------------------
// data: 明文數(shù)據(jù)
// key: 密鑰字符串
// iv:iv向量
// 返回密文數(shù)據(jù)
func DesCFBEncrypt(data, key, iv []byte) []byte {
block, err := des.NewCipher(key)
if err != nil {
return nil
}
// pkcs5填充
data = pkcs5Padding(data, block.BlockSize())
cryptText := make([]byte, len(data))
blockMode := cipher.NewCFBDecrypter(block, iv)
blockMode.XORKeyStream(cryptText, data)
return cryptText
}
//---------------DES CFB解密--------------------
// data: 密文數(shù)據(jù)
// key: 密鑰字符串
// iv:iv向量
// 返回明文數(shù)據(jù)
func DesCFBDecrypter(data, key, iv []byte) []byte {
block, err := des.NewCipher(key)
if err != nil {
return nil
}
blockMode := cipher.NewCFBEncrypter(block, iv)
cryptText := make([]byte, len(data))
blockMode.XORKeyStream(cryptText, data)
// pkcs5填充
cryptText = pkcs5UnPadding(cryptText)
return cryptText
}
五惩猫、測(cè)試
import (
"bytes"
"crypto/cipher"
"crypto/des"
"encoding/base64"
"fmt"
)
func main() {
key := []byte("12345678")
src := []byte("這是需要加密的明文哦!")
// ECB 加密
cipher := DesECBEncrypt(src, key)
// 轉(zhuǎn)base64
bs64 := base64.StdEncoding.EncodeToString(cipher)
fmt.Println(bs64)
// 轉(zhuǎn)回byte
bt, err := base64.StdEncoding.DecodeString(bs64)
if err != nil {
fmt.Println("base64轉(zhuǎn)換失敗")
}
// ECB 解密
str := DesECBEncrypt(bt, key)
fmt.Println(str)
}