본문으로 바로가기

728x90

파일 해쉬 처리하는 코드입니다. 필자는 현재 전자우편을 분석하여 첨부된 파일의 해쉬를 구하고 악성코드인지를 검사하기 위하여 첨부파일의 해쉬를 구할 필요가 있었습니다. 각각 MD5, SHA1, SHA256 알고리즘을 통해서 개별적으로 처리하던 방식에서 한꺼번에 3가지를 처리하는 로직으로 변경해 보았습니다.

 

개선전의 코드는 다음과 같습니다.

public static String makeFileHashMd5(String filename) throws Exception {
	InputStream fis = new FileInputStream(filename);

	byte[] buffer = new byte[1024];
	MessageDigest md5 = MessageDigest.getInstance("MD5");
	int numRead = -1;

	do {
		numRead = fis.read(buffer);
		if (numRead > 0) {
			md5.update(buffer, 0, numRead);
		}
	} while (numRead != -1);

	fis.close();
	
	return hexEncode(md5.digest());
}

public static String makeFileHashSha1(String filename) throws Exception {
	String SHA = "";
	int buff = 16384;

	RandomAccessFile file = new RandomAccessFile(filename, "r");
	MessageDigest hashSum = MessageDigest.getInstance("SHA-1");
	byte[] buffer = new byte[buff];
	byte[] partialHash = null;
	long read = 0;
	// calculate the hash of the hole file for the test
	long offset = file.length();
	int unitsize;
	while (read < offset) {
		unitsize = (int) (((offset - read) >= buff) ? buff : (offset - read));
		file.read(buffer, 0, unitsize);
		hashSum.update(buffer, 0, unitsize);
		read += unitsize;
	}
	file.close();
	partialHash = new byte[hashSum.getDigestLength()];
	partialHash = hashSum.digest();
	
	return hexEncode(partialHash);
}

public static String makeFileHashSha256(String filename) throws Exception {
	String SHA = "";
	int buff = 16384;

	RandomAccessFile file = new RandomAccessFile(filename, "r");
	MessageDigest hashSum = MessageDigest.getInstance("SHA-256");
	byte[] buffer = new byte[buff];
	byte[] partialHash = null;
	long read = 0;
	// calculate the hash of the hole file for the test
	long offset = file.length();
	int unitsize;
	while (read < offset) {
		unitsize = (int) (((offset - read) >= buff) ? buff : (offset - read));
		file.read(buffer, 0, unitsize);
		hashSum.update(buffer, 0, unitsize);
		read += unitsize;
	}
	file.close();
	partialHash = new byte[hashSum.getDigestLength()];
	partialHash = hashSum.digest();
	
	return hexEncode(partialHash);
}

다른 사이트에서 특정 알고리즘으로 개별적으로 해쉬를 구하는 방식에서 Hex 인코딩을 별도로 분리하고 1번 파일을 읽어서 3가지를 처리하도록 하여 속도를 개선하였습니다. 입력은 파일 경로, 출력은 각 3가지 해쉬알고리즘의 해쉬값 배열입니다.

 

// Hex Encoding 처리
private static String hexEncode(byte[] bytes) {
	StringBuffer sb = new StringBuffer();
	for (int i = 0; i < bytes.length; i++) {
		sb.append(Integer.toString((bytes[i] & 0xff) + 0x100, 16).substring(1));
	}
	return sb.toString();
}

// 파일 해쉬 얻기
public static String[] makeFileHashes(String filename) throws Exception {
	InputStream fis = new FileInputStream(filename);

	byte[] buffer = new byte[1024];
	MessageDigest md5 = MessageDigest.getInstance("MD5");
	MessageDigest sha1 = MessageDigest.getInstance("SHA-1");
	MessageDigest sha2 = MessageDigest.getInstance("SHA-256");
	int numRead = -1;

	do {
		numRead = fis.read(buffer);
		if (numRead > 0) {
			md5.update(buffer, 0, numRead);
			sha1.update(buffer, 0, numRead);
			sha2.update(buffer, 0, numRead);
		}
	} while (numRead != -1);

	fis.close();
	
	return new String[] {
			hexEncode(md5.digest()),
			hexEncode(sha1.digest()),
			hexEncode(sha2.digest())
	};
}

 

728x90