Checksum의 이용
컴퓨터 소프트웨어 분야에서의 "checksum"은 바이트 스트림에서 계산된 하나의 값입니다. checksum은 바이트의 signature, 다시 말해서 연산을 이용한 바이트들의 결합이라고 할 수 있습니다. 중요한 것은, 바이트 스트림에서의 변화와 변조가 높은 확률로 간파될 수 있다는 것입니다.

checksum의 예는 데이터 전송에서 찾을 수 있습니다. 어떤 응용프로그램이 100바이트의 정보를 네트웍을 통해 다른 응용프로그램으로 전달할 때, 그 응용 프로그램은 바이트의 값에서 계산된 32 비트 checksum을 추가합니다. 이 정보를 받는 쪽에서 이 checksum은 받은 100 바이트를 기초로해서 다시 계산됩니다. 수신하는 쪽의 checksum이 발신 쪽에서 보내온 것과 다르면, 데이터가 어떠한 방법으로 변조되었음을 알려줍니다.

checksum은 (전형적으로) 계산한 데이터보다도 훨씬 더 작습니다. 그렇기 때문에 대부분의 에러를 가려 내기 위해서는 확률적인 모델에 의지합니다. 바이트 순서에서 숫자를 계산하기 위해서 연산법칙이 적용되었다는 점에서 checksum은 해쉬 코드와 아주 유사하다고 할 수 있습니다.

java.util.zip.CRC32 클래스는 checksum 연산의 표준의 하나인 CRC-32를 구현하고 있습니다. checksum의 사용 방법에 대해서는 다음 응용프로그램을 보십시오.
텍스트 파일에 몇 가지 스트링을 입력하고 있으며, 이 문자열 리스트가 입력 후 변경되었는지 알고 싶은 경우, 예를 들자면, 누가 파일을 편집하기 위해서 텍스트 에디터를 사용했는지 알아 보고 싶은 경우를 생각해봅시다. 응용프로그램을 포함하는 프로그램이 여기에 두가지 있습니다. 처음 프로그램은 파일에 문자열 세트를 입력하고, 문자열에서 checksum을 계산합니다.

    import java.io.*;
    import java.util.zip.CRC32;

    public class Checksum1
    {
        // 파일에 기록할 이름들의 목록
        static final String namelist[] =
        {
            "Jane Jones",
            "Tom Garcia",
            "Sally Smith",
            "Richard Robinson",
            "Jennifer Williams"
        };

        public static void main(String args[])
                           throws IOException
        {
            FileWriter fw = new FileWriter("out.txt");
            BufferedWriter bw = new BufferedWriter(fw);
            CRC32 checksum = new CRC32();

            // 목록의 길이를 입력
            bw.write(Integer.toString(namelist.length));
            bw.newLine();

            // 각 이름을 기록하고 checksum 업데이트
            for (int i= 0; i < namelist.length; i++)
            {
                String name = namelist[i];
                bw.write(name);
                bw.newLine();
                checksum.update(name.getBytes());
            }

            // checksum 기록
            bw.write(Long.toString(checksum.getValue()));
            bw.newLine();

            bw.close();
        }
    }

이 프로그램의 출력은 "out.txt" 파일에 다음과 같은 내용물로 되어 있습니다;

    5
    Jane Jones
    Tom Garcia
    Sally Smith
    Richard Robinson
    Jennifer Williams
    4113203990

마지막 줄의 숫자는 스트링 문자에서 찾아낸 모든 바이트를 결합한 것을 계산한 checksum입니다.
두번째 프로그램은 파일을 읽습니다;

    import java.io.*;
    import java.util.zip.CRC32;

    public class Checksum2
    {
        public static void main(String args[])
                           throws IOException
        {
            FileReader fr = new FileReader("out.txt");
            BufferedReader br = new BufferedReader(fr);
            CRC32 checksum = new CRC32();

            // 파일에서 이름의 수를 읽어낸다
            int len = Integer.parseInt(br.readLine());

            // 파일에서 각 이름을 읽어내고 checksum을 업데이트
            String namelist[] = new String[len];
            for (int i = 0; i < len; i++)
            {
                namelist[i] = br.readLine();
                checksum.update(namelist[i].getBytes());
            }

            // checksum을 읽어낸다
            long cs = Long.parseLong(br.readLine());

            br.close();

            // checksum이 일치하지 않으면 에러를 출력하고, 그렇지 않으면 이름의 목록을 출력
            if (cs != checksum.getValue())
            {
                System.err.println("*** bad checksum ***");
            }
            else
            {
                for (int i = 0; i < len; i++)
                {
                    System.out.println(namelist[i]);
                }
            }
        }
    }

이 프로그램은 파일에서 이름의 명단을 읽어내고 이름을 출력합니다. "out.txt"를 텍스트 편집기로 편집하여 이름 중 하나를 바꾸면, 예를 들어서 "Tom"을 "Thomas"로 바꾼다면, 이 프로그램은 다른 checksum을 계산할 것이고, checksum 에러 메세지를 낼 것입니다.

이제, 누구든지 고의로 텍스트 파일을 변조 시키고, 새로운 checksum을 계산하고 그것 역시 변조시킬 수도 있다고 생각할 수도 있습니다. 이것은 사실상 가능한 일이긴 하나, 결코 쉬운 일은 아닙니다. 그것은 CRC-32 checksum 연산이 일반 사용자에게 그다지 쉬운 것이 아니고, 새로운 checksum 값이 무엇이어야하는지 계산하는 것이 어렵기 때문입니다.

checksum을 사용하는 또 다른 방법은 java.util.zip 에 있는 CheckedInputStream과 CheckedOutputStream 클래스를 사용하는 방법입니다. 이 클래스들은 입출력 스트림에서 실행되는 checksum 의 계산을 지원합니다.
 

출처 : http://www.javastudy.co.kr/docs/techtips/000411.html

Posted by 김용환 '김용환'

댓글을 달아 주세요