Go语言实现DES加密算法(一)—— DES算法概念、DES的CBC模式、Go语言实例实现

DES算法

  1. DES内部实现理论:

    在des中的各个步骤称之为轮,整个加密过程需要进行16轮循环。

Go语言实现DES加密算法(一)—— DES算法概念、DES的CBC模式、Go语言实例实现_第1张图片

 

子密钥:中间的子密钥指的是本轮加密使用的密钥,每一轮都需要使用一个不同的子密钥,由于它只在一轮中使用,只是一个局部密钥,所以称之为子密钥。

轮函数:根据右侧和子密钥生成对左侧进行加密的比特序列,它是密码体系的核心。

右半侧实际上没有进行任何处理,者在加密算法中看起来比较浪费,其设计目的为了保证可解密性,因为完全没有进行任何处理的右半侧是解密过程的必须信息,极大的简化了硬件的设计。

 

我的理解就是各种轮函数不同的处理方法就是不用的模式。

 

CBC模式:

Go语言实现DES加密算法(一)—— DES算法概念、DES的CBC模式、Go语言实例实现_第2张图片

CBC模式的全称是:Cipher Block Chaining模式(密文分组链接模式),在CBC模式中,首先将明文分组与前一个密文分组进行异或运算,然后再进行加密。

初始化向量:当加密第一个明文分组时,由于不存在前一个密文分组,因此需要准备一个长度为一个分组的比特序列来代替前一个密文分组,通常缩写为IV

分析:

1.假设CBC模式加密的密文分组中有一个分组损坏了(由于硬盘故障导致密文分组的值发生了改变),只要密文分组的长度没有发生变化,则解密时最多只会有2个分组的数据解密失败。

2.假设CBC模式的密文分组中有一些比特缺失(可能由于网络故障导致的),那么此时即使只有1比特缺失,也会导致分组长度发生改变,此时该分组之后的所有分组解密都会失败。

 

先附上代码。。。

package main

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

//DES加密函数,src即明文,key即密钥,得到一个密文返回
func DesEnCrypt(src, key []byte) []byte {

	//new一个cipher.block接口,它对应着要加密的块
	block, e := des.NewCipher(key)

	if e != nil {
		fmt.Print(e)
	}

	//Fill函数即为对明文的填充,即,DES加密的明文长度为64位,
	// 少于64位可以填充,多余64位可以根据64位一块,形成多个块,不够的填充。
	//block.BlockSize()就是加密的块长度,fill函数会将明文按照块长度进行分组。
	//这样就形成了多个明文分组。以便于进行DES加密
	srcc := Fill(src, block.BlockSize())


	//make一个密文byte切片用以接收
	dst := make([]byte, len(srcc))


	//使用CBC模式进行加密,只需将加密的块,即初始向量传入就可以得到一个CBC模式:BlockMode
	encrypter := cipher.NewCBCEncrypter(block, key[:block.BlockSize()])
	//使用CBC模式进行加密,并将其赋给dst。
	encrypter.CryptBlocks(dst, srcc)
	return dst
}






//DES解密函数,src即为密文,key为密钥

func DesDecrypt(src, key []byte) []byte {
	
	//new一个cipher.block接口,它对应着要加密的块
	block, e := des.NewCipher(key)

	if e != nil {
		fmt.Print(e)
	}

	
	decrypter := cipher.NewCBCDecrypter(block, key[:block.BlockSize()])

	dst := make([]byte, len(src))

	decrypter.CryptBlocks(dst, src)

	out := Out(dst, block.BlockSize())

	return out
}

func main() {
	src := []byte("iamwek")
	key := []byte("12345678")

	crypt := fmt.Sprintf("%x", DesEnCrypt(src, key))
	fmt.Print(crypt)
	fmt.Println()

	fmt.Printf("%s", DesDecrypt(DesEnCrypt(src, key), key))
	fmt.Println()
}






func Fill(src []byte, blocksize int) []byte {
	fillsize := blocksize - len(src)%blocksize
	repeat := bytes.Repeat([]byte{0}, fillsize)
	return append(src, repeat...)
}

func Out(src []byte, blocksize int) []byte {

	return bytes.TrimRightFunc(src, func(r rune) bool {
		return r == rune(0)
	})
}

 

结果为:

dab2dcc325ecef56
iamwek

 

第一行为加密后的得到的密文

第二行为解密后得到的明文

加密解密时注意初始向量必须一样,并且长度必须为8字节。。

你可能感兴趣的:(密码学)