웹마스터 팁
MySQL 암호화함수를 큐브리드 JSP로 사용하기
2008.01.24 11:40
기존에 PHP-MySQL 기반으로 작성된 웹 응용을 PHP-큐브리드로 전환하는 절차를 살펴보면
데이터베이스를 전환하는 과정과 프로그램을 전환하는 과정으로 나누어 볼 수 있습니다.
PHP 프로그램을 전환하는 과정은 mysql_...으로 기술된 PHP MySQL extension 함수를 cubrid_...의 PHP CUBRID extension 함수로 전환하는 것과
SQL문들 중에서 MySQL과 큐브리드가 동일하거나 호환되는 것은 그대로 두고
상호 호환되지 않는 것을 큐브리드에서 지원하는 방식으로 전환하는 것이 필요할 것입니다.
데이터베이스를 전환하는 과정은 프로그램 전환보다는 조금 단순하다고 할 수 있는데,
데이터베이스 스키마를 큐브리드가 수용하는 형태로 전환하는 것과
실제 데이터를 큐브리드 형태로 전환하는 과정이 있습니다.
그런데 이 과정에서 MySQL의 MD5()나 PASSWORD(), OLD_PASSWORD() 함수를 통해서
저장해 놓은 비밀번호 필드를 큐브리드로 옮기는 것까지는 문제가 없는데 이 자료를 큐브리드에서는
동일한 함수를 지원하지 않기 때문에 활용할 수 없다는 점이 데이터베이스 전환 과정의 걸림돌이었습니다.
이 걸림돌을 큐브리드에서 지원하는 자바 저장 함수를 이용해서 해소 방법을 나누어 볼까 합니다.
원리는 간단합니다.
MySQL의 MD5(), PASSWORD(), OLD_PASSWORD() 함수를 큐브리드의 자바 저장 함수로 만들어 각 데이터베이스에
등록해 놓으면 일반적인 내장 함수처럼 그대로 사용할 수 있다는 것을 응용한 것입니다.
MySQL 5.1 소스를 참조했고,
관련 함수는 소스 트리 내에 sqlpassword.c와 sqlitem_strfunc.cc를 보시면 됩니다.
적용 과정은
1. 큐브리드 자바 저장 함수 작성(소스 작성 및 컴파일)
2. 데이터베이스에 자바 저장 함수 로딩
3. 데이터베이스에 자바 저장 함수 등록
의 과정을 거치시면 됩니다.
이미 작성되어 컴파일된 클래스 파일 또는 JAR 파일을 사용하실 경우에는 로딩과 등록만 하시면 되고
자바 저장 함수를 수정하셔서 사용하실 경우에는 JDK를 설치하시고 소스를 수정하신 다음 컴파일 하셔서 사용하시면 됩니다.
예제에서는 1. 3가지 암호화 함수를 CUBRID_JSP_password라는 클래스 내에 작성하여 컴파일하고
2. mydb라는 데이터베이스에 로딩하고
3. 3가지 함수를 mydb에 등록한 다음에
4. 실제로 SQL문에서 각 함수를 사용한 결과와 MySQL에서 사용한 결과를 비교해 보도록 하겠습니다.
1. 자바 저장 함수 작성과 컴파일
- CUBRID_JSP_password 클래스 파일 작성
import java.security.MessageDigest; import java.security.GeneralSecurityException;
public class CUBRID_JSP_password { public static String MD5(String inpara) { byte[] bpara = new byte[inpara.length()]; byte[] rethash; int i;
for (i=0; i < inpara.length(); i++) bpara[i] = (byte)(inpara.charAt(i) & 0xff );
try { MessageDigest md5er = MessageDigest.getInstance("MD5"); rethash = md5er.digest(bpara); } catch (GeneralSecurityException e) { throw new RuntimeException(e); }
StringBuffer r = new StringBuffer(32); for (i=0; i < rethash.length; i++) { String x = Integer.toHexString(rethash[i] & 0xff).toUpperCase(); if (x.length()<2) r.append("0"); r.append(x); } return r.toString(); }
public static String PASSWORD(String inpara) { byte[] bpara = new byte[inpara.length()]; byte[] rethash; int i;
for (i=0; i < inpara.length(); i++) bpara[i] = (byte)(inpara.charAt(i) & 0xff );
try { MessageDigest sha1er = MessageDigest.getInstance("SHA1"); rethash = sha1er.digest(bpara); // stage1 rethash = sha1er.digest(rethash); // stage2 } catch (GeneralSecurityException e) { throw new RuntimeException(e); }
StringBuffer r = new StringBuffer(82); r.append("*"); for (i=0; i < rethash.length; i++) { String x = Integer.toHexString(rethash[i] & 0xff).toUpperCase(); if (x.length()<2) r.append("0"); r.append(x); } return r.toString(); }
public static String OLD_PASSWORD(String inpara) { byte[] bpara = new byte[inpara.length()]; long lvar1 = 1345345333; long ladd = 7; long lvar2 = 0x12345671; int i;
if (inpara.length() <= 0) return "";
for (i=0; i < inpara.length(); i++) bpara[i] = (byte)(inpara.charAt(i) & 0xff );
for (i=0; i < inpara.length(); i++) { if (bpara[i] == ' ' || bpara[i] == 't') continue; lvar1 ^= (((lvar1 & 63) + ladd) * bpara[i]) + (lvar1 << 8); lvar2 += (lvar2 << 8) ^ lvar1; ladd += bpara[i]; }
lvar1 = lvar1 & 0x7fffffff; lvar2 = lvar2 & 0x7fffffff;
StringBuffer r = new StringBuffer(16); String x = Long.toHexString(lvar1); for (i = 8; i > x.length(); i --) r.append("0"); r.append(x);
x = Long.toHexString(lvar2); for (i = 8; i > x.length(); i --) r.append("0"); r.append(x); return r.toString(); } } |
그림 1 소스 컴파일하기
2. 데이터베이스에 클래스 파일 로딩하기
- 이미 작성된 클래스를 사용하시려면 1번 과정을 생략하시고 첨부된 파일을 그대로 쓰셔도 됩니다.
- 등록하시려는 데이터베이스는 가동 상태이어야 합니다.
- loadjava DB명 클래스명 또는 JAR명의 형태로 입력하시면 됩니다.
- 예제에서는 loadjava mydb CUBRID_JSP_password.class로 로딩합니다.
그림 2 암호화 클래스를 데이터베이스에 등록하기
3. 데이터베이스에 3가지 함수를 mydb에 등록하기
CREATE FUNCTION MD5(inpara STRING) RETURN STRING AS LANGUAGE JAVA NAME 'CUBRID_JSP_password.MD5(java.lang.String) RETURN java.lang.String'+ ';
CREATE FUNCTION PASSWORD(inpara STRING) RETURN STRING AS LANGUAGE JAVA NAME 'CUBRID_JSP_password.PASSWORD(java.lang.String) RETURN java.lang.String';
CREATE FUNCTION OLD_PASSWORD(inpara STRING) RETURN STRING AS LANGUAGE JAVA NAME '+ 'CUBRID_JSP_password.OLD_PASSWORD(java.lang.String) RETURN java.lang.String'; |
그림 3 암호화 자바 저장 함수 등록하기
4. MySQL과 함수 사용 결과 비교하기.
- 큐브리드에서 함수를 테스트한 결과
한글sqlx> select md5('testpassword1234') from db_root; 한글sqlx> select password('testpassword1234') from db_root; 한글sqlx> select old_password('testpassword1234') from db_root; 한글sqlx> ;xr === <라인 $d의 $s 명령어의 결과> === md5('testpassword1234') ====================== ' 2b3fdcfd47e09d9c6ef15d18bbff3f84' 1 rows selected. 현재 트랜잭션이 커밋 되었습니다.
=== <라인 $d의 $s 명령어의 결과> === password('testpassword1234') ====================== '*FECC8558B80EAC79CC0CDCC6577F0CBF53347D3C' 1 rows selected. 현재 트랜잭션이 커밋 되었습니다.
=== <라인 $d의 $s 명령어의 결과> === old_password('testpassword1234') ====================== '241835eb037997a8' 1 rows selected. 현재 트랜잭션이 커밋 되었습니다.
3 명령어가 성공적으로 수행되었습니다. 한글sqlx> |
- MySQL에서 테스트한 결과
mysql> select md5('testpassword1234'); +----------------------------------+ | md5('testpassword1234') | +----------------------------------+ | 2b3fdcfd47e09d9c6ef15d18bbff3f84 | +----------------------------------+ 1 row in set (0.03 sec)
mysql> select password('testpassword1234'); +-------------------------------------------+ | password('testpassword1234') | +-------------------------------------------+ | *FECC8558B80EAC79CC0CDCC6577F0CBF53347D3C | +-------------------------------------------+ 1 row in set (0.00 sec)
mysql> select old_password('testpassword1234'); +----------------------------------+ | old_password('testpassword1234') | +----------------------------------+ | 241835eb037997a8 | +----------------------------------+ 1 row in set (0.00 sec)
mysql> |
欢迎广大客户订购威震流水线及生产线.销售电话:0576-86678139 合作伙伴:流水线博客网