web-dev-qa-db-ja.com

クラウドでの暗号化シークレット(ユーザー名、パスワード)の安全な実装

この情報を受け取るエージェント(バックグラウンドサービス)の構成ファイルをプッシュアウト(またはダウンロードできるようにする)する必要があるマルチテナント(クラウド)環境を構築しています。構成内の情報の1つは、ユーザー名とパスワードです。

エージェントをクラウドに対して安全に識別できると仮定すると、この機密情報を暗号化、共有、プッシュするためにどの暗号化およびセキュリティシステムを使用しますか?

公開秘密鍵のペアで十分ですか?シークレットは各エージェントの公開鍵で暗号化され、暗号化されていない値は破棄されると思います。

この実装についてどう思いますか?このアプリケーション、Windows Azure、ASP.NET MVC、Silverlightでは、主にC#を使用します。

サンプルエージェント側コード(RSACryptoProvider)

これにより、C#で公開秘密キーペアが生成され、ディスクにキーが保存されません

public static void AssignNewKey(){
    const int PROVIDER_RSA_FULL = 1;
    const string CONTAINER_NAME = "KeyContainer";
    CspParameters cspParams;
    cspParams = new CspParameters(PROVIDER_RSA_FULL);
    cspParams.KeyContainerName = CONTAINER_NAME;
// CspProviderFlags.UseNonExportableKey -- Prevent less-knowledgeable attacks against PK
// CspProviderFlags.UseUserProtectedKey -- Interactively Prompt for password
    cspParams.Flags = CspProviderFlags.UseMachineKeyStore;
    cspParams.ProviderName = "Microsoft Strong Cryptographic Provider";
    rsa = new RSACryptoServiceProvider(cspParams);

    rsa.PersistKeyInCsp = false;

    string publicPrivateKeyXML = rsa.ToXmlString(true);
    string publicOnlyKeyXML = rsa.ToXmlString(false);
    // do stuff with keys...
}

サンプルエージェント側コードオプション2(弾力のある城)

public void GenerateKey(string username, string password, string keyStoreUrl)
        {
            IAsymmetricCipherKeyPairGenerator kpg = new RsaKeyPairGenerator();
            kpg.Init(new RsaKeyGenerationParameters(BigInteger.ValueOf(0x13), new SecureRandom(), 1024, 8));
            AsymmetricCipherKeyPair kp = kpg.GenerateKeyPair();

            FileStream out1 = new FileInfo(string.Format("{0}secret.asc", keyStoreUrl)).OpenWrite();
            FileStream out2 = new FileInfo(string.Format("{0}pub.asc", keyStoreUrl)).OpenWrite();

            ExportKeyPair(out1, out2, kp.Public, kp.Private, username, password.ToCharArray(), true);

            out1.Close();
            out2.Close();

        }

private static void ExportKeyPair(
            Stream secretOut,
            Stream publicOut,
            AsymmetricKeyParameter publicKey,
            AsymmetricKeyParameter privateKey,
            string identity,
            char[] passPhrase,
            bool armor)
        {
            if (armor)
            {
                secretOut = new ArmoredOutputStream(secretOut);
            }

            PgpSecretKey secretKey = new PgpSecretKey(
                PgpSignature.DefaultCertification,
                PublicKeyAlgorithmTag.RsaGeneral,
                publicKey,
                privateKey,
                DateTime.Now,
                identity,
                SymmetricKeyAlgorithmTag.Cast5,
                passPhrase,
                null,
                null,
                new SecureRandom()
                //                ,"BC"
                );

            secretKey.Encode(secretOut);

            secretOut.Close();

            if (armor)
            {
                publicOut = new ArmoredOutputStream(publicOut);
            }

            PgpPublicKey key = secretKey.PublicKey;

            key.Encode(publicOut);

            publicOut.Close();
        }
7

各エージェントの公開鍵でデータを暗号化することは、エージェントを暗黙的に認証する方法です。エージェントが実際にデータを受信したかどうか(通信が悪意のある可能性のあるクラウドを経由するセットアップでは)は本当にわかりませんが、適切なエージェントだけがデータを復号化できることはわかっています。したがって、データがどこかに移動した場合、そのデータは適切なエージェントに送られます。これは問題に適したツールのようです。

公開鍵の暗号化はやり過ぎになる可能性があることに注意してください。受信エージェントとデータ送信者が共通の秘密鍵(ランダムに数十バイトの束)を共有するように設定できる場合は、対称暗号化を使用してデータを暗号化できます。

いくつかの落とし穴があります:

  • 公開鍵暗号化スキームを使用する場合、送信者はエージェントの公開鍵を事前に、信頼できる方法で知っている必要があります。エージェントの作成方法と展開方法によっては、これが簡単な場合とそうでない場合があります。

  • エージェントがデータを受信する能力は、その秘密鍵(または対称暗号化の場合は共通の共有秘密鍵)に関する知識から得られます。キーのコピーを取得すると、攻撃者が暗号化されたデータを復号化できるため、その秘密キーの保管に注意する必要があります。

  • 非対称暗号化は、限られたメッセージに対してのみ機能します。たとえば、1024ビットのRSAと通常のPKCS#1パディングでは、メッセージの117バイトにハード制限があります。また、RSAの暗号化と復号化はそれほど高速ではありません(ほとんどの目的には十分高速ですが)。そのため、メッセージ自体は暗号化せず、対称暗号化システム(AES)を使用してデータ自体を暗号化するために使用するランダムな秘密鍵(ランダムなバイトの束)を使用するハイブリッド方式を使用するのが通例です。 )、これは高速で、メッセージの長さが無制限です。

  • 悪意のある受動的な攻撃者がいる場合、しばしば積極的な攻撃者もいます。受動的な攻撃者はデータをスパイするだけです。アクティブな攻撃者もそれを変更できます。暗号化されたデータを微妙に変更して結果を観察することで、多くのスマートな攻撃が行われます(SSL接続で送信されたパスワードはそのようにして回復されました)。したがって、暗号化だけでなく、整合性チェックも必要です。 1つの可能性は、送信者が暗号化されたパケットに署名し、エージェントがそれらを復号化する前に署名を検証することです。

無数の導入済みシステムがこれらに遭遇し、事前に効率的にテストすることができません。あなたは本当にすべきであるすべてのために既存の標準フォーマットを使用し、サポートライブラリは適切に実装するための努力をすでに経ています。 [〜#〜] cms [〜#〜] または OpenPGP の使用をお勧めします。 C#がすでにそれらをサポートしているかどうかはわかりません(特に、OpenPGPの場合は疑問です) Bouncy Castle は、それをサポートするオープンソースライブラリです(C#バージョンがあります)。

最後に、同じデータを受信する必要のあるエージェントが多い場合は、シークレットを使用してデータを暗号化することを1回する方がネットワーク効率が向上する可能性があります。キー。各エージェントの公開キーで暗号化します。これは ブロードキャスト暗号化 と呼ばれ、これが有料テレビベンダーが行うことです(彼らは非常に同じ膨大なコンテンツを何百万人もの顧客に送信します。

9
Thomas Pornin

公開キー/秘密キーのペア-クラウド内のデータに悪意のある俳優がアクセスできると想定する必要があるため、このシナリオには適しているようです。クラウドに配置したエージェントのデータは、クラウド環境のセキュリティが弱いにもかかわらず、暗号化および認証できます。

Thomas Porninの答えは、私の答えよりもはるかに優れているので、追加するビットは実装をテストするために不可欠で、弱い構成または貧弱なコードとして実装はセキュリティモデルを破壊する可能性があります。

2
Rory Alsop

あなたの質問から理解できるように、コンピュータネットワーク認証プロトコル( ")を使用する必要があります。これにより、非セキュアネットワークを介して通信するノードが、安全な方法で互いの身元を証明できるようになります" )あなたの仕事のために、通信プロトコルの目的と仕様は以下を維持することです:

  • 鮮度:
  • 秘密の転送
  • 既知の主要な回復力
  • キー認証
  • キーの確認
  • 明示的な鍵認証

上記の仕様を達成するには、独自の通信プロトコルを設計できます。最も簡単なものは、次のようにすることです。

Sは信頼できるサードパーティで、AとBは安全な通信を希望するクライアントです。

  • A→S:IDA║IDB
  • S→A:カブ
  • A→B:カバイダ

次のようにプロトコルを改善できます。

  • A→S:IDA║IDB
  • S→A:E(Kas、[Kab])║E(Kbs、[Kab])
  • A→B:E(Kbs、[Kab])║IDA

ただし、上記の両方のプロトコルには多くの問題があります。プロトコルが十分に強力であることを確認したい場合は、リストされているプロトコルのいずれかを使用することをお勧めします。

0
Am1rr3zA