8

適度に安全であるが、開発プロセスへの影響という点で非常に摩擦が少ない、何らかの形の「単純な」暗号化を利用したいと思います。

クライアント<>Webサービスの状況で会話の両側を所有していると仮定します。私のアプリケーションはWindowsPhone/ win8 / silverlight / desktopアプリで、サーバーはASP.NetMVCまたはWebAPIです。

私の心の中で、私は次のような単純なものが欲しいです:-

<security encryption="off|sometype|someothertype">
    <privatekey>12345MyKey54321</privatekey>
</security>

クライアントとサーバーの両方での構成パラメーターの形式として。さらに、認証ルーチンは何らかの形式の公開鍵を返し、保存します。

そうすることで、「暗号化モード」が有効になり、提供されたキーを使用して、選択した方法でhttpリクエストが暗号化およびハッシュ化されます。最終的に、ローカル、プロキシ、またはリモートマシンでスニッフィングされたものは、キーと復号化の方法がないとデータを表示できません。サーバーでは、コントローラーのアクションを実行する前に、同じキーを使用してデータが復号化されます。

HttpRequest / WebClient呼び出しをEncryptedHttpRequestのようなものに交換し、MVC / WebAPI側に適切なフックを追加する以外は、他のすべてのクライアントコードとコントローラーアクションは、データが暗号化されているという事実を認識しません。

私は何かが足りないのですか、それともセットアップはこれほど簡単ではないでしょうか?私が検索した限り、このレベルの単純さを提供するものは何もないので、ロジックにいくつかのギャップのある欠陥が欠けていると思いますか?

4

2 に答える 2

19

HTTPSを使用するだけで、探しているすべてを実現できます。証明書を購入する(または自己署名証明書を使用する)だけで、暗号化が行われます。

車輪の再発明をしないでください。

于 2012-08-16T11:23:49.930 に答える
8

私はこれを成功させました。それほど難しくはなく、うまく機能します。製品のライセンスをアクティブ化するために使用します。最も重要なことは、クライアントとサーバーを本当に制御することです。クライアントのコードから秘密鍵を抽出することはできません。

ステップ1:引数をとらないMVCコントローラーアクションメソッドを作成します。

[HttpPost]        public ActionResult Activate()        { ... }

ステップ2:コントローラーで、HttpRequest.InputStreamを使用して、クライアントから送信されたバイトを取得します。

var stream = this.HttpContext.Request.InputStream;

ステップ3:逆シリアル化するCryptoStreamを作成します。

ここでは、暗号化と復号化の両方の例を作成しました。sharedSecretは、十分な長さ(512バイト)のランダムバイトのbyte []です。これは、保護するものです。

public CryptoStream CreateEncryptionStream(Stream writeStream)
{            
    TripleDESCryptoServiceProvider cryptoProvider = new TripleDESCryptoServiceProvider();               
    PasswordDeriveBytes derivedBytes = new PasswordDeriveBytes(this._sharedSecret, null);                
    CryptoStream cryptoStream = new CryptoStream(writeStream, cryptoProvider.CreateEncryptor(derivedBytes.GetBytes(16), derivedBytes.GetBytes(16)), CryptoStreamMode.Write);            
    return cryptoStream;        
}        

public CryptoStream CreateDecryptionStream(Stream readStream)        
{            
    TripleDESCryptoServiceProvider cryptoProvider = new TripleDESCryptoServiceProvider();            
    PasswordDeriveBytes derivedBytes = new PasswordDeriveBytes(this._sharedSecret, null);                
    CryptoStream cryptoStream = new CryptoStream(readStream, cryptoProvider.CreateDecryptor(derivedBytes.GetBytes(16), derivedBytes.GetBytes(16)), CryptoStreamMode.Read);            
    return cryptoStream;        
}

ステップ4:CryptoStreamを別のストリームリーダーを使用して復号化します。

XmlReaderを使用して、既存のすべてのシリアル化コードを平文(サーバー上のディスクまたはデータベースの読み取り/書き込み時)または暗号化(送信時)で機能できるようにします。

using (var reader = XmlReader.Create(decryptionStream, settings))                { ... }

ステップ5:コントローラーで安全な応答を作成します。

これは、ステップ1〜4の逆を実行して、応答オブジェクトを暗号化します。次に、暗号化された応答をメモリストリームに書き込み、ファイル結果として返します。以下に、ライセンス応答オブジェクトに対してこれを行う方法を示しました。

var responseBytes = GetLicenseResponseBytes(licenseResponse);
return File(responseBytes, "application/octet-stream");

private byte[] GetLicenseResponseBytes(LicenseResponse licenseResponse)        
{            
    if (licenseResponse != null)            
    {                
        using (MemoryStream memoryStream = new MemoryStream())                
        {                    
            this._licenseResponseSerializer.Write(memoryStream, licenseResponse);

            return memoryStream.ToArray();                
        }            
    }           
    return null;        
}

ステップ6:クライアント要求応答を実装します。

HttpWebRequestまたはWebClientクラスを使用して、要求を作成できます。これが私が使用するコードからのいくつかの例です。

byte[] postBytes = GetLicenseRequestBytes(licenseRequest);
HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create(licenseServerUrl);
request.Method = "POST";
request.ContentType = "application/octet-stream";
request.Proxy = WebRequest.DefaultWebProxy;
using (Stream requestStream = request.GetRequestStream())
{                
    requestStream.Write(postBytes, 0, postBytes.Length);
}            
return request;

private LicenseResponse ProcessHttpResponse(HttpWebResponse response)
{
    if ((response.StatusCode == HttpStatusCode.OK) && response.ContentType.Contains("application/octet-stream"))
    {
        var stream = response.GetResponseStream();
        if (stream != null)
        {
            var licenseResponse = this._licenseResponseSerializer.Read(stream);
            return licenseResponse;
        }
    }
    return new LicenseResponse(LicensingResult.Error);
}

まとめとヒント

  • クライアントとサーバーのリクエスト/レスポンスのストリームを使用して、バイナリオクテットストリームデータを通信します
  • CryptoStreamを、暗号化アルゴリズム(最も強力な暗号化の可能性を使用することを検討してください)およびデータをシリアル化/逆シリアル化するときにデータを暗号化するための適切な秘密鍵とともに使用します。
  • クライアントとサーバーへのすべての受信データのサイズとフォーマットを確認してください(バッファオーバーランを回避し、例外を早期にスローします)
  • 可能であれば、難読化を使用してクライアントの秘密鍵を保護します(DeepSea難読化ツールをご覧ください)
于 2012-08-16T17:43:49.523 に答える