php->c 컨버팅 다시 한번 도와 주세요 ㅠ.ㅠ
글쓴이: mrbaen / 작성시간: 수, 2008/03/05 - 11:50오전
어제 글을 올려서많은 도움을 받고 차분하게 다시 나름(?)정리 해가면서 삽질을 했는데 하다가 또 막혔네요 ㅠ.ㅠ 도와주세요.
16자리씩 잘라서 비트 연산해서 암호화 하는건데
루프돌다가 4번째 부터 값이 틀려 지네요
php소스
<? function bytexor($a,$b) { //echo "a:/$a/ ||| b:/$b/\n"; $c=""; for($i=0;$i<16;$i++) { $d = $a{$i}^$b{$i}; $c.=$d; //echo"buf$i:/$d/" . ord($d) . "\n"; } return $c; } function decrypt_md5($msg,$key) { $string=""; $buffer=""; $key2=""; while($msg) { $key2=pack("H*",md5($key.$key2.$buffer)); $buffer=bytexor(substr($msg,0,16),$key2); $string.=$buffer; $msg=substr($msg,16); } return($string); } function encrypt_md5($msg,$key) { $string=""; $buffer=""; $key2=""; while($msg) { $i++; //echo $key.$key2.$buffer; $key1 = $key.$key2.$buffer; echo "key1:/$key1/\n"; $md = md5($key1); echo "md5:/$md/\n"; $key2=pack("H*",$md); echo "key2:/$key2/\n"; $buffer=substr($msg,0,16); echo "buffer:/$buffer/\n"; $str = bytexor($buffer,$key2); echo "bytexor:/" . strlen($str) . "/$str/\n"; $string.=$str; echo "ret_msg:/$string/\n"; $msg=substr($msg,16); echo "msg:/$msg/\n"; echo "\n\n"; } return($string); } // 사용 예 $message = "☆━2008년*♡*┐┃설날부턴 ° ː│。°더많이°│ː 。사랑할께~┃└*♡* *‥─━★"; $key = "9857861"; $encrypted = encrypt_md5($message, $key); $decrypted = decrypt_md5($encrypted, $key); echo "msg = ".strlen($message) . "$message"; echo " \n"; echo "Encrypted = ".strlen($encrypted) . "/$encrypted/"; echo " \n"; echo "Decrypted = $decrypted"; echo " \n"; ?>
컨버팅중인 C소스
#include <stdio.h> #include <stdlib.h> #include <errno.h> #include <string.h> #include <ctype.h> #include <math.h> #include <time.h> #include <sys/types.h> #include <netinet/in.h> #include <sys/socket.h> #include <sys/wait.h> #include <unistd.h> #include <netdb.h> //#include "base64EnDecode.h" //#include "Crypt_EnDecode.h" #include <openssl/md5.h> #include <sys/stat.h> #include <fcntl.h> char substr(char *ret , const char *txt, int sno , int eno) { if (eno == 0) eno = strlen(txt) - sno; if (eno > (strlen(txt)-sno)) eno = strlen(txt) - sno; if (sno>strlen(txt)) { strcpy(ret , ""); return; } char buffer1[eno+1] ; int i,j; strcpy(buffer1 , ""); for (i=sno; i<(sno + eno);i++ ) { sprintf(buffer1 , "%s%c" , buffer1 , txt[i]); } //printf("j:%d /1ret:/%s/ buffer1:/%s/ txt:/%s/\n" , j , ret , buffer1 , txt); strcpy(ret , buffer1); //printf("2ret:/%s/ buffer1:/%s/ txt:/%s/\n" , ret , buffer1 , txt); } static char x2b(char c) { if(c>='0' && c<='9') return c-'0'; else if (c>='A' && c<='F') return c-'A'+0xa; else if (c>='a' && c<='f') return c-'a'+0xa; return -1; // error } int bin2hex(char *buf, char *textbuf, int len, int type) { char hexs[]="0123456789ABCDEF"; int i; int j=0; for(i=0;i<len;i++) { textbuf[j++] = hexs[ (buf[i]>>4)&0x0f ]; textbuf[j++] = hexs[ buf[i]&0x0f ]; if(type==1 && (i+1 != len)) { textbuf[j++] = ' '; } } textbuf[j]=0; } int hex2bin( char *buf , char *hexstring , int maxbuf) { //printf("buf:/%s/hexstring:/%s/maxbuf:/%d/\n" , buf , hexstring , maxbuf); char *pc=hexstring; int i=0; int byte=-1; // -1 empty //printf("pc:/%s/hexstring:/%s/maxbuf:/%d/\n" , hexstring , hexstring , maxbuf); while(*pc!='\0' && i<maxbuf ) { if( isxdigit(*pc) ) { if(byte == -1) { byte = x2b(*pc); } else { buf[i] = byte<<4 | x2b(*pc); i++; byte = -1; } } else { if(byte != -1) { buf[i]= byte; i++; byte = -1; } } //printf("pc:/%s/ buf:/%s/ buflen:/%d/\n" , pc,buf , strlen(buf)); pc++; } //printf("buf:/%s/hexstring:/%s/maxbuf:/%d/\n" , buf , hexstring , maxbuf); return i; } void bytexor(char *ret , const char *a, const char *b) { //printf("a:%s b:%s\n" , a , b); char buf[100]=""; int i; for(i = 0; i < 16; i++) { buf[i] = a[i] ^ b[i]; //printf("cc:%d/i:%d/%d\n" ,strlen(buf),i,buf[i]); // buf = tmp; } //strcpy(tmp , substr(buf , 0,16)); strcpy(ret , buf); } char *MD5_Encrypt(char *_md5 , char *msg) { char lsBuff[strlen(msg)]; unsigned char lucpMD5[16] = ""; unsigned char ret[16] = ""; unsigned long lulLen = strlen(msg); int li; strcpy (lsBuff,msg); MD5_CTX lmdContext; MD5_Init(&lmdContext); MD5_Update(&lmdContext,lsBuff,lulLen); MD5_Final(lucpMD5, &lmdContext); for(li=0;li<16;li++) { //printf("%02x",lucpMD5[li]); sprintf(ret , "%s%02x" , ret , lucpMD5[li]); //printf("aa%d:%s\n" , li,ret); } strcpy(_md5 , ret); //printf("ret:%s\n",_md5); } void Hpack(char *key2 , char *key1) { char _md5[100]=""; MD5_Encrypt(_md5 , key1); printf("md:/%s/\n" , _md5); //printf("20:/%s/\n" , key2); hex2bin(key2 , _md5 , 16); //printf("21:/%s/\n" , key2); } char encrypt_md5(char *ret_msg , char *msg , char *key) { char key1[100] = ""; char key2[17] = ""; char msg1[2000] = ""; char buffer[17] = ""; char buf[17] = ""; char tmp[2000] = ""; strcpy(msg1 , msg); while(strlen(msg1)>0) { /* $key2=pack("H*",md5($key.$key2.$buffer)); $buffer=substr($msg,0,16); $string.=bytexor($buffer,$key2); $msg=substr($msg,16); */ sprintf(key1 , "%s%s%s" , key,key2,buffer); printf("key1:/%s/\n" , key1); Hpack(key2 , key1); printf("key2:/%s/\n" , key2); substr(buffer , msg1, 0,16); printf("buffer1:%s\n" , buffer); bytexor(buf , buffer , key2); printf("bytexor:/%d/%s/\n" , strlen(buf),buf); sprintf(ret_msg , "%s%s" , ret_msg , buf); printf("ret_msg:/%s/\n" , ret_msg); substr(msg1 , msg1 , 16,0); printf("msg:%s/\n" , msg1); printf("\n\n"); // exit(0); } } int main(int argc, char *argv[]) { // 사용 예 //$message = "☆━2008년*♡*┐┃설날부턴 ° ː│。°더많이°│ː 。사랑할께~┃└*♡* *‥─━★"; //$key = "985786"; char msg[2000]; char key[10]; strcpy(msg , "☆━2008년*♡*┐┃설날부턴 ° ː│。°더많이°│ː 。사랑할께~┃└*♡* *‥─━★"); strcpy(key , "9857861"); char ret_msg1[2000] = ""; char ret_msg2[2000] = ""; //printf("msg = /%s/\n" , msg); encrypt_md5(ret_msg1 , msg , key); printf("Encrypted = /%s/\n" , ret_msg1); encrypt_md5(ret_msg2 , ret_msg1 , key); //printf("Decrypted = /%s/\n" , ret_msg2); }
첨부된 이미지는 결과 화면 입니다.
File attachments:
첨부 | 파일 크기 |
---|---|
Untitled-2.gif | 29.25 KB |
Forums:
출력이 제대로
683b0004f295d6...의 MD5 해시 값을 두 글자씩 16진수로 읽어들일텐데, 00은 널 문자라서 그 뒤는 문자열로 인식이 안되나봅니다.
아마도 PHP에서는 널 문자 뒤의 문자도 문자열에 포함하도록 길이를 같이 저장하겠죠.
해결방법좀 알려주세요.
ditto님이 말한데로 그런듯 해요.
cdd23788b34d84cf9006f1b832ea6dee
cd d2 37 88 b3 4d 84 cf 90 06 f1 b8 32 ea 6d ee
이것은 0이 연속으로 두번 나오지만 2개식 자르면 00이 아니구요
다음거(문제되는 해시값)
683b0004f295d63bbc392a08053210fb
68 3b 00 04 f2 95 d6 3b bc 39 2a 08 05 32 10 fb
이거는 문제가 발생 하네요.
해결을 어떻게 해야 할까요?
머리가 오버히팅 되두 한참 되서
해결방법을 못찾겠어요 ㅠ.ㅠ
좀 알려주세요.
의외로 공력이 좀
의외로 공력이 좀 드는군요.
말씀드릴게 많은데, 어디서부터 시작해야 될 지 몰라 그냥 코드를 첨부합니다.
"문자열" 이라는 개념은 C 에서 좀 애매합니다.
그러니 그냥 바이트의 배열이라 생각하시고, "길이" 를 알아낼 수 있는 별도의 방법을 강구하셔야 합니다.
짧게 요약하자면, null terminate 기준으로 동작하는 모든 C 함수를 회피하셔야 합니다.
strlen(), printf(), sprintf(), strcpy() 등등.
php 코드의 한줄 한줄을 그대로 옮기는 식으로 만든 코드니 방향만 잡으시고 재작성하시는 게 좋습니다.
OTL
C 에서
C 에서 스트링 개념이 애매한게 아니라..
스트링이 아닌곳에 스트링함수를 쓰기때문에 에러나는거지요..
죄송한데요 md5.h 랑 md5.c 파일은 어떤거를 가져다가 쓰면 되는거져?
죄송한데요 md5.h 랑 md5.c 파일은 어떤거를 가져다가 쓰면 되는거져?
php 소스에 있는거 가져다 썻더니 안되는데
openssl/md5.h 인클루드 하고
php소스에 잇는거랑 gcc소스에 있는거랑 가져다가 해봤는데 에러 몇백줄이 좌악 ㅠ.ㅠ
컴파일하려고
컴파일하려고 삽질하지 마시고, 방향만 잡은 뒤 재작성하세요.
사용된 md5.[ch] 는 검색하면 쉽게 발견하실 수 있습니다.
cv.c 코드 내에 버그가 있습니다.
crypt_md5() 를 다음처럼 수정해야 합니다.
아무 생각없이 디버깅하다, 아무 생각없이 집어넣은 memcpy() 때문에.
덧.
C 에서 byte stream 을 어찌할까하는 고민을 해보시려면,
리눅스 커널의 skbuff 가 좋은 참고자료가 된다고 생각합니다.
queue, list, fifo, filo, lifo, lilo 등 모든 환경과 조건에 사용할 수 있습니다.
(네트웍에 관련된 부가설비는 무시하고 보세요.)
커널에 있는 list 설비(라 해봤자 list.h 꼴랑 하나지만)와 더불어 자주 애용하는 으뜸설비.
OTL
아아..
아아.. 실패입니다.
memcpy() 로 해결이 되는 줄 알았는데 memcpy() 를 잘 못 사용한 버그였더군요.
수정된 코드를 첨부했습니다만, 보시다시피 encrypt() 와 decrypt() 가 나뉘어져 버렸습니다.
어설픈 string_t 가지고는 안되나봐요.
OTL
위에서 다른분들께서
위에서 다른분들께서 말씀하신 것처럼 문자열과 바이트 스트림의 차이를 정확하게 인지해야 할겁니다.
간단하게 생각하면,
바이트 스트림 구조체 만들고 바이트 스트림 처리용 함수 몇개 만들고,
문자열 구조체(문자열, 길이) 만들고 문자열 처리용 함수 몇개 만들면,
이런 류의 컨버팅 작업 때 편하게 이용할 수 있을 겁니다.
---------------------------
Smashing Watermelons~!!
Whatever Nevermind~!!
Keedi Kim
----
use perl;
Keedi Kim
댓글 달기