GO实现DES加解密CBC分组模式
需求:算法:des , 分组模式:CBC
des :
秘钥:8bytes
分组长度:8bytes
cbc:
1. 提供初始化向量,长度与分组长度相同,8bytes
2. 需要填充
加密分析
1. 创建并返回一个使用DES算法的cipher.Block接口。
func NewCipher(key []byte) (cipher.Block, error)
– 包名:des
– 参数:秘钥,8bytes
– 返回值:一个cipher.Block接口
type Block interface {
// 返回加密字节块的大小
BlockSize() int
// 加密src的第一块数据并写入dst,src和dst可指向同一内存地址
Encrypt(dst, src []byte)
// 解密src的第一块数据并写入dst,src和dst可指向同一内存地址
Decrypt(dst, src []byte)
}
2. 进行数据填充
//TODO
填充逻辑
举例:
3. 引入CBC模式, 返回一个密码分组链接模式的、底层用b加密的BlockMode接口,初始向量iv的长度必须等于b的块尺寸。
func NewCBCEncrypter(b Block, iv []byte) BlockMode
– 包名:cipher
– 参数1:cipher.Block
– 参数2:iv, initialize vector
– 返回值:分组模式,里面提供加解密方法
type BlockMode interface {
// 返回加密字节块的大小
BlockSize() int
// 加密或解密连续的数据块,src的尺寸必须是块大小的整数倍,src和dst可指向同一内存地址
CryptBlocks(dst, src []byte)
}
————————————————————
解密分析
1. 创建并返回一个使用DES算法的cipher.Block接口。
func NewCipher(key []byte) (cipher.Block, error)
– 包名:des
– 参数:秘钥,8bytes
– 返回值:一个cipher.Block接口
type Block interface {
// 返回加密字节块的大小
BlockSize() int
// 加密src的第一块数据并写入dst,src和dst可指向同一内存地址
Encrypt(dst, src []byte)
// 解密src的第一块数据并写入dst,src和dst可指向同一内存地址
Decrypt(dst, src []byte)
}
2. 返回一个密码分组链接模式的、底层用b解密的BlockMode接口,初始向量iv必须和加密时使用的iv相同。
func NewCBCDecrypter(b Block, iv []byte) BlockMode
– 包名:cipher
– 参数1:cipher.Block
– 参数2:iv, initialize vector
– 返回值:分组模式,里面提供加解密方法
type BlockMode interface {
// 返回加密字节块的大小
BlockSize() int
// 加密或解密连续的数据块,src的尺寸必须是块大小的整数倍,src和dst可指向同一内存地址
CryptBlocks(dst, src []byte)
}
3. 解密操作
4. 去除填充
package main
import (
"bytes"
"crypto/cipher"
"crypto/des"
"fmt"
)
//输入明文、密钥输出密文
func desCBCEncrypt(src,key []byte) []byte {
fmt.Printf("加密开始,输入数据:%s\n",src)
//1. 创建并返回一个使用DES算法的cipher.Block接口。
block,err := des.NewCipher(key)
if err != nil{
panic(err)
}
fmt.Println("BlockSize is :",block.BlockSize())
//2数据填充
src = paddingInfo(src,block.BlockSize())
fmt.Println(src)
//3. 引入CBC模式, 返回一个密码分组链接模式的、底层用b加密的BlockMode接口,初始向量iv的长度必须等于b的块尺寸。
iv := bytes.Repeat([]byte("1"),block.BlockSize())
blockMode := cipher.NewCBCEncrypter(block,iv)
//4、加密操作
blockMode.CryptBlocks(src,src) //密文赋值,明文
fmt.Printf("加密结束,数据为:%x\n",src)
return src
}
//实现填充函数
func paddingInfo(src []byte,blockSize int) []byte {
//1、得到明文长度
length := len(src)
//2、需要填充的数量
remains := length % blockSize // 9%8 = 1
paddingNum := blockSize-remains //8-1=填充7个需要
fmt.Println(length,"-",blockSize)
fmt.Printf("remains=%d,paddingnum=%d",remains,paddingNum)
//3、将填充的数字转换为字符
s1 := byte(paddingNum)
fmt.Printf("s1 : %x\n", s1)
//4、把字符拼接为数组
s2 := bytes.Repeat([]byte{s1},paddingNum) //[]byte{0x35, '5', '5', '5, '5'}
fmt.Printf("s2 : %x\n", s2)
//5、把拼成的数组追加到src后面
srcNew := append(src,s2...) //切片被打散传入 见bolg案例
//6、返回新数组
return srcNew
}
//解密函数
func desCBCDecrypt(cipherData,key []byte) []byte{
fmt.Printf("解密开始,输入的数据为:%x\n", cipherData)
//1. 创建并返回一个使用DES算法的cipher.Block接口。
block, err := des.NewCipher(key)
fmt.Printf("block size : %d\n", block.BlockSize())
if err != nil{
panic(err)
}
//引入CBC分组模式
iv := bytes.Repeat([]byte("1"),block.BlockSize())
blockMode := cipher.NewCBCDecrypter(block,iv)
//解密操作
blockMode.CryptBlocks(cipherData /*解密后的明文*/ , cipherData /*密文*/)
fmt.Printf("没有去除填充的解密数据为%s\n", cipherData)
//将数据的结尾填充去掉
resultData := uppaddingInfo(cipherData)
return resultData
}
//去除填充
func uppaddingInfo(plainText []byte) []byte {
//1、获取长度
length := len(plainText)
if length == 0{
return []byte{}
}
//2、获取最后一个字符
last := plainText[length-1]
//3、将字符转换为数字
lastone := int(last)
//4、切片获取需要的数据
result := plainText[:length-lastone]
return result
}
func main() {
//src := []byte("123456781")
src := []byte("世界你好")
key := []byte("12345678")
jmData := desCBCEncrypt(src,key)
//解密
result := desCBCDecrypt(jmData,key)
fmt.Printf("解密结束,数据为%s\n", result)
}

