Site Search :
Standard Enterprise XML Methodology Pattern Setting Tunning Other
Article Contributors
GuestBook
Javapattern Maven
XSourceGen Dev
JetSpeed Test
JLook Image
jLook Family Site


MD5를 이용한 스트링 변환
 
대표적인 해쉬함수인 Message Digest알고리즘을 이용한 스트링변환을 예제로 보자 ( 2003/11/25 ) 164
Written by ienvyou - 최지웅
1 of 1
 

여러분 정말 오랜만입니다. 놀새~입니다. 요즘 인터넷을 뒤져봤더니 원 놀새란 대화명을 쓰는 인간들이
워찌나 많던지 원~ 스터디를 시작하고 나서 3개월이 지났는데 아궁~ 이놈의 프로젝트때문에 아티클은
아티클대로 못쓰고 스터디는 스터디대로 못하고 있었습니다. 프로젝트기준에 맞추어 여러 사람들이 
따라가 주기는 하는데 맨날 이 산으로 등반을 하고 나서는 "어라? 이산이 아닌개벼~" 라고 한마디하고
원상복귀^^  몇번 반복하고 대략 3주정도 밤새다 보니 입에는 18소리를 맨날 물고 사는 처지가 되었네요.

지금 이 글쓰는 시간도 밤 12시가 넘어서 다음날 새벽으로 열심히 시계바늘이 이동하고 있는 시점입니다.
일하기가 정말 싫고, 놀구 싶고..ㅎㅎ 이를 우찌하면 좋을까요이~~

자~ 지금까지는 푸념이었고 오늘 쓰게 되는 아티클은 보통 사이트에서 패스워드를 저장하려고 할때
암호화해서 넣는 방법중의 MD5(Message Digest)를 자바로 구현하여 집어넣는 것을 만들려고 합니다.
보통의 금융권의 사이트들이나 일반사이트들은 금융감독원에서 ISMS라고 해서 보안정책을 하달하여
"이것대로 안만들면 죽는줄 알어~"라는 지침이 하달되는데 그 기준을 맞추기 위하여 이미 아래의 
아티클에서 설명이 되었었던 암호화등의 방식을 적용한 H/W or S/W를 설치하여 그 기준에 부합하게 
적용을 하게 됩니다.

위에서 이야기한 MD5는 또 어디서 봤을까요? 어? 못봤어요? 리눅스에 조금만 관심이 있다던지 시스템을
조금 안다고 한다면 보통의 unix운영체제에서 MD어쩌구 저쩌구 라고 보셨을텐데.. 
아구~ 만약 못보았다면 공부좀 열심히 하셔야 겠습니다. 

그럼 아파치에서 사용자 인증을 위한 htpasswd는 보셨나요? 디렉토리에 user리스트등을 걸어서 해당 
사용자에 대한 접근을 시도하도록 하는 거 말이죠~ 어라? 이것도 구경못해봤다구요? 

홍.... 그럼 진짜 쌍코피터지게 공부하셔야 겠군요. 하기사 이런것 몰라도 먹구 사는데 지장은 없습니다만
그래도 안다면 어디가서 아는 척은 할수도 있겠지요.

자 그럼 대체 MD5가 무엇인지를 알고서 넘어가야 왜 쓰는지를 알수 있겠지요? 알아봅시다.

▶ MD2, MD4, MD5란 무엇인가? 

MD2, MD4, MD5는 Rivest가 개발한 메시지 요약 알고리즘이며, 128비트의 메시지 요약을 생성해냅니다.
MD2는 8비트 컴퓨터용으로 최적화되었고, Md4와 Md5는 32비트 컴퓨터용으로 되어있다는 특징을 
가지고 있습니다. 얘네들 같은 경우는 대표적인 해쉬함수측에 포함되어져 있는데, 해쉬함수란놈은 
자바에서처럼  스트링을 일정한 길이의 해쉬코드로 출력을 내보내게 되는데 얘들은 두가지 성질을 
만족해야 하는 특징을 가지고 있습니다.
첫째로 만들어진 해쉬코드를 보고 해당 해쉬코드를 만들었던 스트링을 찾아내지 못해야 하며, 
두번째는 주어진 스트링에 대하여 같은 해쉬코드를 생성하는 또 다른 스트링을 찾아내지 못해야 
한다는 것입니다.

보통의 해쉬함수들은 SNEFRU, MD2, MD4, MD5, SHA등등이 있는데 MD4가 1992년에 아주 똑똑한 
사람에 의하여 해독이 되어 버려서 MD5로 비트길이를 발전시키기에 이르렀다네요..
SHA같은 경우도 MD4에서 파생된 160비트 해쉬코드를 만드는 놈인데 보면 대략 MD5와 
비슷한 형태를 가지고 있습니다.

MD5같은 경우 사실 SHA보다 32비트가 작은 128비트를 가지고 있지만 빠르고, 쉬우며, 간결하다는데
특징을  둘수 있겠네요. 알려진 결과로는 SHA보다 MD5의 수행성능이 약 25%정도 빠르다는 
특징을 가지고 있습니다.
 
SHA같은 경우는 SMTP서버나 기타등등의 데몬등에서 사용자에 대한 내용등을 옵션으로 선택하여 
사용할수도 있게하고 있죠.

▶ 자바에서의 MD5의 사용 

어떤 방식의 해쉬결과가 나오는지 알고 싶다면 옆에 있는 컴퓨터중에 linux같은게 있으면 열어보세요
콘솔로 /etc/passwd파일을 열어서 해당 사용자들에 대한 패스워드가 어떻게 입력이 되어져 있는지 
보세요. cbWWy0LuJU90FgQ9GE/JcA== 등등의 문자로 장식을 하고 있는 게 보일겁니다.

자 이제 그러한 해쉬함수를 이용한 결과값을 자바측에서 얻어낼 것인데, 기본적인 MD5알고리즘을 
이용하여 자바코드를 짜게 된다면 약 400라인정도의 byte연산을 통하여 결과값을 얻어낼 수 
있습니다. 하지만 알고리즘 이해하고 그걸 짜실랍니까?
보통의 인터넷을 뒤진다고 했을때 지금 여러분은 빨리 찾고 빨리 적용하고 싶어서이기 때문에 
API를 이용하여 만들어내는 방법을 더 선호하겠죠~ 연구자 기질이 있다면 그 원리를 알고 싶어할
지는 몰라도 말이죠~ 

시작해보죠~
자바에서 java.security패키지에 보면 여러가지 보안에 관련된 클래스를 사용할 수 있도록 구성되어
있습니다. 거기에 MessageDigest클래스가 해당 알고리즘을 이용하여 digest를 할 수 있도록 구성해줍니다.

보통의 Util을 만든다하면 개발되는 프레임웍의 util package에 위치할 것이기 때문에 공통으로 
사용할 수 있도록 클래스를 구성합니다

▶ SecurityUtil.java 

import java.security.*;

public class  SecurityUtil {

public class  SecurityUtil {

    /**
     *	byte[] ret = HashUtil.digest("MD5", "abcd".getBytes()); 

* 처럼 호출 */ public static byte[] digest(String alg, byte[] input) throws NoSuchAlgorithmException { MessageDigest md = MessageDigest.getInstance(alg); return md.digest(input); } public static String getCryptoMD5String(String inputValue) throws Exception { if( inputValue == null ) throw new Exception("Can't conver to Message Digest 5 String value!!"); byte[] ret = digest("MD5", inputValue.getBytes()); String result = Base64Util.encode(ret); return result; } }

위의 클래스에 해당 스트링값을 던지게 되면 실제 digest된 결과 문자열을 되돌려 줄수 있도록 처리하였는데 이것이 끝이냐~ 아닙니다. 실제 던져진 해쉬함수에 의한 결과를 System.out으로 찍게 되면 찌그러진 코드형태로 나오게 되는데 이것을 우리 눈으로 비교하여 String문자비교를 통하여 추후 사용할 수 있도록 하려면 Base64 인코딩을 시도해야 합니다. 그 유틸리티 클래스는 아래와 같습니다. ▶ Base64Util.java


import sun.misc.*;
import java.io.*;

/**
* 
* Filename  : Base64Util.java
* Class : Base64Util
* Function : Base64 Encoding/Decoding을 수행하는 클래스
* Comment :
* History : 2000-08-16 2:48오후
*
* @version 1.0 * @author carouser */ public class Base64Util { public Base64Util() {} /** * Base64Encoding을 수행한다. binany in ascii out * * @param encodeBytes encoding할 byte array * @return encoding 된 String */ public static String encode(byte[] encodeBytes) { BASE64Encoder base64Encoder = new BASE64Encoder(); ByteArrayInputStream bin = new ByteArrayInputStream(encodeBytes); ByteArrayOutputStream bout = new ByteArrayOutputStream(); byte[] buf = null; try{ base64Encoder.encodeBuffer(bin, bout); } catch(Exception e) { System.out.println("Exception"); e.printStackTrace(); } buf = bout.toByteArray(); return new String(buf).trim(); } /** * Base64Decoding 수행한다. binany out ascii in * * @param strDecode decoding할 String * @return decoding 된 byte array */ public static byte[] decode(String strDecode) { BASE64Decoder base64Decoder = new BASE64Decoder(); ByteArrayInputStream bin = new ByteArrayInputStream(strDecode.getBytes()); ByteArrayOutputStream bout = new ByteArrayOutputStream(); byte[] buf = null; try { base64Decoder.decodeBuffer(bin, bout); } catch(Exception e) { System.out.println("Exception"); e.printStackTrace(); } buf = bout.toByteArray(); return buf; } }
위의 클래스처럼 정의되어 질 수 있으며, 클래스가 작성되었다면 어디서든지 String passwd = SecurityUtil.getCryptoMD5String("Carouser"); 처럼 입력했을 경우 해당 스트링이 MD5에 의하여 변환된 문자열값을 확인하실 수 있슴당~ 오늘 하루도 수고하세요..갑자기 일이 밀려드네요.. 단굘~
 
1
References
 
Copyright ⓒ 2003 www.javapattern.info & www.jlook.com, an jLOOK co.,LTD