예전에 웹메일은 만들다가 중단했던 가장 큰 이유 중 하나는 imap_open 을 사용하기 위해서는 아이디와 비밀번호가 필요하다는 점이었다. 세션을 유지시키려면 아이디와 비밀번호를 저장하고 있었어야 했는데 이 부분을 도대체 어떻게 안전하게 처리할 지 생각해낼 수가 없었다.
(mbox 방식이라면, 그냥 mbox 파일을 imap_open 으로 여는 꽁수가 있다.)
흠 다시 만들 생각을 하고.. 오픈소스 웹메일인 SquirrelMail 은 사용자의 암호와 비밀번호를 어떻게 저장하고 있나를 살펴봤는데 1.4.3a 버젼의 암호 저장 방식은 너무나도 황당했다. -_-;;
SquirrelMail 에선 비밀번호의 길이와 똑같은 길이의 OneTimePad 라는 이름의 salt 를 만들어내고, (비밀번호 길이만큼 srand 로 0~255 사이의 값을 얻어서..) salt 와 비밀번호를 xor 한 다음에 base64 를 해서 저장을 해두는데... 문제는 그 salt 와.. 암호화된 비밀번호를 둘 다 session 에 저장시켜 놓는 다는 점이다.
안전하기 위해선 세션이 가로채기를 당해도 문제가 없도록, xor 된 암호와 salt 를 분산 시켜서 저장해놓았어야 한다고 생각한다. (1.4.4 에서는 salt 는 cookie 에 저장시키기 때문에 이전 방식보다 안전하다고 생각한다.)
뭐 하튼 나도 저런 식으로 비밀번호를 암호화 하고, salt 와 암호화된 비밀번호를 세션과 쿠키에 나눠서 넣는 식으로 관리하면 될 것 같다. 다만 squirrelmail 에서 사용하는 방식은 암호의 길이를 유추해내는게 가능하기 때문에, 암호가 짧아질 경우 안전을 보장하기 힘들어지는 문제점이 있을 수 있어보인다.
-
#define SALT_LEN 32
-
-
char alphabet[] = "abcdefghijklmnopqrstuvwxyzABCDEFG....~!@#$%^*()_+-=[]{}\|'\";:/?.>,<";
-
int alphabet_size = strlen(alphabet);
-
-
int salt[SALT_LEN];
-
-
len = strlen(pass);
-
for( i = 0 ; i <len ; i++ ){
-
salt[i] = alphabet[rand()%alphabet_size];
-
}
-
-
for( ; i <SALT ; i++ ){
-
char r1, r2;
-
r1 = alphabet[rand()%alphabet_size];
-
r2 = alphabet[rand()%alphabet_size];
-
-
salt[i] = r1 ^ r2;
-
}
password 는 키보드로 입력할 수 있는 값이니까 0~9, a~z, A~Z 그리고 특수문자들로만 구성될 것이므로 위의 pseudo code 에서처럼 salt 를 만들어낼 때 password 길이 까지는 0~9, a~z, A~Z 와 특수문자 중에서 랜덤하게 뽑아내고, password 의 길이를 넘어서는 입력 가능한 값 (compiler 용어론 alphabet) 두 개를 xor 해서 나올 수 있는 값으로 뽑아내는 방식도 괜찮을 거 같다.