Feistel---简介以及golang简单实现

简介

工作原理

具体实现

从原理上分析,只要把加密流程看懂,实现这个加密算法并不难。
主观上分析,我认为这个算法实现有两个难点:

  • 子秘钥的计算方式
  • 计算子秘钥与右半部分的函数

下面我首先针对这两点,简单说一下我的实现过程。

子秘钥的衍生

我主要采用的是给定16byte长度的密钥,然后每个byte当做一个子秘钥,我认为这种方式太简单了,不建议大家采取,我暂时还没想到比较好的方法,以后有的话会及时更新。下面看一下代码:

var key string = "ABCDEFGHIJKLMNOP"
//generate keys
func generateKeys(key string) []byte{
	var byte_key = []byte(key)
	keys := []byte{}
	keys = byte_key
	return keys
}

function

我采用方法是将明文的每个字节都和子秘钥做getMod运算,然后得到运算后的结果。

//right and ki function
func function(right []byte,key byte)[]byte {
	outputBytes := []byte{}

	for _,right_byte := range right{
		outputBytes = append(outputBytes,getMod(right_byte,key))
	}

	return outputBytes
}
func getMod(right_byte,key_byte byte) byte {
	if right_byte == 0{
		return key_byte
	}

	if key_byte == 0{
		return right_byte
	}

	if right_byte >= key_byte {
		return right_byte % key_byte
	}else{
		return key_byte % right_byte
	}
}

到这里最主要的功能就已经实现了,下面简单介绍一下迭代的实现。

迭代计算的一轮计算过程

主要就是先用function函数计算出prepare_data,再与left异或得到nextright
再讲right作为下一步的left,这样一轮迭代就做好了,原理明白了,实现起来很简单。下面是源码:

func applyFeistel(left,right []byte,key byte)([]byte,[]byte){
	nextleft := right

	prepare_data := function(right,key)

	nextright := []byte{}

	nextright = Xor(left,prepare_data)

	return nextleft,nextright
}

迭代加密过程

首先我先判断下明文的长度,如果长度不是偶数,那么填充一个字节的0,然后再均分明文为leftright。然后再执行LOOP_NUM次迭代,即可得到密文。

//主要迭代加密过程,返回加密成功的密文和最后一轮所使用的子秘钥
func FeistelEncrypt(data, key string) ([]byte, []byte, byte) {
	byte_data := []byte(data)

	byte_data_len := len(byte_data)
	if byte_data_len%2 != 0 {
		byte_data = append(byte_data, byte(0))
	}
	byte_data_len_len := len(byte_data)
	midlen := int(byte_data_len_len / 2)

	left := byte_data[:midlen]
	right := byte_data[midlen:]
	keys := generateKeys(key)

	var i int

	for i = 0; i < LOOP_NUM; i++ {
		nextleft, nextright := applyFeistel(left, right, keys[i])
		left = nextleft
		right = nextright
		//fmt.Printf("第%d轮的子秘钥:%x\n",i+1,keys[i])

	}

	return right, left, keys[LOOP_NUM-1]


解密的迭代过程

先说思想,解密的话是先调换最后输出的密文:right = left , left = right然后使用与加密过程一样的迭代流程,这里我简单描述下原理:

在加密的时候:

  • F ( r i g h t , k i ) F(right,k_i) xor l e f t left = n e x t r i g h t nextright
  • r i g h t = l e f t right = left

在解密的时候首先是左右交换了我们命名为:

  • D e c r y p t R i g h t = l e f t DecryptRight = left
  • D e c r y p t L e f t = r i g h t DecryptLeft = right

在解密的时候采取同样的计算过程:

  • F ( D e c r y p t R i g h t , k i ) F(DecryptRight,k_i) xor D e c r y p t L e f t DecryptLeft = D e c r y p t N e x t R i g h t DecryptNextRight

然后我们根据加密时的公式进行替换得到:

  • F ( r i g h t , k i ) F(right,k_i) xor F ( r i g h t , k i ) F(right,k_i) xor l e f t left
    因为异或操作相同为0,所以上面的结果为:left,这样我们就得到了加密时的left,附给了:DecryptNextRight ,所以其实顺序是调换的,最后需要再交换一下。

下面给出源码:

//Decrypt

func FeistelDecrypt(right1, left1, keys []byte) ([]byte, byte) {
	var i int
	right := left1
	left := right1
	for i = LOOP_NUM - 1; i >= 0; i-- {
		nextleft, nextright := applyFeistel(left, right, keys[i])
		left = nextleft
		right = nextright
		//fmt.Printf("第%d轮的子秘钥:%x\n",i+1,keys[i])

	}

	return append(right, left...), keys[0]
}

完整源码我已经上传github了:Feistel

猜你喜欢

转载自blog.csdn.net/qq_35324057/article/details/106663186