윈디하나의 솔라나라: MD5, FingerPrint, CC Optimize

목차

MD5란?

1) How to Break MD5 and Other Hash Functions 참조

MD5라이브러리를 이용한 구현

MD5라이브러리(솔라리스 9 이상에 포함됨)를 이용해 MD5 계산 프로그램을 구현했다. (MD5 라이브러리는 솔라리스 9부터 포함되었지만, MD5 계산 프로그램은 솔라리스 10부터 포함되었다)
root@wl ~ # vi md5_solaris.c
#include <md5.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>

#define BUF_SIZE (8 * 1024)

void printuseage(char* argv[]) {
    printf("MD5 Sum Utility for Solaris v2.0\r\n");
    printf(" - with Solaris MD5 Library.\r\n");
#if _FILE_OFFSET_BITS - 0 == 64
    printf(" - with support 64 bit file offset.\r\n");
#endif
    printf("Copyright (C) Jo HoSeok 2005-2008. All rights reserved.\r\n\r\n");
    printf("USEAGE:\r\n %s filename\r\n", argv[0]);
}

int main(int argc, char* argv[])
{
  MD5_CTX        md5_context; // MD5 컨텍스트 값
  unsigned char* auth_buffer; // 결과값
  off_t          readcount;   // 읽은 바이트수, 파일 오프셋 위치
  long long      offset = 0;
  FILE * fp;                  // 파일 핸들러
  char hex_output[16*2 + 1];  // 결과값을 헥스 값으로 변환한 값. + 1 은 null 값
  int i;                      // 루프에서 사용되는 임시 변수

  // 
  if (argc < 2) {
  	printuseage(argv);
    return(1);
  }

  auth_buffer = (void *) malloc(BUF_SIZE);

  fp = fopen(argv[1], "rb");
  if (!fp) {
    printf("Cannot Open %s.\r\n", argv[1]);
    return(1);
  }

  MD5Init(&md5_context); // 초기화
  while (readcount = fread(auth_buffer, 1, BUF_SIZE, fp)) {
    offset += readcount;
    MD5Update(&md5_context, auth_buffer, readcount);
#if _FILE_OFFSET_BITS - 0 == 64
//    printf("   %15lld\r", offset);
#else
//    printf("   %15ld\r", offset);
#endif
  }
  fclose(fp);
  MD5Final(auth_buffer, &md5_context);
  
  // 16진수로 표현
  for (i = 0; i < 16; i++)
    sprintf(hex_output + i * 2, "%02x", auth_buffer[i]);	
  printf("%s %s (%lld bytes)\r\n", argv[1], hex_output, offset);
  free(auth_buffer);
}
root@wl ~ # cc -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64 -lmd5 -o md5  md5_solaris.c 1)
또는
root@wl ~ # cc -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64 -lmd5 -m64 -fast -o md5 md5_solaris.c 1)
root@wl ~ # mkfile 4g 4GFile 2)
1) 두가지 방법 중 한가지로 컴파일 한다. 아래의 방법을 사용하면 컴파일된 바이너리를 다른 CPU를 사용하는 솔라리스에서 실행할 수 없다. 필자는 테스트를 Ultra Sparc IIIi 를 사용했다. x86도 펜티엄 2, 3, 4인지 여부, AMD, Intel여부에 따라 나뉜다. 그만큼 썬의 cc는 커스터마이징을 해주기 때문에 성능향상에 도움이 된다.
[/usr/sfw/bin/gcc -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64 -lmd5 -m64 -mcpu=v9 -o md5_gcc md5_solaris.c] 처럼 하면 gcc에서도 컴파일 할 수 있다.
2) 성능 테스트를 위해 임의의 4GiB파일을 생성시켜놓는다.

FingerPrint

※ 말 그대로 [지문]이다. 솔라리스에 설치된 파일에 대해, 이 파일이 변조되었는지 MD5해시값을 통해 확인할 수 있다. 어떤 파일인지 어떤 패키지인지, 어떤 패치를 설치했는지 나온다.
root@wl ~ $ digest -a md5 /bin/sh
4918cc526b37468c04c702100b1da7dd
root@wl ~ $
Solaris Fingerprint Database An Identification Tool for Solaris Software and Files 에서 MD5해시값을 입력하면 아래와 같이 나온다.
4918cc526b37468c04c702100b1da7dd - - 1 match(es) 
	canonical-path: /sbin/sh 
	package: SUNWcsr 
	version: 11.10.0,REV=2005.01.21.16.34 
	architecture: i386 
	source: Solaris 10/x86 
	patch: 138254-02 

컴파일러 옵션에 따른 성능

-m64, -fast 를 붙여 컴파일한 md5소스와 그렇지 않은 md5 바이너리의 성능을 테스트해보았다. 소스의 수정 없이 단순히 2개의 옵션을 붙이는것만으로 약 5%정도의 성능 향상이 있는것을 알 수 있다. (개인적인 생각이지만, 옵션 바꾼걸로 저정도 성능향상이면 정말 대단한거다)
  1. 일반적인 옵션으로 컴파일

    root@wl ~ # cc -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64 -lmd5 -o md5 md5_solaris.c
    root@wl ~ # ldd md5
            libmd5.so.1 =>   /usr/lib/libmd5.so.1
            libc.so.1 =>     /usr/lib/libc.so.1
            /platform/SUNW,A70/lib/libmd5_psr.so.1
            libm.so.2 =>     /usr/lib/libm.so.2
            /platform/SUNW,A70/lib/libc_psr.so.1
    root@wl ~ # file md5
    md5:            ELF 32-비트 MSB 실행 가능 SPARC32PLUS 버전 1, V8+ 필요, 동적으로 링크됨, 분리 안됨
    root@wl ~ # time ./md5 4GFile
    4GFile c9a5a6878d97b48cc965c1e41859f034 (4294967296 bytes)
    
    real    1m7.090s
    user    0m32.168s
    sys     0m12.842s
    
  2. 최적화된 옵션 적용해 컴파일

    root@wl ~ # cc -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64 -lmd5 -m64 -fast -o md5 md5_solaris.c 1) 2)
    root@wl ~ # ldd md5
            libmd5.so.1 =>   /lib/64/libmd5.so.1
            libc.so.1 =>     /lib/64/libc.so.1
            /platform/SUNW,A70/lib/sparcv9/libmd5_psr.so.1
            libm.so.2 =>     /lib/64/libm.so.2
            /platform/SUNW,A70/lib/sparcv9/libc_psr.so.1
    root@wl ~ # file md5
    md5:            ELF 64-비트 MSB 실행 가능 SPARCV9 버전 1, UltraSPARC3 확장자 필요, 동적으로 링크됨, 분리 안됨
    root@wl ~ # time ./md5 4GFile
    4GFile c9a5a6878d97b48cc965c1e41859f034 (4294967296 bytes)
    
    real    1m6.447s
    user    0m28.164s
    sys     0m11.892s
    
    1) 아래와 유사한 메시지가 나오는 경우 무시할 수 있다.
    cc: Warning: -xarch=native has been explicitly specified, or implicitly specifie d by a macro option, -xarch=native on this architecture implies -xarch=sparcvis2 which generates code that does not run on pre UltraSPARC III processors
    2) 아래와 같은 메시지가 나오는 경우 64비트를 지원하지 않는 경우로 -m64 옵션을 빼고 컴파일 한다
    cc: Option -m64 is not supported on this OS version
  3. 솔라리스 10 기본 소프트웨어

    root@wl ~ # time digest -a md5 4GFile
    c9a5a6878d97b48cc965c1e41859f034
    
    real    1m9.086s
    user    0m30.735s
    sys     0m12.338s
    
올바른 XHTML 1.0 Transitional 입니다 올바른 CSS입니다!