[플밍노트] 16진수 헥사 인코딩의 정석

최근에 퍼지 해시(fuzzy hash), 롤링 해시(rolling hash), 지역 민감 해시(Locality-sensitive hash) 등으로 불리는 코드를 좀 찾아보고 있었습니다. 대체로 ssdeep을 많이 사용하는 것 같은데 ssdeep의 경우 안타깝게도 GPL 이더군요. 그래서 다른 종류는 뭐가 있나 하고 알아보던 중에 트렌드마이크로에서 공개한 TLSH를 찾았습니다. 위키피디아에는 TLSH란 보안과 디지털 포렌직 프로그램을 위해 설계된 지역 민감 해싱 알고리즘이라고 나와 있습니다. 그쵸. 바로 우리가 찾던 그 녀석이죠. 걔다가 착하게도 아파치 2.0 라이선스라는 ㅋㅋㅋ~

형님들이 작성한 코드를 좀 보다가 재미난 부분이 있어서 올려봅니다. 바이너리 데이터를 16진수 헥사 코드로 인코딩하는 코드입니다. 아래처럼 작성되어 있습니다.

void to_hex( unsigned char * psrc, int len, char* pdest )
{
    static unsigned char HexLookup[513]= {
	"000102030405060708090A0B0C0D0E0F"
	"101112131415161718191A1B1C1D1E1F"
	"202122232425262728292A2B2C2D2E2F"
	"303132333435363738393A3B3C3D3E3F"
	"404142434445464748494A4B4C4D4E4F"
	"505152535455565758595A5B5C5D5E5F"
	"606162636465666768696A6B6C6D6E6F"
	"707172737475767778797A7B7C7D7E7F"
	"808182838485868788898A8B8C8D8E8F"
	"909192939495969798999A9B9C9D9E9F"
	"A0A1A2A3A4A5A6A7A8A9AAABACADAEAF"
	"B0B1B2B3B4B5B6B7B8B9BABBBCBDBEBF"
	"C0C1C2C3C4C5C6C7C8C9CACBCCCDCECF"
	"D0D1D2D3D4D5D6D7D8D9DADBDCDDDEDF"
	"E0E1E2E3E4E5E6E7E8E9EAEBECEDEEEF"
	"F0F1F2F3F4F5F6F7F8F9FAFBFCFDFEFF"
    };
    unsigned short* pwHex = (unsigned short*)HexLookup;
	unsigned short* pwDest= (unsigned short*)pdest;

	for (int i=0; i<len; i++ ) {
		*pwDest= pwHex[*psrc];
		pwDest++; psrc++;
	}
	*((unsigned char*)pwDest)= 0;  // terminate the string
}

사실 뭐 특별할 건 없지만 00부터 FF까지 테이블을 작성한 형님들의 노고에 박수를 ㅋㅋㅋ~ 통상적으로 배열을 만들면 "0123456789ABCDEF" 정도 만들어서 사용하기 마련인데요. 한땀한땀 성능을 생각하신 형님들께서는 친히 00부터 FF까지를 모두 테이블에 담아버렸습니다.

테이블을 룩업 하는 과정은 더 C언어 스러운데요. 문자열 테이블을 USHORT 포인터로 변환해서 2바이트씩 한번에 복사해 버림으로써 불필요한 연산을 최소화해주셨습니다. 0을 넣는 부분에는 깨알같이 "terminate the string"이란 주석까지 ㅋ~ 장인 정신이 묻어나는 코드가 이닐수가 없네요. 코드를 보면서 "0123456789ABCDEF"만 만들어서는 쉬프트와 더하기를 남발했던 저는 배꼽 반성을 했습니다.

TLSH GitHub 저장소를 보면 코드와 함께 발표한 논문 자료와 다른 알고리즘(ssdeep, sdhash)과의 비교 자료도 함께 있는데요. 굉장히 인상적입니다. 이런게 바로 리서치가 아닐까 싶네요. 사족을 하나 더 달자면 그간 트렌드마이크로를 그닥 의미 없는 백신 제품이라 생각했는데 이 코드 하나로 저에게는 기업 이미지가 굉장히 좋아졌습니다. 물론 그렇다고 트렌드마이크로 백신을 산다는 소리는 아닙니다 ㅋㅋㅋ