DES 数据加密标准 #
不安全 ,分组密码,8
3DES #
安全,进行了3次des加密
加密过程:加密,解密,加密
解密过程:解密,加密,解密
CBC 密码块链模式 #
特点:密文没有规律,经常使用
最后一个明文分组需要填充
需要初始化向量-一个数组
明文分组的填充 刚好够也需要填充
填充明文分组代码实现 #
package main
//编写填充函数,如果最后一个分组字数不够,填充
//、、、、、字数刚好合适,添加一个新的分组
//填充的字节的值==缺少的字节数
func paddingLastGroup(plainText []byte, bloclSize int) []byte {
//plainText 参数:明文 bloclSize 明文分组字节长度 []byte 返回值
//1、求出最后一个组中剩余的字节数 28%8=3..4 32%8=4.。0
padNum:=ploclSize-len(plainText)%bloclSize //填充的字数
//2、创建新的切片,长度==padNum, 每个字节值byte(padNum)
char :=[]byte{byte(padNum)} //长度1,
//切片创建,并初始化
newPlan := bytes.Repeat(char,padNum)
//3、newPlain数组追加到原始明文的后边
newText := append(plainText,newPlain..)
return newText
}
删除尾部明文分组实现 #
func unPaddingLastGrooup(plainText []byte) []byte {
//1、拿去切片中的最后一个字节
length := len(plainText)
lastChar :=plainText[length -1] //byte 类型
number :=int (lastChar) //尾部填充的字节个数
return plainText[:length -number]
}
对称加密实现(go) #
#加密流程:
1、创建一个底层使用des/3des/aes的密码接口
"crypto/des"
func NewCipher(key []byte) (cipher.Block, error) # -- des
func NewTripleDESCipher(key []byte) (cipher.Block, error) # -- 3des "crypto/aes"
func NewCipher(key []byte) (cipher.Block, error) # == aes
2、如果使用的是cbc/ecb分组模式需要对明文分组进行填充
3、创建一个密码分组模式的接口对象
- cbc
func NewCBCEncrypter(b Block, iv []byte) BlockMode # 加密
- cfb
func NewCFBEncrypter(block Block, iv []byte) Stream # 加密
- ofb
- ctr
4、加密,得到密文
DES 加密代码: #
// 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接口(cbc分组接口)
// 参数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 24
}
DES解密 #
// 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
}
最后一个分组添加填充数据和移除添加数据代码
// 使用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
}
// 删除pks5填充的尾部数据
func PKCS5UnPadding(origData []byte) []byte{
// 1. 计算数据的总长度
length := len(origData)
// 2. 根据填充的字节值得到填充的次数
number := int(origData[length-1])
// 3. 将尾部填充的number个字节去掉
return origData[:(length-number)]
}
测试函数
func DESText() {
// 加密
key := []byte("11111111")
result := DesEncrypt_CBC([]byte("床前明月光, 疑是地上霜. 举头望明月, 低头思故乡."), key)
fmt.Println(base64.StdEncoding.EncodeToString(result))
// 解密
result = DesDecrypt_CBC(result, key)
fmt.Println("解密之后的数据: ", string(result))
}
重要的函数说明
最后一个分组添加填充数据和移除添加数据代码 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 测试函数 重要的函数说明
1、生成一个底层使用DES加/解密的Block接口对象
函数对应的包: import "crypto/des"
func NewCipher(key []byte) (cipher.Block, error)
- 参数 key: des对称加密使用的密码, 密码长度为64bit, 即8byte
- 返回值 cipher.Block: 创建出的使用DES加/解密的Block接口对象
2 、创建一个密码分组为CBC模式, 底层使用b加密的BlockMode接口对象
函数对应的包: import "crypto/cipher"
func NewCBCEncrypter(b Block, iv []byte) BlockMode
- 参数 b: 使用des.NewCipher函数创建出的Block接口对象
- 参数 iv: 事先准备好的一个长度为一个分组长度的比特序列, 每个分组为64bit, 即
8byte
- 返回值: 得到的BlockMode接口对象
-
使用cipher包的BlockMode接口对象对数据进行加/解密
接口对应的包: import "crypto/cipher" type BlockMode interface { // 返回加密字节块的大小 BlockSize() int // 加密或解密连续的数据块,src的尺寸必须是块大小的整数倍,src和dst可指向同一内存地址 CryptBlocks(dst, src []byte) } 接口中的 CryptBlocks(dst, src []byte) 方法: - 参数 dst: 传出参数, 存储加密或解密运算之后的结果 - 参数 src: 传入参数, 需要进行加密或解密的数据切片(字符串)
-
创建一个密码分组为CBC模式, 底层使用b解密的BlockMode接口对象
函数对应的包: import "crypto/cipher"
func NewCBCDecrypter(b Block, iv []byte) BlockMode
- 参数 b: 使用des.NewCipher函数创建出的Block接口对象
- 参数 iv: 事先准备好的一个长度为一个分组长度的比特序列, 每个分组为64bit,
8byte, 该序列的值需要和NewCBCEncrypter函数的第二个参数iv值相同
- 返回值: 得到的BlockMode接口对象
- 自定义函数介绍
对称加密加密需要对数据进行分组, 保证每个分组的数据长度相等, 如果最后一个分组长度不够, 需要进行填充
func PKCS5Padding(ciphertext []byte, blockSize int) []byte
- 参数 ciphertext: 需要加密的原始数据
- 参数 blockSize: 每个分组的长度, 跟使用的加密算法有关系
* des:64bit, 8byte
* 3des:64bit, 8byte
* aes: 128bit, 16byte
对称加密 #
对效率要求很高的时候使用对称加密
Des 3des aes
密钥分发比较困难
密钥可以用非对称加密分发
非对称加密 #
私钥比公钥长
公钥加密私钥解密->数据通信
私钥加密公钥解密->数字签名
保证数据完整性
防止否认
数据对谁重要,谁拿私钥
非对称加密的机密性取决于密钥长度
单向散列函数 #
单向散列函数 – 获取消息的指纹
有一个输入和一个输出,其中输入成为消息,输出称为散列值,单向散列函数可以根据消息的内容计算出散列值,而散列值就可以被用来检查消息的完整性。
性质
1、根据任意长度的消息计算出固定长度的散列值
2、能够快速计算出散列值
3、消息不同散列值不同
4、具备抗碰撞性。(难以发现碰撞的性质称为抗碰撞性)
5、具备单向性
消息认证码 #
一种确认完整性并进行认证的技术。MAC 散列值
1、需要将要发送的数据进行哈希运算
2、进行哈希运算时引入加密步骤
3、在消息认证生成的一方和校验的一方,必须有一个密钥
4.、约定使用相同的哈希函数运算
弊端:
- 密钥分发困难
- 使用非对称加密
- 不能第三方认证
- 不能防止否认
消息认证码能干什么? #
防止信息被修改 被盗取 消息进行加密,然后加消息认证码 进行验证 如果验证对不上,则消息被修改过。
保证数据的完整性,一致性。
数字签名 #
1、签名
* 有原始数据对其进行哈希运算。->散列值
* 使用非对称加密的私钥对散列值加密 ->签名
* 将原始数据和签名一并发送给对方
2、验证
* 接受数据
# 原始数据
# 数字签名
* 数字签名,需要使用公钥解密,得到散列值
* 对原始数据进行哈希运算得到新的散列值
数字签名是什么? #
1、签名的人生成非对称加密的密钥对
2、签名的人将公钥进行分发
3、签名的人将原始数据进行哈希运算->散列值
4、签名的人使用自己的私钥对散列值进行非对称加密->最终得到的数据就是签名
证书 #
公钥证书:里面记有姓名、组织、邮箱地址等个人信息,以及属于此人的公钥,并由认证机构施加数字签名。公钥证书简称为证书
哈希函数 #
哈希函数:接受一个输入,经过计算得到一个输出,长度是固定的
可以进行数据校验、数据完整性验证、秒传