ASP.Net MVC和WebAPI加密

Dan*_*nyT 8 security asp.net-mvc asp.net-web-api

我想利用某种形式的"简单"加密,这种加密相当安全,但对开发过程的影响非常低.

假设我在客户端<> Web服务情况下拥有对话的双方.我的应用程序是Windows phone/win8/silverlight /桌面应用程序,服务器是ASP.Net MVC或WebAPI.

在我看来,我想要一些简单的事情: -

<security encryption="off|sometype|someothertype">
    <privatekey>12345MyKey54321</privatekey>
</security>
Run Code Online (Sandbox Code Playgroud)

作为客户端和服务器上的某种形式的配置参数.此外,身份验证例程将返回并存储某种形式的公钥.

这样做将启用"加密模式",并使用提供的密钥以任何方式加密和散列任何http请求.如果没有密钥和解密方法,最终结果是在本地,代理或远程计算机上嗅到的任何东西都将无法查看数据.在服务器上,在按下控制器操作之前,使用相同的密钥解密数据.

除了交换HttpRequest/WebClient调用类似于EncryptedHttpRequest之类的东西并在MVC/WebAPI方面添加适当的钩子之外,所有其他客户端代码和控制器操作都会对数据被加密的事实一无所知.

我错过了什么或者设置不是这么简单吗?没有我搜索过的,没有任何东西可以提供这种简洁程度,所以我认为我的逻辑中缺少一些差距?

Ali*_*tad 18

您只需使用HTTPS即可实现所有目标.只需购买证书(或使用自签名证书),即可加密.

不要重新发明轮子.

  • 使用Fiddler可以很容易地解密HTTPS通信.http://docs.telerik.com/fiddler/Configure-Fiddler/Tasks/DecryptHTTPS (4认同)

Geo*_*Cox 8

我成功完成了这个.这不是太困难而且运作良好.我用它来激活产品的许可证.最重要的是,您真正控制客户端和服务器 - 没有人可以从客户端的代码中提取您的私钥.

步骤1:创建不带参数的MVC控制器操作方法:

[HttpPost]        public ActionResult Activate()        { ... }
Run Code Online (Sandbox Code Playgroud)

步骤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;        
}
Run Code Online (Sandbox Code Playgroud)

第4步:使用您的CryptoStream另一个流阅读器进行解密.

我使用XmlReader,以便我所有现有的序列化代码都可以清除(在读取/写入磁盘或服务器上的数据库时)或加密(发送时).

using (var reader = XmlReader.Create(decryptionStream, settings))                { ... }
Run Code Online (Sandbox Code Playgroud)

第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;        
}
Run Code Online (Sandbox Code Playgroud)

第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);
}
Run Code Online (Sandbox Code Playgroud)

摘要和提示

  • 使用客户端和服务器上的请求/响应中的流来传递二进制八位字节流数据
  • 使用CryptoStream和加密算法(考虑使用最强的加密功能)和一个好的私钥来在序列化/反序列化时加密数据.
  • 确保检查大小并将所有传入数据格式化到客户端和服务器(避免缓冲区溢出并尽早抛出异常)
  • 如果可能,使用模糊处理保护客户端上的私钥(请查看DeepSea obfustactor)

  • 好方案!但Aliostad的答案更实用,更直接:) (2认同)