ASP.NET Core 数据保护(Data Protection)【上】

前言

上一篇博客记录了如何在 Kestrel 中使用 HTTPS(SSL), 也是咱们目前项目中实际使用到的。html

数据安全每每是开发人员很容易忽略的一个部分,包括我本身。近两年业内也出现了不少由于安全问题致使了不少严重事情发生,因此安全对咱们开发人员很重要,咱们要对咱们的代码的安全负责。web

在工做中,咱们经常会见到 encode,base64,sha256, rsa, hash,encryption, md5 等,一些人对他们还傻傻分不清楚,也不知道何时使用他们,还有一些人认为MD5就是加密算法。算法

在 ASP.NET Core 中,为数据保护相关提供了一批新的 API,包括加密解密机制,下面就让咱们来看看吧。windows

目录

  • 加密,编码,哈希之间的区别
  • 数据保护(Data Protection)介绍
  • ASP.NET Core 中的数据保护
  • 总结

编码,加密,哈希之间的区别

编码
编码是信息从一种形式或格式转换为另外一种形式的过程,他们是可逆的。
如 url、base6四、jsunicode、utf-8等等。api

加密
加密是可逆的,相似于编码也是把数据从一种形式转换为另外一种形式,它经过一个特定的加密的密匙,相对应的有解密的过程。加解密的算法有2种:对称加密算法和非对称加密算法。
对称:DES、AES、SM一、RC4 等等。
非对称:RSA、ECC、SM2 等等。安全

哈希
又叫"散列",就是把任意长度的数据转换成固定长度的“指纹”,这个过程是不可逆的。并且只要输入发生改变,输出的 hash值也会有很大不一样。
它还有一个特性是相同的输入老是有相同的结果, 这种特性刚好合适用来用来保存密码。
如:MD五、SHA256, SHA512, RipeMD, WHIRLPOOL等等。服务器

数据保护(Data Protection)介绍

在看数据保护官方文档的时候,微软的文档是这样写的,大体意思就是他们基于几点需求,要开发一套数据保护的库以便用来给受信任的客户端和不受信任的客户端来使用。这几点要求就是:cookie

一、真实性、完整性
举了一个身份验证cookie的例子,就是服务端生成了一个包含xyz权限的token,而后会在未来的某个时间过时,这个时候就须要从新请求生成一个,怎么样来保证请求的token不是被篡改过的。session

二、机密性
服务器要保证请求是受信任的,因此就须要一些包含特定操做环境的信息,好比一个路径,一个权限或者一个句柄或者其余的一些东西特定于服务器的东西,这些信息不该该透漏给不受信任的客户端,也就是说相似于私钥。框架

三、隔离性
而后就是要求作成一个组件,而且这个组件具备独立性,能够不依赖于系统中的其余组件。如一个bearer token的组件,它要使用这个组件的话,也不须要引用anti-CSRF这种机制了。

再进一步的缩小需求范围,加密的数据不须要在系统以外的其余系统中使用,另外处理速度要尽量的快,由于每一次web请求都会使用加密组件一次或者屡次。

基于以上要求,微软提出来可使用密码学,由于这是一个典型的密码学应用的场景。确实这是一个密码学的应用场景,而且是一个非对称加密算法的场景。可是你们都知道,非对称加密是由一个公钥和私钥用来保证安全性的,即便公钥遭泄露,整个通信仍然是安全的,这就是它比对称加密的好处。可是非对称加密也是有缺点的,就是加密和解密花费的时间长,速度慢。

可是上面的要求又是须要速度尽量快,怎么办呢? 因而微软的工程师们想出了能够经过精简而且优化非对称加密机制,来达到这个要求。由于不须要跨系统或者跨语言什么的,因此也不须要什么协议之类的,这就给优化带来了更多的可能性。

到这里,我就想,若是让我来基于以上几点来设计开发这样一个系统,我应该怎么样设计?怎么样达到要求?
带着这个问题,咱们来进一步看看微软是怎么样作的吧?

下面是一些总结的设计原则 :

一、配置应该尽可能的简单,默认状况下应该能够零配置,开发人员能够直接运行。

二、提供一个简单的API,应该容易使用,而且不会轻易用错。

三、开发人员不须要专门学习怎么样管理这些钥(公钥,私钥),系统应该自动的选择算法和管理钥的生命周期。理想状况下开发人员都不该该访问这些钥的原始文件。

四、钥应该是受保护的,不会被远程调用到。系统应该有一个自动保护机制而且能够自动应用。

若是让我设计这样一个库,我可能不会想到这么多,也许只会想到前3点。

再看一下针对的受众群体:

一、应用程序开发人员和框架开发人员(不须要学习任何知识)。

二、应用开发人员和系统管理员(不使用默认配置,只是设定一些路径等)。

三、针对具备更高安全意识的开发人员提供可扩展api,或特定需求扩展(须要重写系统的组件,有一些独特的需求)。

以上,能够看到微软在开发一个组件的时候对问题的分析,也许咱们能够从中学到一些东西。

ASP.NET Core 中的数据保护

Web应用程序中常常须要存储一些敏感数据(如用户密码),Windows 系统为桌面程序提供了DPAPI用来使用,可是并不适用于 Web 系统。ASP.NET Core提供了一套简单易用的API 用来保护数据。

ASP.NET Core 中,数据保护主要是用来给服务端设计的,用来替换ASP.NET 1.x-4.x中的 ,machineKey主要是用来保证使用Form身份验证时Cookie数据的加密解密,以确保不会被修改。或者ViewState数据的加密解密不被篡改,以及对session状态标识进行验证。

先看一下最简单的使用方法:

using System;
using Microsoft.AspNetCore.DataProtection;
using Microsoft.Extensions.DependencyInjection;

public class Program
{
    public static void Main(string[] args)
    {
        // 添加数据保护到服务中
        var serviceCollection = new ServiceCollection();
        serviceCollection.AddDataProtection();
        var services = serviceCollection.BuildServiceProvider();

        // 从DI中建立一个MyClass的实例 
        var instance = ActivatorUtilities.CreateInstance<MyClass>(services);
        instance.RunSample();
    }

    public class MyClass
    {
        IDataProtector _protector;

        // 参数 'provider' 来自 DI
        public MyClass(IDataProtectionProvider provider)
        {
            _protector = provider.CreateProtector("Contoso.MyClass.v1");
        }

        public void RunSample()
        {
            Console.Write("Enter input: ");
            string input = Console.ReadLine();

            // 加密
            string protectedPayload = _protector.Protect(input);
            Console.WriteLine($"Protect returned: {protectedPayload}");

            // 解密
            string unprotectedPayload = _protector.Unprotect(protectedPayload);
            Console.WriteLine($"Unprotect returned: {unprotectedPayload}");
        }
    }
}

/*
 * 输出:
 *
 * Enter input: Hello world!
 * Protect returned: CfDJ8ICcgQwZZhlAlTZT...OdfH66i1PnGmpCR5e441xQ
 * Unprotect returned: Hello world!
 */

CreateProtector("Contoso.MyClass.v1")中,参数“Contoso.MyClass.v1”能够理解为一个公钥,由于 ASP.NET Core Data Protection 是非对称加密(见前面介绍),因此系统中应该还有一个密钥,那么此处的密钥 ASP.NET Core 在系统内部帮你维护了。

读到这里,有同窗可能会问了,那系统中是如何帮我维护个人密钥的呢? 咱们不妨先来作一个测试。

首先,我在个人开发环境中,先把上面的程序中的解密部分代码注释掉,而后运行上面的程序,输入一个“Hello World!” ,获得了一个加密的字符串CfDJ8ICcgQwZZhlAlTZT...OdfH66i1PnGmpCR5e441xQ(略写)。

而后我把一样的程序拷贝到另一台开发环境的机器上,而后把上面的加密部分代码注释掉,使用第一步生成的CfDJ8ICcgQwZZhlAlTZT...OdfH66i1PnGmpCR5e441xQ来解密,注意这两步中咱们都使用 "Contoso.MyClass.v1" 来作为公钥。

运行程序,查看结果:
image

程序抛出了一个“System.Security.Cryptography.CryptographicException”异常的结果。

为何呢? 这是由于每一台机器都有一个自有的私钥,因为在解密的过程当中,这个私钥是不一样的,因此解密失败,抛出了一个异常。

私钥

私钥存放在哪里呢?

一、若是程序寄宿在 Microsoft Azure下,存储在“%HOME%\ASP.NET\DataProtection-Keys” 文件夹。

二、若是程序寄宿在IIS下,它被保存在HKLM注册表的ACLed特殊注册表键,而且只有工做进程能够访问,它使用windows的DPAPI加密。

三、若是当前用户可用,即win10或者win7中,它存储在“%LOCALAPPDATA%\ASP.NET\DataProtection-Keys”文件夹,一样使用的windows的DPAPI加密。

四、若是这些都不符合,那么也就是私钥是没有被持久化的,也就是说当进程关闭的时候,生成的私钥就丢失了。

下面是博主机器上的私钥文件:

一个xml配置文件,位于C:\Users\用户名\AppData\Local\ASP.NET\DataProtection-Keys文件夹,名为:key-c37e3ed9-fbb5-47bc-9e8c-128afaf1c6d9.xml,内容以下:

<?xml version="1.0" encoding="utf-8"?>
<key id="c37e3ed9-fbb5-47bc-9e8c-128afaf1c6d9" version="1">
  <creationDate>2016-08-15T05:21:16.7925949Z</creationDate>
  <activationDate>2016-08-15T05:21:16.7165905Z</activationDate>
  <expirationDate>2016-11-13T05:21:16.7165905Z</expirationDate>
  <descriptor deserializerType="Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.AuthenticatedEncryptorDescriptorDeserializer, Microsoft.AspNetCore.DataProtection, Version=1.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60">
    <descriptor>
      <encryption algorithm="AES_256_CBC" />
      <validation algorithm="HMACSHA256" />
      <encryptedSecret decryptorType="Microsoft.AspNetCore.DataProtection.XmlEncryption.DpapiXmlDecryptor, Microsoft.AspNetCore.DataProtection, Version=1.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60" xmlns="http://schemas.asp.net/2015/03/dataProtection">
        <encryptedKey xmlns="">
          <!-- This key is encrypted with Windows DPAPI. -->
          <value>AQAAANCMnd8BFdERjHoAwE/Cl+sBAAAArS6GBZu5C024S8VcNDckGgAAAAACAAAAAAAQZgAAAAEAACAAAABBUO4j0CscEZsdcHDAStXnDvtx+zFucmsG90sdhyjfgQAAAAAOgAAAAAIAACAAAABGr9fgvZkLAlgIZkGym5uLiufpaEcuVsp35+J96ItTYlABAADEZxVArK0QtxufuaRt/kVR2ZBZEoLhlYJ44BhvQDd6b9tN0L9Y7W2eeBPBefcZaGZk5xILwZYI5box9omwC/mp8t9wopVaratjZuNs21Al+JzxS+PeV9X0iPtRyfx2K7DJYOUT6IqoFR2ykL5MI9jvkIbUxcQOs0BKOwAHl4yAlYF2tR8pz1FkXKqZafovc11aOZeZhkfd2hiA53tan94bQOP43Z4HF+QWSazrq5IIqdFSOyZQemWL9Z7eYyoNpEktf3eGZQu/KBOg/BH5yizWa+6b7RLcEX6JdQ2/jpmnHNl+HPMIah3UZV0mRfAE2j58cUjosnV+LDQZoLn4OP70YWtO/tTBc4tsEY3n/WboL4PgPPmQ+2jfd/zmEQIon+4d7TY+mGh4c6wXAmAZF517UAHQMC1icx4HSJC8DTuWPlINihPyufejuPmLqW6CW8NAAAAA7ziObXv+Ax4Mm0AtZiGw0/IepDv/gJSxhEwLIDhfvQIQJv//G500EYtIbZJW6sWit//ypfjrUZYglHgKV+GpbA==</value>
        </encryptedKey>
      </encryptedSecret>
    </descriptor>
  </descriptor>
</key>

文件包含一个建立日期,一个过时日期。间隔为90天,当90天以后密钥就会失效,系统将自动生成一个新的密钥并设置新的密钥做为活动的密钥。只要已过时的密钥还存在于系统上,你仍然能够解密任何受保护的数据。

文章不宜太长,下篇再接着写。
若是您以为本篇文章对你有用的话,不妨点个【推荐】。

总结

这篇文章算是对ASP.NET Core Data Protection作了一个大体的介绍,而且包含了一个简单的使用方法。 在实际使用过程当中,其实不少组件内部都会使用到它,好比Session中间件,Identity中间件,Authercation中间件等等,对于普通开发人员在编码的时候可能不会用到,可是在作系统分布式部署的时候若是你不了解这个机制可能就会遇到麻烦了(详见蟋蟀博客的这篇文章),因此仍是能够期待一下下文,更加深刻的了解它,掌握它。


本文地址:http://www.cnblogs.com/savorboard/p/dotnetcore-data-protection.html
做者博客:Savorboard 欢迎转载,请在明显位置给出出处及连接

相关文章
相关标签/搜索