노트내비게이터

지원 OS : Any
개발환경 : PHP, JavaScript, MySQL, HTML
사용제한 : GPL
제작자 : 김현식
자료설명 :

안녕하세요.
노트내비게이터 1.3.3을 릴리즈합니다.
1.2.9와 비교해서 기능상 바뀐 것은 없습니다.
다만, GPL라이센스를 따르기로 하면서 해당 라이센스에서 요구하는 것들을 추가한 것입니다.
1.3.0버전에서 원본 파일이 오염되는 현상을 고쳤습니다.(1.3.1)
또한, register_globals = off 로 되어있는 환경에서도 동작할 수 있도록 만들었습니다(1.3.2 – 1.3.3)

노트 내비게이터란, 일종의 온라인 단어사전입니다.
DB에 단어를 등록하고, 원본 문서를 파서(수동파서, 자동파서)에 넣고 이 프로그램을 실행하면, DB에 등록된 단어마다 HTML문서에 링크가 걸립니다.
그러나, 원본 문서의 모양은 최대한 변형시키지 않습니다. 즉, 파란색이나 밑줄 등이 없는 “숨겨진”링크가 만들어집니다.
해당 단어에 마우스를 올려놓으면 이 단어가 링크내비게이터에 등록된 단어라는 표시가 뜨며(만두가 뜹니다(^^;)), 그것을 클릭하면 팝업창으로 해당 단어의 의미를 보여줍니다.
위 스크린샷에서 보이는 것처럼, 링크는 다단계로 걸릴 수 있습니다. 링크내비게이터의 기술을 사용하여 이론상 무한대의 중첩 링크를 걸 수 있습니다.

이건 인스톨 절차가 까다롭습니다.
기본적으로 MySQL 데이타베이스를 다룰 줄 아셔야 합니다. 적어도 create database명령을 쓰실 줄 알아야 하며, mysql의 user과 db테이블에 새로운 사용자를 등록하는 방법을 모르시면 보안상에 문제가 생길 수 있습니다.
제로보드를 직접 설치한 경험이 있으신 분은 아주 쉽게 하실 수 있습니다. 설치방법이 거의 같게 만들었거든요.(^^;)

1. 압축되어 있는 PHP코드를 받아옵니다.

2. 받아온 파일을 적절한 디렉토리에 풉니다. 적절한 디렉토리란 웹문서(HTML파일)이 있는 디렉토리를 말합니다.
파일을 모두 푼 뒤에 해당 디렉토리를 보시면 note_nav라는 디렉토리가 만들어져 있는 게 보일 겁니다.

3. mysql 계정과 DB를 생성합니다. 보안상의 문제로 꼭 root가 아닌 다른 mysql계정을 생성하시길 바랍니다.
아마 이 부분에서 아주 많은 사람들이 좌절할듯… 제로보드를 스스로 설치해보신 분이라면 쉽게 하실 수 있습니다.

4. note_nav/config.php파일을 편집합니다.
첫째줄은 localhost로 그냥 놔두세요. 거의 그럴 일이 없겠지만 DB서버가 원격지에 있을 경우 localhost를 다른 적절한 서버명으로 고쳐주어야겠죠? 보통은 localhost입니다.
두번째줄은 아까 생성한 mysql user이름,
세번째줄은 해당 유저로 접근하기 위한 패스워드입니다.
네번째줄은 데이타베이스 이름입니다.
다섯번째줄은 노트내비게이터가 있는 절대경로(URL)입니다. (예 : http://my.site.pe.kr/~sam/note_nav)

5. note_nav/sysop/login.php 파일을 웹브라우저로 엽니다. 이 창(로그인페이지)에서 config.php에 적어두었던 계정 정보를 입력합니다.

6. 원하는 노트를 등록하시고…

7. HTML파일에는 다음과 같이 적용합니다.
수동으로 note를 붙이는 경우 : (일시적으로 book를 바꾸고 싶을 때 주로 사용합니다)
– 파일의 맨 처음에
– 태그 뒤쪽에 를 추가합니다. book_name은 6번 시솝 페이지에서 사용하신 바로 그 book입니다.
– 노트를 붙이기를 원하시는 곳에 를 끼워넣습니다. title은 6번 시솝 페이지에서 사용하신 바로 그 title입니다.
– 파일의 맨 마지막에 를 추가합니다.

자동으로 note를 붙이는 경우(parser사용) : (대부분의 경우에 사용하지만 속도가 느립니다. 속도가 중요한 문서의 경우 수동파서만 사용하세요)
$src=”원본 HTML파일이름”;
$book=”참조할 book이름”;
include(“노트내비게이터 URL/parser.php”);
?>

이것만 들어있는 HTML파일을 만드시고(경로는 원본 파일과 같은 경로를 추천합니다. 다른 경로 사용시 주의가 필요합니다),
웹브라우저에서는 저것을 읽기만 하면 됩니다.

자동파서를 피해가고 싶으면 :
HTML본문에서 피해가고 싶은 단어 또는 문장을

로 만들어줍니다. 자동파서는 도 HTML태그로 인식하여 파싱하지 않습니다.

8. 웹브라우저로 결과를 확인합니다.

수동파싱과 자동파싱 둘 다 같이 사용하실 수도 있습니다. 다만 수동파싱은 다단계의 note를 붙일 수 없습니다.
그럼…

김현식 “위 스크린샷”의 스크린샷은
http://nzeo.com 의 자작프로그램 자료실에 있습니다.
또한, 제가 가장 최신 버전을 맨 처음 릴리즈하는 곳이기도 합니다. 07/25 10:02:43

김현식 e-mail : wbstory@paran.com 07/25 10:04:09

김현식 수동파서에 대한 설명이 불충분했습니다.
open_book 함수는 또한 book_open 함수로도 가능하며(둘이 같은 겁니다), book를 열거나 바꾸는 기능을 합니다.
book_close는 또한 close_book 도 가능하며, book을 닫습니다. 반드시 열린 book은 닫아야 합니다. 그러나 book을 바꾸고 싶을 때는 book_close를 호출하지 않습니다(book_close함수가 정확히 하는 일은 수동파서의 전 동작을 마무리합니다) 07/25 10:08:06

김현식 자동파서만 사용하는 경우에는 원본 HTML문서에는 어떠한 수정도 가해지지 않습니다.
자동파서는 오직 하나의 book만 지정할 수 있는 대신에 다단계의 note를 만들 수 있고, 수동파서는 자동파서가 지정한 book외의 다른 book을 일시적으로 지정할 때 사용합니다. 수동파서는 자동파서와 무관하게 동작하므로 수동파서만 적용된 원본 HTML파일을 그냥 읽을 경우 수동파서만 적용된 문서가 불러집니다.
만약 다단계의 note가 필요한데 book이 달라 적용이 곤란한 경우에는 두 가지 방법을 사용하실 수 있습니다.
첫째 : 다른 book의 내용을 복사.
둘째 : Low level로 note를 붙임.
두번째 방법은 파서가 파싱 완료한 HTML문서의 소스 보기를 하시면 눈치채실 겁니다. 다만 두번째 방법은 제가 절대적으로 비추천합니다. Low Level에서는 ID로 note를 찾는데, DB에 수정이 가해지면 ID값이 바뀌기 때문입니다. 07/25 15:51:50

김현식 요약하면, 자동파서만 쓰는 경우에는 원본 HTML문서는 손댈 게 없고, 수동파서를 쓰는 경우에는 굳이 자동파서를 거칠 필요가 없으며, 둘을 같이 쓸 수도 있습니다.
자동파서는 book을 하나만 지정할 수 있으나 수동파서는 book_open함수를 사용하여 book을 지정하므로 book_open함수를 쓸 때마다 book이 바뀝니다. 그리고 수동파서는 자동파서가 어떤 book을 쓰는지 관심가지지 않으며, 자동파서 역시 마찬가지입니다.

1241650913.zip

CRON 활용 table 백업 및 load data로 데이터 insert

김영탁

제가 며칠동안 고생하여 구현한 방법입니다. 혹시라도 필요하신 분 있을까해서 올립니다.

vi에서 아래와 같이 입력하고 /etc/cron.houtly 에 저장해 두면 매시간마다 실행됩니다.
파일 권한은 755로 해줬습니다.

==================================================================================
#!/bin/sh
dat=`date ‘+%Y%m%d%H%M’`
#
# (txt로 변환된 파일을 ftp로 올려두어 파일이 존재하면 아래 스크립트를 실행합니다.)
if [ -f /home/zerotak.com/public_html/db/db.txt ] ; then
#
# Table Name Modify(원래의 테이블을 이름을 바꾸어 그대로 둡니다.)
/usr/local/mysql/bin/mysql -uid -ppw zerotak -e “rename table goods to goods_$dat”
#
# Table Create(미리 만들어둔 테이블 생성 스크립트로 테이블을 만듭니다.)
/usr/local/mysql/bin/mysql -uid -ppw zerotak < /home/zerotak.com/public_html/db/goods.sql
#
# DB Update(새로 만든 빈 테이블에 load data 명령으로 txt파일의 데이터를 집어넣습니다.)
/usr/local/mysql/bin/mysql -uid -ppw zerotak -e “load data infile ‘/home/zerotak.com/public_html/db/db.txt’ replace into table goods fields terminated by ‘,'”
#
# File Rename(위 과정을 실행후 txt파일의 이름을 변경합니다.)
mv /home/zerotak.com/public_html/db/db.txt /home/zerotak.com/public_html/db/db_$dat.txt
#
#
fi
==================================================================================

송효진 좀 위험해 보입니다.
db.txt 의 형식이 잘못되었을경우 발견할때까지 잘못된 데이터가 들어있겠군요.

원본 테이블의 이름을 먼저 바꾸지 말고,
새 테이블을 임시 이름으로 생성하여 데이터 입력한 후,
원본 테이블의 이름을 바꾸고, 새 테이블의 이름을 바꾸면.
서비스 중단시간을 최소화 할 수 있겠군요.

임시테이블에 입력할 때 오류가 있으면 작업이 거기서 중단되도록 하면 서비스에도 지장 없겠고요.

하나의 폼안에서 2개이상의 액션이 필요할때

좋은 방법들이 많이 있군요. 🙂
자바스크립트를 이용한 방법은 일단 제쳐 두고, 하나의 폼 안에 여러개의 submit 버튼을 이용한 경우를 정리해 보겠습니다.

1. submit 버튼의 name을 동일하게 한 경우.





myscript.php:
switch ($_POST[‘action’]) {
case ‘주소록에 기록’:

break;
case ‘스팸목록에 기록’:

break;
case ‘삭제’:

break;
}

2. submit 버튼의 name을 동일하게 한 경우 두번째 예제.





myscript.php:
$keys = array_keys($action);
$action = $action[0];
$match = “/[a-zA-Z0-9]+/”;
if (preg_replace($match, ”, $action)) die (“액션 오류!!”);
if (!file_exists(“./$action.php”)) die (“파일을 찾을 수 없음”);
else include “./$action.php”;

3. 이미지 버튼을 이용할 경우.





myscript.php:
if ($_POST[‘add_address_x’] { … }
else if ($_POST[‘add_spam_x’] { … }
else if ($_POST[‘remove_x’] { … }
else { … }

참고: 이미지 버튼의 경우 $_POST 배열에 [이미지_x] => 20, [이미지_y] => 12 이런식으로 들어가기 때문에 ‘_x’를 이미지 이름 뒤에 붙였습니다.

마지막으로 PHP의 경우 submit 버튼의 name에 직접 key=value&key2=value2 식으로 하던 것을 2번째 예에서 처럼 배열로 넘기는 것이 더 간결하고 효율적일 것 같습니다.

참고로 Perl에서 구현하여 사용하고 있는 것은 다음과 같습니다. 넘어 온 submit 버튼의 name 쿼리를 파싱하여 $IN에 넣어 사용합니다.
$query가 CGI.pm의 개체라고 가정합니다.
my $IN;
for ($query->param) {
for (split /&/) {
/^([^=]+)=(.*)/ or next;
my ($key, $val) = ($query->unescape($1), $query->unescape($2));

$query->param($key => $val);
}
}

foreach ($query->param) {
$IN->{$_} = join “”, $query->param($_);
}

윈도우즈2003서버 설정

Windows Sever 2003 은 서버운영체제 이므로 많은 기능이 비활성화 되어 있어서 설치후에

대부분 불편을 느끼는데 이걸 해결하는 방법을 간단히 적어보니 참조 하세요.

여기에 이 팁은 2003 버전을 손쉽게 사용하도록 해주는 기본팁 입니다.

1.시스템 시작시 ctrl+alt+del 안누르기

실행 – gpedit.msc 입력하고 엔터 나오는창에서

컴퓨터구성- windows 설정 -보안설정 – 로컬정책 – 보안옵션 -대화형로그온 ctrl+alt+del 이걸

더블클릭하거나 속성에서 사용으로 하여주고 확인해준다.

2.로그온시 암호 안물어보기 .

실행 – control userpasswords2 이걸 입력하고 나오는창에서 사용자이름과 암호 사용해야 로그인

할수있음 이앞에 체크를 지우고 확인하면 창이 하나 나오는데 여기에 설치시 설정한 암호를 적고

확인하면 된다.

3. 시스템 종료시 이벤트 추적기 표시 안함.

시작 → 실행 → gpedit.msc → 컴퓨터 구성 → 관리 템플릿 → 시스템 를 선택하고, 우측창에서

시스템 종료 이벤트 추적표시 를 더블클릭하여 “사용 안함” 으로 변경하고 확인한다.

4. Audio 서비스 및 Theme 서비스 활성화하기

Windows Audio 및 Theme 서비스를 활성화 시키기위해서는 서비스관리자를 실행시킨다.시작-실행

→ services.msc 입력하고 엔터

메뉴중 theme 를 더블클릭이나 속성에서 자동으로 해주고 적용하면 시작 버튼이 활성화되니

그걸 클릭해서 실행시킨다. 그럼 Theme 가 활성화되서 사용가능하다.

다음에는사운드를 사용하기위해서 windows audio 를 속성에서 자동으로하고 적용하면 시작버튼이

활성화되니 그걸 클릭해서 적용시킨다.

5. 활성화시킨 Theme 및 Audio 사용하기

제어판-디스플레이-설정-고급-문제해결-하드웨어가속을 최대로한다.

제어판-사운드및오디오장치-볼륨-스프커설정-고급-성능-오디오재생 (최대로한다)

샘플전환속도 (최상으로한다)

그리고 오디오 각종 성능을 최적화한다. 볼륨등 각종 시작음 종료음등..

6. 다이렉트 x 활성화하기

시작-실행에 dxdiag 입력하고 엔터 나오는창에서 디스플레이 이항목에서 가속을 최대로하고

3 가지 3 D 항목이 사용안함으로 되어 있는걸 사용으로 하여준다.

Directdraw 사용으로변경

Direct3d 사용으로 변경

agp 질감가속 사용으로 변경

소리에서 DirectX 기능 에 하드웨어 소리가속을 최대로한다.

7. 시스템 설정

내컴퓨터-속성-고급-시작및복구-설정-디버깅정보쓰기를 작은메모리덤프(64KB)로한다.

내컴퓨터-속성-고급-성능-설정-고급-아래위 두곳에 시스템으로 설정된 프로세서와 메모리

사용계획을 두곳다 프로그램으로 하여준다.

8. 인터넷 옵션 설정

도구-인터넷옵션-보안에서 보안을 보통으로 하여준다. 방법은

제어판-프로그램 추가/제거-windows 구성요소 추가/제거-Internet Exporer 보안강화구성-

이걸클릭후에 체크해제하고 밑에 자세히를클릭해서 연다-그럼 안에 관리자구성 과 기타사용자그룹

이렇게 두개가 보이는데 여기에 체크해제를한다. 그런다음에 확인하고나서 밑에 다음을 클릭

하면 된다. 그러면 잠시 작업후에 비활성화되는데 인터넷옵션 보안에는 보통으로 된다.

9. 메뉴팝업속도를 빠르게 하기

메뉴창이 열리는 속도가 느린것을 감지할수 있는데 빠르게 하는 방법이다.

시작 -> 실행창에서 regedit를 입력하여 레지스트리 편집창을 뛰운후

HKEY_CURRENT_USERControlPaneldesktop에서 MenuShowDelay항목의 값이 기본 400으

로 셋팅되어있느데 이걸 1~8 사이로 하여준다.

10. xp 처럼 디스플레이 사용하기

xp 처럼 바탕화면 아이콘이나 모양을 사용하려면 내컴퓨터-속성-고급-성능-설정-시각효과

여기서 두번째 최적모양으로설정 이걸 선택하고 확인해준다.

11. 스케너나 디지탈 카메라를 사용하려면.

관리도구-서비스-Windows Image Acquisition(WIA) 여기에 속성에서 자동으로 하여준다.

그후에 드라이버를 설치하거나 usb 로 설치하면 된다.

12. 내문서나 미디어플레이어 사용후에 흔적 지우기.

이팁은 기본이 아니지만 서비스 차원에서 제공한다. 익스창이나 미플 이나

내문서등 윈도에서 사용된 각종 흔적을 지우는 법이다.

실행-gpedit.msc 입력하고 엔터 나오는창에서

사용자구성-관리템플릿-작업표시줄및시작매뉴-여기에서 우측창에 다음 두가지를

더블클릭이나 속성에서 사용으로 하여준다. 재부팅후에 작동한다.

종료시 최근에 사용한문서 기록지우기 하고

최근에 사용한 문서 기록을 보관안함. 이두개를 설정하면된다.

RSA 공개키 암호화 알고리즘 – PHP 구현

이형철
http://hc.pe.kr
http://hc.pe.kr/notefiles/8187/RSAKeyGen.exe

이번에 프로젝트 하다가 RSA 공개키 암호화 알고리즘이 필요해서 만들었습니다.
클라이언트 측으로 몰래 보내야할 자료(password 등)가 있을 때 사용하시기 바랍니다.

차례
1. RSA의 소개
2. RSA를 php에서 이용하기 위한 소스 코드(예제 포함)

링크 : RSA 키 pair 생성하는 프로그램(제가 만들었습니다.)
===================================================================
암호의 역사는 로마 시대로 까지 거슬러올라간다고 하지만 인터넷을 통해 수많은 금융 거래가 이루어지있는 요즘 처럼 암호화된 통신이 널리 사용되는 때도 아마 없을 것이다. 실제로 어떤 파일 혹은 문장을 인터넷상의 다른 사용자에게 비밀리에 전송하려고 할 때 어떤 방법을 사용할 수 있을까? 가장 먼저 생각할 수 있는 것은 우리가 흔히 zip 파일을 압축할 때 이용하는 대칭키 알고리즘(혹은 비밀키 알고리즘)이다. 이 방식에서는 암호화하는 측과 암호를 푸는 측이 같은 키를 이용한다. 그러나 인터넷 상의 정보는 언제든지 훔쳐보기가 가능하기 때문에 이 방법은 네트웍상의 통신에 적용하기에 적절하지 않다. 암호(비밀키)를 인터넷을 통해 주고 받는 것이 불가능하기 때문이다.

그리하여 나오게 된 것이 공개키 알고리즘인데 공개키 알고리즘은 암호화 할 때 사용하는 암호와 암호를 풀 때 사용하는 암호가 서로 다르다. 서로 다른 키를 사용함으로서 비밀리에 키를 교환할 필요 자체가 없어졌다. 제 3 자는 암호화키를 알고 있더라도 암호문을 풀 수 없으므로 암호화할 때 사용하는 키는 중간에 누가 가로채도 상관없다. 아니 오히려 사용하기 편하게 잘 보이는 곳에 놔두는 것이 좋을 것이다. 누구든지 이 공개키로 메시지를 암호화해서 보내면 그 메시지를 받는 사람은 숨겨둔 비밀키(혹은 개인키라고도 한다)를 이용하여 이를 풀어볼 수 있다. 얼핏 생각하면 믿기 힘든 이러한 일이 수학의 마술로 인해 가능해 졌다.

공개키 알고리즘의 대표적인 RSA는 1977년에 Ron Rivest, Adi Shamir와 Leonard Adleman에 의해 개발되었다. RSA는 큰 수의 소인수 분해가 매우 어렵다는 사실을 이용한다. 현재 슈퍼컴퓨터와 복잡한 수학적 기법들을 이용해 155자리 합성수가 인수분해 되었는데(1999년 8월) 155를 2진수로 표현하면 512 비트이기 때문에 흔히 RSA에서 사용하는 키는 이보다 길이가 2배 긴 1024비트를 이용한다.

RSA의 원리

집합 {1, 2, … , n-1} 의 원소들 중에서 n 과 서로소의 관계에 있는 원소들의 개수를 φ(n)으로 나타내고 이를 Euler의 φ-function이라고 한다. 특별히 소수 p에 대해서 φ(p) = p-1 이다. 큰 정수 n에 대해 φ(n)의 값을 알기 위해서는 n의 소인수 분해가 필수적이다. 즉, n이 두 소수 p와 q의 곱일 때 φ(n) = (p-1)(q-1)이다. 따라서 소인수 분해 없이 φ(n)을 구하기는 매우 어렵다. Euler의 정리란, 서로 소인 두 양의 정수 a, n에 대해 aφ(n) ≡ 1 (mod n) 이 성립한다는 것이다.

Step 1
두개의 큰 소수 p, q를 선정하여 자신의 비밀열쇠로 한다
Step 2
n = pq인 n을 공개하고 φ(n)과 서로 소인 임의의 정수 e를 선택하여 공개키로 한다.
Step 3
ed ≡ 1 (mod φ(n)) 이 되는 d를 Euclidean Algorithm등으로 계산하여 비밀 열쇠로 한다.
즉, p와 q 그리고 d는 비밀 열쇠로, n과 e는 공개키로 한다.

암호화 Step
평문 M을 공개키 e를 사용하여 Me를 계산한 다음 modular n으로 간단히 한다.
즉 암호문 C는 다음과 같다. C = Me (mod n)

복호화 Step.
암호문 C를 비밀열쇠 d를 이용하여 Cd한 다음 modular n으로 간단히 한다.
다시 평문이 나오게 되는 관계식은 다음과 같다.
Cd ≡ (Me)d = Mtφ(n)+1 = Mφ(n)t M ≡ M (mod n)
여기서 t는 ed ≡ 1 (mod φ(n))에서 유도되는 ed = tφ(n)+1 을 만족하는 정수이다.

실제 사용 예
예를 들어 설명하면 다음과 같다. RSA 암호화 기법에는 private key, public key, modulus가 필요하다.
암호화하는데에는 public key와 modulus, 복호화하는데에는 private key와 modulus가 이용된다.

암호화 : (암호화된문장) = (원래문장)^(public key) mod modulus
암호화 : (원래문장) = (암호화된문장)^(private key) mod modulus

단, 여기서 (원래 문장)의 비트수는 (modulus)의 비트수보다 작아야 한다. 따라서 실제의 메세지를 n보다 작거나 같은 길이로 잘라서 입력해야 한다. 좀 더 구체적인 예를 들기 위해서 이번에는 크기가 매우(!) 작은 수를 이용하여 위의 과정을 따라가 보자
public key = 5
private key = 77
modulus = 119
비밀키를 자신이 소유하고 공개키는 안전한 공개키 디렉토리에 등록한다.
그런 다음 아스키코드 한자리 “a”=65를 전송한다고 해 보자.(아스키코드는 7비트 이내에 있으므로 7비트 짜리 modulus로 전송할 수 있다.)

암호화 : 65^5 mod 119 = 46
복호화 : 46^77 mod 119 = 65

잘 작동한다는 것을 알 수 있다.

키를 생성하기

이러한 RSA 암호화 알고리즘을 이용하기 위해서는 자신만의 공개키, 비밀키, modulus의 쌍을 필요로 한다. 이러한 숫자 쌍을 생성하는 프로그램을 제작해 보았다.(첨부 파일에 있는 RSAKeyGen.exe 실행)

php 소스 코드

php에서 RSA 암호화 알고리즘을 이용할 수 있도록 함수 및 예제를 아래에 첨부하였다.
// PHP의 BCMath 기능을 필요로합니다. –enable-bcmath 옵션을 붙여 컴파일 해야합니다.
// 최신 버젼의 PHP에는 BCMath가 기본으로 들어가 있습니다.

// Calculate (p ^ q) mod r
function pow_mod($p, $q, $r)
{
// Extract powers of 2 from $q
$factors = array();
$div = $q;
$power_of_two = 0;

// BCCOMP_LARGER == 1
while(bccomp($div, “0”) == 1)
{
$rem = bcmod($div, 2);
$div = bcdiv($div, 2);

if($rem) array_push($factors, $power_of_two);
$power_of_two++;
}

// Calculate partial results for each factor, using each partial result as a
// starting point for the next. This depends of the factors of two being
// generated in increasing order.
$partial_results = array();
$part_res = $p;
$idx = 0;
foreach($factors as $factor)
{
while($idx < $factor)
{
$part_res = bcpow($part_res, “2”);
$part_res = bcmod($part_res, $r);

$idx++;
}

array_push($partial_results, $part_res);
}

// Calculate final result
$result = “1”;
foreach($partial_results as $part_res)
{
$result = bcmul($result, $part_res);
$result = bcmod($result, $r);
}

return $result;
}

// Function to add padding to a decrypted string
// We need to know if this is a private or a public key operation
function add_PKCS1_padding($data, $isPublicKey, $blocksize)
{
$pad_length = $blocksize – 3 – strlen($data);
if($isPublicKey)
{
$block_type = “x02”;
$padding = “”;
for($i = 0; $i < $pad_length; $i++)
{
$rnd = mt_rand(1, 255);
$padding .= chr($rnd);
}
}
else
{
$block_type = “x01”;
$padding = str_repeat(“xFF”, $pad_length);
}

return “x00” . $block_type . $padding . “x00” . $data;
}

// Remove padding from a decrypted string
function remove_PKCS1_padding($data, $blocksize)
{
assert(strlen($data) == $blocksize);
$data = substr($data, 1);

// We cannot deal with block type 0
if($data{0} == “”)
die(“Block type 0 not implemented.”);

// Then the block type must be 1 or 2
assert(($data{0} == “x01”) || ($data{0} == “x02”));

// Remove the padding
$offset = strpos($data, “”, 1);
return substr($data, $offset + 1);
}

function hex_to_number($data)
{
$len = strlen($data);
$result = “0”;
for($i = 0; $i < $len - 1; $i++)
{
$result = bcadd($result, hexdec($data{$i}));
$result = bcmul($result, 16);
}
$result = bcadd($result, hexdec($data{$len-1}));
return $result;
}

// Convert binary data to a decimal number
function binary_to_number($data)
{
$base = “256”;
$radix = “1”;
$result = “0”;
for($i = strlen($data) – 1; $i >= 0; $i–)
{
$digit = ord($data{$i});
$part_res = bcmul($digit, $radix);
$result = bcadd($result, $part_res);
$radix = bcmul($radix, $base);
}
return $result;
}

// Convert a number back into binary form
function number_to_binary($number, $blocksize)
{
$base = “256”;
$result = “”;
$div = $number;
while($div > 0)
{
$mod = bcmod($div, $base);
$div = bcdiv($div, $base);
$result = chr($mod) . $result;
}
return str_pad($result, $blocksize, “x00”, STR_PAD_LEFT);
}

function rsa_encrypt($message, $public_key, $modulus, $keylength)
{
$padded = add_PKCS1_padding($message, true, $keylength / 8);
$number = binary_to_number($padded);
$encrypted = pow_mod($number, $public_key, $modulus);
return $encrypted;
}

function rsa_decrypt($message, $private_key, $modulus, $keylength)
{
$decrypted = pow_mod($message, $private_key, $modulus);
$result = number_to_binary($decrypted, $keylength / 8);
return remove_PKCS1_padding($result, $keylength / 8);
}

$public_key = hex_to_number(“9E649FF1”);
$private_key = hex_to_number(“7C0732C4379EDE1FB6E6CF2E7B262B41”);
$modulus = hex_to_number(“95C3BE09B678F8BD55F859CC24B4797B”);

$enc = rsa_encrypt(“메롱 약오르지롱~”, $public_key, $modulus, 128);
echo rsa_decrypt($enc, $private_key, $modulus, 128);
?>

위의 예제에서는 128 비트 암호화를 이용하였으나 충분히 512 비트 1024비트로 확장할 수 있다. 비트수가 늘어날수록 암호는 깨기 어려워지는 대신 속도가 느려지는 단점이 있다.