DES加密算法,为对称加密算法中的一种。是以64比特的明文为一个单位来进行加密,超过64比特的数据,要求按固定的64比特的大小分组,分组有很多模式。DES使用的密钥长度为64比特,但由于每隔7个比特设置一个奇偶校验位,因此其密钥长度实际为56比特。奇偶校验为最简单的错误检测码,即根据一组二进制代码中1的个数是奇数或偶数来检测错误。
加密模式
- ECB模式 全称Electronic Codebook模式,译为电子密码本模式
- CBC模式 全称Cipher Block Chaining模式,译为密文分组链接模式
- CFB模式 全称Cipher FeedBack模式,译为密文反馈模式
- OFB模式 全称Output Feedback模式,译为输出反馈模式。
- CTR模式 全称Counter模式,译为计数器模式。
填充方式
当明文长度不为分组长度的整数倍时,需要在最后一个分组中填充一些数据使其凑满一个分组长度。
- NoPadding
API或算法本身不对数据进行处理,加密数据由加密双方约定填补算法。例如若对字符串数据进行加解密,可以补充\0或者空格,然后trim - PKCS5Padding
加密前:数据字节长度对8取余,余数为m,若m>0,则补足8-m个字节,字节数值为8-m,即差几个字节就补几个字节,字节数值即为补充的字节数,若为0则补充8个字节的8
解密后:取最后一个字节,值为m,则从数据尾部删除m个字节,剩余数据即为加密前的原文。
加密字符串为为AAA,则补位为AAA55555;加密字符串为BBBBBB,则补位为BBBBBB22;加密字符串为CCCCCCCC,则补位为CCCCCCCC88888888。 - PKCS7Padding
PKCS7Padding 的填充方式和PKCS5Padding 填充方式一样。只是加密块的字节数不同。PKCS5Padding明确定义了加密块是8字节,PKCS7Padding加密快可以是1-255之间。
以下是go 实现的DES加密和解密代码:
本代码采用CBC加密模式,填充方式采用PKCS5Padding
package main
import (
"crypto/des"
"bytes"
"crypto/cipher"
"fmt"
"encoding/base64"
)
//DES加密方法
func MyDESEncrypt (origData,key []byte){
//将字节秘钥转换成block快
block,_ := des.NewCipher(key)
//对明文先进行补码操作
origData = PKCS5Padding(origData,block.BlockSize())
//设置加密方式
blockMode := cipher.NewCBCEncrypter(block,key)
//创建明文长度的字节数组
crypted := make([]byte, len(origData))
//加密明文,加密后的数据放到数组中
blockMode.CryptBlocks(crypted,origData)
//将字节数组转换成字符串
fmt.Println(base64.StdEncoding.EncodeToString(crypted))
}
//实现明文的补码
func PKCS5Padding(ciphertext []byte, blockSize int) []byte {
//计算出需要补多少位
padding := blockSize - len(ciphertext)%blockSize
//Repeat()函数的功能是把参数一 切片复制 参数二count个,然后合成一个新的字节切片返回
// 需要补padding位的padding值
padtext := bytes.Repeat([]byte{byte(padding)}, padding)
//把补充的内容拼接到明文后面
return append(ciphertext,padtext...)
}
//解密
func MyDESDecrypt(data string, key []byte) {
//倒叙执行一遍加密方法
//将字符串转换成字节数组
crypted,_ := base64.StdEncoding.DecodeString(data)
//将字节秘钥转换成block快
block, _ := des.NewCipher(key)
//设置解密方式
blockMode := cipher.NewCBCDecrypter(block,key)
//创建密文大小的数组变量
origData := make([]byte, len(crypted))
//解密密文到数组origData中
blockMode.CryptBlocks(origData,crypted)
//去补码
origData = PKCS5UnPadding(origData)
//打印明文
fmt.Println(string(origData))
}
//去除补码
func PKCS5UnPadding(origData []byte) []byte {
length := len(origData)
// 去掉最后一个字节 unpadding 次
unpadding := int(origData[length-1])
//解密去补码时需取最后一个字节,值为m,则从数据尾部删除m个字节,剩余数据即为加密前的原文
return origData[:(length - unpadding)]
}
func main () {
//定义明文
data := []byte("hello world")
//密钥
key := []byte("12345678")
//加密
MyDESEncrypt(data,key)
//解密
MyDESDecrypt("CyqS6B+0nOGkMmaqyup7gQ==",key)
}
其中解密只需把加密过程倒叙走一遍。
屏幕快照 2018-05-16 下午11.13.08.png关于明文补码和去补码操作:
加密前明文补码规则 (cipher.NewCBCEncrypter 调用前操作):
加密前:数据字节长度对8取余,余数为m,若m>0,则补足8-m个字节,字节数值为8-m,即差几个字节就补几个字节,字节数值即为补充的字节数,若为0则补充8个字节的8
对应的明文补码代码部分:
//实现明文的补码
func PKCS5Padding(ciphertext []byte, blockSize int) []byte {
//计算出需要补多少位
padding := blockSize - len(ciphertext)%blockSize
//Repeat()函数的功能是把参数一 切片复制 参数二count个,然后合成一个新的字节切片返回
// 需要补padding位的padding值
padtext := bytes.Repeat([]byte{byte(padding)}, padding)
//把补充的内容拼接到明文后面
return append(ciphertext,padtext...)
}
解密后去除补码规则(cipher.NewCBCDecrypter调用解密完成后):
解密后:取最后一个字节,值为m,则从数据尾部删除m个字节,剩余数据即为加密前的原文。
对应的去补码代码部分:
//去除补码
func PKCS5UnPadding(origData []byte) []byte {
length := len(origData)
// 去掉最后一个字节 unpadding 次
unpadding := int(origData[length-1])
//解密去补码时需取最后一个字节,值为m,则从数据尾部删除m个字节,剩余数据即为加密前的原文
return origData[:(length - unpadding)]
}
网友评论