Java防止文件被篡改之文件校验和
Java防止文件被篡改之文件校验和
转载:请注明出处,谢谢!
1.为什么要防止文件被篡改?
答案是显然的,为了保证版权,系统安全性等。之前公司开发一个系统,技术核心是一个科学院院士的研究成果,作为一款商业软件来说,保证公司及作者版权是非常重要的。系统安全性就更不用说了,系统两三下就被搞垮了,那这个系统就不算是一个合格的系统。
2.文件校验和作用
我们都知道,一个系统或者软件都是由众多文件组成的。文件校验和的作用就是保证系统版本的正确性和唯一性。具体原理下面会详细解释。
3.文件校验和的原理
思路和实现的方式可能多种多样,我说的是自己的思路和实现方式,请读者自己斟酌使用。
原理:主要有两个核心:
1.每个不同的文件的md5值是不同的
2.每个文件被修改后的md5会发生改变
4.实现思路
1. 拿到系统的根目录
2. 采用递归,遍历目录文件
3. 计算每个文件的md5值 , 并相加。 原因:每个文件md5值不同,相加后的md5值也必定是唯一。 一个md5值占32位,4个字节。大家都知道,1GB = 1024MB ; 1MB = 1024KB; 1KB=1024B ; 1B = 8bit ; 也就是说就算系统有10000个文件,10000*4B/1024 = 39KB 。这个值是远远小于String的最大值的。String 最大值位2GB左右,本人未亲自测试过,数据从网上得来。
4.所有文件的md5值相加后,得到一个总的md5值,并且是唯一的。
5.用户客户端启动时,会先校验文件和,若和服务器中的校验和不一致,则判定客户端非法,禁止其一切行为!
注意:有些文件是一值在改变的,如log日志。故这些一直在变的文件,不应该参与文件校验和计算
5.代码实现
校验文件
public class CheckSystemFolderSum { // 所有文件md5总和
private static String fileSum = ""; /**
* 遍历文件夹下的所有文件(递归) 并对每个文件计算md5值 得到所有文件的md5值之和
* @param file 软件系统的根文件夹 , suffix 目录文件后缀(以该后缀结尾的目录不会遍历和计算md5值)
* @return 系统所有文件md5之和
*/
public String traverseFolder(File file , String suffix){ if(file == null){
throw new NullPointerException("遍历路径为空路径或非法路径");
} if (file.exists()) { //判断文件或目录是否存在 File[] files = file.listFiles(); if (files.length == 0) { // 文件夹为空
return null;
} else {
for (File f : files) { // 遍历文件夹 if (f.isDirectory()) { // 判断是否是目录 if(!(f.getName().endsWith(".no"))){ // 如果不是以.no结尾的目录 则计算该目录下的文件的md5值 // 递归遍历
traverseFolder(f,suffix);
} } else {
// 得到文件的md5值
String string = checkMd5(f);
// 将每个文件的md5值相加
fileSum+=string;
}
}
} } else {
return null; // 目录不存在
} return fileSum; // 返回所有文件md5值字符串之和
}
计算文件md5值 /**
* 检验文件生成唯一的md5值 作用:检验文件是否已被修改
* @param file 需要检验的文件
* @return 该文件的md5值
*/
private static String checkMd5(File file) { // 若输入的参数不是一个文件 则抛出异常
if(!file.isFile()){
throw new NumberFormatException("参数错误!请输入校准文件。");
} // 定义相关变量
FileInputStream fis = null;
byte[] rb = null;
DigestInputStream digestInputStream = null; try { fis = new FileInputStream(file);
MessageDigest md5 = MessageDigest.getInstance("md5");
digestInputStream = new DigestInputStream(fis,md5);
byte[] buffer = new byte[4096]; while (digestInputStream.read(buffer) > 0); md5 = digestInputStream.getMessageDigest();
rb = md5.digest(); } catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
}finally{
try {
fis.close();
} catch (IOException e) {
e.printStackTrace();
}
} StringBuilder sb = new StringBuilder();
for (int i = 0; i < rb.length; i++) {
String a = Integer.toHexString(0XFF & rb[i]);
if (a.length() < 2) {
a = '0' + a;
}
sb.append(a);
}
return sb.toString(); //得到md5值
}
测试
测试结果没有问题。
源码下载: 请注意,源码文件的包名涉及隐私已被去除,还有代码中的地址等需修改。请大家调试完成后再进行测试!
下载地址:https://download.csdn.net/download/javabuilt/10291183
此代码只是一个原理的DEMO,实际应用需要根据实际情况做相应的调整!
---------------------
本文原来是我在CSDN上写的,现在搬过来。
作者:JavaBuilt
来源:CSDN
原文:https://blog.csdn.net/JavaBuilt/article/details/79583921
版权声明:本文为博主原创文章,转载请附上博文链接!
最新文章
- [HIHO1328]逃离迷宫(bfs,位压)
- Linux软件间的依赖关系(转)
- 对比字节流和字符流,回答为什么FileReader不能用来拷贝图片
- 关于TOE(TCP/IP Offload Engine)
- C# 曲线上的点(二) 获取距离最近的点
- 让WeuiPicker隐藏日期中的日,只保留年月
- k短路([SDOI2010]魔法猪学院)
- JComboBox实现当前所选项功能和JFrame窗口释放资源的dispose()方法
- ggplot2
- es5 温故而知新 简单继承示例
- Splash go() 方法
- CVE2016-8863libupnp缓冲区溢出漏洞原理分析及Poc
- e551. 精简的Applet
- HiHoCoder1513:小Hi的烦恼——题解
- SQL VM上磁盘延迟高, 但Host和Storage Array上的延迟却很低的问题
- [置顶] 自娱自乐1之Linux UDC驱动(形式模板)
- Jenkins报错Caused: java.io.IOException: Cannot run program ";sh"; (in directory ";D:\Jenkins\Jenkins_home\workspace\jmeter_test";): CreateProcess error=2, 系统找不到指定的文件。
- EF Core 2.0中Transaction事务会对DbContext底层创建和关闭数据库连接的行为有所影响
- Centos7安装JDK1.8 Linux64bit
- Adobe Photoshop Lightroom 5.3和序列号
热门文章
- Educational Codeforces Round 65 (Rated for Div. 2)(ACD)B是交互题,不怎么会
- P1164 小A点菜(动态规划背包问题)
- webstorm编写vue、react 将大驼峰组件命名转换成短横杠命名
- 仅显示sessionid,servername,serverport的一个springboot小程序
- jzoj 6798. 【2014广州市选day2】regions
- VMware安装Centos7并联网使用
- 双向绑定数据的实现(new Proxy 版本)
- C#托管堆和非托管堆
- ES6 数组方法库
- python库的基本情况