Java使用Cipher类,InputStream,OnputStream实现文件的加解密
题目要求:
说明:注释我觉得挺多的了,应该可以看懂。代码具体实现与题目有一点点出入,关系不大。重要的是根据中文API文档查找到相关类,相关方法的使用方法进行学习,运用后才能真正理解。
分享一下java的中文API文档
链接:https://pan.baidu.com/s/16UI6v2bnaYagFHxbRObISw
提取码:82xv
代码实现:
package fileOperation;
import java.awt.HeadlessException;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.security.Key;
import java.security.SecureRandom;
import java.util.Scanner;
import javax.crypto.Cipher;
import javax.crypto.CipherInputStream;
import javax.crypto.CipherOutputStream;
import javax.crypto.KeyGenerator;
import javax.swing.JFileChooser;
public class encryAndDecry {
Key key; //类成员
static String ALGORITHM = "";
public encryAndDecry(String str,String algorithm) {
getKey(str,algorithm);//生成密钥
}
public void getKey(String strKey,String ALGORITHM) { //获取密钥
try {
KeyGenerator _generator = KeyGenerator.getInstance(ALGORITHM); // 密钥生成器
_generator.init(new SecureRandom(strKey.getBytes())); //初始化生成器
this.key = _generator.generateKey(); //生成密钥
_generator = null; //将生成器置空
} catch (Exception e) { //异常抛出
throw new RuntimeException("Error initializing SqlMap class. Cause: " + e);
}
}
/*
* 文件file进行加密并保存目标文件destFile中
* @param file 要加密的文件
* @param destFile 加密后存放的文件名
*/
public void encrypt(String file, String destFile,String ALGORITHM) throws Exception {
long t1 = System.currentTimeMillis(); //加密前系统时间
Cipher cipher = Cipher.getInstance(ALGORITHM); //用ALGORITHM算法创建一个cipher对象
cipher.init(Cipher.ENCRYPT_MODE, this.key); //初始化cipher对象,Cipher.ENCRYPT_MODE代表加密
InputStream is = new FileInputStream(file); //文件输入流
OutputStream out = new FileOutputStream(destFile); //文件输出流
CipherInputStream cis = new CipherInputStream(is, cipher); //cipher输入流,即加密
//CipherInputStream由InputStream和Cipher组成,read()方法返回从底层InputStream读入但是由Cipher额外处理的数据
byte[] buffer = new byte[1024]; //缓冲区
int r;
while ((r = cis.read(buffer)) > 0) { //read返回已经读取多少个字节写进缓冲区,读取完返回-1
out.write(buffer, 0, r); //从缓冲区将数据写进加密文件
}
long t2 = System.currentTimeMillis(); //加密后系统时间
cis.close();
is.close();
out.close(); //文件关闭
System.out.println("加密用时:"+(t2-t1)+"ms");
}
/*
* @param file 已加密的文件
* @param destFile 解密后存放的文件名
*/
public void decrypt(String file, String destFile,String ALGORITHM) throws Exception {
if(!file.contains("enc"))
{
return;
}
long t1 = System.currentTimeMillis(); //解密前系统时间
Cipher cipher = Cipher.getInstance(ALGORITHM);
cipher.init(Cipher.DECRYPT_MODE, this.key); //Cipher.DECRYPT_MODE代表解密
InputStream is = new FileInputStream(file);
OutputStream out = new FileOutputStream(destFile);
CipherOutputStream cos = new CipherOutputStream(out, cipher); //cipher输出流,即解密
byte[] buffer = new byte[1024]; //缓冲区
int r;
while ((r = is.read(buffer)) >= 0) {
System.out.println();
cos.write(buffer, 0, r);
}
long t2 = System.currentTimeMillis(); //解密后系统时间
cos.close();
out.close();
is.close(); //文件关闭
System.out.println("解密用时:"+(t2-t1)+"ms");
}
//对文件夹进行操作
public void folderOperation(File file,String addpath,boolean choice,encryAndDecry ead) throws Exception {
addpath = addpath +"\\"; //如果找到文件,缺少\,如D:\test
if(file.isDirectory())//文件夹
{
File f[] = file.listFiles();
for(int i=0;i<f.length;i++)
{
if(f[i].isDirectory()) { //是文件夹的话,对路径进行递归处理
folderOperation(f[i],addpath+f[i].getName()+"\\",choice,ead);
}
else {
folderOperation(f[i], addpath+f[i].getName(),choice,ead);
}
}
}
else { //遍历到了文件
String s[] = addpath.split("\\.");
String restr = s[0].substring(0,s[0].length()-3); //去掉加密文件后的enc
if(choice)//加密
{
ead.encrypt(addpath, s[0]+"enc."+s[1],ALGORITHM);
}
else { //解密
ead.decrypt(addpath, restr+"dec."+s[1],ALGORITHM);
}
}
}
public File choiceFile() { //文件选择函数
JFileChooser fc = new JFileChooser(); //文件选择器
int flag = 0; File f = null;
fc.setFileSelectionMode(JFileChooser.FILES_AND_DIRECTORIES); //可以选择文件或文件夹
try{
flag = fc.showOpenDialog(null); //打开选择框
}
catch(HeadlessException head){ //异常处理
System.out.println("Open File Dialog ERROR!");
}
if(flag==JFileChooser.APPROVE_OPTION){
f=fc.getSelectedFile(); //获得文件或文件夹
}
return f;
}
public static void main(String[] args) throws Exception {
Scanner in = new Scanner(System.in); //标准输入扫描器对象
System.out.println("请选择加密算法? DES/AES/DESede");
ALGORITHM = in.nextLine();
System.out.println("请输入密钥进行加密:");
String secretKey = in.nextLine(); //从键盘输入字符串
encryAndDecry ead = new encryAndDecry(secretKey,ALGORITHM); //实例化对象
File f_en = null; String path_en = null; //条件初始化
File f_de = null; String path_de = null;
f_en = ead.choiceFile(); //获取选择文件
if(f_en==null)
{
System.out.println("文件获取失败!");
return;
}
path_en = f_en.getPath(); //获取文件路径
System.out.println(path_en);
if(f_en.isDirectory()) //如果是个文件夹
{
ead.folderOperation(f_en,path_en,true,ead); //true表示加密
}
else {
String s[] = path_en.split("\\."); //将文件切分,取名字与后缀名
ead.encrypt(path_en, s[0]+"enc."+s[1],ALGORITHM); //调用加密函数
}
System.out.println("请输入密钥进行解密:");
String verificationCode = in.nextLine(); //输入验证码
in.close(); //关闭输入
if(verificationCode.equals(secretKey)) //验证码与密钥相同
{
f_de = ead.choiceFile();
if(f_de==null)
{
System.out.println("文件获取失败!");
return;
}
path_de = f_de.getPath();
System.out.println(path_de);
if(!f_de.isDirectory()) //需要解密是文件
{
String str[] = path_de.split("\\.");
String tempstr = str[0].substring(0,str[0].length()-3); //去掉加密文件后的enc
ead.decrypt(path_de, tempstr+"dec."+str[1],ALGORITHM); //调用解密函数
System.out.println("解密成功");
}
else {
ead.folderOperation(f_de, path_de, false, ead); //false代表解密
}
}
else { //异常处理
System.out.println("密钥错误!");
return;
}
}
}
参考链接:https://blog.csdn.net/m0_37671741/article/details/96450535
https://blog.csdn.net/achuo/article/details/72190567