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) }