赞
踩
CBC模式的全称是:Cipher Block Chaining模式(密文分组链接模式)。
在CBC模式中,首先将明文分组与前一个密文分组进行XOR运算,然后再进行加密。
基于CBC的数据块的加密和解密迭代过程如上图所示,每一个数据块的加密和解密过程都依赖上一个数据块。一旦有一个数据块出现错误将会出现“雪崩效应”。
当加密第一个明文分组时,由于不存在“前一个密文分组”,因此需要事先准备一个长度为一个分组的比特序列来代替“前一个密文分组”,这个比特序列称为初始化向量(Initialization Vector),通常缩写为IV,一般来说,每次加密时都会随机产生一个不同的比特序列来作为初始化向量。
如上图所示Feistel网络实现对于单个数据块的加密。Feistel迭代开始前将64bit数据块拆分为左右32比bit,然后进行如上图所示的迭代过程,总共迭代16次。每一次迭代的子密钥是不同的。每次迭代过程都是对右半部分数据块采用轮函数处理(加密)。
子密钥的生成如上图所示,用户输入的是64bit的密钥(8个字符)首先做一次ip置换将64bit的密钥置换为56bit的密钥。56bit的密钥再进行一次PC-1置换后拆分为左右28bit的密钥。进行16轮迭代,产生16个子密钥。每次迭代将左右28bit密钥做左移1位的运算,然后再进行 PC-2的置换,组合再一起后得到ki。
轮函数的实现主要是进行了 ebox的置换处理和sbox的置换处理:
总体来说子密钥的生成的实现逻辑和轮函数的实现逻辑较为复杂具体可以参考我的代码实现。
package main import ( "bytes" "crypto/cipher" "crypto/des" "encoding/hex" "fmt" ) func main() { //明文 src := []byte("ReganYue") //秘钥 key := []byte("87654321") //加密 encrypt_msg := EncryptDES(src, key) fmt.Println("encrypt_msg = ", hex.EncodeToString(encrypt_msg)) //解密 decrypt_msg := DecryptDES(encrypt_msg, key) fmt.Println("decrypt_msg = ", string(decrypt_msg)) } //加密 func EncryptDES(src, key []byte) []byte { //通过秘钥创建加密块 block, err := des.NewCipher(key) if err != nil { panic(err) } //获取每个块的大小 length := block.BlockSize() //对明文进行填充 //src = utils.PaddingText(src, length) src = ZeroPadding(src, length) iv := []byte("12345678") //创建CBC加密模式 blockMode := cipher.NewCBCEncrypter(block, iv) dst := make([]byte, len(src)) blockMode.CryptBlocks(dst, src) return dst } //解密 func DecryptDES(src, key []byte) []byte { block, err := des.NewCipher(key) if err != nil { panic(err) } iv := []byte("12345678") //创建CBC解密模式 blockMode := cipher.NewCBCDecrypter(block, iv) dst := make([]byte, len(src)) //解密 blockMode.CryptBlocks(dst, src) //return utils.UnPaddingText(dst) return ZeroUnPadding(dst) } //填充最后一个分组 //src:待填充的明文 //blockSize:分组大小 func PaddingText(src []byte, blockSize int) []byte { //求出最后一个分组需要填充的字节数 padding := blockSize - len(src)%blockSize//3 // [3,3,3] padText := bytes.Repeat([]byte{byte(padding)}, padding) //将填充数据拼接到明文后面 nextText := append(src, padText...) return nextText } //去除尾部填充数据 func UnPaddingText(src []byte) []byte { len := len(src) number := int(src[len-1]) newText := src[:len-number] return newText } //ciphertext:待填充的明文 blocksize:每个块的大小 func ZeroPadding(ciphertext []byte, blocksize int) []byte { //计算需要填充几个字节 padding := blocksize - len(ciphertext)%blocksize padtext := bytes.Repeat([]byte{0}, padding) return append(ciphertext, padtext...) } //去除尾部填充数据 func ZeroUnPadding(origdata []byte) []byte { return bytes.TrimRightFunc(origdata, func (r rune) bool { return r == rune(0) }) } /* 加密之后: 0101 明文分组: 1011 1110 1110 0101 1011 */
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。