package com.test;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
public class AES extends AESMap {
/**
* 这是一个AES加密算法.
* @param filePath 你相加密的文件夹路径.
* @param savePath 保存加密后的文件路径
* @param strKey 用户密码.
* @param Nb 加密时明文的分组长度(32bits)
* @param Nk the 密码长度.
* @return 加密后数据
*/
public long encryptFile(String filePath, String savePath, String strKey,
int Nb, int Nk) {
FileInputStream fis = null;
FileOutputStream fos = null;
int leave = 0;
int length = 0;
long copy_rounds = 0;
try {
/*以二进制读的方式打开要加密的文件*/
fis = new FileInputStream(filePath);
/*以二进制写的方式打开保存密文的文件*/
fos = new FileOutputStream(savePath, true);
/*得到要加密的文件的长度*/
length = fis.available();
if (length == 0)
return 0;
/*求剩余的字块的字节数*/
leave = length % (4 * Nb);
/*得到整块的加密轮数*/
long rounds = length / (4 * Nb);
if (leave != 0)
rounds++;
copy_rounds = rounds;
/*作为加密时存放要加密的明文块*/
byte[] state = new byte[4 * 8];
/*用来进行短块处理时的缓存区*/
byte[] copy = new byte[4 * 8];
/*得到加密的轮数*/
int Nr = GetRounds(Nb, Nk);
/*生成各轮子密钥*/
KeyExpansion(strKey, Nb, Nk, Nr);
if (copy_rounds == 1 && rounds == 1) {
if (leave == 0)
fis.read(state, 0, 4 * Nb);//明文的长度恰好等于分组长度;
else {
fis.read(state, 0, leave);//明文的长度小于八个字符;
for (int i = leave; i < 4 * Nb; i++)
state[i] = 0; //后面用空格补齐;
}
state = Transform(ByteToChar(state), Nb, Nr); //加密变换;
fos.write(state, 0, 4 * Nb);//将加密后的密文块写入目标文件;
rounds--;
} else if (copy_rounds > 1 && leave != 0)//如果明文的长度大于分组长度且字符数不是分组长度的整数倍
{ //时,需要进行短块处理;
fis.read(state, 0, 4 * Nb);
state = Transform(ByteToChar(state), Nb, Nr);//先加密最前面的一块;
fos.write(state, 0, leave);//仅将余数个字符存入文件,而将后部分密文
//与后面的明文合在一起加密;
int j = 0;
for (int i = leave; i < 4 * Nb; i++)
copy[j++] = state[i];
fis.read(copy, j, leave);
copy = Transform(ByteToChar(copy), Nb, Nr);
fos.write(copy, 0, 4 * Nb);
rounds -= 2;
}
while (rounds > 0)//以下处理的明文是分组的整数倍的情况;
{
fis.read(state, 0, 4 * Nb);
state = Transform(ByteToChar(state), Nb, Nr);
fos.write(state, 0, 4 * Nb);
rounds--;
}
} catch (FileNotFoundException e) {
e.printStackTrace();
System.out.println("文件夹没有找到!");
} catch (IOException e) {
e.printStackTrace();
System.out.println("读写文件时,发生异常!");
} finally {
try {
if (fis != null) {
fis.close(); //关闭源文件
fis = null;
}
if (fos != null) {
fos.close();
fos = null; //关闭目标文件
}
} catch (IOException e) {
e.printStackTrace();
System.out.println("文件关闭出现异常!");
}
}
return ((copy_rounds - 1) * 4 * Nb + leave);//返回文件长度;
}
/**
* 这个方法是用来解密密文的.
* @param OpenPath 密文路径.
* @param SavePath 解密后文件的保存路径.
* @param m_Key 解密文件的密钥.
* @param Nb 解密时密文的分组长度(32bits)
* @param Nk 密钥长度.
* @return 解密后的数据
*/
public long dencryptFile(String OpenPath, String SavePath, String m_Key,
int Nb, int Nk) {
//以二进制读的方式打开要加密的文件;
//以二进制写的方式打开保存密文的文件;
FileInputStream fis = null;
FileOutputStream fos = null;
int Length = 0;
long copy_rounds = 0;
int leave = 0;
try {
fis = new FileInputStream(OpenPath);
fos = new FileOutputStream(SavePath, true);
Length = fis.available();
//得到要加密的文件的长度;
if (Length == 0)
return 0;
leave = Length % (4 * Nb);//求剩余的字块的字节数;
long rounds = Length / (4 * Nb);//得到整块的加密轮数;
if (leave != 0)
rounds++;
copy_rounds = rounds;
byte[] state = new byte[4 * 8]; //解密时存放密文块;
int Nr = GetRounds(Nb, Nk); //得到解密时循环轮数;
KeyExpansion(m_Key, Nb, Nk, Nr); //生成各轮子密钥
byte[] copy = new byte[32];
if (leave != 0)//需要进行短块处理
{
fis.read(copy, 0, leave);//先把余数个密文字符保存;
fis.read(state, 0, 4 * Nb);//读取紧接着的一个密文块;
state = ReTransform(ByteToChar(state), Nb, Nr); //解密;
int j = 0;
for (int i = leave; i < 4 * Nb; i++)
//把解密后的明文和前面的余数个合在一起组成一块,
copy[i] = state[j++]; //一起解密;
copy = ReTransform(ByteToChar(copy), Nb, Nr);
//将解密后的明文写入目标文件;
fos.write(copy, 0, 4 * Nb);
fos.write(state, j, leave);//将余数个明文写入目标文件;
rounds -= 2; //已经完成了两轮解密所以减二;
}
while (rounds > 0)//对后面是分组长度的整数倍的密文块解密;
{
fis.read(state, 0, 4 * Nb);//读取密文块;
copy = ReTransform(ByteToChar(state), Nb, Nr); //解密变换;
fos.write(copy, 0, 4 * Nb);//将解密后的明文写入目标文件;
rounds--; //轮数减一;
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if (fis != null) {
fis.close(); //关闭源文件
fis = null;
}
if (fos != null) {
fos.close();
fos = null; //关闭目标文件
}
} catch (IOException e) {
e.printStackTrace();
System.out.println("文件关闭出现异常!");
}
}
return ((copy_rounds - 1) * 4 * Nb + leave);//返回文件长度
}
/**
* This method is used to shift the data in array A.
* @param A
//////////////////////////////////////////////////// //
功能:将数组A中的四个字节循环左移一个字节;
//////////////////////////////////////////////////// //
*/
public void RotByte(char[] A) {
char temp;
temp = A[0];
A[0] = A[1];
A[1] = A[2];
A[2] = A[3];
A[3] = temp;
}
/**
* 密钥扩展的时候进行S盒替换
* @param A是存放四个字节的数组
*/
public void SubByte(char[] A) {
for (int i = 0; i < 4; i++)
A[i] = S_BOX[A[i]];
}
/**
* 这个方法是用来得到加密轮数
* @param Nb以32bit为单位的待加密明文的长度
* @param Nk是初始密钥的长度
* @return 返回加密轮数(Nr)
*/
public int GetRounds(int Nb, int Nk) {
switch (Nb) {
case 4:
switch (Nk) {
case 4:
return 10;
case 6:
return 12;
case 8:
return 14;
default:
return 0;
}
case 6:
switch (Nk) {
case 4:
case 6:
return 12;
case 8:
return 14;
default:
return 0;
}
case 8:
switch (Nk) {
case 4:
case 6:
case 8:
return 14;
default:
return 0;
}
default:
return 0;
}
}
/**
* 这个方法是用来进行密钥扩展的
* @param strKey 用户输入的密钥
* @param Nb 以32bit为单位的待加密明文的长度
* @param Nk 以32bit为单位的初始密钥的长度.
* @param Nr 加密的轮加密的轮.
* @return 扩展后的子密钥存放在数组w中
*/
public void KeyExpansion(String strKey, int Nb, int Nk, int Nr) {
int i = 0;
for (; i < 4; i++)
for (int j = 0; j < Nk; j++)
key[i * Nk + j] = strKey.charAt(i * 4 + j);
i = 0;
while (i < Nk) {
w[i * 4] = key[i * 4];
w[i * 4 + 1] = key[i * 4 + 1];
w[i * 4 + 2] = key[i * 4 + 2];
w[i * 4 + 3] = key[i * 4 + 3];
i++;
}
i = Nk;
while (i < Nb * (Nr + 1)) {
char[] temp = new char[4];
temp[0] = w[(i - 1) * 4 + 0];
temp[1] = w[(i - 1) * 4 + 1];
temp[2] = w[(i - 1) * 4 + 2];
temp[3] = w[(i - 1) * 4 + 3];
if ((i % Nk) == 0) {
RotByte(temp);
SubByte(temp);
for (int j = 0; j < 4; j++)
temp[j] ^= Rcon[((i - 1) / Nk) * 4 + j];//与Rcon异或;
} else if (Nk == 8 && i % Nk == 4)
SubByte(temp);
w[i * 4 + 0] = (char)
java 基于AES实现对文件的加密 解密
5星 · 超过95%的资源 需积分: 47 120 浏览量
2010-02-02
15:41:05
上传
评论 8
收藏 6KB RAR 举报
willvc123
- 粉丝: 36
- 资源: 170
最新资源
- 功率拓扑快速参考指南-ti,TI官方出品
- 开关电源拓朴图表,各种电路拓扑表格
- 登录和注册 前端:vue3+iview plus +axios 后台:spring boot +mybatis
- 软件测试入门简介:从基础到实践的全面介绍
- 2024CDA Level Ⅰ 认证考试大纲
- YOLO 数据集:淋巴病灶检测(1类别,包含训练集、验证集)
- 基于AT91RM9200处理器+XC3S250E(FPGA)+AD5322采集板Cadence ORCAD(硬件原理图+PCB)
- java+vue2实现zebra打印机,js实现
- J-link烧录软件,用于hex文件烧录
- VB打开时间同步页面/Internet时间设置.vbs
资源上传下载、课程学习等过程中有任何疑问或建议,欢迎提出宝贵意见哦~我们会及时处理!
点击此处反馈
- 1
- 2
前往页