Feistel概述 Feistel密码结构,在密码学研究中,Feistel密码结构是用于分组密码中的一种对称结构。理解了Feistel密码结构,对于理解DES算法的原理有很大的帮助。 Feistel建议使用乘积密码的概念来逼近理想分组密码。乘积密码是指依次使用两个或两个以上基本密码,所得结果的密码强度将强于所有单个密码的强度。Feistel密码交替使用代替和置换来进行加密解密。 代替和置换的定义如下: 代替:每个明文元素或元素组被唯一地替换为相应的密文元素或元素组。 置换:明文元素的序列被替换为该序列的一个置换。也就是说,序列中没有元素被添加、删除或替换,但序列中元素出现的顺序改变了。
原理 关于Feistel的加密与解密过程如下图所示:
上图是Feistel的密码结构。加密算法的输入是长为2w位的明文分组和密钥K。明文分组被分为等长的两部分:L0和R0。这两半数据经过n轮迭代后组合成密文分组。第i轮迭代的输入Li-1和Ri-1来自于上轮迭代的输出;而输入的子密钥Ki是由整个密钥K推导出的。一般地,Ki不同于K,也互不相同。尽管可以使用任意轮数,但上图使用了16轮。每轮迭代都有相同的结构。代替作用在数据的左半部分。它通过用轮函数F作用于数据的右半部分后,与左半部分数据进行异或来完成。每轮迭代的轮函数是相同的,但是输入的子密钥Ki不同。换一种说法,F是w位长的右半分组以及y位长的子密钥的函数,输出w位的值:F(REi,Ki+1)。代替之后,交换数据的左右两半完成置换。
影响因素 Feistel结构的具体实现依赖于以下参数和特征:
分组长度:分组长度越长意味着安全性越高,但是会降低加、解密的速度。这种安全性的增加来自更好的扩散性。传统上,64位的分组长度比较合理,在分组密码设计里很常用。
密钥长度:密钥较长同样意味着安全性较高,但会降低加、解密的速度。这种安全性的增加来自更好的抗穷尽攻击能力和更好的混淆性。现在一般认为64位的密钥还不够。通常使用的密钥长度是128位。
迭代轮数:Feistel密码的本质在于单轮不能提供足够的安全性而多轮加密可取得很高的安全性。迭代轮数的典型值是16。
子密钥产生算法:子密钥产生越复杂,密码分析就越困难。
轮函数F:同样,轮函数越复杂,抗攻击的能力就越强。
代码实现 只要把理论搞清楚,代码实现并不算难,具体代码如下:
package com.general.encryanddecode;
import java.util.Arrays;
/**
*
*@author generalandroid
*
*Feistel密码算法
* **/
public class FeistelTest {/**加密轮数**/
private static final int LOOP_NUM=16;
private String [] keys=new String[LOOP_NUM];
private String [] pContent;
private String [] cContent;
private int origin_length;
public static void main(String[] args){FeistelTest feistelTest=new FeistelTest("Android将军->GeneralAndroid","ABCDE");
feistelTest.encrypt();
feistelTest.decrypt();
}
public FeistelTest(String content,String key){
generateKey(key);
divideGroups(content);
System.out.println("原始明文:"+content+"\n原始密钥:"+key);
}public void encrypt(){
StringBuilder c=new StringBuilder();
for(int i=0;
i"密文:\n"+c.toString());
}
public void decrypt(){
StringBuilder p=new StringBuilder();
for(int i=0;
i-1;
i--){
content=f(i,content,flag);
}
}
return content;
}
/**f函数**/
public String f(int time,String content,int flag){
if(content.length()>8){
System.out.println("ERROR!!!!!");
}
String LE=content.substring(0,4);
String RE=content.substring(4,8);
String LE1=null;
String RE1=null;
String key=keys[time];
//System.out.println("LE:"+LE+"\t RE:"+RE+"\t key:"+key);
char[] tmp=new char[4];
for(int j=0;
j<4;
j++){
tmp[j]=(char)(RE.charAt(j)^key.charAt(4*j)^LE.charAt(j));
}
//System.out.println("tmp re:"+Arrays.toString(tmp));
LE1=RE;
RE1=new String(tmp);
//System.out.println("time:"+time+"\t L:"+LE1+RE1+"\t key:"+key);
if (((flag == 0) && (time == 15)) || ((flag == 1) && (time == 0))) {
return RE1+LE1;
}return LE1+RE1;
}}
/****
* 运行结果:
*
*
原始明文:Android将军->GeneralAndroid
原始密钥:ABCDE
密文:
oAB尴ooc尀冿uehbtDXlGdthoFB@7101
明文:
Android将军->GeneralAndroid *
* *****/
复制代码
参考资料 【python|Feistel密码原理与实现】《密码编码学与网络安全》第六版
推荐阅读
- 操作系统|[译]从内部了解现代浏览器(1)
- Java|Java基础——数组
- 人工智能|干货!人体姿态估计与运动预测
- 推荐系统论文进阶|CTR预估 论文精读(十一)--Deep Interest Evolution Network(DIEN)
- java简介|Java是什么(Java能用来干什么?)
- Java|规范的打印日志
- Linux|109 个实用 shell 脚本
- 程序员|【高级Java架构师系统学习】毕业一年萌新的Java大厂面经,最新整理
- Python专栏|数据分析的常规流程
- Spring注解驱动第十讲--@Autowired使用