2012-08-15 106 views
8

我想利用某種形式的「簡單」加密,這種加密在開發過程的影響方面相當安全但摩擦非常低。ASP.Net MVC和WebAPI加密

假設我擁有一個客戶端的對話的雙方<> web服務的情況。我的應用程序是Windows Phone/win8/silverlight /桌面應用程序,服務器是ASP.Net MVC或WebAPI。

在我心中,我想是這樣簡單的事情: -

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

某種形式的客戶端和服務器上的配置參數。此外,身份驗證例程將返回並存儲某種形式的公鑰。

這樣做將啓用「加密模式」並導致任何http請求被加密&使用提供的密鑰以選定的方式進行散列。最終的結果是在本地,代理或遠程機器上嗅探到的任何東西都無法在沒有密鑰和解密方法的情況下查看數據。在服務器上,數據在使用控制器操作之前使用相同的密鑰進行解密。

除了換出HttpRequest/WebClient調用EncryptedHttpRequest之類的東西,並在MVC/WebAPI端添加適當的鉤子之外,所有其他客戶端代碼和控制器操作都不知道數據被加密的事實。

我錯過了什麼,或者可以設置不是這麼簡單嗎?據我搜索,沒有提供這種簡單程度的東西,所以我想我的邏輯中缺少一些缺陷缺陷?

+0

重新發明SSL/TLS? – Aliostad 2012-08-16 11:22:21

+0

問題是中間人攻擊中使用像Fiddler這樣的工具是多麼容易。 – DannyT 2012-08-16 14:19:29

回答

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的與加密算法一起(考慮使用最強大的加密possilbe)和一個很好的私鑰來加密數據時,你序列化/反序列化它。
  • 確保檢查的大小和格式的所有傳入的數據在客戶端和服務器(避免緩衝區溢出和早期拋出異常)
  • 如果可能的話使用模糊處理(看看在深海obfustactor保護你的私鑰在客戶機上)
+2

偉大的解決方案!但Aliostad的答案是更實際和直接:) – 2012-11-19 15:57:36

+0

完美的嵌入式Linux機器溝通數據庫與此實現。 – NTMS 2016-03-03 08:06:30

18

只需使用HTTPS就可以實現您所需的全部功能。只需購買證書(或使用自簽名證書)並且有您的加密。

不要重新發明車輪。

+3

使用Fiddler很容易解密HTTPS通信。 http://docs.telerik.com/fiddler/Configure-Fiddler/Tasks/DecryptHTTPS – 2015-02-19 14:52:04