DES-CBC

1、测试框架

package main

import "fmt"

/*需求:
算法:DES
密钥:8bytes
分组长度:8bytes
分组:CBC
1、提供初始化向量,长度与分组相同,8bytes
2、需要填充

加密分析

1、创建并返回一个使用DES算法的cipher.Block接口。
func NewCipher(key []byte) (cipher.Block, error)
-包名:des
-参数:key 密钥,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)
	}

解密分析
*/
//输入明文、密钥,输出密文
func desCBCEncrtpt(src, key []byte)[]byte{
	//TODO
	fmt.Printf("加密开始,输入的数据为:%s\n",src)
	fmt.Printf("加密结束,加密数据为:%x\n",key)

	return []byte{}
}
func main()  {
	src := []byte("12345678")
	key := []byte("12345678")
	cipherData := desCBCEncrtpt(src,key)
	fmt.Printf("cipherData:%x\n",cipherData)
}

2、无填充的实现

package main

import (
	"bytes"
	"crypto/cipher"
	"crypto/des"
	"fmt"
)
//输入明文、密钥,输出密文
func desCBCEncrtpt(src, key []byte)[]byte{
	//TODO
	fmt.Printf("加密开始,输入的数据为:%s\n",src)

	// 1、创建并返回一个使用DES算法的cipher.Block接口。
	block,err := des.NewCipher(key)
	if err != nil{
		panic(err)
	}
	//2、进行数据填充
	//TODO

	//3、引入CBC
	// 返回一个密码分组链接模式的、底层用b加密的BlockMode接口,初始向量iv的长度必须等于b的块尺寸。
	iv := bytes.Repeat([]byte("1"),block.BlockSize())	//将[]byte("1")重复block.BlockSize()次
	blockMode := cipher.NewCBCEncrypter(block , iv)

	//4、加密操作
	blockMode.CryptBlocks(src,src)	//参数1:密文	参数2:明文
	fmt.Printf("加密结束,加密数据为:%x\n",src)

	return src
}
func main()  {
	src := []byte("12345678")
	key := []byte("12345678")
	cipherData := desCBCEncrtpt(src,key)
	fmt.Printf("cipherData:%x\n",cipherData)
}

3、填充逻辑

填充的时候,根据所需要填充的数量进行填充,需要填充5个字符时,会创建一个5个“5”的数组,追加到原始数据的后面

//填充函数
//参数1:原始数据;参数2:原始数据的长度
func paddingInfo(src []byte,blockSize int) []byte {
	// 1、得到明文长度
	length := len(src)
	// 2、需要填充的长度
	remains := length % blockSize
	paddingNumber := blockSize - remains
	// 3、把填充的数值转换为字符
	s1 := byte(paddingNumber)
	// 4、把字符拼成数组
	s2 := bytes.Repeat([]byte{s1},paddingNumber)
	// 5、把拼成的数组追加到src返回新的数字
	srcNew := append(src,s2...)
	// 6、返回
	return srcNew
}

4、解密(无去除)

/*解密分析

1、创建并返回一个使用DES算法的cipher.Block接口。
func NewCipher(key []byte) (cipher.Block, error)
-包名:des
-参数:key 密钥,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、引入CBC模式

返回一个密码分组链接模式的、底层用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、去除填充
*/

func desCBCDecrtpt(cipherData, key []byte)[]byte{
	fmt.Printf("解密开始,输入的数据为:%x\n",cipherData)
	// 1、创建并返回一个使用DES算法的cipher.Block接口。
	block,err := des.NewCipher(key)
	if err != nil{
		panic(err)
	}

	//2、引入CBC
	// 返回一个密码分组链接模式的、底层用b加密的BlockMode接口,初始向量iv的长度必须等于b的块尺寸。
	iv := bytes.Repeat([]byte("1"),block.BlockSize())	//将[]byte("1")重复block.BlockSize()次
	blockMode := cipher.NewCBCDecrypter(block , iv)

	//3、解密操作
	blockMode.CryptBlocks(cipherData,cipherData)	//参数1:明文文	参数2:密文
	fmt.Printf("解密结束,解密数据为:%s\n",cipherData)
	
	//4、去除填充
	//TODO
	return cipherData
}

附:完整思路与程序

package main

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

/*需求:
算法:DES
密钥:8bytes
分组长度:8bytes
分组:CBC
1、提供初始化向量,长度与分组相同,8bytes
2、需要填充

加密分析

1、创建并返回一个使用DES算法的cipher.Block接口。
func NewCipher(key []byte) (cipher.Block, error)
-包名:des
-参数:key 密钥,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
-参数:key 密钥,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、引入CBC模式

返回一个密码分组链接模式的、底层用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、去除填充



*/
//输入明文、密钥,输出密文
func desCBCEncrtpt(src, key []byte)[]byte{
	fmt.Printf("加密开始,输入的数据为:%s\n",src)
	// 1、创建并返回一个使用DES算法的cipher.Block接口。
	block,err := des.NewCipher(key)
	if err != nil{
		panic(err)
	}
	//2、进行数据填充
	//TODO
	src = paddingInfo(src,block.BlockSize())
	//3、引入CBC
	// 返回一个密码分组链接模式的、底层用b加密的BlockMode接口,初始向量iv的长度必须等于b的块尺寸。
	iv := bytes.Repeat([]byte("1"),block.BlockSize())	//将[]byte("1")重复block.BlockSize()次
	blockMode := cipher.NewCBCEncrypter(block , iv)

	//4、加密操作
	blockMode.CryptBlocks(src,src)	//参数1:密文	参数2:明文
	return src
}

//填充函数

func paddingInfo(src []byte,blockSize int) []byte {
	// 1、得到明文长度
	length := len(src)
	// 2、需要填充的长度
	remains := length % blockSize
	paddingNumber := blockSize - remains
	// 3、把填充的数值转换为字符
	s1 := byte(paddingNumber)
	// 4、把字符拼成数组
	s2 := bytes.Repeat([]byte{s1},paddingNumber)
	// 5、把拼成的数组追加到src返回新的数字
	srcNew := append(src,s2...)
	// 6、返回
	return srcNew
}
func main()  {
	src := []byte("不是一番寒彻骨,哪得梅花扑鼻香!")
	key := []byte("12345678")
	//调用加密函数
	cipherData := desCBCEncrtpt(src,key)
	fmt.Printf("cipherData:%x\n",cipherData)
	//调用解密函数
	plainText := desCBCDecrtpt(cipherData,key)
	fmt.Printf("decodeData:%s\n",plainText)
}

func desCBCDecrtpt(cipherData, key []byte)[]byte{
	fmt.Printf("解密开始,输入的数据为:%x\n",cipherData)
	// 1、创建并返回一个使用DES算法的cipher.Block接口。
	block,err := des.NewCipher(key)
	if err != nil{
		panic(err)
	}

	//2、引入CBC
	// 返回一个密码分组链接模式的、底层用b加密的BlockMode接口,初始向量iv的长度必须等于b的块尺寸。
	iv := bytes.Repeat([]byte("1"),block.BlockSize())	//将[]byte("1")重复block.BlockSize()次
	blockMode := cipher.NewCBCDecrypter(block , iv)

	//3、解密操作
	blockMode.CryptBlocks(cipherData,cipherData)	//参数1:明文文	参数2:密文

	//4、去除填充
	plainText := unpaddingInfo(cipherData)
	return plainText
}

//去除重复
func unpaddingInfo(plainTexe []byte) []byte{
	//1、获取长度
	length := len(plainTexe)
	if length == 0 {
		return []byte{}
	}
	//2、获取最后一个字符
	lastByte := plainTexe[length-1]
	//3、将字符转成数字
	unpaddingNumber := int(lastByte)
	//4、切片获取
	return plainTexe[:length-unpaddingNumber]
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章