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
版權聲明:本文為博主原創文章,轉載請附上博文鏈接!


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM