14 手動によるデータ暗号化
DBMS_CRYPTO
PL/SQLパッケージを使用して、データを手動で暗号化できます。
- 暗号化で解決しないセキュリティの問題
データの暗号化には多くのメリットがありますが、多くのデメリットもあります。 - データ暗号化の課題
暗号化によってセキュリティが強化される場合、いくつかの技術的な課題が伴います。 - DBMS_CRYPTOパッケージを使用したデータ暗号化ストレージ
DBMS_CRYPTO
パッケージは、セキュリティ問題に取り組むための様々な方法を提供します。 - OFBモードで暗号化された暗号文のOracle Databaseリリース11gでの使用
Oracle Databaseリリース11gでは、出力フィードバック(OFB)を使用するように暗号文が構成されても、かわりに電子コードブック(ECB)モードが使用されました。 - データの暗号化APIの使用例
データ暗号化APIの使用例として、DBMS_CRYPTO.SQL
プロシージャの使用、AES 256ビット・データの暗号化およびBLOBデータの暗号化などがあります。 - 暗号化データのデータ・ディクショナリ・ビュー
Oracle Databaseには、暗号化されたデータに関する情報を検索できるデータ・ディクショナリ・ビューが用意されています。
親トピック: データへのアクセス制御
14.1 暗号化で解決しないセキュリティの問題
データの暗号化には多くのメリットがありますが、多くのデメリットもあります。
- 原則1: 暗号化はアクセス制御の問題を解決しない
データを暗号化するとき、暗号化によってアクセス制御の構成が妨げられないように注意する必要があります。 - 原則2: 暗号化は不正な管理者からデータを保護しない
Oracle Database VaultなどのOracle機能を使用して、不正なデータベース管理者からデータベースを保護できます。 - 原則3: すべてのデータを暗号化してもデータは保護されない
通常、データの暗号化によってセキュリティが強化されるのであれば、すべてのデータを暗号化することにより、データはすべて保護されると考えますが、これは誤りです。
親トピック: 手動によるデータ暗号化
14.1.1 原則1: 暗号化はアクセス制御の問題を解決しない
データを暗号化するとき、暗号化によってアクセス制御の構成が妨げられないように注意する必要があります。
ほとんどの組織で、データのアクセスを、そのデータを参照する必要があるユーザーのみに制限する必要があります。たとえば、人事管理システムでは、従業員には各自の雇用レコードのみを参照できるように制限し、従業員の上司には直属の部下の雇用レコードを参照できるようにする場合があります。人事部門の担当者が複数の従業員の従業員レコードを参照する必要がある場合もあります。
一般的には、アクセス制御メカニズムを使用して、データを見る必要がある人にデータ・アクセスを制限するセキュリティ・ポリシーに対処できます。Oracle Databaseは、強力で独自に評価されたアクセス制御メカニズムを何年もの間提供してきました。仮想プライベート・データベースにより、アクセス制御を詳細なレベルまで規定できます。
人事部門のレコードは機密情報とみなされるため、セキュリティをより強化するためにこの情報はすべて暗号化する必要があると考えがちです。しかし、暗号化によってきめ細かいアクセス制御を規定できなくなるため、データ・アクセスの妨げとなる場合があります。たとえば、従業員、その上司および人事部門の担当者すべてが、従業員レコードにアクセスする必要がある場合があります。従業員データがすべて暗号化されている場合、この3人は暗号化されていない形式のデータにアクセスできる必要があります。したがって、従業員、上司および人事部門の担当者はデータを復号化するために同じ暗号化キーを共有する必要があります。このように、アクセス制御の向上という観点では、暗号化によってセキュリティが強化されず、アプリケーションの正しい機能や効率的な機能の妨げとなる場合があります。さらに、システムの複数のユーザー間で暗号化キーの送信および共有を安全に行うことは難しいという別の問題もあります。
格納データを暗号化するときの基本原則は、暗号化によってアクセス制御が妨げられないようにすることです。たとえば、emp
に対するSELECT
権限を持つユーザーが、基本的には参照できるすべてのデータへの参照を暗号化メカニズムによって制限されないようにする必要があります。また、ユーザーが表のすべての暗号化データを参照する必要がある場合は、あるキーを使用して表の一部を暗号化し、別のキーを使用して表の他の部分を暗号化するメリットはほとんどありません。この場合、ユーザーがデータを参照できるように、データを復号化するオーバーヘッドが増加するのみです。アクセス制御が適切に実装されている場合は、暗号化によってデータベース自体の中でセキュリティが強化されることはほとんどありません。データベース内のデータにアクセスする権限を持つユーザーについては、暗号化しても権限は変わりません。したがって、アクセス制御の問題解決に暗号化を使用しないでください。
親トピック: 暗号化で解決しないセキュリティの問題
14.1.2 原則2: 暗号化は不正な管理者からデータを保護しない
Oracle Database VaultなどのOracle機能を使用して、不正なデータベース管理者からデータベースを保護できます。
不正なユーザーがパスワードを推測して上位(データベース管理者)の権限を取得する可能性を懸念して、この脅威から保護するために格納データを暗号化することを考える組織もあります。
ただし、この問題の正しい解決策は、データベース管理者アカウントを保護し、その他の権限付きアカウントのデフォルトのパスワードを変更することです。データベースに侵入する最も簡単な方法は、管理者が変更しないままにしている権限付きアカウントのデフォルトのパスワードを使用することです。その一例がSYS
/CHANGE_ON_INSTALL
です。
不正なユーザーがDBA
権限を取得すると、データベースに対して多くの破壊的な行為を実行できますが、暗号化ではそれらの行為の多くからデータベースを保護できません。たとえば、データを破壊または削除する行為、ユーザー・データをファイル・システムにエクスポートし、そのデータを電子メールで自分自身に戻してパスワード・クラッカを実行するなどの行為があります。
データベース管理者は通常すべての権限を所有しているため、データベース管理者がデータベース内のすべてのデータを参照できることについて懸念を持つ組織もあります。そのような組織では、データベース管理者はデータベースを管理するのみで、そのデータベースに含まれるデータを参照できないようにする必要があると考えます。また、1人のユーザーに非常に多くの権限が集中することを懸念し、DBA機能を分割するか、または2人でアクセスするルールを規定する方が望ましいと考える組織もあります。
すべてのデータ(または大量のデータ)を暗号化すると、前述の問題が解決すると考えがちですが、このような不正行為からデータを保護するためのより優れた方法があります。たとえば、Oracle DatabaseではDBA
権限の制限付きの分割がサポートされています。Oracle Databaseでは、SYSDBA
ユーザーとSYSOPER
ユーザーに対するネイティブなサポートが提供されています。SYSDBA
はすべての権限を所有しますが、SYSOPER
は制限付き権限セット(データベースの起動および停止など)を所有します。
さらに、複数のシステム権限を網羅する、より小さなロールを作成することもできます。たとえば、jr_dba
ロールには、すべてのシステム権限を含めるのではなく、準データベース管理者に適切なロールのみ(CREATE TABLE
、CREATE USER
など)を含めます。
Oracle Databaseは、SYS
(またはSYS
権限を持つユーザー)によって実行されたアクションを監査し、オペレーティング・システムの保護位置にその監査証跡を格納できます。このモデルを使用すると、オペレーティング・システムに対してルート権限を持つ別の監査人が、SYS
によって実行されたすべてのアクションを監査できるため、監査人は、すべてのデータベース管理者が実行したアクションに対する責任をデータベース管理者自身に持たせることができます。
データベース管理者のアクセス権と制御権をOracle Database Vaultを使用して調整することもできます。
データベース管理者は信頼される立場にいます。諜報機関のような最も機密性の高いデータを扱う組織においても、通常、データベース管理者機能は分割されません。かわりに、データベース管理者には信頼性が必要なため、厳しく管理されます。定期的な監査によって不適切なアクティビティを明らかにできます。
格納データの暗号化が、データベースの管理を妨げないことが重要です。そうでない場合は、より大きいセキュリティ問題になる可能性があります。たとえば、データを暗号化することでそのデータが破損した場合セキュリティ問題となり、データ自体を解釈できず、修復不可能になる可能性があります。
暗号化を使用すると、データベース管理者(または権限を持つその他のユーザー)がデータベース内のデータを参照する機能を制限できます。ただし、これは、データベース管理者の権限を適切に管理すること、または強力なシステム権限の使用を制御することの代用にはなりません。信頼できないユーザーが重要な権限を持っている場合、そのユーザーが組織に多くの脅威をもたらすこととなり、暗号化されていないクレジット・カード番号を参照されるよりもはるかに深刻な状況に陥る場合もあります。
関連項目:
Oracle Database Vaultを使用したデータベース管理者のアクセス権と制御権の調整の詳細は、『Oracle Database Vault管理者ガイド』を参照してください。親トピック: 暗号化で解決しないセキュリティの問題
14.1.3 原則3: すべてのデータを暗号化してもデータは保護されない
通常、データの暗号化によってセキュリティが強化されるのであれば、すべてのデータを暗号化することにより、データはすべて保護されると考えますが、これは誤りです。
前述の2つの原則で説明したとおり、暗号化ではアクセス制御の問題に適切に対処できないため、暗号化によって通常のアクセス制御を妨げないことが重要になります。さらに、本番データベース全体を暗号化すると、読取り、更新または削除を行うために、すべてのデータを復号化する必要があります。暗号化は、本来、パフォーマンス集中型の操作であるため、すべてのデータを暗号化するとパフォーマンスに大きい影響を与えます。
可用性はセキュリティの重要な側面です。データの暗号化によって、データを使用できなくなったり、パフォーマンスが低下して可用性に悪影響を与えた場合は、すべてのデータを暗号化することで新たなセキュリティ問題が発生することになります。セキュリティの適切な手続きとして、暗号化キーを定期的に変更する必要がありますが、このときデータベースにアクセスできなくなります。これも可用性に悪影響を与えます。キーを変更する場合は、データを復号化して新しいキーで再度暗号化するまでの間、データベースにアクセスできなくなります。
格納データをオフラインで暗号化することは、メリットもあります。たとえば、組織が半年から1年単位で遠隔地にオフラインでバックアップを格納する場合があります。もちろん、保護の第1段階は、物理的なアクセス制御を確立することによって、データを格納する施設を保護することです。さらに、このデータを格納する前に暗号化すると、メリットがあります。このデータはオンラインでアクセスされないため、パフォーマンスについて考慮する必要はありません。Oracleデータベースにはこの機能が備わっていませんが、暗号化サービスを提供するベンダーがあります。この方法を検討する組織は、バックアップ・データの大規模な暗号化を実施する前に、プロセスを徹底的にテストする必要があります。オフラインで格納する前に、暗号化されたデータを正常に復号化でき、正しく再インポートできることを確認する必要があります。
親トピック: 暗号化で解決しないセキュリティの問題
14.2 データ暗号化の課題
暗号化によってセキュリティが強化される場合、いくつかの技術的な課題が伴います。
- 暗号化され索引付けされたデータ
暗号化データが索引付けされている場合は、特別な問題が発生します。 - 生成された暗号化キー
暗号化されたデータの安全性は、データの暗号化に使用されるキーの安全性に依存します。 - 転送された暗号化キー
暗号化キーがアプリケーションによってデータベースに渡される場合は、暗号化キーを暗号化する必要があります。 - 暗号化キーの格納
データベースまたはオペレーティング・システムに暗号化キーを格納できます。 - 暗号化キーの変更の重要性
慎重なセキュリティの手続きでは、暗号化キーを定期的に変更するように指示されます。 - バイナリ・ラージ・オブジェクトの暗号化
一部のデータ型は、暗号化に手間がかかります。
親トピック: 手動によるデータ暗号化
14.2.1 暗号化され索引付けされたデータ
暗号化データが索引付けされている場合は、特別な問題が発生します。
たとえば、ある会社が国民識別番号(米国社会保障番号(SSN)など)を各従業員の従業員番号として使用しているとします。会社は従業員番号を機密性の高いデータと考えているため、employees
表のemployee_number
列のデータを暗号化します。employee_number
列には一意の値が含まれているため、データベース設計者は、パフォーマンスを向上するためにそのデータを索引付けします。
ただし、DBMS_CRYPTO
(または別のメカニズム)を使用して列のデータを暗号化した場合、その列の索引にも暗号化された値が含まれます。列の索引に暗号化された値が含まれている場合、この索引は等価性チェック(たとえば、SELECT * FROM emp WHERE employee_number = '987654321'
)には使用できますが、それ以外の目的には事実上使用できません。索引付けされたデータを暗号化しないでください。
国民識別番号は一意のIDとして使用しないことをお薦めします。かわりに、CREATE SEQUENCE
文を使用して、一意の識別番号を生成してください。国民識別番号を使用しない理由は、次のとおりです。
-
国民識別番号の乱用に関連するプライバシの問題があること(識別情報の盗難など)
-
国民識別番号に一部の重複があること(例: 米国社会保障番号)
親トピック: データ暗号化の課題
14.2.2 生成された暗号化キー
暗号化されたデータの安全性は、データの暗号化に使用されるキーの安全性に依存します。
暗号化キーは、安全な暗号化キー生成方法を使用して安全に生成する必要があります。Oracle Databaseは、DBMS_CRYPTO
のRANDOMBYTES
ファンクションを使用した完全な乱数の生成を提供しています。(このファンクションは、非推奨になっている以前のDBMS_OBFUSCATION_TOOLKIT
のGetKey
プロシージャによって提供されていた機能にかわるものです。)DBMS_CRYPTO
は、以前にRSA Securityによって認証された安全な乱数ジェネレータ(RNG)をコールします。
ノート:
DBMS_RANDOM
パッケージは使用しないでください。DBMS_RANDOM
パッケージは擬似乱数を生成します。「セキュリティのための乱雑性についての推奨事項(RFC-1750)」には、擬似乱数プロセスを使用して機密の数値を生成すると、真のセキュリティを維持できなくなると述べられています。
キーの値を暗号化する場合は、必ず正しいバイト数を指定してください。たとえば、ENCRYPT_AES128
暗号化アルゴリズムの場合は、16バイトのキーを指定する必要があります。
親トピック: データ暗号化の課題
14.2.3 転送された暗号化キー
暗号化キーがアプリケーションによってデータベースに渡される場合は、暗号化キーを暗号化する必要があります。
暗号化しないと、キーの転送時に、侵入者がキーにアクセスできる可能性があります。ネットワーク・データの暗号化では、暗号化キーを含む送信中のデータはすべて、改ざんまたは傍受から保護されます。
親トピック: データ暗号化の課題
14.2.4 暗号化キーの格納
データベースまたはオペレーティング・システムに暗号化キーを格納できます。
- 暗号化キーの格納について
暗号化キーの格納は、暗号化で最も重要で難しい問題の1つです。 - データベースへの暗号化キーの格納
データベースに暗号化キーを格納しても、データベース管理者が暗号化データにアクセスできなくなるとはかぎりません。 - オペレーティング・システムへの暗号化キーの格納
暗号化キーをオペレーティング・システムのフラット・ファイルに格納する場合、PL/SQLからコールアウトを実行して暗号化キーを取得できます。 - ユーザー自身による暗号化キーの管理
ユーザーにキーを提供させる場合は、ユーザー自身がそのキーに責任を持つことを想定しています。 - 透過的データベース暗号化および表領域暗号化を使用した手動暗号化
透過的データベース暗号化および表領域暗号化は、暗号化された表および表領域に対するキーを自動的に管理して、安全な暗号化を提供します。
親トピック: データ暗号化の課題
14.2.4.1 暗号化キーの格納について
暗号化キーの格納は、暗号化で最も重要で難しい問題の1つです。
対称キーで暗号化されたデータを復元するには、データを復号化しようとする承認済のアプリケーションまたはユーザーがキーにアクセスできる必要があります。同時に、アクセス権のない暗号化データに不正アクセスしようとするユーザーは、キーにアクセスできないようにする必要があります。
親トピック: 暗号化キーの格納
14.2.4.2 データベースへの暗号化キーの格納
データベースに暗号化キーを格納しても、データベース管理者が暗号化データにアクセスできなくなるとは限りません。
すべての権限を持つデータベース管理者は暗号化キーを含む表にもアクセスできます。ただし、明確な意図のない詮索好きなユーザーまたはオペレーティング・システム上のデータベース・ファイルを破壊しようとするユーザーに対しては、適切なセキュリティ対策になる可能性があります。
簡単な例として、従業員データを含む表(EMP
)を作成するとします。列の1つに格納されている各従業員の社会保障番号(SSN)を暗号化します。従業員のSSNは、別の列に格納されているキーを使用して暗号化できます。ただし、表全体に対するSELECT
権限を持っているユーザーは、暗号化キーを取得し、対応するSSNを復号化できます。
この暗号化スキーマは簡単に侵害できるようにみえますが、多少の取り組みで、非常に強力な不正侵入対策ソリューションを作成できます。たとえば、この方法を使用してSSNを暗号化する前に、employee_number
のデータをさらに変換するテクニックを使用することで、SSNを暗号化できます。これは、employee_number
と従業員の誕生日のXOR
(排他的論理和)演算を使用して値の妥当性を判別するような単純なテクニックの場合もあります。
別の保護として、暗号化を実行するPL/SQLパッケージの本体を(WRAP
ユーティリティを使用して)ラップして、コードを不明瞭化(スクランブル化)する方法もあります。WRAP
ユーティリティは入力SQLファイルを処理し、その中のPL/SQLユニットを不明瞭化します。たとえば、次のコマンドではkeymanage.sql
ファイルを入力として使用しています。
wrap iname=/mydir/keymanage.sql
開発者は次に、ラップされたパッケージに含まれるキーを使用して、パッケージ内のファンクションにDBMS_CRYPTO
パッケージ・コールをコールさせることができます。
Oracle Databaseでは、動的に生成されたPL/SQLコードを不明瞭化できます。DBMS_DDL
パッケージには、動的に生成されたPL/SQLプログラム・ユニットを不明瞭化するために使用できるサブプログラムが2つ含まれています。たとえば、次のブロックでは、DBMS_DDL.CREATE_WRAPPED
プロシージャを使用して、動的に生成されたPL/SQLコードをラップします。
BEGIN
......
SYS.DBMS_DDL.CREATE_WRAPPED(function_returning_PLSQL_code());
......
END;
ラップは解読不可能ではありませんが、侵入者が暗号化キーにアクセスするのはかなり困難になります。各暗号化データの値ごとに異なるキーが提供されている場合でも、キーの値をパッケージ内に埋め込まないでください。かわりに、キーの管理を実行するパッケージをラップ(つまり、データ変換またはパディング)してください。
関連項目:
WRAP
コマンドライン・ユーティリティと動的ラップのためのDBMS_DDL
サブプログラムの詳細は、『Oracle Database PL/SQLパッケージおよびタイプ・リファレンス』を参照してください。
また、データをラップするかわりに暗号化キーを別の表に格納し、プロシージャを使用してキー表に対するコールをエンベロープする方法もあります。キー表は、主キーと外部キー関係を使用してデータ表に結合できます。たとえば、employee_number
は、従業員情報と暗号化されたSSNを格納するemployees
表の主キーです。また、employee_number
列は、従業員のSSNの暗号化キーを格納するssn_keys
表に対する外部キーです。ssn_keys
表に格納されたキーも使用前に(XOR
演算により)変換できるため、キー自体が暗号化されずに格納されることはありません。プロシージャをラップすると、キーを使用前に変換する方法を隠すことができます。
この方法のメリットは次のとおりです。
-
表への直接アクセス権を持つユーザーは、暗号化されていない機密データを参照することも、キーを取得してデータを復号化することもできません。
-
復号化されたデータへのアクセスは、暗号化されたデータの選択、キー表からの復号化キーの取得、およびデータの復号化に使用するキーの変換を実行するプロシージャを介して制御できます。
-
データ変換アルゴリズムは、プロシージャをラップし、プロシージャ・コードを不明瞭化することによって、偶発的な傍受から隠されます。
-
データ表とキー表の両方に対する
SELECT
権限があっても、キーは使用前に変換されるため、この権限を持つユーザーがそのデータを復号化できる保証はありません。
この方法のデメリットは、キー表とデータ表の両方に対するSELECT
権限があり、キー変換アルゴリズムを導出できるユーザーが、暗号化スキームを解読できることです。
前述の方法は完全ではありませんが、クリアテキストで格納されている機密情報を簡単に取得できないように保護するには十分です。
親トピック: 暗号化キーの格納
14.2.4.3 オペレーティング・システムへの暗号化キーの格納
暗号化キーをオペレーティング・システムのフラット・ファイルに格納する場合、PL/SQLからコールアウトを実行して暗号化キーを取得できます。
ただし、オペレーティング・システムにキーを格納し、それに対してコールアウトを行う場合、データはオペレーティング・システムでの保護と同じ程度にのみ保護されます。
セキュリティ上の主な懸念が、オペレーティング・システムからデータベースに侵入される可能性があるということである場合、オペレーティング・システムにキーを格納することは、データベース自体にキーを格納することより、侵入者にとっては暗号化されたデータを取得しやすくなります。
親トピック: 暗号化キーの格納
14.2.4.4 ユーザー自身による暗号化キーの管理
ユーザーにキーを提供させる場合は、ユーザー自身がそのキーに責任を持つことを想定しています。
ヘルプ・デスクへのコールの40%が、パスワードを忘れたユーザーからのコールであることから、ユーザーが暗号化キーを管理することのリスクは明らかです。多くの場合、ユーザーは暗号化キーを忘れるか、キーを書き留めておくため、セキュリティ上の弱点が生じます。ユーザーが暗号化キーを忘れたり、会社を退職した場合、データは復元できなくなります。
ユーザーにキーを提供する、またはユーザーがキーを管理する場合は、ネットワーク暗号化を使用して、キーがクリアテキストでクライアントからサーバーに渡されないようにする必要があります。また、キー・アーカイブ・メカニズムを開発する必要があります。これも困難なセキュリティの問題です。キー・アーカイブおよびバックドアは、暗号化によって解決しようとしているセキュリティ上の弱点を生み出すことになります。
親トピック: 暗号化キーの格納
14.2.4.5 透過的データベース暗号化および表領域暗号化を使用した手動暗号化
透過的データベース暗号化および表領域暗号化は、暗号化された表および表領域に対するキーを自動的に管理して、安全な暗号化を提供します。
アプリケーションで、メディアに格納されている機密性の高い列データの保護を必要とする場合は、これらの2種類の暗号化を使用することで、これを簡単にすばやく行えます。
関連項目:
透過的データ暗号化の詳細は、『Oracle Database Advanced Securityガイド』を参照してください。
親トピック: 暗号化キーの格納
14.2.5 暗号化キーの変更の重要性
慎重なセキュリティの手続きでは、暗号化キーを定期的に変更するように指示されます。
格納データの場合、これを実行するには、データを定期的に暗号解除し、適切な別のキーを使用して再度暗号化する必要があります。
暗号化キーの変更は、おそらくデータへのアクセスがない間に実行しますが、また別の課題が生まれます。クレジット・カード番号を暗号化するWebベースのアプリケーションでは、暗号化キーを切り替える間はアプリケーション全体を停止できないため、特に問題になります。
親トピック: データ暗号化の課題
14.2.6 バイナリ・ラージ・オブジェクトの暗号化
一部のデータ型は、暗号化に手間がかかります。
たとえば、Oracle Databaseでは、非常に大規模なオブジェクト(たとえば、数GB)をデータベースに格納するバイナリ・ラージ・オブジェクト(BLOB)をサポートしています。BLOBは、列として内部的に格納するか、または外部ファイルに格納できます。
関連トピック
親トピック: データ暗号化の課題
14.3 DBMS_CRYPTOパッケージを使用したデータ暗号化ストレージ
DBMS_CRYPTO
パッケージは、セキュリティ問題に取り組むための様々な方法を提供します。
暗号化は、複数のセキュリティへの脅威に対処できる理想的なソリューションではありませんが、データベースに格納する前に機密性の高いデータを選択的に暗号化することによって、セキュリティを強化できます。そのようなデータの例は次のとおりです。
-
クレジット・カード番号
-
国民識別番号
Oracle Databaseには、格納データの暗号化および復号化のためのPL/SQLパッケージDBMS_CRYPTO
が用意されています。このパッケージは、Advanced Encryption Standard(AES)の暗号化アルゴリズムも含めて、複数の業界標準暗号化およびハッシング・アルゴリズムをサポートしています。AESは、データ暗号化規格(DES)にかわる規格として、National Institute of Standards and Technology(NIST)によって承認されました。
DBMS_CRYPTO
パッケージは、RAW
およびイメージやサウンドなどのラージ・オブジェクト(LOB)を含むOracle Databaseの一般的なデータ型の暗号化および復号化に使用できます。特に、BLOBとCLOBをサポートしています。さらに、様々なデータベース文字セット間でデータを暗号化するためのグローバリゼーション・サポートも提供します。
次の暗号化アルゴリズムがサポートされています。
-
Advanced Encryption Standard(AES)
-
SHA-2暗号化ハッシュ設定:
-
HASH_SH256
-
HASH_SH384
-
HASH_SH512
-
-
SHA-2メッセージ認証コード(MAC)
DBMS_CRYPTO
ではブロック暗号修飾子も提供されています。Public Key Cryptographic Standard(PKCS)#5を含む複数のパディング・オプションおよびCipher Block Chaining(CBC)を含む4つのブロック暗号連鎖モードから選択できます。パディングは8バイトの倍数で実行する必要があります。
ノート:
-
DESはNational Institute of Standards and Technology(NIST)の推奨対象ではなくなりました。
-
SHA-1を使用する方がMD5より安全性が高くなります。
-
SHA-2を使用する方がSHA-1より安全性が高くなります。
-
キー付きMD5は、無防備ではありません。
-
このリリースでは、DESおよびMD5アルゴリズムは非推奨です。より強力なアルゴリズムを使用するようにOracle Database環境を移行するには、My Oracle Supportノート2118136.2で説明されているパッチをダウンロードしてインストールします。
表14-1に、DBMS_CRYPTO
パッケージ機能の概要を示します。
表14-1 DBMS_CRYPTOパッケージ機能の概要
機能 | DBMS_CRYPTOでサポートされている機能 |
---|---|
暗号化アルゴリズム |
AES |
パディング形式 |
PKCS5、複数ゼロ |
ブロック暗号連鎖モード |
CBC、CFB、ECB、OFB |
暗号化ハッシュ・アルゴリズム |
SHA-1、SHA-2、MD4、MD5、HASH_SH256、HASH_SH384、HASH_SH512 |
キー・ハッシュ(MAC)・アルゴリズム |
HMAC_MD5、HMAC_SH1、HMAC_SH256、HMAC_SH384、HMAC_SH512 |
暗号化擬似乱数ジェネレータ |
|
データベース型 |
|
DBMS_CRYPTO
は、新しいシステムと既存のシステムの両方に対応する広範囲のアルゴリズムをサポートしています。3DES_2KEYおよびMD4は下位互換性を維持するために提供されていますが、3DES、AESまたはSHA-1を使用するとセキュリティをより強化できます。3DES_2KEYおよびMD4の使用はお薦めしません。
DBMS_CRYPTO
パッケージには、比較の際に便利な暗号チェックサム機能(MD5)と、安全な乱数を生成する機能(RANDOMBYTES
関数)が含まれています。安全な乱数生成は暗号化の重要な部分です。予測可能なキーは簡単に推定されるキーであり、キーを簡単に推定できることによってデータが簡単に復号化される可能性があります。ほとんどの暗号解読が、総当たり解析(可能性のあるすべてのキーを繰り返す)によってではなく、脆弱なキーや適切に格納されていないキーを見つけ出すことによって行われています。
ノート:
DBMS_RANDOM
は暗号化キーの生成には不適切なため、使用しないでください。
キーの管理はプログラムによって実行されます。つまり、アプリケーション(またはファンクションのコール側)が、暗号化キーを提供する必要があります。これは、アプリケーション開発者がキーを安全に格納し、取得する方法を検討する必要があることを意味します。様々なキー管理方法の相対的なメリットとデメリットについては、後続の項で説明します。DESアルゴリズム自体の有効なキーの長さは56ビットです。
関連項目:
-
DBMS_CRYPTO
パッケージの詳細は、『Oracle Database PL/SQLパッケージおよびタイプ・リファレンス』を参照してください。 -
UTL_RAW
パッケージの詳細は、『Oracle Database PL/SQLパッケージおよびタイプ・リファレンス』を参照してください。
親トピック: 手動によるデータ暗号化
14.4 OFBモードで暗号化された暗号文のOracle Databaseリリース11gでの使用
Oracle Databaseリリース11gでは、出力フィードバック(OFB)を使用するように暗号文が構成されても、かわりに電子コードブック(ECB)モードが使用されました。
DBMS_CRYPTO.CHAIN_OFB
暗号ブロック連鎖修飾子を設定して、出力フィードバック(OFB)モードを使用するように暗号文の暗号化を構成すると、Oracle Bug 13001552のため、その構成で電子コードブック(ECB)モードが誤って使用されました。この不具合はOracle Databaseリリース12cで修正されています。したがって、Oracle Databaseリリース11gからリリース12cにアップグレードした後、リリース11gでOFBノードを使用して暗号化された暗号文は、Oracle Databaseリリース12cでは修正されたOFBモードで正しく復号化されません。
この問題を解決するには:
DBMS_CRYPTO
PL/SQLパッケージに対するEXECUTE
権限があるユーザーとして、データベースにログインします。DBMS_CRYPTO.CHAIN_ECB
ブロック暗号連鎖修飾子を使用して、暗号文を復号化します。
次の例のdbmscrypto11.sql
は、Oracle Databaseリリース11gでの誤った動作を示します。
dbmscrypto11.sql:
set serveroutput on
declare
l_mod_ofb pls_integer;
l_mod_ecb pls_integer;
v_key raw(32);
v_iv raw(16);
v_test_in raw(16);
v_ciphertext raw(16);
v_test_out_ECB raw(16);
v_test_out_OFB raw(16);
begin
l_mod_ofb := dbms_crypto.ENCRYPT_AES256
+ dbms_crypto.CHAIN_OFB
+ DBMS_CRYPTO.PAD_NONE ;
l_mod_ecb := dbms_crypto.ENCRYPT_AES256
+ dbms_crypto.CHAIN_ECB
+ DBMS_CRYPTO.PAD_NONE ;
v_key := hextoraw
('603deb1015ca71be2b73aef0857d77811f352c073b6108d72d9810a30914dff4');
v_iv := hextoraw('000102030405060708090A0B0C0D0E0F');
v_test_in := hextoraw('6bc1bee22e409f96e93d7e117393172a');
v_ciphertext := dbms_crypto.encrypt(src => v_test_in,
TYP => l_mod_ofb,
key => v_key,
iv => v_iv);
v_test_out_ECB := dbms_crypto.decrypt(src => v_ciphertext,
TYP => l_mod_ecb,
key => v_key,
iv => v_iv);
v_test_out_OFB := dbms_crypto.decrypt(src => v_ciphertext,
TYP => l_mod_ofb,
key => v_key,
iv => v_iv);
dbms_output.put_line
('Input plaintext : '||rawtohex(v_test_in));
dbms_output.put_line
('11g: Ciphertext (encrypt in OFB mode): '||rawtohex(v_ciphertext));
dbms_output.put_line
('11g: Output of decrypt in ECB mode : '||rawtohex(v_test_out_ECB));
dbms_output.put_line
('11g: Output of decrypt in OFB mode : '||rawtohex(v_test_out_OFB));
end;
/
生成される出力は次のようになります。
SQL> @dbmscrypto11.sql
Input plaintext : 6BC1BEE22E409F96E93D7E117393172A
11g: Ciphertext (encrypt in OFB mode): F3EED1BDB5D2A03C064B5A7E3DB181F8
11g: Output of decrypt in ECB mode : 6BC1BEE22E409F96E93D7E117393172A
11g: Output of decrypt in OFB mode : 6BC1BEE22E409F96E93D7E117393172A
この出力は、Oracle Databaseリリース11gではOFBモードが誤ってECBモードになるため、OFBまたはECBモードのどちらで復号化しても正しいプレーンテキストになることを示しています。
次の例のdbmscrypto12from11.sql
は、Oracle Databaseリリース11gからリリース12cにアップグレードした後、リリース11gのOFBモードで暗号化した暗号文を適切に復号化するには、OFBモードではなく、ECBモードを使用する必要があることを示します。
dbmscrypto12from11.sql:
set serveroutput on
declare
l_mod_ofb pls_integer;
l_mod_ecb pls_integer;
v_key raw(32);
v_iv raw(16);
v_test_in raw(16);
v_ciphertext11 raw(16);
v_test_out_ECB raw(16);
v_test_out_OFB raw(16);
begin
l_mod_ofb := dbms_crypto.ENCRYPT_AES256
+ dbms_crypto.CHAIN_OFB
+ DBMS_CRYPTO.PAD_NONE ;
l_mod_ecb := dbms_crypto.ENCRYPT_AES256
+ dbms_crypto.CHAIN_ECB
+ DBMS_CRYPTO.PAD_NONE ;
v_key := hextoraw
('603deb1015ca71be2b73aef0857d77811f352c073b6108d72d9810a30914dff4');
v_iv := hextoraw('000102030405060708090A0B0C0D0E0F');
v_test_in := hextoraw('6bc1bee22e409f96e93d7e117393172a');
v_ciphertext11 := hextoraw('F3EED1BDB5D2A03C064B5A7E3DB181F8');
v_test_out_ECB := dbms_crypto.decrypt(src => v_ciphertext11,
TYP => l_mod_ecb,
key => v_key,
iv => v_iv);
v_test_out_OFB := dbms_crypto.decrypt(src => v_ciphertext11,
TYP => l_mod_ofb,
key => v_key,
iv => v_iv);
dbms_output.put_line
('Input plaintext (to 11g) : '||rawtohex(v_test_in));
dbms_output.put_line
('11g: Ciphertext (encrypt in OFB mode): '||rawtohex(v_ciphertext11));
dbms_output.put_line
('12c: Output of decrypt in ECB mode : '||rawtohex(v_test_out_ECB));
dbms_output.put_line
('12c: Output of decrypt in OFB mode : '||rawtohex(v_test_out_OFB));
end;
/
生成される出力は次のようになります。
SQL> @dbmscrypto12from11.sql
Input plaintext (to 11g) : 6BC1BEE22E409F96E93D7E117393172A
11g: Ciphertext (encrypt in OFB mode): F3EED1BDB5D2A03C064B5A7E3DB181F8
12c: Output of decrypt in ECB mode : 6BC1BEE22E409F96E93D7E117393172A
12c: Output of decrypt in OFB mode : 4451EBE041EB29E191BBA0E9D67FAEB2
Oracle Databaseリリース11gからリリース12cへのアップグレードを予定している場合は、復号化操作でECBモードを使用するように、OFBモードが指定されたすべてのスクリプトを編集してください。この方法によって、スクリプトはリリース11gとリリース12c以降の両方で使用できるため、ビジネスの継続性を確保できます。
親トピック: 手動によるデータ暗号化
14.5 データの暗号化APIの使用例
データ暗号化APIの使用例として、DBMS_CRYPTO.SQL
プロシージャの使用、AES 256ビット・データの暗号化およびBLOBデータの暗号化などがあります。
- データ暗号化プロシージャの例
DBMS_CRYPTO.SQL
PL/SQLプログラムを使用してデータを暗号化できます。 - AES 256ビット・データ暗号化および復号化プロシージャの例
PL/SQLブロックを使用して、事前定義された変数を暗号化および復号化できます。 - BLOBデータの暗号化および復号化プロシージャの例
BLOBデータを暗号化できます。
親トピック: 手動によるデータ暗号化
14.5.1 データ暗号化プロシージャの例
DBMS_CRYPTO.SQL
PL/SQLプログラムを使用してデータを暗号化できます。
このサンプル・コードでは、次の処理を実行します。
-
文字列(
VARCHAR2
型)をRAW
データ型に変換した後、DESを使用して暗号化します。DBMS_CRYPTO
パッケージの暗号化および復号化ファンクションとプロシージャはRAW
データ型にのみ機能するため、このステップが必要となります。 -
SHA-1アルゴリズムを使用した160ビット・ハッシュの作成方法を示します。
-
MD5アルゴリズムを使用したキー依存の一方向ハッシュであるMACの計算方法を示します。
次に、DBMS_CRYPTO.SQL
プロシージャを示します。
DECLARE
input_string VARCHAR2(16) := 'tigertigertigert';
raw_input RAW(128) :=
UTL_RAW.CAST_TO_RAW(CONVERT(input_string,'AL32UTF8','US7ASCII'));
key_string VARCHAR2(8) := 'scottsco';
raw_key RAW(128) :=
UTL_RAW.CAST_TO_RAW(CONVERT(key_string,'AL32UTF8','US7ASCII'));
encrypted_raw RAW(2048);
encrypted_string VARCHAR2(2048);
decrypted_raw RAW(2048);
decrypted_string VARCHAR2(2048);
-- Begin testing Encryption:
BEGIN
dbms_output.put_line('> Input String : ' ||
CONVERT(UTL_RAW.CAST_TO_VARCHAR2(raw_input),'US7ASCII','AL32UTF8'));
dbms_output.put_line('> ========= BEGIN TEST Encrypt =========');
encrypted_raw := dbms_crypto.Encrypt(
src => raw_input,
typ => DBMS_CRYPTO.DES_CBC_PKCS5,
key => raw_key);
dbms_output.put_line('> Encrypted hex value : ' ||
rawtohex(UTL_RAW.CAST_TO_RAW(encrypted_raw)));
decrypted_raw := dbms_crypto.Decrypt(
src => encrypted_raw,
typ => DBMS_CRYPTO.DES_CBC_PKCS5,
key => raw_key);
decrypted_string :=
CONVERT(UTL_RAW.CAST_TO_VARCHAR2(decrypted_raw),'US7ASCII','AL32UTF8');
dbms_output.put_line('> Decrypted string output : ' ||
decrypted_string);
if input_string = decrypted_string THEN
dbms_output.put_line('> String DES Encyption and Decryption successful');
END if;
dbms_output.put_line('');
dbms_output.put_line('> ========= BEGIN TEST Hash =========');
encrypted_raw := dbms_crypto.Hash(
src => raw_input,
typ => DBMS_CRYPTO.HASH_SH1);
dbms_output.put_line('> Hash value of input string : ' ||
rawtohex(UTL_RAW.CAST_TO_RAW(encrypted_raw)));
dbms_output.put_line('> ========= BEGIN TEST Mac =========');
encrypted_raw := dbms_crypto.Mac(
src => raw_input,
typ => DBMS_CRYPTO.HMAC_MD5,
key => raw_key);
dbms_output.put_line('> Message Authentication Code : ' ||
rawtohex(UTL_RAW.CAST_TO_RAW(encrypted_raw)));
dbms_output.put_line('');
dbms_output.put_line('> End of DBMS_CRYPTO tests ');
END;
/
親トピック: データの暗号化APIの使用例
14.5.2 AES 256ビット・データ暗号化および復号化プロシージャの例
PL/SQLブロックを使用して、事前定義された変数を暗号化または復号できます。
次の例では、事前定義の変数input_string
が、Cipher Block ChainingとPKCS #5パディングを使用するAES 256ビット・アルゴリズムを使用しています。
declare input_string VARCHAR2 (200) := 'Secret Message'; output_string VARCHAR2 (200); encrypted_raw RAW (2000); -- stores encrypted binary text decrypted_raw RAW (2000); -- stores decrypted binary text num_key_bytes NUMBER := 256/8; -- key length 256 bits (32 bytes) key_bytes_raw RAW (32); -- stores 256-bit encryption key encryption_type PLS_INTEGER := -- total encryption type DBMS_CRYPTO.ENCRYPT_AES256 + DBMS_CRYPTO.CHAIN_CBC + DBMS_CRYPTO.PAD_PKCS5; begin DBMS_OUTPUT.PUT_LINE ('Original string: ' || input_string); key_bytes_raw := DBMS_CRYPTO.RANDOMBYTES (num_key_bytes); encrypted_raw := DBMS_CRYPTO.ENCRYPT ( src => UTL_I18N.STRING_TO_RAW (input_string, 'AL32UTF8'), typ => encryption_type, key => key_bytes_raw ); -- The encrypted value in the encrypted_raw variable can be used here: decrypted_raw := DBMS_CRYPTO.DECRYPT ( src => encrypted_raw, typ => encryption_type, key => key_bytes_raw ); output_string := UTL_I18N.RAW_TO_CHAR (decrypted_raw, 'AL32UTF8'); DBMS_OUTPUT.PUT_LINE ('Decrypted string: ' || output_string); end;
親トピック: データの暗号化APIの使用例
14.5.3 BLOBデータの暗号化および復号化プロシージャの例
BLOBデータを暗号化できます。
次に、BLOBデータを暗号化および復号化するためのPL/SQLプログラム(blob_test.sql
)のサンプルを示します。このサンプル・コードは次の操作を実行し、ステップごとに進捗状況(または問題)を出力します。
-
BLOB列の表を作成します。
-
RAWの値をその表に挿入します。
-
RAWデータを暗号化します。
-
暗号化されたデータを復号化します。
blob_test.sql
プロシージャは次のとおりです。
-- 1. Create a table for BLOB column: create table table_lob (id number, loc blob); -- 2. Insert 3 empty lobs for src/enc/dec: insert into table_lob values (1, EMPTY_BLOB()); insert into table_lob values (2, EMPTY_BLOB()); insert into table_lob values (3, EMPTY_BLOB()); set echo on set serveroutput on declare srcdata RAW(1000); srcblob BLOB; encrypblob BLOB; encrypraw RAW(1000); encrawlen BINARY_INTEGER; decrypblob BLOB; decrypraw RAW(1000); decrawlen BINARY_INTEGER; leng INTEGER; begin -- RAW input data 16 bytes srcdata := hextoraw('6D6D6D6D6D6D6D6D6D6D6D6D6D6D6D6D'); dbms_output.put_line('---'); dbms_output.put_line('input is ' || srcdata); dbms_output.put_line('---'); -- select empty lob locators for src/enc/dec select loc into srcblob from table_lob where id = 1; select loc into encrypblob from table_lob where id = 2; select loc into decrypblob from table_lob where id = 3; dbms_output.put_line('Created Empty LOBS'); dbms_output.put_line('---'); leng := DBMS_LOB.GETLENGTH(srcblob); IF leng IS NULL THEN dbms_output.put_line('Source BLOB Len NULL '); ELSE dbms_output.put_line('Source BLOB Len ' || leng); END IF; leng := DBMS_LOB.GETLENGTH(encrypblob); IF leng IS NULL THEN dbms_output.put_line('Encrypt BLOB Len NULL '); ELSE dbms_output.put_line('Encrypt BLOB Len ' || leng); END IF; leng := DBMS_LOB.GETLENGTH(decrypblob); IF leng IS NULL THEN dbms_output.put_line('Decrypt BLOB Len NULL '); ELSE dbms_output.put_line('Decrypt BLOB Len ' || leng); END IF; -- 3. Write source raw data into blob: DBMS_LOB.OPEN (srcblob, DBMS_LOB.lob_readwrite); DBMS_LOB.WRITEAPPEND (srcblob, 16, srcdata); DBMS_LOB.CLOSE (srcblob); dbms_output.put_line('Source raw data written to source blob'); dbms_output.put_line('---'); leng := DBMS_LOB.GETLENGTH(srcblob); IF leng IS NULL THEN dbms_output.put_line('source BLOB Len NULL '); ELSE dbms_output.put_line('Source BLOB Len ' || leng); END IF; /* * Procedure Encrypt * Arguments: srcblob -> Source BLOB * encrypblob -> Output BLOB for encrypted data * DBMS_CRYPTO.AES_CBC_PKCS5 -> Algo : AES * Chaining : CBC * Padding : PKCS5 * 256 bit key for AES passed as RAW * -> hextoraw('000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F') * IV (Initialization Vector) for AES algo passed as RAW * -> hextoraw('00000000000000000000000000000000') */ DBMS_CRYPTO.Encrypt(encrypblob, srcblob, DBMS_CRYPTO.AES_CBC_PKCS5, hextoraw ('000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F'), hextoraw('00000000000000000000000000000000')); dbms_output.put_line('Encryption Done'); dbms_output.put_line('---'); leng := DBMS_LOB.GETLENGTH(encrypblob); IF leng IS NULL THEN dbms_output.put_line('Encrypt BLOB Len NULL'); ELSE dbms_output.put_line('Encrypt BLOB Len ' || leng); END IF; -- 4. Read encrypblob to a raw: encrawlen := 999; DBMS_LOB.OPEN (encrypblob, DBMS_LOB.lob_readwrite); DBMS_LOB.READ (encrypblob, encrawlen, 1, encrypraw); DBMS_LOB.CLOSE (encrypblob); dbms_output.put_line('Read encrypt blob to a raw'); dbms_output.put_line('---'); dbms_output.put_line('Encrypted data is (256 bit key) ' || encrypraw); dbms_output.put_line('---'); /* * Procedure Decrypt * Arguments: encrypblob -> Encrypted BLOB to decrypt * decrypblob -> Output BLOB for decrypted data in RAW * DBMS_CRYPTO.AES_CBC_PKCS5 -> Algo : AES * Chaining : CBC * Padding : PKCS5 * 256 bit key for AES passed as RAW (same as used during Encrypt) * -> hextoraw('000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F') * IV (Initialization Vector) for AES algo passed as RAW (same as used during Encrypt) * -> hextoraw('00000000000000000000000000000000') */ DBMS_CRYPTO.Decrypt(decrypblob, encrypblob, DBMS_CRYPTO.AES_CBC_PKCS5, hextoraw ('000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F'), hextoraw('00000000000000000000000000000000')); leng := DBMS_LOB.GETLENGTH(decrypblob); IF leng IS NULL THEN dbms_output.put_line('Decrypt BLOB Len NULL'); ELSE dbms_output.put_line('Decrypt BLOB Len ' || leng); END IF; -- Read decrypblob to a raw decrawlen := 999; DBMS_LOB.OPEN (decrypblob, DBMS_LOB.lob_readwrite); DBMS_LOB.READ (decrypblob, decrawlen, 1, decrypraw); DBMS_LOB.CLOSE (decrypblob); dbms_output.put_line('Decrypted data is (256 bit key) ' || decrypraw); dbms_output.put_line('---'); DBMS_LOB.OPEN (srcblob, DBMS_LOB.lob_readwrite); DBMS_LOB.TRIM (srcblob, 0); DBMS_LOB.CLOSE (srcblob); DBMS_LOB.OPEN (encrypblob, DBMS_LOB.lob_readwrite); DBMS_LOB.TRIM (encrypblob, 0); DBMS_LOB.CLOSE (encrypblob); DBMS_LOB.OPEN (decrypblob, DBMS_LOB.lob_readwrite); DBMS_LOB.TRIM (decrypblob, 0); DBMS_LOB.CLOSE (decrypblob); end; / truncate table table_lob; drop table table_lob;
親トピック: データの暗号化APIの使用例
14.6 暗号化データのデータ・ディクショナリ・ビュー
Oracle Databaseには、暗号化されたデータに関する情報を検索できるデータ・ディクショナリ・ビューが用意されています。
表14-2に、これらのデータ・ディクショナリ・ビューを示します。
表14-2 暗号化データに関する情報を表示するデータ・ディクショナリ・ビュー
ビュー | 説明 |
---|---|
|
ユーザーがアクセスできるすべての表にあるすべての暗号化列の暗号化アルゴリズム情報が表示されます。 |
|
データベースにあるすべての暗号化列の暗号化アルゴリズム情報が表示されます。 |
|
ユーザー・スキーマのすべての表にあるすべての暗号化列の暗号化アルゴリズム情報が表示されます。 |
|
暗号化されている現在のプラガブル・データベース(PDB)表領域に関する情報が表示されます。 |
|
透過的データ暗号化のウォレットのステータスおよびウォレットの場所に関する情報が表示され、現在のPDBのみに適用されます。 |
|
現在のPDBでサポートされている暗号化アルゴリズムが表示されます。 |
関連項目:
これらのビューの詳細は、Oracle Databaseリファレンスを参照してください。親トピック: 手動によるデータ暗号化