这学期写的最多的应用就是加密,文件处理,网络和多线程了。这个小程序是实验课做的,没多少技术含量,不过对于了解JAVA多线程,文件处理,加密,文件分割合并技术还是挺有参考价值的。

   文件分割采用多线程,分割几块就开几个线程,所以PC上大文件有点慢,加密用的RSA(模式:公钥加密私钥解密),只进行文件头加密(整块加密它也做不了),校验用MD5(虽然已经被破解不过对了解数字指纹技术还是很经典的),对每个分块都进行校验以保证安全。说到文件分割合并技术,这可是分布式文件系统的一个基础架构。

看看效果吧:

 

1.没有图形界面,下面三个文件夹,加密切割或解密合并时得到的文件存放于GetFile中,将要进行切割的文件或要进行合并的分块文件放入LoadFile中,PrivateKey中放入密钥。

 

 

2.

将精舞门.avi放入LoadFile中,运行主程序FileCuter,输入切割份数6,完成加密分块

 

3.文件分块。

4.生成的密钥 

5.将分块文件导入LoadFile,输入指令2进行合并,合并时会进行密钥校验,分块校验和解密。合并后的文件名为RECOVER。

6.用diff命令对原文件和合并后的文件进行校验,文件没有差异,恢复成功!

7.将第四块拿掉,不完整被检测出来。

8.用别的密钥进行解密,被检测出来

8.载入正确的密钥,将分块3和5换为其他文件的分块(也就是分块被修改了),密钥审核通过,问题分块校验不通过。

9.修改问题文件的文件名也没用

10.文件相关信息被写入文件内部,表面文件名及文件顺序不影响程序的正确执行。

   实验目的主要是完成密码算法方面的应用,程序在处理过小的文件时可能发生错误,但都不是主要问题~~

代码 : (VIM一个一个敲出来的,就不注释了)

CreateKey.java

import java.io.*;

public class CreateKey{

private int id;

public CreateKey(int id){

this.id=id;

}

public  void Create(String filename,byte[] key,int num){

RandomAccessFile fout=null;

try{

fout=new RandomAccessFile("PrivateKey/"+filename+".pri_key","rw");

fout.seek(num*16);

fout.write(key);

fout.close();

}catch(Exception e){

System.out.println("密钥写入失败!");

}

}

public synchronized void writeMD5(int test,byte[] md5,String filename){

while(id!=test){

                        try{

                                wait();

                        }catch(Exception e){

                                e.printStackTrace();

                        }

                }

try{

RandomAccessFile fout=new RandomAccessFile("PrivateKey/"+filename+".pri_key","rw");

File f=new File("PrivateKey/"+filename+".pri_key");

fout.seek(16*(test-1));

fout.write(md5);

fout.close();

}catch(Exception e){}

id++;

notifyAll();

}

 Cut.java

 

import java.io.*;

import java.util.Map;

import java.security.*;

import org.apache.commons.codec.digest.DigestUtils;

public class Cut extends Thread{

private int id;

private int num;

private long start;

private long end;

private String file;

private String filename;

private byte[] key;

private CreateKey ck;

private BufferedInputStream fin;

private BufferedOutputStream fout;

private DigestInputStream dis;

public Cut(int id,int num,long start,long end,String f,CreateKey ck){

String[] name=f.split("\\.");

this.file=f;

this.start=start;

this.end=end;

this.filename=name[0];

this.id=id;

this.num=num;

this.ck=ck;

}

public byte[] PriKey(){

byte[] privatekey=new byte[400];;

try{

                        Map<String,Object> keymap=RSACode.initKey();

                        this.key=RSACode.getPublicKeyEncoded(keymap);

                        privatekey=RSACode.getPrivateKeyEncoded(keymap);

ck.Create(filename,privatekey,num);

return privatekey;

                }catch(Exception e){

                }

return privatekey;

        }

public void Deal(){

byte[] b=new byte[53];

int i=0;

int o=0;

long prilen=end-start;

try{

fin.skip(start);

fout.write(id);

fout.write(num);

if(id==1){

byte[] k=PriKey();

fout.write(MD5Code.getMD5(k));

}

}catch(Exception e){}

System.out.println(filename+id+".cut 创建中...");

while(prilen>0){

                try{      

if(prilen<53){

                        byte[] b1=new byte[(int)prilen];

                                i=dis.read(b1);

                                fout.write(b1);

                                fout.flush();

                                }

                        else{

        if(id==1&&o<1){

i=fin.read(b);

      byte[] c=RSACode.encryptByPublicKey(b,key);

                            fout.write(c,0,c.length);

fout.flush();

      }else{

i=dis.read(b);

      fout.write(b,0,i);

      fout.flush();

                        }

}

                        prilen-=i;

o++;

                }catch(Exception e){}

}

try{

dis.close();

MessageDigest md=dis.getMessageDigest();

                byte[] b1=md.digest();

System.out.println(filename+id+".cut 完成!");

ck.writeMD5(id,b1,filename);

fout.close();

}catch(Exception e){}

}

public void run(){

try{

                        fin=new BufferedInputStream(new FileInputStream("LoadFile/"+this.file));

dis=new DigestInputStream(fin,MessageDigest.getInstance("MD5"));

                }catch(Exception e){

                        System.out.println("读取文件失败!");

                }

try{

fout=new BufferedOutputStream(new FileOutputStream("GetFile/"+filename+id+".cut"));

}catch(Exception e){

System.out.println(filename+id+"创建失败!");

}

try{

Deal();

}catch(Exception e){}

}

}

FCut.java

 

import java.io.*;

public class FCut{

private int num;

private int stat=0;

public FCut(int n){

num=n;

}

public  void startCut(){

CreateKey ck=new CreateKey(1);

File dir=new File("LoadFile");

                File[] filelist;

                filelist=dir.listFiles();

String filename=filelist[0].getName();

long size=filelist[0].length();

int o=1;

long start=size/num;

Cut[] cut=new Cut[num];

for(int i=0;i<num;i++){

if(o==num)

                                cut[i]=new Cut(i+1,num,(i*start),size,filename,ck);

                        else

                                cut[i]=new Cut(i+1,num,(i*start),((i+1)*start),filename,ck);

                        cut[i].start();

}

for(int i=0;i<num;i++){

                        try{

                                cut[i].join();

                        }catch(Exception e){

                                e.printStackTrace();

                }

}

stat=1;

}

public int getStat(){

return stat;

}

}

FileCuter.java

 

import java.util.Scanner;

public class FileCuter{

public static void main(String[] star){

Scanner sc=new Scanner(System.in);

int cmd,num;

System.out.println("\n           ****安全文件切割合并程序****\n");

System.out.println("输入指令:1--文件加密切割,2--文件解密合并,3--退出\n");

while(true){

                        System.out.print("CMD:>");

                        cmd=sc.nextInt();

if(cmd==1){

System.out.print("请输入切割份数:");

num=sc.nextInt();

FCut fc=new FCut(num);

fc.startCut();

while(true){

if(fc.getStat()==1)break;

}

}

else if(cmd==2){

Merge m=new Merge();

                        m.Merge();

}

else if(cmd==3){

System.out.println("Bye!");

break;

}

else

System.out.println("输入不正确");

}

}

}

MD5Code.java

 

import org.bouncycastle.util.encoders.Base64;

import org.apache.commons.codec.digest.DigestUtils;

public class MD5Code{

public static byte[] encodeMD5(String data)throws Exception{

return DigestUtils.md5(data);

}

public static String decodeMD5(String data)throws Exception{

return DigestUtils.md5Hex(data);

}

public static byte[] getMD5(byte[] data)throws Exception{

                return DigestUtils.md5(data);

        }

public static String getMD5Hex(byte[] data)throws Exception{

return DigestUtils.md5Hex(data);

}

}

Merge.java

 

import java.io.*;

import java.util.*;

import org.apache.commons.codec.digest.DigestUtils;

import org.apache.commons.codec.binary.Hex;

public class Merge{

public BufferedInputStream FinList(String s){

BufferedInputStream fin=null;

try{

fin=new BufferedInputStream(new FileInputStream(s));

}catch(Exception e){

                        e.printStackTrace();

                }

return fin;

}

public String[] FileList(){

BufferedInputStream fin;

File dir=new File("LoadFile");

File[] flist=dir.listFiles();

int len=flist.length;

String[] name=new String[len];

int[] id=new int[len];

int test=0;

for(int i=0;i<len;i++){

if(!flist[i].isDirectory()){

name[i]=flist[i].getName();

                                try{

                                        fin=FinList(flist[i].toString());

                                        id[i]=fin.read();

                                        test=fin.read();

fin.close();

                                }catch(Exception e){

                                         e.printStackTrace();

                                 }

                        }

else

continue;

}

if(test!=len){

System.out.println("文件分块数目不正确!");

name[0]="0";

return name;

}

else{

for (int i=1;i<len;i++)

                                  for (int j=0;j<=len-i-1;j++)

                                  {

                                         if (id[j]>id[j+1])

                                         {

                                                  int t=id[j];

                                                  String temp=name[j];

                                                  id[j]=id[j+1];

                                                  name[j]=name[j+1];

                                                  id[j+1]=t;

                                                  name[j+1]=temp;

}

}

return name;

}

}

public String[] GetFileMD5(String[] flisttest){

BufferedInputStream fin;

String[] md5=new String[flisttest.length+1];

File dir=new File("PrivateKey");

                File[] flist=dir.listFiles();

if(flist.length==0){

System.out.println("密钥载入失败!");

md5[0]="0";

return md5;

}

byte[] b=new byte[16];

try{

fin=FinList(flist[0].toString());

for(int i=0;i<flisttest.length;i++){

fin.read(b);

md5[i]=Hex.encodeHexString(b);

}

md5[flisttest.length]=DigestUtils.md5Hex(fin);

fin.close();

}catch(Exception e){

System.out.println("密钥文件解析失败!");

}

return md5;

}

public int CheckFileMD5(String[] flist,String[] md5){

int flag=1;

BufferedInputStream fin;

String m;

for(int i=0;i<flist.length;i++){

try{

fin=FinList("LoadFile/"+flist[i]);

fin.read();

fin.read();

if(i==0){

byte[] b=new byte[16];

fin.read(b);

if(!Hex.encodeHexString(b).equals(md5[md5.length-1])){

System.out.println("密钥不正确!");

flag=0;

}

else

System.out.println("密钥验证通过!");

fin.skip(64);

m=DigestUtils.md5Hex(fin);

}

else{

m=DigestUtils.md5Hex(fin);

}

if(!md5[i].equals(m)){

System.out.println("分块:"+flist[i]+" 校验失败!");

flag=0;

}

else

System.out.println("分块:"+flist[i]+" 验证通过!");

fin.close();

}catch(Exception e){

System.out.println("读取"+flist[i]+"MD5失败!");

flag=0;

}

}

return flag;

}

public byte[] GetKey(String[] fl){

BufferedInputStream fin;

                File dir=new File("PrivateKey");

File[] flist=dir.listFiles();

File f=new File(flist[0].toString());

int len=(int)(f.length()-fl.length*16);

                byte[] b=new byte[len];

                try{

                        fin=FinList(flist[0].toString());

fin.skip(fl.length*16);

                        fin.read(b);

                        fin.close();

                }catch(Exception e){

                        System.out.println("密钥文件解析失败!");

                }

                return b;

        }

public void Merge(){

String[] fl=FileList();

if(fl[0].equals("0"))

return;

                String[] md5=GetFileMD5(fl);

if(md5[0].equals("0"))

return;

                int a=CheckFileMD5(fl,md5);

BufferedInputStream fin;

if(a==0)

return;

else{

try{

System.out.println("文件合并开始!");

BufferedOutputStream fout=new BufferedOutputStream(new FileOutputStream("GetFile/RECOVER"));

byte[] key=GetKey(fl);

byte[] b=new byte[64];

int n=0,sign=0;

for(int i=0;i<fl.length;i++){

fin=FinList("LoadFile/"+fl[i]);

fin.skip(2);

System.out.println("分块: "+fl[i]+" 写入中...");

if(i==0){

fin.skip(16);

while((n=fin.read(b))>0){

if(sign==0){

fout.write(RSACode.decryptByPrivateKey(b,key),0,53);

sign=1;

}

else

fout.write(b,0,n);

}

}

else{

while((n=fin.read(b))>0){

fout.write(b,0,n);

}

}

fin.close();

}

fout.close();

}catch(Exception e){

System.out.println("文件合并失败!");

return;

}

System.out.println("文件合并结束!");

}

}

}

 

RSACoder.java

 

 

import javax.crypto.Cipher;

public class RSACode{

private static final String KEY_ALGORITHM="RSA";

private static final String PUB_KEY="RSAPublicKey";

private static final String PRI_KEY="RSAPrivateKey";

private static final int KEY_SIZE=512;

public static Map<String,Object> initKey()throws Exception{

KeyPairGenerator keyPairGen=KeyPairGenerator.getInstance(KEY_ALGORITHM);

keyPairGen.initialize(KEY_SIZE);

KeyPair keypair=keyPairGen.generateKeyPair();

RSAPublicKey publickey=(RSAPublicKey)keypair.getPublic();

RSAPrivateKey privatekey=(RSAPrivateKey)keypair.getPrivate();

Map<String,Object> keymap=new HashMap<String,Object>(2);

keymap.put(PUB_KEY,publickey);

keymap.put(PRI_KEY,privatekey);

return keymap;

}

public static byte[] getPublicKeyEncoded(Map<String,Object> map)throws Exception{

Key key=(Key)map.get(PUB_KEY);

return key.getEncoded();

}

public static byte[] getPrivateKeyEncoded(Map<String,Object> map)throws Exception{

Key key=(Key)map.get(PRI_KEY);

return key.getEncoded();

}

public static PublicKey PubKey(byte[] k)throws Exception{

X509EncodedKeySpec x509KeySpec=new X509EncodedKeySpec(k);

KeyFactory keyfactory=KeyFactory.getInstance(KEY_ALGORITHM);

PublicKey publickey=keyfactory.generatePublic(x509KeySpec);

return publickey;

}

public static PrivateKey PriKey(byte[] k)throws Exception{

PKCS8EncodedKeySpec pkcs8KeySpec=new PKCS8EncodedKeySpec(k);

KeyFactory keyfactory=KeyFactory.getInstance(KEY_ALGORITHM);

PrivateKey privatekey=keyfactory.generatePrivate(pkcs8KeySpec);

return privatekey;

}

public static byte[] decryptByPublicKey(byte[] data,byte[] key)throws Exception{

Cipher cipher=Cipher.getInstance(KEY_ALGORITHM);

cipher.init(Cipher.DECRYPT_MODE,PubKey(key));

return cipher.doFinal(data);

}

public static byte[] decryptByPrivateKey(byte[] data,byte[] key)throws Exception{

Cipher cipher=Cipher.getInstance(KEY_ALGORITHM);

cipher.init(Cipher.DECRYPT_MODE,PriKey(key));

return cipher.doFinal(data);

}

public static byte[] encryptByPublicKey(byte[] data,byte[] key)throws Exception{

Cipher cipher=Cipher.getInstance(KEY_ALGORITHM);

                cipher.init(Cipher.ENCRYPT_MODE,PubKey(key));

                return cipher.doFinal(data);

}

public static byte[] encryptByPrivateKey(byte[] data,byte[] key)throws Exception{

                Cipher cipher=Cipher.getInstance(KEY_ALGORITHM);

                cipher.init(Cipher.ENCRYPT_MODE,PriKey(key));

                return cipher.doFinal(data);

        }

}