简介
工作原理
具体实现
从原理上分析,只要把加密流程看懂,实现这个加密算法并不难。
主观上分析,我认为这个算法实现有两个难点:
- 子秘钥的计算方式
- 计算子秘钥与右半部分的函数
下面我首先针对这两点,简单说一下我的实现过程。
子秘钥的衍生
我主要采用的是给定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
,然后再均分明文为left
和right
。然后再执行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)
F(right,ki)
xor
l e f t left left = n e x t r i g h t nextright nextright - r i g h t = l e f t right = left right=left
在解密的时候首先是左右交换了我们命名为:
- D e c r y p t R i g h t = l e f t DecryptRight = left DecryptRight=left
- D e c r y p t L e f t = r i g h t DecryptLeft = right DecryptLeft=right
在解密的时候采取同样的计算过程:
-
F
(
D
e
c
r
y
p
t
R
i
g
h
t
,
k
i
)
F(DecryptRight,k_i)
F(DecryptRight,ki)
xor
D e c r y p t L e f t DecryptLeft DecryptLeft = D e c r y p t N e x t R i g h t DecryptNextRight DecryptNextRight
然后我们根据加密时的公式进行替换得到:
-
F
(
r
i
g
h
t
,
k
i
)
F(right,k_i)
F(right,ki)
xor
F ( r i g h t , k i ) F(right,k_i) F(right,ki)xor
l e f t left 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