ENCRYPT_RAW
ENCRYPT_RAW
ENCRYPT_RAW는 BINARY 키를 사용해 BINARY 값을 암호화하는 암호화 함수예요. 키와 초기화 벡터(IV), 선택적으로 추가 인증 데이터(AAD)를 직접 지정해 암호화할 때 사용해요.
본문
카테고리: 암호화 함수
구문 (Syntax)
ENCRYPT_RAW( <value_to_encrypt> , <key> , <iv> ,
[ [ <additional_authenticated_data> , ] <encryption_method> ]
)
인자 (Arguments)
필수:
<value_to_encrypt> — 암호화할 이진 값이에요.
<key> — 데이터를 암호화/복호화하는 데 사용하는 키예요. 키는 BINARY 값이어야 해요. 키는 길이만 맞으면 어떤 값이든 될 수 있어요. 예를 들어 AES128의 경우 키는 128비트(16바이트), AES256의 경우 키는 256비트(32바이트)여야 해요.
값을 암호화하는 데 사용한 키는 값을 복호화하는 데 사용해야 해요.
<iv> — 이 파라미터는 이 데이터를 암호화·복호화하는 데 사용할 초기화 벡터(IV)를 담아요. IV는 특정 길이의 BINARY 값이어야 해요:
- GCM의 경우 96비트(12바이트)여야 해요. GCM 암호화 방식은 이 필드를 다른 크기로도 허용하지만, Snowflake는 현재 96비트만 지원해요.
- CCM의 경우 56비트(7바이트)여야 해요.
- ECB의 경우 이 파라미터가 필요 없어요.
- 그 외 지원되는 암호화 모드에서는 128비트(16바이트)여야 해요.
이 값은 첫 번째 암호화 라운드를 초기화하는 데 사용돼요. 특히 GCM 같은 암호화 모드에서는 같은 IV와 키 조합을 두 번 이상 사용하면 안 돼요.
이 파라미터가 NULL로 설정되면 구현은 매 호출마다 새 의사 난수 IV를 선택해요.
선택:
<additional_authenticated_data> — 추가 인증 데이터(AAD)는 복호화 과정에서 기밀성과 진위가 보장되는 추가 데이터예요. 하지만 이 AAD는 암호화되지 않으며, ENCRYPT 또는 ENCRYPT_RAW 함수의 반환 값의 필드로 포함되지도 않아요.
AAD가 암호화 함수(ENCRYPT 또는 ENCRYPT_RAW)에 전달되면, 같은 AAD가 복호화 함수(DECRYPT 또는 DECRYPT_RAW)에도 전달되어야 해요. 복호화 함수에 전달된 AAD가 암호화 함수에 전달된 AAD와 일치하지 않으면 복호화는 실패해요.
AAD와 passphrase의 차이점은, passphrase는 비밀로 유지하려는 반면(그렇지 않으면 암호화가 사실상 무의미해져요) AAD는 공개로 남겨둘 수 있다는 거예요. AAD는 공개 정보 조각과 암호화 값이 서로 연결되어 있음을 인증하는 데 도움을 줘요. ENCRYPT 함수의 예시 섹션에는 AAD가 일치할 때와 일치하지 않을 때의 동작을 보여주는 예시가 있어요.
ENCRYPT_RAW와 DECRYPT_RAW의 경우 AAD의 데이터 타입은 BINARY여야 해요. ENCRYPT와 DECRYPT의 경우 AAD의 데이터 타입은 VARCHAR 또는 BINARY일 수 있으며, 암호화된 값의 데이터 타입과 일치할 필요는 없어요.
AAD는 GCM(기본값) 같은 AEAD 지원 암호화 모드에서만 지원돼요.
<encryption_method> — 데이터를 암호화/복호화하는 데 사용할 방법을 지정하는 문자열이에요. 이 문자열은 하위 필드를 담아요:
<algorithm>-<mode> [ /pad: <padding> ]
algorithm은 현재 다음으로 제한돼요:
'AES': passphrase가 전달되면(예: ENCRYPT에) 함수는 AES-256 암호화(256비트)를 사용해요. 키가 전달되면(예: ENCRYPT_RAW에) 함수는 키 길이에 따라 128, 192, 또는 256비트 암호화를 사용해요.
algorithm은 대소문자를 구분하지 않아요.
mode는 메시지를 암호화하는 데 사용할 블록 암호 모드를 지정해요. 다음 표는 지원되는 모드와 그 중 패딩을 지원하는 모드를 보여줘요:
| 모드 | 패딩 | 설명 |
|---|---|---|
| 'ECB' | 예 | 키로 각 블록을 개별적으로 암호화. 이 모드는 일반적으로 권장되지 않으며 외부 구현과의 호환성을 위해서만 포함됨. |
| 'CBC' | 예 | 암호화된 블록이 이전 블록과 XOR됨. |
| 'GCM' | 아니요 | Galois/Counter Mode는 AEAD 지원이 되는 고성능 암호화 모드. AEAD는 AEAD 태그를 생성해 암호화된 데이터의 진위와 기밀성을 추가로 보장. 또한 AEAD는 AAD(추가 인증 데이터)를 지원. |
| 'CTR' | 아니요 | 카운터 모드. |
| 'OFB' | 아니요 | 출력 피드백. 암호문이 블록의 평문과 XOR됨. |
| 'CFB' | 아니요 | 암호 피드백은 OFB와 CBC의 결합. |
mode는 대소문자를 구분하지 않아요.
padding은 블록 크기의 배수가 아닌 길이의 메시지를 어떻게 패딩할지 지정해요. 패딩은 ECB와 CBC 모드에만 적용되며, 다른 모드에서는 무시돼요. 패딩의 가능한 값:
'PKCS': 블록 패딩에 PKCS5를 사용해요.'NONE': 패딩 없음. ECB 또는 CBC 모드를 사용할 때는 사용자가 패딩을 직접 처리해야 해요.
padding은 대소문자를 구분하지 않아요.
기본 설정: 'AES-GCM'. mode를 지정하지 않으면 GCM이 사용돼요. padding을 지정하지 않으면 PKCS가 사용돼요.
반환값 (Returns)
암호화된 값을 반환해요. 반환되는 값의 데이터 타입은 VARIANT예요.
단일 값 하나만 반환되지만, 그 값은 두세 개의 필드를 담아요:
- 첫 번째 필드는 초기화 벡터(IV)예요. 암호화와 복호화 모두 IV를 사용해요.
- 두 번째 필드는
value_to_encrypt의 암호문(암호화된 값)이에요. - 암호화 모드가 AEAD 지원이면, 반환 값에는 세 번째 필드인 AEAD 태그도 포함돼요.
IV와 태그 크기는 암호화 모드에 따라 달라져요. VARIANT 안의 세 필드는 모두 BINARY 타입이에요.
사용 시 유의사항 (Usage notes)
ENCRYPT()로 암호화한 데이터를 복호화하려면DECRYPT()를 사용해요.DECRYPT_RAW()를 사용하지 마세요.ENCRYPT_RAW()로 암호화한 데이터를 복호화하려면DECRYPT_RAW()를 사용해요.DECRYPT()를 사용하지 마세요.- 함수의 파라미터는 보안을 위해 마스킹돼요. 다음 같은 민감 정보는 쿼리 로그에 보이지 않고 Snowflake에도 보이지 않아요:
- 암호화 또는 복호화할 문자열 또는 이진 값.
- passphrase 또는 키.
- 이 함수들은 FIPS 호환 암호화 라이브러리를 사용해 암호화와 복호화를 효과적으로 수행해요.
- 데이터를 복호화하는 데 사용하는 passphrase 또는 키는 그 데이터를 암호화하는 데 사용한 것과 같아야 해요.
예시 (Examples)
이 예시는 암호화와 복호화를 보여줘요.
가독성을 위해 BINARY_OUTPUT_FORMAT을 HEX로 설정해요:
ALTER SESSION SET BINARY_OUTPUT_FORMAT='HEX';
테이블을 만들고 로드해요.
주의: 이 예시를 단순화하기 위해 암호화/복호화 키를 암호화된 값과 함께 테이블에 저장해요. 이것은 안전하지 않아요. 키는 암호화된 데이터를 저장하는 테이블에 암호화되지 않은 값으로 절대 저장하면 안 돼요.
CREATE OR REPLACE TABLE binary_table (
encryption_key BINARY, -- DO NOT STORE REAL ENCRYPTION KEYS THIS WAY!
initialization_vector BINARY(12), -- DO NOT STORE REAL IV'S THIS WAY!!
binary_column BINARY,
encrypted_binary_column VARIANT,
aad_column BINARY);
INSERT INTO binary_table (encryption_key,
initialization_vector,
binary_column,
aad_column)
SELECT SHA2_BINARY('NotSecretEnough', 256),
SUBSTR(TO_BINARY(HEX_ENCODE('AlsoNotSecretEnough'), 'HEX'), 0, 12),
TO_BINARY(HEX_ENCODE('Bonjour'), 'HEX'),
TO_BINARY(HEX_ENCODE('additional data'), 'HEX')
;
암호화해요:
UPDATE binary_table SET encrypted_binary_column =
ENCRYPT_RAW(binary_column,
encryption_key,
initialization_vector,
aad_column,
'AES-GCM');
+------------------------+-------------------------------------+
| number of rows updated | number of multi-joined rows updated |
|------------------------+-------------------------------------|
| 1 | 0 |
+------------------------+-------------------------------------+
이것은 DECRYPT_RAW() 함수의 해당 호출을 보여줘요. 초기화 벡터(IV)는 암호화된 값에서 가져오므로, 초기화 벡터를 따로 저장할 필요가 없어요. 마찬가지로 AEAD 태그도 암호화된 값에서 읽어요.
주의: 이 예시를 단순화하기 위해 암호화/복호화 키를 암호화된 값과 함께 테이블에서 읽어요. 이것은 안전하지 않아요. 키는 암호화된 데이터를 저장하는 테이블에 암호화되지 않은 값으로 절대 저장하면 안 돼요.
SELECT 'Bonjour' as original_value,
binary_column,
hex_decode_string(to_varchar(binary_column)) as decoded,
encrypted_binary_column,
decrypt_raw(as_binary(get(encrypted_binary_column, 'ciphertext')),
encryption_key,
as_binary(get(encrypted_binary_column, 'iv')),
aad_column,
'AES-GCM',
as_binary(get(encrypted_binary_column, 'tag')))
as decrypted,
hex_decode_string(to_varchar(decrypt_raw(as_binary(get(encrypted_binary_column, 'ciphertext')),
encryption_key,
as_binary(get(encrypted_binary_column, 'iv')),
aad_column,
'AES-GCM',
as_binary(get(encrypted_binary_column, 'tag')))
))
as decrypted_and_decoded
FROM binary_table;
+----------------+----------------+---------+---------------------------------------------+----------------+-----------------------+
| ORIGINAL_VALUE | BINARY_COLUMN | DECODED | ENCRYPTED_BINARY_COLUMN | DECRYPTED | DECRYPTED_AND_DECODED |
|----------------+----------------+---------+---------------------------------------------+----------------+-----------------------|
| Bonjour | 426F6E6A6F7572 | Bonjour | { | 426F6E6A6F7572 | Bonjour |
| | | | "ciphertext": "CA2F4A383F6F55", | | |
| | | | "iv": "416C736F4E6F745365637265", | | |
| | | | "tag": "91F28FBC6A2FE9B213D1C44B8D75D147" | | |
| | | | } | | |
+----------------+----------------+---------+---------------------------------------------+----------------+-----------------------+
이전 예시는 긴 DECRYPT_RAW() 호출을 반복했어요. WITH 절을 사용해 반복을 줄일 수 있어요:
WITH
decrypted_but_not_decoded as (
decrypt_raw(as_binary(get(encrypted_binary_column, 'ciphertext')),
encryption_key,
as_binary(get(encrypted_binary_column, 'iv')),
aad_column,
'AES-GCM',
as_binary(get(encrypted_binary_column, 'tag')))
)
SELECT 'Bonjour' as original_value,
binary_column,
hex_decode_string(to_varchar(binary_column)) as decoded,
encrypted_binary_column,
decrypted_but_not_decoded,
hex_decode_string(to_varchar(decrypted_but_not_decoded))
as decrypted_and_decoded
FROM binary_table;
+----------------+----------------+---------+---------------------------------------------+---------------------------+-----------------------+
| ORIGINAL_VALUE | BINARY_COLUMN | DECODED | ENCRYPTED_BINARY_COLUMN | DECRYPTED_BUT_NOT_DECODED | DECRYPTED_AND_DECODED |
|----------------+----------------+---------+---------------------------------------------+---------------------------+-----------------------|
| Bonjour | 426F6E6A6F7572 | Bonjour | { | 426F6E6A6F7572 | Bonjour |
| | | | "ciphertext": "CA2F4A383F6F55", | | |
| | | | "iv": "416C736F4E6F745365637265", | | |
| | | | "tag": "91F28FBC6A2FE9B213D1C44B8D75D147" | | |
| | | | } | | |
+----------------+----------------+---------+---------------------------------------------+---------------------------+-----------------------+