본문 바로가기

SQL Server/SQL Server Tip & Tech

SQL Server 2005 암호화

안쓰면 쉽게 잊는다지만... 나이 때문일까? 머리 속 지우개 성능이 갈수록 좋아지고 있다. ㅎㅎㅎ

매번 BOL 찾아 보기도 좀 그렇고... 복습하기 쉽게 간단히 정리해 봅니다.

SQL Server 2005의 암호화 계층은 아래와 같습니다.


이 그림을 보면 데이터라는 박스를 3곳에서 찾을 수 있습니다.

각 데이터 박스의 바로 윗 계층을 읽어보면 인증서, 대칭키, 비대칭키입니다.

즉, 데이터를 암호화하는데 사용되는 것에는 인증서, 대칭키 그리고 비대칭키가 있다... 라는 의미가 되겠죠.

실제로 SQL Server 2005에서 데이터를 암호화하는 함수로는 아래의 4가지 함수를 제공하고 있습니다.

- EncryptByAsmKey() : 비대칭키를 사용하여 암호화
- EncryptByCert() : 인증서를 사용하여 암호화
- EncryptByKey() : 대칭키를 사용하여 암호화
- EncryptByPassPhrase() : 패스워드를 사용하여 암호화

마지막 EncryptByPassPhrase() 역시 대칭키 암호화 방식입니다. (알고리듬은 뭘 쓸까요??? AES? Triple DES?)
하지만, 암호화 계층도에 있는 키를 사용하지 않습니다.
대신 유저가 직접 키를 입력합니다. (정확히 말하면... 키를 생성하기 위한 문자열을 입력합니다.)

이 방식은 소스 어딘가에 키를 생성하는 문자열이 하드 코딩 될 수 밖에 없으므로, 키 자체의 보안이 취약합니다.
(그런 이유로 전 이 함수를 사용하지 않습니다.)


인증서나 키를 사용하여 데이터를 암호화하기 위한 사전 준비 단계는 이렇습니다.

1. 데이터베이스 마스터키를 생성한다.

CREATE MASTER KEY
    ENCRYPTION BY PASSWORD = '<password>';


2. 데이터베이스 마스터키를 파일로 백업하여 보관한다.

BACKUP MASTER KEY TO FILE = '<file path>'
   
ENCRYPTION BY PASSWORD = '<password>';


3. 서비스 마스터키를 백업하여 보관한다. (서비스 마스터키는 데이터베이스 마스터키가 생성될 때 자동으로 생성됩니다.)

BACKUP SERVICE MASTER KEY TO FILE = '<file path>'
   
ENCRYPTION BY PASSWORD = '<password>';



이제 암호화할 데이터와 방법을 결정하면 됩니다.

앞 서 얘기한 바와 같이... 데이터를 암호화하기 위해 우리는 인증서, 대칭키, 비대칭키 중 하나를 선택할 수 있습니다.

암호의 강함을 놓고 보면 인증서 = 비대칭키 > 대칭키 입니다.

하지만 강한 암호는 더 많은 CPU 리소스를 필요로하기 때문에... 무턱대고 강한 암호만을 사용할 수 없는데요...

그래서 일반적으로는 데이터를 암호화할 때 대칭키를 사용하고, 대신 대칭키를 인증서 또는 비대칭키로 암호화해서 사용합니다.

예를 들면 이런 식입니다.

1. 인증서를 생성합니다. (기간을 정의하지 않으면, 오늘 ~ 1년 후가 됩니다.)

CREATE CERTIFICATE CertKeyProtection

    WITH SUBJECT = 'Key Protection'

    , START_DATE = '2009/07/15'

    , EXPIRY_DATE = '2012/07/14';


2. 인증서로 암호화한 대칭키를 생성합니다.

CREATE SYMMETRIC KEY KeyUserData

    WITH ALGORITHM = AES_256

    ENCRYPTION BY CERTIFICATE CertKeyProtection;


3. 대칭키로 데이터를 암호화합니다.

OPEN SYMMETRIC KEY KeyUserData
    DECRYPTION BY CERTIFICATE CertKeyProtection;


SELECT
EncryptByKey(Key_GUID('KeyUserData'), N'암호화할 문자열');

4. 대칭키로 데이터를 복호화합니다.

SELECT CAST(DecryptByKey(<암호화된 바이너리>) AS nvarchar(max));

 

CLOSE SYMMETRIC KEY KeyUserData;




음... 일단 이 정도만 정리해 두겠습니다. ^^


p.s

만약, 복호화할 필요 없는 데이터라면 Hash하여 저장합니다. 예를 들면 회원 비밀번호 같은 것들이겠죠?

이런 경우엔 HashByte() 함수를 사용합니다.

HashBytes ( '<algorithm>', { @input | 'input' } )
<algorithm>::= MD2 | MD4 | MD5 | SHA | SHA1
DECLARE @HashThis nvarchar(max);
SELECT @HashThis = CONVERT(nvarchar,'dslfdkjLK85kldhnv$n000#knf');
SELECT HashBytes('SHA1', @HashThis);
GO


용법은 위와 같은데 (BOL에서 copy - paste)...

처음 예로 든 회원 테이블의 비밀번호 필드라고한다면... 단순히 저 방식으로 저장하는 것은 조금 위험합니다.
원래의 비밀번호를 임의의 문자열과 섞을 필요도 있고, 레코드의 고유키값과 섞을 필요도 있으니까요.