DECRYPT_RAW
DECRYPT_RAW
DECRYPT_RAW()는 BINARY 키로 BINARY 값을 복호화해요.
함께 보기:
ENCRYPT , ENCRYPT_RAW , DECRYPT , TRY_DECRYPT , TRY_DECRYPT_RAW
본문
문법
DECRYPT_RAW( <value_to_decrypt> , <key> , <iv> ,
[ [ [ <additional_authenticated_data> , ] <encryption_method> , ] <aead_tag> ]
)
인자
필수:
value_to_decrypt
복호화할 이진 값이에요.
key
데이터를 암호화/복호화하는 데 사용할 키예요. 키는 BINARY 값이어야 해요. 길이만 맞으면 아무 값이나 될 수 있어요. 예를 들어 AES128의 경우 키는 128비트(16바이트)여야 하고, AES256의 경우 키는 256비트(32바이트)여야 해요. 값을 암호화하는 데 사용한 키로 값을 복호화해야 해요.
iv
이 매개변수는 이 데이터를 암호화하고 복호화하는 데 사용할 초기화 벡터(Initialization Vector, IV)를 포함해요. IV는 특정 길이의 BINARY 값이어야 해요. GCM의 경우 이 필드는 96비트(12바이트)여야 해요. GCM 암호화 방식은 이 필드가 다른 크기여도 허용하지만, Snowflake는 현재 96비트만 지원해요. CCM의 경우 56비트(7바이트)여야 해요. ECB의 경우 이 매개변수는 필요하지 않아요. 그 외 지원되는 모든 암호화 모드에서는 128비트(16바이트)여야 해요. 이 값은 첫 번째 암호화 라운드를 초기화하는 데 사용돼요. 특히 GCM 같은 암호화 모드에서는 같은 IV와 키 조합을 두 번 이상 사용하면 안 돼요. 이 매개변수가 NULL로 설정되면 구현은 호출할 때마다 새 의사 난수 IV를 선택해요.
선택:
<algorithm>-<mode> [ /pad: <padding> ]
additional_authenticated_data
부가 인증 데이터(Additional Authenticated Data, AAD)는 복호화 과정에서 기밀성과 무결성이 보장되는 추가 데이터예요. 그러나 이 AAD는 암호화되지 않으며 ENCRYPT 또는 ENCRYPT_RAW 함수가 반환하는 값에 필드로 포함되지 않아요. AAD가 암호화 함수(ENCRYPT 또는 ENCRYPT_RAW)에 전달되면, 복호화 함수(DECRYPT 또는 DECRYPT_RAW)에도 같은 AAD를 전달해야 해요. 복호화 함수에 전달된 AAD가 암호화 함수에 전달된 AAD와 일치하지 않으면 복호화는 실패해요. AAD와 패스프레이즈의 차이는, 패스프레이즈는 비밀로 유지해야 하지만(그렇지 않으면 암호화가 사실상 무용지물) AAD는 공개된 채로 남길 수 있다는 점이에요. AAD는 공개 정보와 암호화된 값이 서로 연관되어 있음을 인증하는 데 도움을 줘요. ENCRYPT 함수의 예제 섹션에는 AAD가 일치할 때와 일치하지 않을 때의 동작을 보여주는 예제가 있어요. ENCRYPT_RAW와 DECRYPT_RAW의 경우 AAD의 데이터 타입은 BINARY여야 해요. ENCRYPT와 DECRYPT의 경우 AAD의 데이터 타입은 VARCHAR 또는 BINARY일 수 있고, 암호화된 값의 데이터 타입과 일치할 필요는 없어요. AAD는 GCM(기본값) 같은 AEAD 지원 암호화 모드에서만 지원돼요.
encryption_method
이 문자열은 데이터를 암호화/복호화하는 데 사용할 방식을 지정해요. 이 문자열은 하위 필드를 포함해요. 알고리즘은 현재 다음으로 제한돼요: 'AES': 패스프레이즈가 전달되면(예: ENCRYPT에) 함수는 AES-256 암호화(256비트)를 사용해요. 키가 전달되면(예: ENCRYPT_RAW에) 함수는 키 길이에 따라 128, 192, 256비트 암호화를 사용해요. 알고리즘은 대소문자를 구분하지 않아요. 모드는 메시지를 암호화하는 데 사용할 블록 암호 모드를 지정해요. 다음 표는 지원되는 모드와 그 모드 중 어떤 것이 패딩을 지원하는지 보여줘요.
| 모드 | 패딩 | 설명 |
|---|---|---|
| 'ECB' | 예 | 키로 각 블록을 개별적으로 암호화. 이 모드는 일반적으로 권장되지 않으며 외부 구현과의 호환성을 위해서만 포함됨. |
| 'CBC' | 예 | 암호화된 블록을 이전 블록과 XOR함. |
| 'GCM' | 아니요 | Galois/Counter Mode는 AEAD를 지원하는 고성능 암호화 모드. AEAD는 AEAD 태그를 생성해 암호화된 데이터의 무결성과 기밀성을 추가로 보장함. 또한 AEAD는 AAD(부가 인증 데이터)를 지원함. |
| 'CTR' | 아니요 | 카운터 모드. |
| 'OFB' | 아니요 | 출력 피드백. 암호문을 블록의 평문과 XOR함. |
| 'CFB' | 아니요 | 암호 피드백은 OFB와 CBC의 조합. |
모드는 대소문자를 구분하지 않아요. 패딩은 블록 크기의 배수가 아닌 길이의 메시지를 어떻게 패딩할지 지정해요. 패딩은 ECB와 CBC 모드에만 적용되며, 다른 모드에서는 무시돼요. 패딩의 가능한 값은: 'PKCS': 블록 패딩에 PKCS5를 사용. 'NONE': 패딩 없음. ECB 또는 CBC 모드를 사용할 때는 사용자가 패딩을 직접 처리해야 해요. 패딩은 대소문자를 구분하지 않아요. 기본 설정: 'AES-GCM'. 모드를 지정하지 않으면 GCM이 사용돼요. 패딩을 지정하지 않으면 PKCS가 사용돼요.
aead_tag
이 BINARY 값은 AEAD 지원 복호화 모드가 암호화된 데이터의 무결성과 기밀성을 확인하는 데 필요해요. ENCRYPT_RAW 함수가 반환한 AEAD 태그를 사용해요. 아래 예제는 이 값에 접근하고 사용하는 방법을 보여줘요.
반환
이 함수는 복호화된 값을 반환해요. 반환되는 값의 데이터 타입은 BINARY예요.
사용 지침
-
ENCRYPT()로 암호화한 데이터를 복호화하려면DECRYPT()를 사용해요.DECRYPT_RAW()는 사용하지 마세요. -
ENCRYPT_RAW()로 암호화한 데이터를 복호화하려면DECRYPT_RAW()를 사용해요.DECRYPT()는 사용하지 마세요. -
함수의 매개변수는 보안을 위해 마스킹돼요. 다음 같은 민감한 정보는 쿼리 로그에서 볼 수 없고 Snowflake에도 노출되지 않아요.
-
암호화하거나 복호화할 문자열 또는 이진 값.
-
패스프레이즈 또는 키.
-
-
함수는 암호화와 복호화를 효과적으로 수행하기 위해 FIPS 호환 암호화 라이브러리를 사용해요.
-
데이터를 복호화하는 데 사용하는 패스프레이즈 또는 키는 그 데이터를 암호화하는 데 사용한 패스프레이즈 또는 키와 동일해야 해요.
-
암호화된 이진 값에서 필드(암호문, 초기화 벡터 또는 태그)를 추출할 때는 다음을 사용해요.
as_binary(get(encrypted_value, '<field_name>'))
예를 들어:
as_binary(get(encrypted_value, 'ciphertext'))
encrypted_value:*field_name*::binary는 사용하지 마세요. 필드 접근 연산자 :는 추출된 필드 값을 문자열로 변환하는데, 소스가 BINARY이므로 그 문자열이 항상 유효한 UTF-8 문자열은 아니기 때문이에요.
예제
이 예제는 암호화와 복호화를 보여줘요.
가독성을 위해 BINARY_OUTPUT_FORMAT을 HEX로 설정해요:
_to_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" | | |
| | | | } | | |
+----------------+----------------+---------+---------------------------------------------+---------------------------+-----------------------+