DB/PostgreSQL

[Postgresql] 데이터 해시화, 암호화, 복호화

불곰1 2021. 4. 3. 22:41

해시화

MD5

md5 는 해시화로 한번 변형을 하면 복원을 할 수 없습니다. 예전에는 비밀번호와 같은 값을 많이 변환했지만 보안적인 측면에서 이미 취약하다고 하기 때문에 탈취가 되어도 크게 중요하지 않은 데이터에서만 사용하기를 권장합니다.

형식

md5(문자열) return hex

예시

SELECT md5('abcd');
-- e2fc714c4727ee9395f324cd2e7f331f

digest

digest를 사용하면 md5 뿐만 아니라 sha1, sha256, sha512와 같이 평문을 해시화 할 수 있습니다. 반환 타입은 bytea 이므로 encode()함수를 사용해 16진수로 변환하여 사용하면 됩니다.

형식

해시 타입
md5, sha1, sha224, sha256, sha384, sha512

digest(문자열, 해시타입) return bytea

예시

select digest('abcd', 'md5');
-- E'\\xE2FC714C4727EE9395F324CD2E7F331F'

select encode(digest('abcd', 'md5'), 'hex');
-- e2fc714c4727ee9395f324cd2e7f331f

select encode(digest('abcd', 'sha256'), 'hex');
-- 88d4266fd4e6338d13b845fcf289579d209c897823b9217da3e161936f031589

암복호화

Postgresql에서 데이터 암복호화를 하기 위해서는 extension을 설치해야 합니다.

CREATE EXTENSION pgcrypto;

암호화와 복호화는 순서가 반대입니다. 암호화가 1 → 2 → 3 이 순으로 진행이 되었다면 복호화는 3 → 2 → 1 순으로 진행돼야 합니다.

암호화

convert_to

보통은 아래와 같이 변환을 하지 않아도 되지만 어느 데이터가 들어올 지 예상이 되지 않을 땐 사용하는 것이 안전합니다.

형식

convert_to('문자열', 인코딩) return bytea - utf8 범위 안에서 표현됨

예시

select convert_from('abcd', 'utf8')
-- abcd

select convert_to('abcd', 'utf8')
-- abcd

encrypt

encrypt는 bytea 타입으로 리턴이 되므로 encode 함수를 사용해 16진수로 변경하여 사용합니다.

형식

암호화 방식
blowfish = bf
rijndael = aes -
des      = des - 56비트로 키 길이가 짧아서 보안에 취약
3des     = 3des - des를 3번 반복한 것으로 잘 안씀

암호화 모드
cbc — 가장 많이 사용 (기본값)
ecb — 보안에 취약

패딩
pkcs — 가변 길이 자료 (기본값)
none — 자료는 암호 블록의 배수 크기여야 함

encrypt(암호화할 문자열, 암호키, 암호화 방식-암호화 모드/pad:패딩) return bytea

예시

select encrypt('abcd', 'key','aes');
-- E'\\xF0C769069D2BAF4A05966F7C0B46E173'

select encrypt('abcd', 'key','aes-ecb/pad:none');
-- E'\\x046EA9A26F7D7C9DC7C8F5CED5FEE132'

select encrypt(convert_to('abcd', 'utf8'), 'key','aes');
-- E'\\xF0C769069D2BAF4A05966F7C0B46E173'

encode

bytea 타입으로 나온 결과를 입력된 타입으로 변경합니다.

형식

지원 타입
base64, hex, escape

형식
encode(bytea 타입 데이터, 지원타입) return text

예시

select encode('123\000456'::bytea, 'escape')
-- 123\000456

select encode(encrypt(convert_to('abcd', 'utf8'), 'key','aes'), 'hex');
-- f0c769069d2baf4a05966f7c0b46e173

select encode(encrypt(convert_to('abcd', 'utf8'), 'key','aes'), 'base64');
-- 8MdpBp0rr0oFlm98C0bhcw==

armor

ASCII-armor(PGP;Pretty Good Privacy) 형식으로 변환합니다. ASCII-armor란 바이너리를 텍스트로 인코딩하는 컨버터로 암호화된 결과를 ASCII로 묶어 이메일과 같은 표준 메시징 형식으로 보낼 수 있습니다. CRC 값을 가지는 Base64 인코딩 타입을 기본값으로 가집니다.

형식

armor(data bytea [ , keys text[], values text[] ]) returns text

예시

select armor('abcd'::bytea)
-----BEGIN PGP MESSAGE-----

YWJjZA==
=S2Mq
-----END PGP MESSAGE-----

select armor(encrypt(convert_to('abcd', 'utf8'), 'key','aes'));
-----BEGIN PGP MESSAGE-----

8MdpBp0rr0oFlm98C0bhcw==
=+v1Q
-----END PGP MESSAGE-----

복호화

decrypt

encrypt의 역순이라 생각하면 쉽습니다. 암호화 방식, 모드, 패딩 모두 동일합니다.

형식

복호화 방식
blowfish = bf
rijndael = aes -
des      = des - 56비트로 키 길이가 짧아서 보안에 취약
3des     = 3des - des를 3번 반복한 것으로 잘 안씀

복호화 모드
cbc — 가장 많이 사용 (기본값)
ecb — 보안에 취약

패딩
pkcs — 가변 길이 자료 (기본값)
none — 자료는 암호 블록의 배수 크기여야 함

decrypt(복호화할 문자열, 암호키, 복호화 방식-복호화 모드/pad:패딩) return bytea

예시

with enc_table (enc_data) as (
    select encrypt('abcd', 'key','aes')
)

select decrypt(enc_data, 'key', 'aes')
from enc_table
-- abcd

-- 키나 암호화 방식이 맞지 않으면 올바르게 복호화 되지 않음
select decrypt(enc_data, 'key1', 'aes')
from enc_table
-- E'\\xEF1E3AC015A0DE4B91FAE0507E5A1193'

select decrypt(enc_data, 'key', 'des')
from enc_table
-- E'\\xF0EC79F56DE25140FDEBB862D534C100'

decode

encode의 역순입니다. 타입은 encode와 동일하게 지원합니다.

형식

decode(text 타입 데이터, 지원타입) return bytea

예시

select decode('123\000456', 'escape');
-- E'\\x31323300343536'

with enc_table (enc_data) as (
    select encode(encrypt('abcd', 'key','aes'), 'hex')
)

select decrypt(decode(enc_data, 'hex'), 'key', 'aes')
from enc_table;
-- abcd

convert_from

형식

convert_from('utf8 범위 안의 bytea 문자열', 인코딩) return text

예시

select convert_from('abcd', 'utf8')
-- abcdwith enc_table (enc_data) as (
 select encode(encrypt(convert_to('abcd', 'utf8'), 'key','aes'), 'hex')
)

select convert_from(decrypt(decode(enc_data, 'hex'), 'key', 'aes'), 'utf8')
from enc_table;

dearmor

형식

dearmor(data text) returns bytea

예시

with enc_table (enc_data) as (
    select armor('abcd'::bytea)
)

select dearmor(enc_data)
from enc_table;
-- abcd

with enc_table (enc_data) as (
    select armor(encrypt(convert_to('abcd', 'utf8'), 'key','aes'))
)

select convert_from(decrypt(dearmor(enc_data), 'key', 'aes'), 'utf8')
from enc_table;
-- abcd