我已經成功完成了這項工作。這不是太困難,而且運作良好。我用它來激活產品的許可證。最重要的是你真正控制了客戶端和服務器 - 沒有人能從客戶端的代碼中提取你的私鑰。
步驟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的與加密算法一起(考慮使用最強大的加密possilbe)和一個很好的私鑰來加密數據時,你序列化/反序列化它。
- 確保檢查的大小和格式的所有傳入的數據在客戶端和服務器(避免緩衝區溢出和早期拋出異常)
- 如果可能的話使用模糊處理(看看在深海obfustactor保護你的私鑰在客戶機上)
重新發明SSL/TLS? – Aliostad 2012-08-16 11:22:21
問題是中間人攻擊中使用像Fiddler這樣的工具是多麼容易。 – DannyT 2012-08-16 14:19:29