加密机网联对账文件解密问题-加密机不支持网联对账大文件SM4解密-使用SM4软加解密方法解密网联对账文件

3 篇文章 0 订阅
2 篇文章 0 订阅

加密机网联对账文件解密问题-加密机不支持网联对账大文件SM4解密-使用SM4软加解密方法解密网联对账文件

在处理解密网联的对账文件过程中发现由于我们的加密机中未实现SM4大文件加解密方法,其中最大支持长度为< 4K = 4095 - 16(密钥长度) = 4079。所有对于网联大文件加解密我使用了bc.2.57版本实现了大文件的软加密和解密

  • 直接上代码如下:
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.security.Security;
import javax.crypto.Cipher;
import javax.crypto.spec.SecretKeySpec;
import org.bouncycastle.jce.provider.BouncyCastleProvider;

/**
 * SM2加4解密工具类
 */
public class SM4Helper {

	/**
	 * 网联对应的SM4算法
	 */
	public static final String ALGORITHM_NAME = "SM4/ECB/PKCS5Padding";

	/**
	 * 加密文件缓冲区长度
	 */
	private static final int ENCRYPT_FILE_BUFF_LENGTH = 512;

	/** BC provider */
	public static final BouncyCastleProvider BCProvider = new BouncyCastleProvider();

	static {
		Security.addProvider(BCProvider);
	}

	/**
	 * 加密文件 【支持大文件加解密】
	 * 
	 * @param srcFile 源明文文件
	 * @param outFile 输出的密文文件
	 * @param key     密钥
	 * @throws Exception
	 */
	public static void encryptFile(String srcFile, String outFile, String key) throws Exception {
		Cipher cipher = Cipher.getInstance(ALGORITHM_NAME, BCProvider);
		cipher.init(Cipher.ENCRYPT_MODE, new SecretKeySpec(key.getBytes("ISO8859-1"), ALGORITHM_NAME));
		byte[] buffData = new byte[ENCRYPT_FILE_BUFF_LENGTH];
		int count = 0;
		FileInputStream reader = new FileInputStream(srcFile);
		FileOutputStream writer = new FileOutputStream(outFile);
		try {
			while ((count = reader.read(buffData, 0, buffData.length)) > 0) {
				byte[] cipherData;
				if (count == ENCRYPT_FILE_BUFF_LENGTH) {
					cipherData = cipher.update(buffData);  //读取缓冲数据持续计算
				} else {
					byte[] plainData = new byte[count];
					System.arraycopy(buffData, 0, plainData, 0, plainData.length);
					cipherData = cipher.doFinal(plainData);
				}
				writer.write(cipherData, 0, cipherData.length);
				writer.flush();
			}
		}
		catch (Exception err) {
			throw err;
		}
		finally{
			writer.close();
			reader.close();
		}
		
	}

	/**
	 * 解密文件 【支持大文件加解密】
	 * 
	 * @param srcFile 源密文文件
	 * @param outFile 输出原文文件
	 * @param key     密钥 长度16个字符
	 * @return
	 * @throws Exception
	 */
	public static void decryptFile(String srcFile, String outFile, String key) throws Exception {

		Cipher cipher = Cipher.getInstance(ALGORITHM_NAME, BCProvider);
		cipher.init(Cipher.DECRYPT_MODE, new SecretKeySpec(key.getBytes("ISO8859-1"), ALGORITHM_NAME));
		// 缓存长度
		int buffLength = ENCRYPT_FILE_BUFF_LENGTH ;
		byte[] buffData = new byte[buffLength];
		int count = 0;
		FileInputStream reader = new FileInputStream(srcFile);
		FileOutputStream writer = new FileOutputStream(outFile);
		try {
			while ((count = reader.read(buffData, 0, buffData.length)) > 0) {
				byte[] plainData;
				if (count == buffLength) {
					plainData = cipher.update(buffData);  //读取缓冲数据持续计算
				} else {
					byte[] cipherData = new byte[count];
					System.arraycopy(buffData, 0, cipherData, 0, cipherData.length);
					plainData = cipher.doFinal(cipherData);
				}
				writer.write(plainData, 0, plainData.length);
				writer.flush();
			}
		}
		catch (Exception err) {
			throw err;
		}
		finally{
			writer.close();
			reader.close();
		}
	}

}
  • 结语
    大文件计算的关键点在于解决大文件加载的性能,所以采用读取流的形式加载到缓冲区,
    再使用 cipher.update(buffData); //读取缓冲数据持续计算
    最后再使用 cipher.doFinal(cipherData); 完成计算
    writer.flush(); 控制写入文件的频率,可以根据缓冲区大小来设置writer.flush();的调用,可根据自身实际情况来。
  • 9
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

北海山人

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值