大文件加密(實(shí)現(xiàn)在文件流中進(jìn)行加密解密的方法)
對(duì)一般小的文件可以使用這樣的加密解密方法(des):
這里是把文件作為byte,全部緩存到
內(nèi)存中,如byte[] filebyte = getBytesFromFile(file_in);
在內(nèi)存中直接用加密類對(duì)其進(jìn)行加密,如CryptoUtils.decrypt(filebyte, newkey);
可是會(huì)產(chǎn)生一個(gè)
問(wèn)題,如果要加密的文件很大,比如要加密的文件 1G,而內(nèi)存只有512M,這樣就會(huì)使byte很大,導(dǎo)致緩沖區(qū)溢出,現(xiàn)在尋求如果對(duì)大文件進(jìn)行加密的方法。

/**//*
* 加密文件
* file1加密后產(chǎn)生file2密文
* */

public static boolean enCryptoFile(String file1 ,String file2, String key)

{
//key轉(zhuǎn)為成為bytes
byte[] newkey = new byte[8];
newkey = key.getBytes();
//輸入文件轉(zhuǎn)換成為bytes
File file_in = new File(file1);
byte[] filebyte = getBytesFromFile(file_in);
//定義輸出文件
File file_out = new File(file2);
FileOutputStream out = null;

try
{
out = new FileOutputStream(file_out);
filebyte = CryptoUtils.encrypt(filebyte, newkey);
out.write(filebyte,0,filebyte.length);
out.close();
return true;

} catch (Exception e1)
{
// TODO Auto-generated catch block
e1.printStackTrace();
System.out.println("File enCrypto Error!");
}
return false;
}

/**//*
* 解密文件
* file1密文解密成file2明文
* key只能是8個(gè)byte
* */

public static boolean deCryptoFile(String file1 ,String file2, String key)

{
//key轉(zhuǎn)為成為bytes
byte[] newkey = new byte[8];
newkey = key.getBytes();
//輸入文件轉(zhuǎn)換成為bytes
File file_in = new File(file1);
byte[] filebyte = getBytesFromFile(file_in);
//定義輸出文件
File file_out = new File(file2);
FileOutputStream out = null;

try
{
out = new FileOutputStream(file_out);
filebyte = CryptoUtils.decrypt(filebyte, newkey);
out.write(filebyte,0,filebyte.length);
out.close();
return true;
}catch(Exception e)

{
e.printStackTrace();
System.out.println("File deCrypto Error!");
return false;
}
}

解決方法:
經(jīng)過(guò)研究發(fā)現(xiàn)1024個(gè)明文經(jīng)過(guò)加密后變成1032個(gè)密文,
這樣在進(jìn)行流解密的時(shí)候,就需要讀1032個(gè)密文,解密成為1024個(gè)明文。

/**//*
* 加密文件
* file1加密后產(chǎn)生file2密文
* */
public static boolean enoldCrByteFile(String file1 ,String file2, String key)

{
//key轉(zhuǎn)為成為bytes
byte[] newkey = new byte[8];
newkey = key.getBytes();

try
{
File file_in = new File(file1);
File file_out = new File(file2);
FileInputStream in = new FileInputStream(file_in);
FileOutputStream out =new FileOutputStream(file_out);
byte[] bytes = new byte[1024];
//String end = "<!~!>";
//System.out.print(end);
//byte [] bend = end.getBytes();
while((in.read(bytes))!=-1)

{
byte[] bout = CryptoUtils.encrypt(bytes, newkey);
System.out.println(bytes.length);
System.out.println(bout.length);
out.write(bout,0,1032);
//out.write(bend,0,bend.length);
}
in.close();
out.close();
return true;
}catch(Exception e)

{
e.printStackTrace();
System.out.println("File enCrypto Error!");
return false;
}
}


/**//*
* 解密文件
* file1密文解密成file2明文
* key只能是8個(gè)byte
* */
public static boolean deoldCrByteFile(String file1 ,String file2, String key)

{
//key轉(zhuǎn)為成為bytes
byte[] newkey = new byte[8];
newkey = key.getBytes();

try
{
File file_in = new File(file1);
File file_out = new File(file2);
FileInputStream in = new FileInputStream(file_in);
FileOutputStream out =new FileOutputStream(file_out);
byte[] bytes = new byte[1032];
//String end = "<!~!>";
//System.out.print(end);
//byte [] bend = end.getBytes();
while((in.read(bytes))!=-1)

{
byte[] bout = CryptoUtils.decrypt(bytes, newkey);
out.write(bout,0,bout.length);
//out.write(bend,0,bend.length);
}
in.close();
out.close();
return true;
}catch(Exception e)

{
e.printStackTrace();
System.out.println("File deCrypto Error!");
return false;
}
}

重構(gòu)成這樣,減少大對(duì)象創(chuàng)建。
此方法是對(duì)文件流進(jìn)行了byte切割,對(duì)流中的byte進(jìn)行加密。加密后的byte保存到文件中。在解密的時(shí)候同樣進(jìn)行分割文件byte流(這里的分割要與加密產(chǎn)生密文byte長(zhǎng)度相同),這樣就可以實(shí)現(xiàn)占用內(nèi)存少且快速高效的加密方法了。

/**//*
* 加密文件
* file1加密后產(chǎn)生file2密文
* */
public static boolean enCrByteFile(String file1 ,String file2, String key)

{
Date date = new Date(); //程序開(kāi)始 時(shí)間
String dateStr1 = new Timestamp(date.getTime()).toString();
System.out.println("加密開(kāi)始time=" + dateStr1);

//key轉(zhuǎn)為成為bytes
byte[] newkey = new byte[8];
newkey = key.getBytes();
// 初始化一個(gè)用于des初始化的iv常量, 象形加密編碼的要求

IvParameterSpec iv = new IvParameterSpec(new byte[]
{ 0x12, 0x34, 0x56,
0x78, (byte) 0x90, (byte) 0xAB, (byte) 0xCD,
(byte) 0xEF });
DESKeySpec dks = null;

try
{
dks = new DESKeySpec(newkey);

} catch (InvalidKeyException e1)
{
// TODO Auto-generated catch block
e1.printStackTrace();
}

SecretKeyFactory keyFactory = null;

try
{
keyFactory = SecretKeyFactory.getInstance(CIPHER_DES);

} catch (NoSuchAlgorithmException e1)
{
// TODO Auto-generated catch block
e1.printStackTrace();
}
SecretKey secureKey = null;

try
{
secureKey = keyFactory.generateSecret(dks);

} catch (InvalidKeySpecException e1)
{
// TODO Auto-generated catch block
e1.printStackTrace();
}

Cipher cipher = null;

try
{
cipher = Cipher.getInstance(CIPHER_DES_CBC);

} catch (NoSuchAlgorithmException e1)
{
// TODO Auto-generated catch block
e1.printStackTrace();

} catch (NoSuchPaddingException e1)
{
// TODO Auto-generated catch block
e1.printStackTrace();
}


try
{
cipher.init(Cipher.ENCRYPT_MODE, secureKey, iv);

} catch (InvalidKeyException e1)
{
// TODO Auto-generated catch block
e1.printStackTrace();

} catch (InvalidAlgorithmParameterException e1)
{
// TODO Auto-generated catch block
e1.printStackTrace();
}

//return cipher.doFinal(src);


try
{
File file_in = new File(file1);
File file_out = new File(file2);
FileInputStream in = new FileInputStream(file_in);
FileOutputStream out =new FileOutputStream(file_out);
byte[] bytes = new byte[1024];
//String end = "<!~!>";
//System.out.print(end);
//byte [] bend = end.getBytes();
while((in.read(bytes))!=-1)

{
//byte[] bout = CryptoUtils.encrypt(bytes, newkey);
byte[] bout = cipher.doFinal(bytes);//
//System.out.println(bytes.length);
//System.out.println(bout.length);
out.write(bout,0,1032);
//out.write(bend,0,bend.length);
}
in.close();
out.close();
return true;
}catch(Exception e)

{
e.printStackTrace();
System.out.println("File enCrypto Error!");
return false;
}
}


/**//*
* 解密文件
* file1密文解密成file2明文
* key只能是8個(gè)byte
* */
public static boolean deCrByteFile(String file1 ,String file2, String key)

{
//key轉(zhuǎn)為成為bytes
byte[] newkey = new byte[8];
newkey = key.getBytes();
// 初始化一個(gè)用于des初始化的iv常量, 象形加密編碼的要求

IvParameterSpec iv = new IvParameterSpec(new byte[]
{ 0x12, 0x34, 0x56,
0x78, (byte) 0x90, (byte) 0xAB, (byte) 0xCD,
(byte) 0xEF });
DESKeySpec dks = null;

try
{
dks = new DESKeySpec(newkey);

} catch (InvalidKeyException e1)
{
// TODO Auto-generated catch block
e1.printStackTrace();
}

SecretKeyFactory keyFactory = null;

try
{
keyFactory = SecretKeyFactory.getInstance(CIPHER_DES);

} catch (NoSuchAlgorithmException e1)
{
// TODO Auto-generated catch block
e1.printStackTrace();
}
SecretKey secureKey = null;

try
{
secureKey = keyFactory.generateSecret(dks);

} catch (InvalidKeySpecException e1)
{
// TODO Auto-generated catch block
e1.printStackTrace();
}

Cipher cipher = null;

try
{
cipher = Cipher.getInstance(CIPHER_DES_CBC);

} catch (NoSuchAlgorithmException e1)
{
// TODO Auto-generated catch block
e1.printStackTrace();

} catch (NoSuchPaddingException e1)
{
// TODO Auto-generated catch block
e1.printStackTrace();
}

try
{
cipher.init(Cipher.ENCRYPT_MODE, secureKey, iv);

} catch (InvalidKeyException e1)
{
// TODO Auto-generated catch block
e1.printStackTrace();

} catch (InvalidAlgorithmParameterException e1)
{
// TODO Auto-generated catch block
e1.printStackTrace();
}

try
{
File file_in = new File(file1);
File file_out = new File(file2);
FileInputStream in = new FileInputStream(file_in);
FileOutputStream out =new FileOutputStream(file_out);
byte[] bytes = new byte[1032];
//String end = "<!~!>";
//System.out.print(end);
//byte [] bend = end.getBytes();
while((in.read(bytes))!=-1)

{
byte[] bout = CryptoUtils.decrypt(bytes, newkey);
out.write(bout,0,bout.length);
//out.write(bend,0,bend.length);
}
in.close();
out.close();
return true;
}catch(Exception e)

{
e.printStackTrace();
System.out.println("File deCrypto Error!");
return false;
}
}

環(huán)境pc、p3.0G、1G內(nèi)存
測(cè)試加密效率,對(duì)一個(gè)434M的文件進(jìn)行加密,用時(shí)2分06秒,內(nèi)存占用不超過(guò)20M(實(shí)際上就18M多一點(diǎn)),cpu占用率約為60%,感覺(jué)在加密過(guò)程中機(jī)器反應(yīng)遲鈍。
感覺(jué)這個(gè)效率還不錯(cuò),并沒(méi)有比全部緩存到內(nèi)存中慢,但是占用內(nèi)存卻很少。推薦以后使用此方法。
加密開(kāi)始time={SysUpTime = 141204 days 10:4:21} {Timestamp = Fri Aug 29 18:36:26 CST 2008}
加密結(jié)束time={SysUpTime = 141204 days 10:25:28} {Timestamp = Fri Aug 29 18:38:32 CST 2008}
這個(gè)效率還不錯(cuò),不過(guò)還有可以提高效率的地方,比如把1024換成des加密的使用的8位倍數(shù)的,減少一些最后補(bǔ)齊的加密;把des算法換成RC4等
posted on 2008-08-30 15:22
歲月如歌 閱讀(10300)
評(píng)論(2) 編輯 收藏