web-dev-qa-db-ja.com

シークレットを安全に保管するための最適な方法

シークレットを保存して使用する必要があるソフトウェアに取り組んでいます。

これらの秘密は、たとえば次のようなものです。

  • データベースに接続するためのパスワード
  • OAuth 2.0 client_credentials付与のクライアントシークレット。

これらのパスワードをどこかに(できればある種の構成ファイルに)保存し、reasonableセキュリティで保護する必要があります。

適切なセキュリティとは、HSMや複雑なインフラストラクチャ(PKIなど)などのハードウェアベースの重いソリューションがないことを意味します。

ソフトウェアはJavaであり、Javaが実行できる場所ならどこでも実行できます(特にWindows、GNU/Linux、Solaris、AIX)。

Javaがそれらを処理する方法を提供しない限り、OSやGNOMEキーストア、KDEウォレット、またはこれらのいずれかなどのディストリビューション固有のツールに依存することはできません(ただし、疑問です)。

ソフトウェアを構成するときに秘密暗号を暗号化し、必要に応じて実行時に解読するために対称暗号を使用することを考えました。しかし、暗号化キーの処理方法がわかりません。

私は4つの可能な解決策を見つけました:

  1. PBKDF2(SHA256-AES256-CBC)またはプレーンAES256-CBCをハードコーディングされた暗号鍵とオプションでいくつかのコード難読化(with ProGuard
    • これについては専用のCWEがあります。 CWE-321 -ハードコードされた暗号化キーの使用。だから私はこれが解決策だとは思いません。
  2. PBKDF2(SHA256-AES256-CBC)またはプレーンAES256-CBCをファイルシステムのファイル内のキーで使用します
    • 何らかの方法で保護する必要があるファイルにキーを公開します
      • 暗号化されたファイルシステムおよび/または
      • 強制ACL
      • 他に何か?
  3. Javaキーストアを使用してください
    • Javaキーストアのロックを解除するにはパスワードが必要なので、Javaキーストアのパスワードをどこに保存しますか?それを保護するには?蛇は自分の尻尾を食べています...
    • どういうわけか2と同等
  4. ホワイトボックス暗号化を使用する
    • これにはいくつかの弱点があり、難読化とほぼ同じです。 (これはオプション1の中にあります)。
    • WBCのJava実装が成熟しているかどうかはわかりません。

私はその質問を見てきました: Webアプリケーションにユーザー名/パスワードを保存する方法

だから私の質問は次のとおりです:秘密データを保護するための「最良の」共鳴可能なオプションは何ですか?

結局のところ2の方が簡単だと思います。秘密鍵の保護は、OpenSSHのようにソフトウェア自体ではなくOSに依存しますが、完全には確信していません。

編集:

PBKDF2は、PKCS#12 v1鍵導出アルゴリズムなど、他のパスワードベース鍵導出アルゴリズムに置き換えることができます。

ボーナス:

PBKDF2(SHA256-AES256-CBC)またはプレーンAES256-CBCから選択した場合、何が最適ですか?

  • PBKDF2は「遅い」ため、パスワードの保護に適していると言われています。そして、それはそのために設計されました。
  • AES256-CBCはより単純です(PBKDF2のようにキーをソルト/ハッシュ/反復する必要はありません)
7
superbob

私はあなたの脅威モデルが攻撃者であり、何らかのWebエクスプロイトを介してWebサーバー上のファイルを読み取るためのアクセス権を取得していると想定しています。そうでない場合は、提案された暗号化戦略で正確に何を軽減しているのか質問する必要があります。

そうであれば、2に似たオプションがおそらく最も簡単です。

キー暗号化キーのアルゴリズムとしてAES128-CBCを使用します。 CSPRNGで生成された128ビットの暗号化キーを使用すると、キーストレッチアルゴリズムを使用する必要がありません。 PBKDF2などのアルゴリズムは、ユーザーが指定した弱いパスワードを保護する場合にのみ必要です。自分でキーを設定できる場合は、それらが必要なビット強度であることを簡単に確認できます。

AES256は低速で、AES128に追加のセキュリティはありません。

設定ファイルとキーファイルがアクセス制御リストによってロックされていることを確認してください。

鍵ファイル:

<128 bit random key>

カスタムサービスアカウントでのみ読み取ることができます。

設定ファイル:

Passwords to systems, encrypted by the key in the Key file.

WebサーバーIDでのみ読み取ることができます。


これらのファイルがウェブサーバーから提供されていないことを確認してください(例:example.com/config.txtは機能しません)。これが機能する方法は、プロセスを実行するサービスアカウントがあることです。 Webサービスはこのプロセスを呼び出し、サービスに構成ファイルのパスワードを復号化するように要求します。サービスは、Webサーバープロセスのみが呼び出しできることを検証します。

これにより、システムまたはサーバーでのLFIの悪用からシークレットが保護されます。これは、Webサーバーユーザーのコンテキストで攻撃者がキーファイルを読み取ったり、構成ファイルの資格情報を復号化したりする権限がないためです。

物理的なアクセス、別の管理者レベルのアカウントによるシステムへの論理的なアクセス、またはプロセスの呼び出しを可能にする脆弱性からは保護されません。これは基本的に、Web ID(Webサイト自体が実行されているユーザー)による構成ファイルの直接の読み取りに対してのみ保護します。これが問題にならない場合は、シークレットを暗号化する必要はまったくありません。本当に保護できるのは、構成ファイルを見る可能性のある関係者によるカジュアルな観察だけです。

2
SilverlightFox

Javaを使用している場合、Java KeyStoreを使用してはいけませんか?

https://docs.Oracle.com/javase/7/docs/api/Java/security/KeyStore.html

このクラスは、暗号鍵と証明書のストレージ機能を表します。

キーストアは、さまざまなタイプのエントリを管理します。エントリの各タイプは、KeyStore.Entryインターフェースを実装します。 3つの基本的なKeyStore.Entry実装が提供されます。

KeyStore.PrivateKeyEntryこのタイプのエントリは、暗号化されたPrivateKeyを保持します。これは、オプションで、不正なアクセスを防ぐために保護された形式で格納されます。また、対応する公開鍵の証明書チェーンも伴います。

秘密鍵と証明書チェーンは、自己認証のために特定のエンティティによって使用されます。この認証のアプリケーションには、ソフトウェアのリリースやライセンス供与の一部としてJARファイルに署名するソフトウェア配布組織が含まれます。

KeyStore.SecretKeyEntryこのタイプのエントリは、暗号化されたSecretKeyを保持します。これは、オプションで、不正なアクセスを防ぐために保護された形式で保存されます。

KeyStore.TrustedCertificateEntryこのタイプのエントリには、別のパーティに属する単一の公開鍵証明書が含まれています。キーストアの所有者は、証明書の公開鍵が実際に証明書のサブジェクト(所有者)によって識別されるIDに属していると信頼しているため、これは信頼できる証明書と呼ばれます。

このタイプのエントリは、他のパーティを認証するために使用できます。

1
Julian Knight