Your wish is my command

It’s a long journey

Determine CPU Type on FreeBSD

/etc/make.conf에 CPUTYPE을 설정하려고 CPUTYPE을 정확하게 알고싶다면 sysutils/x86info를 사용하면 된다.

# x86info
x86info v1.27.  Dave Jones 2001-2010
Feedback to <davej@redhat.com>.

Found 2 CPUs
--------------------------------------------------------------------------
CPU #1
EFamily: 1 EModel: 0 Family: 15 Model: 10 Stepping: 0
CPU Model: Unknown CPU
Processor name string: AMD Phenom(tm) II X6 1055T Processor
Monitor/Mwait: min/max line size 0/0
Address Size: 48 bits virtual, 48 bits physical
The physical package has 12 of 8 possible cores implemented.
--------------------------------------------------------------------------
CPU #2
EFamily: 1 EModel: 0 Family: 15 Model: 10 Stepping: 0
CPU Model: Unknown CPU
Processor name string: AMD Phenom(tm) II X6 1055T Processor
Monitor/Mwait: min/max line size 0/0
Address Size: 48 bits virtual, 48 bits physical
The physical package has 12 of 8 possible cores implemented.
--------------------------------------------------------------------------
 running at an estimated 2.85GHz

그냥 athelon64로 설정했음.

Ssh Tunneling

기록은 기억보다 오래 기억된다는 측면에서

ssh -f -L 3307:dbdev.woosum.net:4444 whitekid@woosum.net sleep 864000

이렇게 하면 ssh로 woosum.net으로 접속하고 다시 여기서 dbdev.woosum.net:4444로 접속하여 tunneling을 127.0.0.1의 3307 포트에 만든다.

  • -f : background 작업으로
  • -L 3307 : 로컬에서 listen할 포트
  • dbdev.woosum.net : 접속할 호스트
  • 4444 : ssh-host에서 ssh로 접속해서 다시 접속할 호스트
  • whitekid@woosum.net : ssh로 접속할 정보
  • sleep 864000 : 접속해서 하루동안 sleep 실행, -f 옵션이 있으므로 연결하고 바로 command prompt로 떨어진다.

주의: 연결할 때 localhost 말고 127.0.0.1로 접속할 것.

FreeBSD Ports의 Rails를 3.1.0으로 업데이트하기..

FreeBSD의 ports에 들어있는 rails는 3.0.10입니다. 뭐 예내들이 조금 늦는가 했습니다. 근데 대기중인 pr에도 rails 3.1.0으로 업데이트하는 pr이 없습니다.

이미 rails guide는 3.1.0으로 가있는데.. 안되는 것도 있고… 지금와서 3.0.10에서 작업할 수 는 없잖아요.

결국 몇 시간 삽질끝에 ports를 업데이트 했습니다. 역시 쉽지 않습니다. rails는 하나의 ports가 아닌 여러 ports의 집합이죠. 그래서 www/rubygems-rails만 수정한다고 되는 것이 아니죠. actionpack, activerecord, activeresource도 모두  ports에서 업데이트 해야합니다. 게다가 하다보니깐 rubygem의 ports들이 상당히 예전 버전이 많습니다. 현재하고 호환이 안되는 버전으로요… 결국 이것까지 같이 업데이트 되고~~ ^^;

오랜만에 send-pr 할거냐구요? 글쎄요.. 아직은 모르겠습니다~ 우선 몇몇 project에 적용해서 되는지 보구요..

다시 정리하는 /etc/make.conf

CPUTYPE= i686
CFLAGS= -O2 -fno-strict-aliasing -pipe
KERNCONF= YOUR_KERNEL_CONF_HERE
NO_X= true
WITHOUT_X11= yes

MASTER_SITE_BACKUP?= \
    http://ftp.kr.FreeBSD.org/pub/FreeBSD/ports/distfiles/${DIST_SUBDIR}/
    http://ftp.kaist.ac.kr/FreeBSD/ports/distfiles/${DIST_SUBDIR}/

MASTER_SITE_OVERRIDE?= ${MASTER_SITE_BACKUP}

# sf.net 다운로드 사이트중 가장 빠른것 설정
MASTER_SITE_SOURCEFORGE= \
    http://cdnetworks-kr-2.dl.sourceforge.net/project/%SUBDIR%/

MySQL의 Aes_encrypt / Aes_decrypt와 호환되는 Python/ Php 구현

Nate 해킹사건 때문에 데이터 암호화를 보다 더 강화하기로 했다. 물론 AES로 하자고 그래서 하는데, 부득불 mysql의 aes_encrypt / aes_decrypt와 호환되게 한다고 해서 하다가 몇가지 꼼수를 부리게 되었다.

AES

표준 암호화/ 복호화 알고리즘은 미국 어디선가 공모해서 여러가지 응모한 알고리즘 중에 rijndael을 선택하였고, 그중에 128bit 블럭 알고리즘은 표준으로 정하고 AES(Advanced Encrypt Standard)라고 이름을 붙혔다.

결국 rijndael-128 == AES 인 것이다.

rijndael 의 모드

  • ECB: 각 블럭은 서로 독립적이다. MySQL에서 쓰는 모드는 이거다.
  • CFB, CBC, CTR 등 나머지 모드는 약간 미묘한 차이가 있지만, MySQL은 ECB를 쓰기에 나중에 시간나면 공부하자.

MySQL의 AES의 제한사항은

  • 128 비트 밖에 지원하지 못한다. 196, 256등 다른 비트를 지원하지 못하며 지원하려면 소스를 다시 컴파일해야한다.
  • 다시 컴파일 한다고 그래도 한가지 방식밖에 못쓴다. ㅡㅡ
  • initialization vector를 사용하지 않는다. mcrypt에서는 random iv를 사용해서 보안을 한층 더 강화할 수 있을 것 같은데…
  • 블럭 비트의 여유 바이트를 맞추기 위해서 데이터에 약간의 추가 데이터를 더하는데, 안의 데이터는 추가할 데이터의 길이만큼을 chr(length(pading)))을 더해서 맞춘다.
  • 패딩 길이는 0은 없다. 1부터 시작한다. 0이 없는 이유는 0이 붙으면 다시 decrypt할때 어디까지 잘라내야할 지 곤란하기 때문이다.

구현

  • rijndael은 그냥 mcrypt를 쓴다. MySQL은 aes 소스 자체를 포함하고 있다. 이게 mcrypt인지 아닌지는 모름..
  • AES == rijndael-128 / ecb

Python 버전

참고로 python에서 padding은 \x00을 사용한다.

PHP 버전

php 버전의 문제는 bin2hex는 php 버전이 있지만, 역은 undocumented다. 그래서 구현해줘야한다.

참고

  • MySQL의 AES가 128면 불안해 하는 사람(^^)들이 있다면, MySQL의 aes 함수들은 포기하고 libmcrypt를 이용해서 stored procedure를 만드는 것이 좋다.
  • 근데 굳이 MySQL의 command line에서 이것을 쓴다는 것은 글쎄 개인적인 소견으론 바람직하지 않는 것 같다.
  • MySQL에서 사용하는 것을 포기한다면 initialization vector를 사용하는 것이 좋겠다.
  • 음 다음에 데이터 암호화 한다면 아래처럼 해볼듯…
    • 랜덤 iv 생성 -> 데이터 암호화 (with salt) -> iv 자체도 암호화 -> 약간 섞어서 최종 데이터 생성 -> bin2hex

Array Recusive하게 모든 문자열 인코딩 바꾸기

요즘 json API를 작업하는데, 문제는 내부 문자셋이 euc-kr다. 그래서 결과를 모두 받아서 array 통체로 문자열 인코딩을 변경할 필요가 있어서 간단하게 해봤음.~

public function conv($array){
  $output = array();
  $param = array(&$this, &$output);

  array_walk($array, function($v, $k, $param){
    if(is_array($v)){
      $v = $param[0]->conv($v);
    } else if (is_string($v)){
      $v = iconv('euckr', 'utf8', $v);
    }

    $param[1][$k] = $v;
  }, &$param);
  return $output;
}

function __destruct(){
    echo json_encode($this->conv($this->resp));
  }
}

Ubuntu 설치후 한글이 안이쁠때..

우분투를 처음 설치하면 한글 폰트에 Antialias가 설정되어 있지 않은 상태다. 아주 예전 한글이 안티앨리어스가 더 안이뻤을 때 이야기인데 아직도 이게 기본값이여서 그런건데…

간단하게 /etc/fonts/conf.d/29-language-selector-ko-kr.conf 파일을 날려버리면 된다. 안전하게는 이름을 다른 것으로 변경하면 되겠지!!

Python 2.7 Release Note를 보다가..

http://docs.python.org/dev/whatsnew/2.7.html#pep-372-adding-an-ordered-dictionary-to-collections

순서가 보장되는 딕셔너리.. 그래 이거 필요했다. 특히 json으로 넒길때 아무리 순서가 없다지만. .그래도 순서 있는게 좋지 않겠어?

http://docs.python.org/dev/whatsnew/2.7.html#pep-378-format-specifier-for-thousands-separator

format()이란것을 통해서 해야된다는 것이 불편하긴 하지만… 그래도 locale 모듈을 통해서 한다는 것에 비하면, 천지차이라고나 할까?

http://docs.python.org/dev/whatsnew/2.7.html#pep-3106-dictionary-views

그래 이것도 맞는 것 같다… key를 iteration하면서 그 리스트를 수정하는 경우.. 뭔가 애매한 부분이 있었었지…

아래건… 실수할 가능성이 많아진 문법인듯..

>>> {1,2,3,4,5}
set([1, 2, 3, 4, 5])
>>> set() # empty set
set([])
>>> {} # empty dict
{}

http://docs.python.org/dev/library/io.html#module-io

cStringIO 보단 그냥 io 써야겠다.. C로 작성되어 2~20배 빨라졌다고 함… 근데 편차가 왜이리 큰겨?

http://docs.python.org/dev/library/shutil.html#shutil.make_archive

간단한 압축엔 유용하겠는걸…

Python Exception Handler Decorator

쩝.. 내가봐도 참 난해한 코드 ㅋㅋㅋ

class MyException(Exception): pass
class MyException1(Exception): pass
class MyException2(Exception): pass


def exception_catch(exceptions, exception_handler):
    def wrap(func):
        def new_func(*args, **kwargs):
            try:
                return func(*args, **kwargs)
            except exceptions, e:
                return exception_handler(e, *args, **kwargs)
        return new_func
    return wrap

def error_handler(*args, **kwargs):
    print 'handle error'

def my_function():
    pass

@exception_catch((MyException, MyException1), error_handler)
def my_raise_function():
    raise MyException, 'hello'

@exception_catch((MyException, MyException1), error_handler)
def my_raise_function_1():
    raise MyException2, 'unexpected error'

@exception_catch(MyException, error_handler)
def my_raise_function_2():
    raise MyException, 'unexpected error'


my_function()
my_raise_function()
my_raise_function_2()