2011. 7. 13. 14:58

PHP 암호화 관련 개념 정리

암호화

암호화(Cryptography)는 일종의 예술이다. 암호문은 몇 개의 단어를 바꾼 로마의 궤변에서부터 요즘에 사용하는 공개 키와 개인 키(public and private key) 메커리즘에 이르기까지 여러 세기에 걸쳐 사용되었다. 암호화의 목적은 지정된 사람 이외에는 누구도 볼 수 없는 암호문을 만드는 것이다.

이제 몇 페이지에 요즈음 인터넷에서 사용되는 몇 가지 암호화 방식과 동작 원리, 사용대상 등에 대해 살펴보도록 하자.

단방향 암호화

이 방식은 원문을 해독할 수 없도록 암호화하는 과정이다. 언뜻 들으면 사용할 수 없는 방법 같지만 실제 컴퓨터 분야에서는 많이 사용되는 방법이다.

단방향 암호화에 사용되는 알고리즘은 자주 해싱 알고리즘(hashing algorithms)이라고 부른다. 이것은 원문을 이용해 고유한 문자열을 만들어 내는 과정이다. PHP에서 가장 널리 사용되는 해싱 알고리즘은 MD5 알고리즘이다. 이 알고리즘의 실제 동작 방식에 대해서는 자세히 설명하지 않지만 이 방식은 어떤 문자열을 받아서 128비트로 된 고유한 값(fingerprint)을 만들어 내는 것이다.

현재 이 고유한 값을 이용해 거꾸로 원래의 문자열을 알아내는 방법은 불가능하다고 생각된다. 또한 두 가지 문자열에서 생성된 값이 서로 같게 될 확률도 거의 없다. 이 시스템을 완전히 난공불락으로 생각할 수도 있지만, 예상 가능한 문자열을 이용해 무작위로 입력해 그 결과를 비교하는 방법에는 취약하다. 이 공격에 필요한 시간은 해시 데이터의 복잡성에 따라 다르지만 짧은 암호 해독에 걸리는 시간은 그리 길지 않다.

암호가 안전하기만 하다면 MD5 알고리즘은 암호를 암호화하는 좋은 방법이다. 그 이유는 원래의 암호를 다시 해독할 수는 없지만 로그인 시에 사용자가 입력한 암호를 해시로 만들어 비교할 수는 있기 때문이다.

일반 텍스트로 저장된 암호는 보안상 매우 위험하면 MD5 알고리즘을 이용해 변환된 값을 저장해야 한다. 사용자가 로그인해 자신의 암호를 입력하면 이것은 MD5 암호화 과정을 거치게 된다. 만일 이 해시 값이 이미 저장되어 있던 것과 같으며, 두 개의 암호는 서로 같다고 판단된다.

간단한 암호를 사용하는 것은 브루트 포스 공격(brute force attack)의 대상이 되기 때문에 매우 위험하다는 것을 명심하기 바란다. 안전한 암호를 선택하는 방법은 이 장의 끝에 나와 있는 참고 자료를 이용하면 된다.

PHP의 md5() 함수는 다음과 같이 문자열을 입력받아 고유한 값을 만들어 낸다: 

<?php
$fingerprint = md5($password);
?>

Important 

MD5 알고리즘은 다양한 용도로 사용된다. 그 중하나는 파일이 수정되었는지를 확인할 때 사용된다는 것이다. 파일의 MD5 해시를 저장해 두면 이 파일이 변경되었는지를 금방 확인할 수 있다. 


CRC32 함수도 비슷한 기능을 한다. CRC32 함수는 128비트가 아닌 32비트의 고유 값을 생성하기 때문에 암호에는 적당하지 않다. 따라서 두 개의 입력 값이 같은 결과를 나타탤 확률이 더 높다.

MD5와 CRC32 함수 이외에, PHP는 mhash 라이브러리를 제공한다. 이 추가적인 알고리즘는 mhash() 함수를 이용한다. 이 함수는 두 개 또는 세 개의 인자를 사용한다. 첫 번째 인자는 알고리즘을 나타내는 상수, 두 번재 인자는 해시로 만들 문자열, 세 번째 인자는 해싱 알고리즘에서 사용되는 키(key)이다. 다음은 MD5 알고리즘과 mhash()를 이용한 해싱의 예이다: 

<?php
$passphrase = "this is my secret passphrase";
echo("My passpharse hashed using md5 is: ");
echo(mhash(MASH_MD5, $passphrase));
?>

mhash를 지원하는 주요 알고리즘은 다음과 같다. 좀더 자세한 정보는 http://mhash.sourceforce.net/ 을 참고하면 된다.

알고리즘 
특징 

CRC32 
이 알고리즘은 주로 데이터 전송 시에 체크섬(checksums)을 위해 사용된다. mhash는 이 알고리즘을 위해 두 가지를 제공하는데, MHASH_CRC32는 주로 이더넷 통신에서 사용되면 MHASH_CRC32는 ZIP 프로그램에서 사용된다. 

MD5 
md5() 함수의 알고리즘이다. 상수 MHASH_MD5를 사용한다. 

MD4 
MD4는 MD5와 비슷하지만 보안성이 떨어진다. MD5로 대체되었기 때문에 MD4를 사용하지 않는다. MHASH_MD4 상수를 사용한다. 

SHA1 
이 알고리즘은 NIST의 디지털 서명 표준을 사용된다. 상수 MHASG_SHA1을 사용한다. 

HAVAL 
MD5의 변형 판으로 다양한 길이의 결과를 갖는다. mhash에서는 MHASH_HAVAL256, MHASH_MAVAL192, MHASH_HAVAL160, MHASH_HAVAL128 등을 사용한다. 

RIPEMD160 
MD4, MD5, RIPEMD를 대체하기 위해 설계된 160비트 알고리즘이다. 그러나 여전히 MD5가 많이 사용되고 있다. 상수 MHASH_RIPEMD160을 이용한다. 

TIGER 
TIGER은 매우 빠른 해싱 기능을 위해 설계되었다. 원래 64비트 컴퓨터에서 사용하려고 설계되었지만 다른 컴퓨터에서 그다지 느리지는 않다. 상수 MHASH_TIGER192, MHASH_TIGER160, MHASH_TIGER128을 사용한다. 

GOST 
러시아의 디지털 서명 표준으로 256비트를 지원한다. 상수 MHASH_GOST를 사용한다. 


대칭형 암호화(Symmetric Encryption)

키(key)를 이용해 문자열을 암호화하는 방버이다. 전송자와 수신자가 알고 있는 키를 이용해 동일한 알고리즘에서 문자열을 암호화/복호화 한다. 2차 세계 대전 중에 암호화 기계(enigma machine)에 사용된 방식이다.

이 암호화 방식은 많은 약점과 문제점이 있다. 그 중 하나는 전송자와 수신자가 키를 알고있는 유일한 사람들인지를 확인하는 것이다. 만일 누군가 타인이 키를 얻어 암호화 된 메시지를 가로챈다면 이 메시지를 해석하는 것은 매우 간단한 일이다. 일반적으로 생각해서 만일 키를 안전하게 보관할 수만 있다면 이 방식은 매우 안전하다. PHP에서는 mcrypt 라이브러리를 이용해서 다양한 알고리즘을 이용하는 호스트에 접근할 수 있다.

mcrypt에서 사용되는 일반적인 암호화 방식은 다음과 같다. 보다 자세한 정보는 http://mcrypt.hellug.gr/mcrypt/mcrypt.html을 참고했다.

알고리즘 
특징 

DES 
전통적인 DES 알고리즘으로 키의 길이가 작아 비교적 보안에 취약하다. 상수 MCRYPT_DES를 사용한다. 

3DES/Triple DES 
DES의 변형 판이다. 유효 키 길이는 112비트이다. 상수 MCRYPT_3DES를 사용한다. 

CAST-128 
캐나다에서 설계된 알고리즘으로 128비트 키와 64비트 블럭을 가진다. 상수 MCRYPT_CAST_128을 사용한다. 

CAST-256 
CAST-128의 확장 판으로 알고리즘으로 256비트 키와 128비트 블럭을 가진다. 상수 MCRYPT_CAST_256을 사용한다. 

XTEA 
128비트 키와 64비트 브럭을 가진다. 상수 MCRYPT_XTEA를 사용한다. 

3-WAY 
96비트 키와 블럭을 가진다. 상수 MCRYPT_THREEWAY를 사용한다. 

SKIPJACK 
미국 NSA에서 조건부 암호화 표준으로 설계한 알고리즘이지만 표준화되지 못했다. mcryp에서 추가 라이브러리를 이용해 접근할 수 있으며 80비트 키를 가진다. 상수 MCRYPT_SKIPJACK를 사용한다. 

BLOWFISH 
DES를 개선한 알고리즘으로 최대 448비트 길이의 키를 사용할 수 있다. 상수 MCRYPT_BLOWFISH를 사용한다. 

TWOFISH 
보안성이 높고 융통성이 있다. 128, 192, 256비트 키를 지원한다. 상수 MCRYPT_TWOFISH를 사용한다. 

LOKI97 
128, 192, 256비트 길이의 키를 이용한다. 상수 MCRYPT_LOKI97를 사용한다. 

RC2 
블럭 크기를 64비트이며 키는 8에서 1024비트이다. 오래된 알고리즘으로 16비트 컴퓨터에 적당하다. 상수 MCRYPT_RC2를 사용한다. 

ARCFOUR/RC4 
RC4는 RSADSL의 상표이므로 mcrypt는 RC4 알고리즘을 지원하지 않지만 ARCFOUR와 호환된다. 스트림 기반의 암호문과 최대 2048 비트 키를 지원한다. 상수 MCRYPT_ARCFOUR를 사용한다. 

RIJNDAEL 
가변적인 길의 블럭 암호문과 키를 가진다. 상수 MCRYPT_RIJNDAEL_128, MCRYPT_RIJNDAEL_192, MCRYPT_RIJNDAEL_256을 사용한다. 

SERPENT 
128비트 블럭 암호문으로 DES보다 빠르다. 상수 MCRYPT_SERPENT를 사용한다. 

IDEA 
64비트 블럭과 128비트 키를 사용한다. 상수 MCRYPT_IDEA를 사용한다. 

ENIGMA/CRYPT 
하나의 원통을 가진 암호화 기계를 기반으로 해서 보안성이 낮다. 상수 MCRYPT_CRYPT를 사용한다. 

GOST 
256비트 키와 64비트 블럭을 가진다. 상수 MCRYPT_GOST를 사용한다. 

SAFER 
64비트, 128비트 키를 지원하는 빠르고 안전한 알고리즘이다. 상수 MCRYPT_SAFER64, MCRYPT_SAFER128을 사용한다. 

SAFER+ 
SAFER 알고리즘의 확장판으로 128, 196, 256비트 키를 지원한다. 상수 MCRYPT_SAFERPLUS를 사용한다. 


예를 들어, 3DES 알고리즘을 사용하려면 다음과 같이 키를 이용해 문자열을 암호화한다: 

<?php
$key = "This is our secret key";
$string = "This is ths string that we want to encrypt"; // 문자열 암호화
$encrypted_message = mcrypt_ech(MCRYPT_3DES, $key, $string, MCRYPT_ENCRYPT);
?>

이 메시지를 해독하려면 $encrypted_message를 문자열로 해서 MCRYPT_DECRYPT 상수를 이용하면 된다. 위의 코드를 mcrypt 2.2.x와 2.4.x에서 동작한다. mcrypt 2.4.x 함수가 좀더 더 유연한 기능을 제공하므로 이 함수를 사용하기를 권한다.

비대칭 암호화

비대칭 암호화(Asymmetric encryption)는 몇 년 전부터 일반인들이 사용할 수 있게 되었다. 이 방식은 상자와 자물쇠로 생각하면 이해가 쉽다. 예를 들어, 제인이 앨리스에게 보내는 비밀 메시지를 가지고 있다면 앨리스는 제인에게 열려있는 자물쇠를 보낼 수 있다. 제인은 자신의 메시지를 상자에 넣고 앨리스가 보내준 자물쇠를 이용해 상자를 잠근다.

이제 상자를 열과 메시지를 읽을 수 있는 유일한 사람은 앨리스인데 열쇠는 앨리스만이 가지고 있기 때문이다.

비대칭 암호화를 이용할 때는 자신의 공개 키(pubic key)를 보내야 한다. 이 공개 키를 열려져 있는 자물쇠라고 생각해보자. 누구든지 이 열려진 자물쇠를 이용해 여러분에게 비밀 메시지를 보낼 수 있고 개인 키(private key)는 여러분이 가지고 있으므로 이 자물쇠를 열수 있는 유일한 사람이 된다.

이 시스템은 인터넷에서 흔히 사용된다. 만일 인터넷에서 물건을 구입하거나 PGP(Pretty Good Privacy)를 사용한다면 이 시스템을 이용하는 것이다.

PHP는 OpenSSL을 이용해 이 시스템을 지원한다. 또한 OpenSSL은 CURL을 이용해 리모트 서버에 SSL(Secure Socket Layer)로 연결할 수 있다. 사용되는 세부 알고리즘은 상당히 복잡하다. 이 장의 마지막에 있는 참고 정버를 이용하면 많은 정보를 얻을 수 있다. 비대칭 암화는 다른 것보다 좀더 안전하다.

아래는 지원하는 암호화 방식의 종류
MCRYPT_3DES
MCRYPT_ARCFOUR_IV (libmcrypt > 2.4.x only)
MCRYPT_ARCFOUR (libmcrypt > 2.4.x only)
MCRYPT_BLOWFISH
MCRYPT_CAST_128
MCRYPT_CAST_256
MCRYPT_CRYPT
MCRYPT_DES
MCRYPT_DES_COMPAT (libmcrypt 2.2.x only)
MCRYPT_ENIGMA (libmcrypt > 2.4.x only, alias for MCRYPT_CRYPT)
MCRYPT_GOST
MCRYPT_IDEA (non-free)
MCRYPT_LOKI97 (libmcrypt > 2.4.x only)
MCRYPT_MARS (libmcrypt > 2.4.x only, non-free)
MCRYPT_PANAMA (libmcrypt > 2.4.x only)
MCRYPT_RIJNDAEL_128 (libmcrypt > 2.4.x only)
MCRYPT_RIJNDAEL_192 (libmcrypt > 2.4.x only)
MCRYPT_RIJNDAEL_256 (libmcrypt > 2.4.x only)
MCRYPT_RC2
MCRYPT_RC4 (libmcrypt 2.2.x only)
MCRYPT_RC6 (libmcrypt > 2.4.x only)
MCRYPT_RC6_128 (libmcrypt 2.2.x only)
MCRYPT_RC6_192 (libmcrypt 2.2.x only)
MCRYPT_RC6_256 (libmcrypt 2.2.x only)
MCRYPT_SAFER64
MCRYPT_SAFER128
MCRYPT_SAFERPLUS (libmcrypt > 2.4.x only)
MCRYPT_SERPENT (libmcrypt > 2.4.x only)
MCRYPT_SERPENT_128 (libmcrypt 2.2.x only)
MCRYPT_SERPENT_192 (libmcrypt 2.2.x only)
MCRYPT_SERPENT_256 (libmcrypt 2.2.x only)
MCRYPT_SKIPJACK (libmcrypt > 2.4.x only)
MCRYPT_TEAN (libmcrypt 2.2.x only)
MCRYPT_THREEWAY
MCRYPT_TRIPLEDES (libmcrypt > 2.4.x only)
MCRYPT_TWOFISH (for older mcrypt 2.x versions, or mcrypt > 2.4.x )
MCRYPT_TWOFISH128 (TWOFISHxxx are available in newer 2.x versions, but not in the 2.4.x versions)
MCRYPT_TWOFISH192
MCRYPT_TWOFISH256
MCRYPT_WAKE (libmcrypt > 2.4.x only)
MCRYPT_XTEA (libmcrypt > 2.4.x only)
 

여러곳에 퍼져있는 글이라 원작자는 알 수 없으나 많은 도움이 되었습니다.
원작자님 감사합니다.