java实现DES加解密算法
来源:互联网 发布:高清网络摄像机方案 编辑:程序博客网 时间:2024/05/22 06:08
以下是我用java实现的DES算法,实现中可能存在一点问题自己没空去找,但我觉得DES的算法过程肯定没错!现在暂时没时间去找到底是哪里的问题,有空再瞧瞧自己的代码喽!
makekey.java是生成密钥以及子密钥
import java.util.Random;
public class makekey {
Random rand=new Random();
byte[] skey=new byte[64];
static byte[][] key=new byte[16][48];
static byte[] lun={1,1,2,2,2,2,2,2,1,2,2,2,2,2,2,1};
static byte[] keyex={13,16,10,23,0,4,2,27,14,5,20,9,
22,18,11,3,25,7,15,6,26,19,12,1,
40,51,30,36,46,54,29,39,50,44,32,47,
43,48,38,55,33,52,45,41,49,35,28,31};
byte[] keyzuoyou=new byte[56];
byte[] keyyou=new byte[28];
byte[] keyzuo=new byte[28];
public makekey(){//
findskey();////
cutskey(keyzuoyou);////
makesonkey();//??////
}
public void makesonkey(){//产生16个子密钥
for(int l=0;l<16;l++){
cut();
xhzlkey(keyzuo,lun[l]);
xhzlkey(keyyou,lun[l]);
he();
huodzmy(keyzuoyou,key[l]);
}
}
public void huodzmy(byte[] byt,byte[] zmy){
for(int k=0;k<zmy.length;k++)
zmy[k]=byt[keyex[k]];
}
public void cut(){//将56位密钥分成左右各28位的密钥用于循环左移
for(int l=0;l<28;l++)
keyzuo[l]=keyzuoyou[l];
for(int k=28,n=0;k<56;k++){
keyyou[n]=keyzuoyou[k];
n++;
}
}
public void xhzlkey(byte[] byt,int num){//实现循环左移
byte[] temp=new byte[num];
for(int k=0;k<num;k++)
temp[k]=byt[k];
for(int l=0;l<byt.length-num;l++){
byt[l]=byt[l+num];
}
for(int m=byt.length-1,g=num-1;g>=0;g--)
{
byt[m]=temp[g];
m--;
}
//outzmy(byt);///test
}
public void he(){//将经过循环左移后的左右各28位密钥合并
for(int l=0;l<28;l++)
keyzuoyou[l]=keyzuo[l];
for(int k=28,n=0;n<28;n++){
keyzuoyou[k]=keyyou[n];
k++;
}
}
public static void outzmy(byte[] byt){//用于显示子密钥的代码
System.out.println("$$");
for(int p=0;p<byt.length;p++)
{
if(p%8==0)
System.out.print("\n");
System.out.print(byt[p]);
}
}
/*public void outckey(byte[] byt){
for(int k=1;k<=byt.length;k++){
if((k-1)%7==0)
System.out.print("\n");
System.out.print(byt[k-1]);
}
}*/
public void cutskey(byte[] byt){//去掉无用的校验位得到56位的有用初始化的key
for(int i=0,l=0;i<64;i++){
if((i+1)%8==0)
continue;
byt[l]=skey[i];
l++;
}
}
public void findskey(){//产生随机的64位密钥,包含8位校验位
for(int i=0;i<64;i++){
if((i+1)%8==0){
int k=i,l=k-7,num=0;
while(k>=l){
if(skey[k]==1)
num++;
k--;
}
if(num%2==0)
skey[i]=1;
else
skey[i]=0;
continue;
}
skey[i]=(byte)rand.nextInt(2);
}
/*for(int p=0;p<64;p++)
{
if(p%8==0)
System.out.print("\n");
System.out.print(skey[p]);
}*/
}
/*public static void main(String[] args) {
// TODO Auto-generated method stub
new makekey();
}*/
}
mingwen.java是加解密过程中明文对应的处理逻辑
public class mingwen {
static byte[] mingex={57,49,41,33,25,17,9,1,59,51,43,35,27,19,11,3,
61,53,45,37,29,21,13,5,63,55,47,39,31,23,15,7,
56,48,40,32,24,16,8,0,58,50,42,34,26,18,10,2,
60,52,44,36,28,20,12,4,62,54,46,38,30,22,14,6};//初次置换用到的转换表
static byte[] exxming={39,7,47,15,55,23,63,31,38,6,46,14,54,22,62,30,
37,5,45,13,53,21,61,29,36,4,44,12,52,20,60,28,
35,3,43,11,51,19,59,27,34,2,42,10,50,18,58,26,
33,1,41,9,49,17,57,25,32,0,40,8,48,16,56,24};//最后置换用到的转换表
public static byte[] mingwenex(byte[] byt,byte[] exming,boolean ischu){//初次和最后用到的转换实现
if(ischu)
for(int j=0;j<byt.length;j++)
exming[j]=byt[mingex[j]];
else
for(int j=0;j<byt.length;j++)
exming[j]=byt[exxming[j]];
return exming;//
}
public static byte[] cutmingzuo(byte[] byt,byte[] mingzuo){//初次分割明文用到该功能
for(int k=0;k<mingzuo.length;k++)
mingzuo[k]=byt[k];
return mingzuo;//
}
public static byte[] cutmingyou(byte[] byt,byte[] mingyou){//初次分割明文用到该功能
for(int v=32;v<byt.length;v++)
mingyou[v-32]=byt[v];
return mingyou;//
}
public static byte[] heming(byte[] mingzuo,byte[] mingyou,byte[] byt){//最后用于合并16轮变换后的密文
for(int b=0;b<mingzuo.length;b++)
byt[b]=mingzuo[b];
for(int y=0;y<mingyou.length;y++)
byt[32+y]=mingyou[y];
return byt;//
}
public static byte[] getmingyou(byte[] byt,byte[] mingyou){//将明文右半部分扩展成48位的mingyou
int num=0,k=0,b=0;
while(num<8){
for(int i=k+1,m=b;i<5+k;i++,m++)
mingyou[i]=byt[m];
num++;
k+=6;b+=4;
}
for(int g=3,n=6;g<=27;g+=4,n+=6)
mingyou[n]=byt[g];
for(int b1=4,c=5;b1<=28;b1+=4,c+=6)
mingyou[c]=byt[b1];
mingyou[0]=byt[31];
mingyou[47]=byt[0];
return mingyou;//
}
}
jiajiem.java是DES加解密过程的逻辑功能实现
public class jiajiem {
byte[] phe={15,6,19,20,28,11,27,16,0,14,22,25,4,17,30,9,1,7,23,13,31,26,2,8,18,12,29,5,21,10,3,24};
byte[] shimingwen=new byte[64];//初始要加密的64位明文串
byte[] tempming=new byte[64];//经过16轮操作后合并的中间密文串
byte[] miwen=new byte[64];//最终得到的密文
byte[] mingzuo=new byte[32];//用于保存操作过程产生的32左明文
byte[] mingtemp=new byte[32];//一轮完后用于保存交换左右明文的中间量
byte[] sout=new byte[32];//用于保存经过S盒后的输出
byte[] pout=new byte[32];//用于保存经过P盒后的输出
byte[] mingyou=new byte[32];//用于保存操作过程产生的32右明文
byte[] mingyouex=new byte[48];//用于保存操作过程产生的扩展的48位右明文
byte[] miwenuse=new byte[64];//need it to co
public jiajiem(byte[] mingwenbyt,boolean isen){
if(isen)
en(mingwenbyt);
else
co(mingwenbyt);
}
public void co(byte[] mingwenbyt){
System.out.println("现在是在解密!");//
int num=0;
fuzhi(mingwen.mingwenex(mingwenbyt,shimingwen, true),shimingwen);//初次的简单明文置换操作
fuzhi(mingwen.cutmingzuo(shimingwen, mingzuo),mingzuo);//将明文分割成左右明文
fuzhi(mingwen.cutmingyou(shimingwen, mingyou),mingyou);//将明文分割成左右明文
while(num<16){
fuzhi(mingwen.getmingyou(mingyou, mingyouex),mingyouex);//扩展32位的右明文为48位用于和子密钥进行异或
fuzhi(xor(makekey.key[15-num],mingyouex),mingyouex);
fuzhi(S(mingyouex,sout),sout);
fuzhi(P(sout,pout),pout);
fuzhi(mingyou,mingtemp);
fuzhi(xor(mingzuo,pout),pout);
fuzhi(pout,mingyou);///
fuzhi(mingtemp,mingzuo);
num++;//so
}
fuzhi(mingwen.heming(mingzuo, mingyou,tempming),tempming);
fuzhi(mingwen.mingwenex(tempming,miwen,false),miwen);//第二次的简单中间密文置换操作
fuzhi(outmiwen(miwen),miwenuse);//为了输出解密后的字符串
}
public void en(byte[] mingwenbyt){
System.out.println("现在是在加密!");//
int num=0;
fuzhi(mingwen.mingwenex(mingwenbyt,shimingwen, true),shimingwen);//初次的简单明文置换操作
fuzhi(mingwen.cutmingzuo(shimingwen, mingzuo),mingzuo);//将明文分割成左右明文
fuzhi(mingwen.cutmingyou(shimingwen, mingyou),mingyou);//将明文分割成左右明文
while(num<16){
fuzhi(mingwen.getmingyou(mingyou, mingyouex),mingyouex);//扩展32位的右明文为48位用于和子密钥进行异或
fuzhi(xor(makekey.key[num],mingyouex),mingyouex);
fuzhi(S(mingyouex,sout),sout);
fuzhi(P(sout,pout),pout);
fuzhi(mingyou,mingtemp);
fuzhi(xor(mingzuo,pout),pout);
fuzhi(pout,mingyou);//
fuzhi(mingtemp,mingzuo);
num++;//so
}
fuzhi(mingwen.heming(mingzuo, mingyou,tempming),tempming);
fuzhi(mingwen.mingwenex(tempming,miwen,false),miwen);//第二次的简单中间密文置换操作
fuzhi(outmiwen(miwen),miwenuse);//为了解密方便
}
public static byte[] outmiwen(byte[] byt){
for(int k=0;k<byt.length;k++)
System.out.print(byt[k]);
return byt;
}
public void fuzhi(byte[] from,byte[] to){
for(int h=0;h<from.length;h++)
to[h]=from[h];
}
public void fuzhif(byte[] from,byte[] to,int num){
for(int h=num;h<num+4;h++)
to[h]=from[h];
}
public byte[] xor(byte[] zmy,byte[] youmw){//实现子密钥和右明文的异或操作,同时实现左明文和经过p盒置换的右明文串进行置换
for(int i=0;i<zmy.length;i++){
if(zmy[i]==youmw[i])
youmw[i]=0;
else
youmw[i]=1;
}
return youmw;
}
public byte[] S(byte[] xorming,byte[] pming){//实现s的操作,将其转换到p盒前的状态
int num=0,k=0,m=0;
byte hang,lie;
while(num<8){
hang=(byte)(2*(xorming[k])+xorming[k+5]);
lie=(byte)(Math.pow(2,3)*xorming[k+1]+Math.pow(2,2)*xorming[k+2]+2*xorming[k+3]+xorming[k+4]);
fuzhif(erjztobyt(s[num][hang][lie],pming,m),pming,m);///4important
k+=6;//
m+=4;
num++;
}
//makekey.outzmy(pming);///test find the pming is have shu ju;
return pming;//
}
public byte[] P(byte[] pqian,byte[] phou){
for(int h=0;h<pqian.length;h++)
phou[h]=pqian[phe[h]];
return phou;//
}
public byte[] erjztobyt(byte byt,byte[] bb,int num){//从num开始的下标将所得到的的二进制数分别复制到bb
int xx=3,k=0;
while(xx>=0){
if(Math.pow(2, xx)>byt){
bb[num+k]=0;
xx--;
k++;
}
else if(Math.pow(2,xx)<byt){
bb[num+k]=1;
byt-=Math.pow(2,xx);
xx--;
k++;
}
else{
bb[num+k]=1;
xx--;
while(xx>=0){///
k++;
bb[num+k]=0;
xx--;
}
}
}
return bb;
}
byte[][][] s={
{
{14,4,13,1,2,15,11,8,3,10,6,12,5,9,0,7},
{0,15,7,4,14,2,13,1,10,6,12,11,9,5,3,8},
{4,1,14,8,13,6,2,11,15,12,9,7,3,10,5,0},
{15,12,8,2,4,9,1,7,5,11,3,14,10,0,6,13}},
{
{15,1,8,14,6,11,3,4,9,7,2,13,12,0,5,10},
{3,13,4,7,15,2,8,14,12,0,1,10,6,9,11,5},
{0,14,7,11,10,4,13,1,5,8,12,6,9,3,2,15},
{13,8,10,1,3,15,4,2,11,6,7,12,0,5,14,9}},
{
{10,0,9,14,6,3,15,5,1,13,12,7,11,4,2,8},
{13,7,0,9,3,4,6,10,2,8,5,14,12,11,15,1},
{13,6,4,9,8,15,3,0,11,1,2,12,5,10,14,7},
{1,10,13,0,6,9,8,7,4,15,14,3,11,5,2,12}},
{
{7,13,14,3,0,6,9,10,1,2,8,5,11,12,4,15},
{13,8,11,5,6,15,0,3,4,7,2,12,1,10,14,9},
{10,6,9,0,12,11,7,13,15,1,3,14,5,2,8,4},
{3,15,0,6,10,1,13,8,9,4,5,11,12,7,2,14}},
{
{2,12,4,1,7,10,11,6,8,5,3,15,13,0,14,9},
{14,11,2,12,4,7,13,1,5,0,15,10,3,9,8,6},
{4,2,1,11,10,13,7,8,15,9,12,5,6,3,0,14},
{11,8,12,7,1,14,2,13,6,15,0,9,10,4,5,3}},
{
{12,1,10,15,9,2,6,8,0,13,3,4,14,7,5,11},
{10,15,4,2,7,12,9,5,6,1,13,14,0,11,3,8},
{9,14,15,5,2,8,12,3,7,0,4,10,1,13,11,6},
{4,3,2,12,9,5,15,10,11,14,1,7,6,0,8,13}},
{
{4,11,2,14,15,0,8,13,3,12,9,7,5,10,6,1},
{13,0,11,7,4,9,1,10,14,3,5,12,2,15,8,6},
{1,4,11,13,12,3,7,14,10,15,6,8,0,5,9,2},
{6,11,13,8,1,4,10,7,9,5,0,15,14,2,3,12}},
{
{13,2,8,4,6,15,11,1,10,9,3,14,5,0,12,7},
{1,15,13,8,10,3,7,4,12,5,6,11,0,14,9,2},
{7,11,4,1,9,12,14,2,0,6,10,13,15,3,5,8},
{2,1,14,7,4,10,8,13,15,12,9,0,3,5,6,11}}};
}
Main.java是程序的入口
import java.util.Scanner;
import java.util.Scanner;
public class Main {
Scanner scan=new Scanner(System.in);
String code;
makekey key=new makekey();//产生子密钥
public Main(){
System.out.println("请输入要加密的字符串!");
code=scan.nextLine();
while(code.charAt(0)!='0'){
String str=strtoerjz(code);
byte[] byt=new byte[str.length()];
for(int k=0;k<byt.length;k++)
byt[k]=(byte)(str.charAt(k)-'0');
System.out.println("加密前其对应的unicode码(二进制)是:\n"+str);
System.out.println("加密后其对应的二进制是:\n");
jiajiem jia=new jiajiem(byt,true);
System.out.println("\n解密后对应的二进制是:\n");
jiajiem jie=new jiajiem(jia.miwenuse,false);
System.out.println("\n解密得到的二进制转换成字符串是:"+erjztostr(jie.miwenuse));///$$
System.out.println("\n请输入要加密的字符串!");
code=scan.nextLine();
}
}
public String erjztostr(byte[] byt){
System.out.println();
String str="";short temp=0;
for(int i=0,num=0;i<byt.length;i++){
temp+=Math.pow(2,15-i+num)*byt[i];
if((i+1)%16==0){
str+=(char)temp;
//System.out.println(temp);///
temp=0;
num+=16;
}
}
return str;
}
public String strtoerjz(String str){
short temp;
byte shiliu=15;
String erjz="";
for(int i=0;i<str.length();i++){
temp=(short)str.charAt(i);
while(shiliu>=0){
if(Math.pow(2,shiliu)<temp){
erjz+='1';
temp-=Math.pow(2, shiliu);
shiliu--;
}
else if(Math.pow(2, shiliu)>temp){
erjz+='0';
shiliu--;
}
else{
erjz+='1';
shiliu--;
while(shiliu>0){
erjz+='0';
shiliu--;
}
}
}
shiliu=15;
}
return erjz;
}
public static void main(String[] args) {
// TODO Auto-generated method stub
new Main();
}
}
运行截图:
注:由于DES一次只能加密一个64位的块,而java中一个字符占16位,所以刚好是4个字符构成一次加解密要的64位,本程序中只考虑了一次4位字符的加解密情况,如果想一下加解密很多的字符请在Main.java中做相应改动!
- java实现DES加解密算法
- DES加解密算法实现
- java des加解密算法
- Java实现DES加解密
- Java☞DES加解密算法简介及实现
- DES加解密算法Qt实现
- DES加解密算法实现详解
- DES加解密算法实现类
- DES加解密算法
- DES加解密算法
- java实现3des加解密
- DES加解密(Java)
- Java Des加解密
- java des加解密
- java des 加解密
- java DES加解密
- DES加解密(Java)
- 用vb实现DES加解密算法(三)--解密
- 社會의 均平運動
- 500万数据,查询分页,500毫秒搞定
- SQL数据库
- 无法访问 private 成员(在“boost::asio::detail::noncopyable”类中声明)
- 求解:mySQL =0
- java实现DES加解密算法
- 現代政治思想의 發源
- 学广州传智播客学Java,别再说自己不行啦
- openstack中为什么要用GRE和VLAN?
- 字符串的连接
- freemarker乱码问题解决方案
- litezip学习(WINDOW下的轻量级压缩库)
- Sharing Data Locally between ios apps
- linux下配置Nginx+双tomcat负载均衡