jdk 自带文件加解密

jdk 自带文件加解密(包含xlsx上传fastdfs后文件损坏处理方案)

为了文件在服务器中的存放安全,需要对文件进行加密,(此处不讨论系统安全、应用安全问题),原理很简单,就不赘述。简单实现方案如:github fileCode

package com.***.util;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.security.InvalidKeyException;
import java.security.Key;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;

import javax.crypto.Cipher;
import javax.crypto.CipherInputStream;
import javax.crypto.CipherOutputStream;
import javax.crypto.KeyGenerator;
import javax.crypto.NoSuchPaddingException;

/**
 * 文件加/解密
 * 
 * @see https://my.oschina.net/iyinghui/blog/1805949
 * @author wang.xinyu
 */
public class FileSercet {
	private static String key = "$5wI6=";
	public static final String postfix = ".crypt";

	/**
	 * 根据参数生成KEY
	 */
	public static Key getKey() {
		try {
			KeyGenerator _generator = KeyGenerator.getInstance("DES");
			// _generator.init(new SecureRandom(strKey.getBytes()));这种方式,在windows可以,可是在linux每次生成的key不一样
			SecureRandom secureRandom = SecureRandom.getInstance("SHA1PRNG");
			secureRandom.setSeed(key.getBytes());
			_generator.init(secureRandom);
			Key key = _generator.generateKey();
			_generator = null;
			// System.out.println(key);
			return key;
		} catch (Exception e) {
			throw new RuntimeException("Error initializing SqlMap class. Cause: " + e);
		}
	}

	/**
	 * 流数据加密
	 * 
	 * @author wang.xinyu
	 * @param is
	 * @return CipherInputStream
	 * @throws Exception
	 */
	public static InputStream EncFile(InputStream is) throws Exception {
		Cipher cipher = Cipher.getInstance("DES");
		cipher.init(Cipher.ENCRYPT_MODE, getKey());
		return new CipherInputStream(is, cipher);
	}

	/**
	 * 流数据解密
	 * 
	 * @param is
	 * @return CipherInputStream
	 * @throws NoSuchPaddingException
	 * @throws NoSuchAlgorithmException
	 * @throws InvalidKeyException
	 * @throws IOException
	 * @throws Exception
	 */
	public static void DecFile(InputStream is, OutputStream out) throws Exception {
		Cipher cipher = Cipher.getInstance("DES");
		cipher.init(Cipher.DECRYPT_MODE, getKey());
		try (CipherOutputStream cos = new CipherOutputStream(out, cipher);) {
			byte[] buffer = new byte[1024];
			int r;
			while ((r = is.read(buffer)) >= 0) {
				cos.write(buffer, 0, r);
			}
			cos.flush();
		}
	}

	/**
	 * 加密
	 * 
	 * @param srcFile
	 *            要加密的文件
	 * @param encFile
	 *            加密后的文件
	 * @param key
	 *            密钥
	 * @throws Exception
	 *             异常
	 */
	public static void EncFile(File srcFile, File encFile) throws Exception {
		// 检查是否存在
		if (!srcFile.exists()) {
			System.out.println("source file not exixt");
			return;
		}
		if (!encFile.exists()) {
			System.out.println("encrypt file created");
			encFile.createNewFile();
		}

		Cipher cipher = Cipher.getInstance("DES");
		// cipher.init(Cipher.ENCRYPT_MODE, getKey());
		cipher.init(Cipher.ENCRYPT_MODE, getKey());
		InputStream is = new FileInputStream(srcFile);
		OutputStream out = new FileOutputStream(encFile);
		CipherInputStream cis = new CipherInputStream(is, cipher);
		byte[] buffer = new byte[1024];
		int r;
		while ((r = cis.read(buffer)) > 0) {
			out.write(buffer, 0, r);
		}
		cis.close();
		is.close();
		out.close();

	}

	/**
	 * 解密
	 * 
	 * @param encFile
	 *            加密了的文件
	 * @param decFile
	 *            要解密生成的文件
	 * @param key
	 *            密钥
	 * @throws Exception
	 *             异常
	 */
	public static void DecFile(File encFile, File decFile) throws Exception {
		if (!encFile.exists()) {
			System.out.println("encrypt file not exixt");
			return;
		}

		if (!decFile.exists()) {
			System.out.println("decrypt file created");
			decFile.createNewFile();
		}

		Cipher cipher = Cipher.getInstance("DES");
		cipher.init(Cipher.DECRYPT_MODE, getKey());
		InputStream is = new FileInputStream(encFile);
		OutputStream out = new FileOutputStream(decFile);
		CipherOutputStream cos = new CipherOutputStream(out, cipher);
		byte[] buffer = new byte[1024];
		int r;
		while ((r = is.read(buffer)) >= 0) {
			cos.write(buffer, 0, r);
		}
		cos.close();
		out.close();
		is.close();
	}

	/**
	 * 测试类
	 * 
	 * @param args
	 *            参数
	 */
	public static void main(String[] args) {
		File srcFile = new File("E:\\fas\\FileCode.java"); // 初始文件
		File encFile = new File("E:\\fas\\FileCode_enc" + postfix); // 加密文件
		File decFile = new File("E:\\fas\\FileCode_dec.java"); // 解密文件

		try {
			// EncFile(srcFile, encFile); // 加密操作
			// DecFile(encFile, decFile);

			// =====================
			if (!encFile.exists()) {
				System.out.println("encrypt file created");
				encFile.createNewFile();
			}
			InputStream is = new FileInputStream(srcFile);
			InputStream ercIn = EncFile(is);
			OutputStream out = new FileOutputStream(encFile);
			byte[] buffer = new byte[1024];
			int r;
			while ((r = ercIn.read(buffer)) > 0) {
				out.write(buffer, 0, r);
			}
			is.close();
			out.close();

			// =====================
			if (!decFile.exists()) {
				System.out.println("decrypt file created");
				decFile.createNewFile();
			}
			InputStream encFileInput = new FileInputStream(encFile);
			FileOutputStream decFileInput = new FileOutputStream(decFile);
			DecFile(encFileInput, decFileInput);

		} catch (Exception e) {
			e.printStackTrace();
		}
	}
}

xlsx文件上传fastdfs再下载打开会提示文件已损坏,而其它文件不会出现这个情况。尝试过多种方案都无法解决,无奈之下只能改变文件类型来避过。
有知道原因的请留言,谢谢!

<dependency>
	<groupId>cn.hutool</groupId>
	<artifactId>hutool-all</artifactId>
	<version>5.5.8</version>
</dependency>
<dependency>
	<groupId>com.github.tobato</groupId>
	<artifactId>fastdfs-client</artifactId>
	<version>1.26.5</version>
</dependency>
/**
 * 上传附件
 * 
 * @param inputStream
 * @param fileSize
 * @param fileExtName
 * @param metaDataSet
 * @return
 * @throws Exception
 */
public StorePath upload(InputStream inputStream, String fileExtName, Set<MetaData> metaDataSet)
		throws Exception {
	if (StringUtils.isBlank(fileExtName)
			|| !Arrays.asList(accessoryAllowFileType.split(",")).contains(fileExtName)) {
		// 非法文件
		throw new ServiceException("非法文件");
	}

	InputStream encInput = null;
	try (InputStream _temp = FileSercet.EncFile(inputStream);) {
		byte[] bytes = null;
		/* xlsx 加密后上传到fastdfs,再下载xlsx文件提示文件已损坏 */
		if ("xlsx".equals(fileExtName.toLowerCase())) {
			// 文件加密后压缩zip包
			bytes = ZipUtil.gzip(_temp); // 压缩
			logger.debug("文件加密并压缩");
		} else {
			bytes = IOUtils.toByteArray(_temp);
		}

		// 文件上传到文件服务器
		encInput = new ByteArrayInputStream(bytes);
		return storageClient.uploadFile(encInput, bytes.length, "crypt", metaDataSet);
	} finally {
		if (inputStream != null) {
			inputStream.close();
		}
		if (encInput != null) {
			encInput.close();
		}
	}
}


/**
 * 下载附件
 * 
 * @param amsAccessory
 * @param outputStream
 * @throws Exception
 */
public void downLoad(AmsAccessory amsAccessory, OutputStream outputStream) throws Exception {
	StorePath storePath = StorePath.parseFromUrl(amsAccessory.getUploadFilePath());
	InputStream input = null;
	try (InputStream encInput = new ByteArrayInputStream(
			storageClient.downloadFile(storePath.getGroup(), storePath.getPath(), new DownloadByteArray()));) {
		// xlsx需要解压原因请看上传方法说明
		if ("xlsx".equals(amsAccessory.getFileType().toLowerCase())) {
			byte[] _byte = ZipUtil.unGzip(encInput); // 解压
			input = new ByteArrayInputStream(_byte);
		} else {
			input = encInput;
		}
		FileSercet.DecFile(input, outputStream); // 文件解密

		byte[] readLine = new byte[2048];
		while (input.read(readLine) != -1) {
			outputStream.write(readLine);
		}
		outputStream.flush();
	} catch (Exception e) {
		throw e;
	} finally {
		if (input != null) {
			input.close();
		}
	}

}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值