標準 SQL での AEAD 暗号化のコンセプト

このトピックでは、BigQuery での AEAD 暗号化の背後にあるコンセプトについて説明します。BigQuery でサポートされているさまざまな AEAD 暗号化関数の説明については、AEAD 暗号化関数をご覧ください。

AEAD 暗号化の目的

BigQuery では、データを保護するために保存データに暗号化を使用します。さらに、顧客管理の暗号鍵(CMEK)もサポートしているため、ユーザーは特定の暗号鍵を使用してテーブルを暗号化できます。ただし、場合によっては、テーブルに含まれる個々の値を暗号化する必要があります。

たとえば、すべての顧客のデータを共通の 1 つのテーブルで保持し、それぞれに異なる鍵を使用して各顧客のデータを暗号化しなければならない場合があります。その場合、データが複数のテーブルに分散されていれば、「暗号削除」を行うことができます。暗号消去(別名、暗号シュレディング)とは、暗号鍵を削除し、その暗号鍵を使って暗号化されたデータを判読不能にするプロセスを指します。

AEAD 暗号化関数を使用すると、暗号化と復号に使用する鍵からなる鍵セットを作成し、これらの鍵を使用してテーブル内の個々の値を暗号化および復号できます。また、鍵セットに含まれる鍵のローテーションを行うこともできます。

鍵セット

鍵セットは、1 つのプライマリ暗号鍵とそれ以外のセカンダリ暗号鍵からなる暗号鍵の集合です。各鍵には、暗号化アルゴリズムまたは復号アルゴリズムと、その鍵の状態(有効、無効、または破棄)がエンコードされます。破棄されない鍵の場合は、鍵のバイト自体もエンコードされます。プライマリ暗号鍵により、平文の入力テキストを暗号化する方法が決まります。プライマリ暗号鍵が無効状態になることはありません。セカンダリ暗号鍵は復号専用であり、有効または無効な状態のいずれかになります。鍵セットを使用して暗号化されたデータは、その鍵セットを使用して復号できます。

BigQuery での鍵セットは、シリアル化された google.crypto.tink.Keyset プロトコル バッファとして BYTES で表現されます。

次の例では、3 つの鍵からなる AEAD 鍵セットが JSON 文字列として表現されています。

primary_key_id: 569259624
key {
  key_data {
    type_url: "type.googleapis.com/google.crypto.tink.AesGcmKey"
    value: ",&\264kh\377\306\217\371\233E<\0350A4\023B-pd\203\277\240\371\212^\210bf\347\256"
    key_material_type: SYMMETRIC
  }
  status: ENABLED
  key_id: 569259624
  output_prefix_type: TINK
}
key {
  key_data {
    type_url: "type.googleapis.com/google.crypto.tink.AesGcmKey"
    value: "\374\336+.\333\245k\364\010`\037\267!\376\233\\3\215\020\356B\236\240O\256U\021\266\217\277\217\271"
    key_material_type: SYMMETRIC
  }
  status: DISABLED
  key_id: 852264701
  output_prefix_type: TINK
}
key {
  status: DESTROYED
  key_id: 237910588
  output_prefix_type: TINK
}

上記の例では、プライマリ暗号鍵は ID が 569259624 に設定された、JSON 文字列の最初にリストされている鍵です。セカンダリ暗号鍵は 2 つあります。一方は ID 852264701 の無効状態にされた鍵、もう一方は ID 237910588 の破棄状態にされた鍵です。AEAD 暗号化関数で、この鍵セットを使用して暗号化すると、暗号文にはプライマリ暗号鍵の ID 569259624 がエンコードされます。

AEAD 関数でこの鍵セットを使用して復号するときは、暗号文にエンコードされた鍵 ID に基づいて、該当する復号鍵が選択されます。上記の例で、ID が 852264701 または 237910588 のいずれかの鍵を使用して復号しようとすると、エラーが発生します。ID 852264701 の鍵は無効化されていて、ID 237910588 の鍵は破棄されているためです。ID 852264701 の鍵を有効な状態に復元すると、この鍵を復号鍵として使用できるようになります。

鍵の種類により、その鍵で使用する暗号化モードが決まります。

同じ鍵セットを使用して複数の平文を暗号化すると、通常は平文ごとに異なる暗号文の値が返されます。OpenSSL が提供する擬似乱数ジェネレータを使用して選択された、それぞれに異なる初期化ベクトル(IV)が暗号化に使用されるためです。

AES

AEAD 暗号化関数では Advanced Encryption Standard(AES)暗号化が使用されます。AES 暗号化は、入力としての平文とあわせて暗号鍵を取り、暗号化したバイトのシーケンスを出力として返します。このバイトのシーケンスは、暗号化に使用されたのと同じ鍵を使用して復号できます。AES が使用するブロックサイズは 16 バイトです。つまり、平文は 16 バイトのブロックのシーケンスとして扱われます。暗号文には、暗号化に使用されたキーを示す、Tink 固有の接頭辞が含まれます。AES 暗号化では複数のブロック暗号モードがサポートされています。

ブロック暗号モード

AEAD 暗号化関数でサポートされているブロック暗号モードには、GCM と CBC の 2 つがあります。

GCM

Galois/Counter Mode(GCM)は、AES 暗号化モードの 1 つです。このモードの関数は、ブロックに連番を付けてから、各ブロック番号に初期化ベクトル(IV)を結合します。初期化ベクトルとは、平文データをランダム化するベースとなるランダム値または疑似ランダム値です。次に、関数は結合されたブロック番号と IV を AES に従って暗号化します。この暗号化された結果に対してビット排他論理和(XOR)演算を行って、暗号文を生成します。GCM モードでは 128 ビットまたは 256 ビットの暗号鍵が使用されます。

CBC モード

CBC では、平文の各ブロックとその前のブロックに対して XOR 演算を行ってブロックを「チェーン化」した後、そのチェーンを暗号化します。CBC モードで使用する暗号鍵の長さは、128 ビット、192 ビット、256 ビットのいずれかです。CBC では初期ブロックとして 16 バイトの初期化ベクトルを使用します。この初期ブロックと最初の平文ブロックに対して XOR 演算を行います。

追加データ

AEAD 暗号化関数では、additional_data 引数の使用がサポートされています。この引数は Associated Data(AD)または追加認証データとも呼ばれます。鍵セットとは異なり、この追加データだけで暗号文を復号することはできません。この追加データは暗号化されたデータの信頼性と整合性を保証しますが、秘匿性は保証しません。

たとえば、特定の顧客のデータを暗号化するときに、CAST(customer_id AS STRING)additional_data を出力できます。これにより、データを復号する際に、そのデータが想定された customer_id を使用して暗号化されたことを確認できます。暗号化に使われたのと同じ additional_data 値でなければ復号できないためです。詳細については、RFC 5116 をご覧ください。

復号

AEAD.ENCRYPT の出力は暗号文 BYTES です。この暗号文は、AEAD.DECRYPT_STRING 関数または AEAD.DECRYPT_BYTES 関数で復号できます。これらの関数では、暗号化に使用された鍵を含む鍵セットを使用する必要があります。その鍵は 'ENABLED' 状態でなければなりません。また、暗号化に使われたのと同じ additional_data を使用する必要もあります。

鍵セットが復号に使用されるときは、暗号文にエンコードされた鍵 ID に基づいて、該当する復号鍵が選択されます。

AEAD.DECRYPT_STRING は平文の文字列を出力する一方、AEAD.DECRYPT_BYTES は平文 BYTES を出力します。AEAD.DECRYPT_STRING は文字列値がエンコードされた暗号文を復号できます。AEAD.DECRYPT_BYTESBYTES 値がエンコードされた暗号文を復号できます。このいずれかの関数を使用して、誤ったデータ型がエンコードされた暗号文を復号すると(たとえば、AEAD.DECRYPT_STRING を使用して BYTES 値がエンコードされた暗号文を復号するなど)、動作が不定になり、エラーが発生する可能性があります。

鍵のローテーション

暗号鍵をローテーションする主な目的は、所定の鍵で暗号化されたデータの量を減らし、攻撃者が鍵を不正使用した場合にアクセス可能なデータを少なくすることです。

鍵セットのローテーションには、次の処理が必要です。

  1. すべての鍵セット内に新しいプライマリ暗号鍵を作成します。
  2. すべての暗号化データを復号してから再び暗号化します。

最初の処理を行うのは、KEYS.ROTATE_KEYSET 関数です。その方法として、この関数は鍵セットに新しいプライマリ暗号鍵を追加し、古いプライマリ暗号鍵をセカンダリ暗号鍵に変更します。

このページは役立ちましたか?評価をお願いいたします。

フィードバックを送信...

ご不明な点がありましたら、Google のサポートページをご覧ください。