私はこれを成功させました。それほど難しくはなく、うまく機能します。製品のライセンスをアクティブ化するために使用します。最も重要なことは、クライアントとサーバーを本当に制御することです。クライアントのコードから秘密鍵を抽出することはできません。
ステップ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難読化ツールをご覧ください)