メインコンテンツへスキップ
メインコンテンツへスキップ

暗号化関数

これらの関数は、AES(Advanced Encryption Standard)アルゴリズムを用いてデータの暗号化および復号を行います。

鍵長は暗号化モードに依存します。-128--196--256- 各モードに対して、それぞれ 162432 バイトの長さになります。

初期化ベクトルの長さは常に 16 バイトです(16 バイトを超える部分は無視されます)。

aes_decrypt_mysql

導入バージョン: v20.12

MySQL の AES_ENCRYPT 関数で暗号化されたデータを復号します。

同じ入力に対しては、decrypt と同じ平文を生成します。 keyiv が本来想定される長さより長い場合、aes_decrypt_mysql は MySQL の aes_decrypt と同様に動作し、key を「折りたたみ」、iv の余分なビットを無視します。

以下の復号モードをサポートします:

  • aes-128-ecb, aes-192-ecb, aes-256-ecb
  • aes-128-cbc, aes-192-cbc, aes-256-cbc
  • aes-128-cfb128
  • aes-128-ofb, aes-192-ofb, aes-256-ofb

構文

aes_decrypt_mysql(mode, ciphertext, key[, iv])

引数

  • mode — 復号モード。String
  • ciphertext — 復号する暗号化されたテキスト。String
  • key — 復号鍵。String
  • iv — 省略可。初期化ベクトル。String

戻り値

復号後の文字列を返します。String

使用例

MySQL データの復号

-- MySQLで事前に暗号化したデータを復号化してみましょう:
mysql> SET  block_encryption_mode='aes-256-ofb';
Query OK, 0 rows affected (0.00 sec)

mysql> SELECT aes_encrypt('Secret', '123456789101213141516171819202122', 'iviviviviviviviv123456') as ciphertext;
+------------------------+
| ciphertext             |
+------------------------+
| 0x24E9E4966469         |
+------------------------+
1 row in set (0.00 sec)

SELECT aes_decrypt_mysql('aes-256-ofb', unhex('24E9E4966469'), '123456789101213141516171819202122', 'iviviviviviviviv123456') AS plaintext
┌─plaintext─┐
│ シークレット    │
└───────────┘

aes_encrypt_mysql

導入バージョン: v20.12

MySQL の AES_ENCRYPT 関数と同じ方法でテキストを暗号化します。 生成された暗号文は MySQL の AES_DECRYPT 関数で復号できます。 同じ入力に対しては encrypt 関数と同じ暗号文を生成します。 key または iv が本来の長さより長い場合、aes_encrypt_mysql は MySQL の aes_encrypt と同様に動作し、key を「折りたたみ」処理し、iv の余分なビットは無視します。

サポートされている暗号化モードは次のとおりです:

  • aes-128-ecb, aes-192-ecb, aes-256-ecb
  • aes-128-cbc, aes-192-cbc, aes-256-cbc
  • aes-128-ofb, aes-192-ofb, aes-256-ofb

構文

aes_encrypt_mysql(mode, plaintext, key[, iv])

引数

  • mode — 暗号化モード。String
  • plaintext — 暗号化するテキスト。String
  • key — 暗号鍵。mode が要求する長さより長い場合、MySQL 固有のキー折りたたみ処理が行われます。String
  • iv — 任意。初期化ベクトル。先頭の 16 バイトのみが考慮されます。String

戻り値

暗号文を表すバイナリ文字列。String

使用例

同一入力の比較

-- 同じ入力が与えられた場合、encryptとaes_encrypt_mysqlは同じ暗号文を生成します:
SELECT encrypt('aes-256-ofb', 'Secret', '12345678910121314151617181920212', 'iviviviviviviviv') = aes_encrypt_mysql('aes-256-ofb', 'Secret', '12345678910121314151617181920212', 'iviviviviviviviv') AS ciphertexts_equal;
┌─ciphertexts_equal─┐
│                 1 │
└───────────────────┘

長いキーを使用すると暗号化に失敗する

-- ただし、keyまたはivが想定より長い場合、encryptは失敗します:
SELECT encrypt('aes-256-ofb', 'Secret', '123456789101213141516171819202122', 'iviviviviviviviv123');
サーバーから例外を受信しました (バージョン 22.6.1):
Code: 36. DB::Exception: localhost:9000 から受信。DB::Exception: 無効なキーサイズ: 33 が指定されましたが、32 が必要です: encrypt('aes-256-ofb', 'Secret', '123456789101213141516171819202122', 'iviviviviviviviv123') の処理中。

MySQL 互換性

-- aes_encrypt_mysql は MySQL 互換の出力を生成します:
SELECT hex(aes_encrypt_mysql('aes-256-ofb', 'Secret', '123456789101213141516171819202122', 'iviviviviviviviv123')) AS ciphertext;
┌─ciphertext───┐
│ 24E9E4966469 │
└──────────────┘

IV を長くしても結果は同じ

-- より長いIVを指定しても同じ結果が得られることに注意
SELECT hex(aes_encrypt_mysql('aes-256-ofb', 'Secret', '123456789101213141516171819202122', 'iviviviviviviviv123456')) AS ciphertext
┌─ciphertext───┐
│ 24E9E4966469 │
└──────────────┘

decrypt

導入バージョン: v20.12

この関数は、以下のモードで AES により暗号化されたバイナリ文字列を復号します。

  • aes-128-ecb, aes-192-ecb, aes-256-ecb
  • aes-128-cbc, aes-192-cbc, aes-256-cbc
  • aes-128-ofb, aes-192-ofb, aes-256-ofb
  • aes-128-gcm, aes-192-gcm, aes-256-gcm
  • aes-128-ctr, aes-192-ctr, aes-256-ctr
  • aes-128-cfb, aes-128-cfb1, aes-128-cfb8

構文

decrypt(mode, ciphertext, key[, iv, aad])

引数

  • mode — 復号モード。String
  • ciphertext — 復号対象の暗号化されたテキスト。String
  • key — 復号鍵。String
  • iv — 初期化ベクトル。-gcm モードでは必須で、それ以外では任意。String
  • aad — 追加認証データ。この値が正しくない場合は復号されません。-gcm モードでのみ有効で、それ以外のモードでは例外をスローします。String

戻り値

復号されたプレーンテキストを返します。String

暗号化されたデータを正しく復号する

-- encrypt関数の例のテーブルを再利用
SELECT comment, hex(secret) FROM encryption_test;
┌─comment──────────────┬─hex(secret)──────────────────────────────────┐
│ aes-256-gcm          │ A8A3CCBC6426CFEEB60E4EAE03D3E94204C1B09E0254 │
│ aes-256-gcm with AAD │ A8A3CCBC6426D9A1017A0A932322F1852260A4AD6837 │
└──────────────────────┴──────────────────────────────────────────────┘
┌─comment──────────────────────────┬─hex(secret)──────────────────────┐
│ aes-256-ofb no IV                │ B4972BDC4459                     │
│ aes-256-ofb no IV, different key │ 2FF57C092DC9                     │
│ aes-256-ofb with IV              │ 5E6CB398F653                     │
│ aes-256-cbc no IV                │ 1BC0629A92450D9E73A00E7D02CF4142 │
└──────────────────────────────────┴──────────────────────────────────┘

暗号化データの誤復号

SELECT comment, decrypt('aes-256-cfb128', secret, '12345678910121314151617181920212') AS plaintext FROM encryption_test
-- データの一部のみが正しく復号化され、残りは暗号化時に `mode`、`key`、または `iv` が異なっていたため判読不能になっていることに注意してください。
┌─comment──────────────┬─plaintext──┐
│ aes-256-gcm          │ OQ�E
                             �t�7T�\���\�   │
│ aes-256-gcm with AAD │ OQ�E
                             �\��si����;�o�� │
└──────────────────────┴────────────┘
┌─comment──────────────────────────┬─plaintext─┐
│ aes-256-ofb no IV                │ Secret    │
│ aes-256-ofb no IV, different key │ �4�
                                        �         │
│ aes-256-ofb with IV              │ ���6�~        │
│aes-256-cbc no IV                │ �2*4�h3c�4w��@
└──────────────────────────────────┴───────────┘

encrypt

導入バージョン: v20.12

平文を次のいずれかのモードで AES を使用して暗号文に変換します:

  • aes-128-ecb, aes-192-ecb, aes-256-ecb
  • aes-128-cbc, aes-192-cbc, aes-256-cbc
  • aes-128-ofb, aes-192-ofb, aes-256-ofb
  • aes-128-gcm, aes-192-gcm, aes-256-gcm
  • aes-128-ctr, aes-192-ctr, aes-256-ctr
  • aes-128-cfb, aes-128-cfb1, aes-128-cfb8

構文

encrypt(mode, plaintext, key[, iv, aad])

引数

  • mode — 暗号化モード。String
  • plaintext — 暗号化対象のテキスト。String
  • key — 暗号鍵。String
  • iv — 初期化ベクトル。-gcm モードでは必須で、それ以外では任意。String
  • aad — 追加認証データ。これは暗号化されないが、復号に影響する。-gcm モードでのみ有効で、それ以外では例外がスローされる。String

戻り値

バイナリ文字列形式の暗号文を返す。String

暗号化の例

CREATE TABLE encryption_test
(
    `comment` String,
    `secret` String
)
ENGINE = MergeTree;

INSERT INTO encryption_test VALUES
('aes-256-ofb IVなし', encrypt('aes-256-ofb', 'Secret', '12345678910121314151617181920212')),
('aes-256-ofb IVなし、異なるキー', encrypt('aes-256-ofb', 'Secret', 'keykeykeykeykeykeykeykeykeykeyke')),
('aes-256-ofb IVあり', encrypt('aes-256-ofb', 'Secret', '12345678910121314151617181920212', 'iviviviviviviviv')),
('aes-256-cbc IVなし', encrypt('aes-256-cbc', 'Secret', '12345678910121314151617181920212'));

SELECT comment, hex(secret) FROM encryption_test;
┌─comment──────────────────────────┬─hex(secret)──────────────────────┐
│ aes-256-ofb IV なし                │ B4972BDC4459                     │
│ aes-256-ofb IV なし、異なるキー │ 2FF57C092DC9                     │
│ aes-256-ofb IV あり              │ 5E6CB398F653                     │
│ aes-256-cbc IV なし                │ 1BC0629A92450D9E73A00E7D02CF4142 │
└──────────────────────────────────┴──────────────────────────────────┘

GCM モードの使用例

INSERT INTO encryption_test VALUES
('aes-256-gcm', encrypt('aes-256-gcm', 'Secret', '12345678910121314151617181920212', 'iviviviviviviviv')),

('aes-256-gcm (AAD付き)', encrypt('aes-256-gcm', 'Secret', '12345678910121314151617181920212', 'iviviviviviviviv', 'aad'));

SELECT comment, hex(secret) FROM encryption_test WHERE comment LIKE '%gcm%';
┌─comment──────────────┬─hex(secret)──────────────────────────────────┐
│ aes-256-gcm          │ A8A3CCBC6426CFEEB60E4EAE03D3E94204C1B09E0254 │
│ aes-256-gcm (AAD付き) │ A8A3CCBC6426D9A1017A0A932322F1852260A4AD6837 │
└──────────────────────┴──────────────────────────────────────────────┘

tryDecrypt

導入バージョン: v22.10

decrypt 関数と類似していますが、誤ったキーを使用して復号に失敗した場合には NULL を返します。

構文

tryDecrypt(mode, ciphertext, key[, iv, aad])

引数

  • mode — 復号モード。String
  • ciphertext — 復号対象の暗号化テキスト。String
  • key — 復号キー。String
  • iv — オプション。初期化ベクトル。-gcm モードでは必須で、それ以外のモードでは任意。String
  • aad — オプション。追加認証データ。この値が正しくない場合は復号は行われません。-gcm モードでのみ有効で、それ以外のモードでは例外をスローします。String

戻り値

復号された文字列を返し、復号に失敗した場合は NULL を返します。Nullable(String)

テーブルの作成とデータの挿入

-- user_id が一意のユーザーID、encrypted が暗号化された文字列フィールド、iv が復号化/暗号化のための初期化ベクトルであるテーブルを作成します。
-- ユーザーは自身のIDと暗号化されたフィールドを復号化するためのキーを知っていることを前提とします:
CREATE TABLE decrypt_null
(
    dt DateTime,
    user_id UInt32,
    encrypted String,
    iv String
)
ENGINE = MergeTree;

-- データを挿入します:
INSERT INTO decrypt_null VALUES
('2022-08-02 00:00:00', 1, encrypt('aes-256-gcm', 'value1', 'keykeykeykeykeykeykeykeykeykey01', 'iv1'), 'iv1'),
('2022-09-02 00:00:00', 2, encrypt('aes-256-gcm', 'value2', 'keykeykeykeykeykeykeykeykeykey02', 'iv2'), 'iv2'),
('2022-09-02 00:00:01', 3, encrypt('aes-256-gcm', 'value3', 'keykeykeykeykeykeykeykeykeykey03', 'iv3'), 'iv3');

-- 1つのキーで復号化を試行します:
SELECT
    dt,
    user_id,
    tryDecrypt('aes-256-gcm', encrypted, 'keykeykeykeykeykeykeykeykeykey02', iv) AS value
FROM decrypt_null
ORDER BY user_id ASC
┌──────────────────dt─┬─user_id─┬─value──┐
│ 2022-08-02 00:00:00 │       1 │ ᴺᵁᴸᴸ   │
│ 2022-09-02 00:00:00 │       2 │ value2 │
│ 2022-09-02 00:00:01 │       3 │ ᴺᵁᴸᴸ   │
└─────────────────────┴─────────┴────────┘