0
点赞
收藏
分享

微信扫一扫

【密码学二】一文读懂对称加密-----DES、3DES、AES、golang实现对称加密

booksmg2014 2022-05-05 阅读 51

对称加密

在这里插入图片描述

1、编码

2、DES

2.1、什么事DES

2.2、 加密和解密

2.3、DES的加密与解密 - 图例

在这里插入图片描述

2.4、DES在go代码实现

package main

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

func main() {
	// 加密
	key := []byte("11111111")
	result := DesEncrypt_CBC([]byte("yesyes hello world"), key)
	fmt.Println(base64.StdEncoding.EncodeToString(result))
	// 解密
	result = DesDecrypt_CBC(result, key)
	fmt.Println("解密之后的数据: ", string(result))
}

// DesEncrypt_CBC src -> 要加密的明文
// key -> 秘钥, 大小为: 8byte
func DesEncrypt_CBC(src, key []byte) []byte {
	// 1. 创建并返回一个使用DES算法的cipher.Block接口
	block, err := des.NewCipher(key)
	// 2. 判断是否创建成功
	if err != nil {
		panic(err)
	}
	// 3. 对最后一个明文分组进行数据填充
	src = PKCS5Padding(src, block.BlockSize())
	// 4. 创建一个密码分组为链接模式的, 底层使用DES加密的BlockMode接口
	//    参数iv的长度, 必须等于b的块尺寸
	tmp := []byte("helloAAA")
	blackMode := cipher.NewCBCEncrypter(block, tmp)
	// 5. 加密连续的数据块
	dst := make([]byte, len(src))
	blackMode.CryptBlocks(dst, src)

	fmt.Println("加密之后的数据: ", dst)

	// 6. 将加密数据返回
	return dst
}

// DesDecrypt_CBC src -> 要解密的密文
// key -> 秘钥, 和加密秘钥相同, 大小为: 8byte
func DesDecrypt_CBC(src, key []byte) []byte {
	// 1. 创建并返回一个使用DES算法的cipher.Block接口
	block, err := des.NewCipher(key)
	// 2. 判断是否创建成功
	if err != nil {
		panic(err)
	}
	// 3. 创建一个密码分组为链接模式的, 底层使用DES解密的BlockMode接口
	tmp := []byte("helloAAA")
	blockMode := cipher.NewCBCDecrypter(block, tmp)
	// 4. 解密数据
	dst := src
	blockMode.CryptBlocks(src, dst)
	// 5. 去掉最后一组填充的数据
	dst = PKCS5UnPadding(dst)

	// 6. 返回结果
	return dst
}

// PKCS5Padding 使用pks5的方式填充
func PKCS5Padding(ciphertext []byte, blockSize int) []byte {
	// 1. 计算最后一个分组缺多少个字节
	padding := blockSize - (len(ciphertext) % blockSize)
	// 2. 创建一个大小为padding的切片, 每个字节的值为padding
	padText := bytes.Repeat([]byte{byte(padding)}, padding)
	// 3. 将padText添加到原始数据的后边, 将最后一个分组缺少的字节数补齐
	newText := append(ciphertext, padText...)
	return newText
}

// PKCS5UnPadding 删除pks5填充的尾部数据
func PKCS5UnPadding(origData []byte) []byte {
	// 1. 计算数据的总长度
	length := len(origData)
	// 2. 根据填充的字节值得到填充的次数
	number := int(origData[length-1])
	// 3. 将尾部填充的number个字节去掉
	return origData[:(length - number)]
}


3、三重DES

在这里插入图片描述

在这里插入图片描述

3.1 三重DES在go中实现

package main

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

func main() {
	// 加密
	key := []byte("111111112222222233333333")
	result := TripleDESEncrypt([]byte("yesyes hello world"), key)
	fmt.Println(base64.StdEncoding.EncodeToString(result))
	// 解密
	result = TripleDESDecrypt(result, key)
	fmt.Println("解密之后的数据: ", string(result))
}

// TripleDESEncrypt 3DES加密
func TripleDESEncrypt(src, key []byte) []byte {
	// 1. 创建并返回一个使用3DES算法的cipher.Block接口
	block, err := des.NewTripleDESCipher(key)
	if err != nil {
		panic(err)
	}
	// 2. 对最后一组明文进行填充
	src = PKCS5Padding(src, block.BlockSize())
	// 3. 创建一个密码分组为链接模式, 底层使用3DES加密的BlockMode模型
	blockMode := cipher.NewCBCEncrypter(block, key[:8])
	// 4. 加密数据
	dst := src
	blockMode.CryptBlocks(dst, src)
	return dst
}

// TripleDESDecrypt 3DES解密
func TripleDESDecrypt(src, key []byte) []byte {
	// 1. 创建3DES算法的Block接口对象
	block, err := des.NewTripleDESCipher(key)
	if err != nil {
		panic(err)
	}
	// 2. 创建密码分组为链接模式, 底层使用3DES解密的BlockMode模型
	blockMode := cipher.NewCBCDecrypter(block, key[:8])
	// 3. 解密
	dst := src
	blockMode.CryptBlocks(dst, src)
	// 4. 去掉尾部填充的数据
	dst = PKCS5UnPadding(dst)
	return dst
}

// PKCS5Padding 使用pks5的方式填充
func PKCS5Padding(ciphertext []byte, blockSize int) []byte {
	// 1. 计算最后一个分组缺多少个字节
	padding := blockSize - (len(ciphertext) % blockSize)
	// 2. 创建一个大小为padding的切片, 每个字节的值为padding
	padText := bytes.Repeat([]byte{byte(padding)}, padding)
	// 3. 将padText添加到原始数据的后边, 将最后一个分组缺少的字节数补齐
	newText := append(ciphertext, padText...)
	return newText
}

// PKCS5UnPadding 删除pks5填充的尾部数据
func PKCS5UnPadding(origData []byte) []byte {
	// 1. 计算数据的总长度
	length := len(origData)
	// 2. 根据填充的字节值得到填充的次数
	number := int(origData[length-1])
	// 3. 将尾部填充的number个字节去掉
	return origData[:(length - number)]
}


4、AES

4.1、AES的加密和解密

在这里插入图片描述

4.2、 Go中对AES的使用

package main

import (
	"bytes"
	"crypto/aes"
	"crypto/cipher"
	"encoding/base64"
	"fmt"
)

func main() {
	// 加密
	key := []byte("1234567812345678")
	result := AESEncrypt([]byte("yesyes hello world"), key)
	fmt.Println(base64.StdEncoding.EncodeToString(result))
	// 解密
	result = AESDecrypt(result, key)
	fmt.Println("解密之后的数据: ", string(result))

}

// AESEncrypt AES加密
func AESEncrypt(src, key []byte) []byte {
	// 1. 创建一个使用AES加密的块对象
	block, err := aes.NewCipher(key)
	if err != nil {
		panic(err)
	}
	// 2. 最后一个分组进行数据填充
	src = PKCS5Padding(src, block.BlockSize())
	// 3. 创建一个分组为链接模式, 底层使用AES加密的块模型对象
	blockMode := cipher.NewCBCEncrypter(block, key[:block.BlockSize()])
	// 4. 加密
	dst := src
	blockMode.CryptBlocks(dst, src)
	return dst
}

// AESDecrypt AES解密
func AESDecrypt(src, key []byte) []byte {
	// 1. 创建一个使用AES解密的块对象
	block, err := aes.NewCipher(key)
	if err != nil {
		panic(err)
	}
	// 2. 创建分组为链接模式, 底层使用AES的解密模型对象
	blockMode := cipher.NewCBCDecrypter(block, key[:block.BlockSize()])
	// 3. 解密
	dst := src
	blockMode.CryptBlocks(dst, src)
	// 4. 去掉尾部填充的字
	dst = PKCS5UnPadding(dst)
	return dst
}

// PKCS5Padding 使用pks5的方式填充
func PKCS5Padding(ciphertext []byte, blockSize int) []byte {
	// 1. 计算最后一个分组缺多少个字节
	padding := blockSize - (len(ciphertext) % blockSize)
	// 2. 创建一个大小为padding的切片, 每个字节的值为padding
	padText := bytes.Repeat([]byte{byte(padding)}, padding)
	// 3. 将padText添加到原始数据的后边, 将最后一个分组缺少的字节数补齐
	newText := append(ciphertext, padText...)
	return newText
}

// PKCS5UnPadding 删除pks5填充的尾部数据
func PKCS5UnPadding(origData []byte) []byte {
	// 1. 计算数据的总长度
	length := len(origData)
	// 2. 根据填充的字节值得到填充的次数
	number := int(origData[length-1])
	// 3. 将尾部填充的number个字节去掉
	return origData[:(length - number)]
}


5、应选择哪种对称加密


5、应选择哪种对称加密

举报

相关推荐

0 条评论