文件加密算法比较:SHA1、SHA256、MD5
MD5算法:
MD5是一个安全散列算法,输入两个不同的明文不会得到相同的输出值,根据输出值,不能得到原始的明文,即其过程是不可逆的;所以要破解MD5没有现成的算法,只能穷举法,把可能出现的明文,用MD5算法散列之后,把得到的散列值和原始的数据形成一个一对一的映射表,通过匹配从映射表中找出破解密码所对应的原始明文。
SHA1算法:
SHA-1是一种数据加密算法,该算法的思想是接收一段明文,然后以一种不可逆的方式将它转换成一段(通常更小)密文,也可以简单的理解为取一串输入码(称为预映射或信息),并把它们转化为长度较短、位数固定的输出序列即散列值(也称为信息摘要或信息认证代码)的过程。
单向散列函数的安全性在于其产生散列值的操作过程具有较强的单向性。如果在输入序列中嵌入密码,那么任何人在不知道密码的情况下都不能产生正确的散列值,从而保证了其安全性。SHA将输入流按照每块512位(64个字节)进行分块,并产生20个字节的被称为信息认证代码或信息摘要的输出。
该算法输入报文的长度不限,产生的输出是一个160位的报文摘要。输入是按512 位的分组进行处理的。SHA-1是不可逆的、防冲突,并具有良好的雪崩效应。
通过散列算法可实现数字签名实现,数字签名的原理是将要传送的明文通过一种函数运算(Hash)转换成报文摘要(不同的明文对应不同的报文摘要),报文摘要加密后与明文一起传送给接受方,接受方将接受的明文产生新的报文摘要与发送方的发来报文摘要解密比较,比较结果一致表示明文未被改动,如果不一致表示明文已被篡改。
算法测试内容:
- 三种加密算法的运行效率
- 更改文件内容文件的hash值是否改变
- 更改文件名称文件的hash值是否该表
算法实现:
import java.io.File;
import java.io.FileInputStream;
import java.math.BigInteger;
import java.security.MessageDigest;
import java.util.HashMap;
import java.util.Map;
class FileSafeCodeDemo {
/**
* @param file
* @param algorithm 所请求算法的名称 for example: MD5, SHA1, SHA-256, SHA-384, SHA-512 etc.
* @return
*/
public static String getFileMD5(File file,String algorithm) {
if (!file.isFile()) {
return null;
}
MessageDigest digest = null;
FileInputStream in = null;
byte buffer[] = new byte[1024];
int len;
try {
digest = MessageDigest.getInstance(algorithm);
in = new FileInputStream(file);
while ((len = in.read(buffer, 0, 1024)) != -1) {
digest.update(buffer, 0, len);
}
in.close();
} catch (Exception e) {
e.printStackTrace();
return null;
}
BigInteger bigInt = new BigInteger(1, digest.digest());
return bigInt.toString(16);
}
/**
* 获取文件夹中文件的MD5值
*
* @param dirFile
* @param algorithm 所请求算法的名称 for example: MD5, SHA1, SHA-256, SHA-384, SHA-512 etc.
* @param listChild 是否递归子目录中的文件
* @return
*/
public static Map<String, String> getDirMD5(File dirFile, String algorithm, boolean listChild) {
if (!dirFile.isDirectory()) {
return null;
}
// <filepath,algCode>
Map<String, String> pathAlgMap = new HashMap<String, String>();
String algCode;
File files[] = dirFile.listFiles();
for (int i = 0; i < files.length; i++) {
File file = files[i];
if (file.isDirectory() && listChild) {
pathAlgMap.putAll(getDirMD5(file, algorithm, listChild));
} else {
algCode = getFileMD5(file, algorithm);
if (algCode != null) {
pathAlgMap.put(file.getPath(), algCode);
}
}
}
return pathAlgMap;
}
//用时测试
public static void TimeConsumingTest(File file){
//测试md5
long startTime = System.currentTimeMillis();
for (int i=0;i<5000;i++){
getFileMD5(file,"MD5");
}
long endTime = System.currentTimeMillis();
System.out.println("MD5算法运行5000次平均每次耗时为: "+(float)(endTime-startTime)/1000+"ms");
//测试md5
long startTimeSha1 = System.currentTimeMillis();
for (int i=0;i<5000;i++){
getFileMD5(file,"SHA1");
}
long endTimeSha1 = System.currentTimeMillis();
System.out.println("SHA1算法运行5000次平均每次耗时为: "+(float)(endTimeSha1-startTimeSha1)/1000+"ms");
//测试md5
long startTimeSha2 = System.currentTimeMillis();
for (int i=0;i<5000;i++){
getFileMD5(file,"SHA-256");
}
long endTimeSha2 = System.currentTimeMillis();
System.out.println("SHA2算法运行5000次平均每次耗时为: "+(float)(endTimeSha2-startTimeSha2)/1000+"ms");
}
//测试内容更改前后hash值是否变化
public static boolean checkHash(String hashcode,String hashAfterChange){
return hashcode.equals(hashAfterChange);
}
public static void checkChange(File file,File file1,String algorithm){
/**
* 测试更改文件内容md5值是否变化
*/
String md5String = getFileMD5(file,algorithm);
String md5AfterChange = getFileMD5(file1,algorithm);
Boolean flag = checkHash(md5String,md5AfterChange);
if (flag){
System.out.println("内容更改后hash值没有改变");
System.out.println(md5String);
}else {
System.out.println("hash值改变");
//md5值:2d069a6fa7efd35d652139af54639d67
System.out.println("更改前md5值:"+md5String);
System.out.println("内容更改后md5值:"+md5AfterChange);
}
}
public static void main(String[] args){
File file = new File("C:\\md5test.xlsx");
//更改内容后的文件
File file1 = new File("C:\\changeContent\\md5test.xlsx");
//更改文件名之后的文件
File file2 = new File("C:\\changeName\\md5changeName.xlsx");
checkChange(file,file2,"SHA-256");
TimeConsumingTest(file);
checkChange(file,file1,"SHA-256");
}
}
还没有评论,来说两句吧...