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

前言 

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

数据安全往往是开发人员很容易忽略的一个部分,包括我自己。近两年业内也出现了很多因为安全问题导致了很多严重事情发生,所以安全对我们开发人员很重要,我们要对我们的代码的安全负责。

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

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

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

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

1、编码

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

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

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

数据保护(Data Protection)介绍 

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

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

2、机密性
 服务器要保证请求是受信任的,所以就需要一些包含特定操作环境的信息,比如一个路径,一个权限或者一个句柄或者其他的一些东西特定于服务器的东西,这些信息不应该透漏给不受信任的客户端,也就是说类似于私钥。

3、隔离性
 然后就是要求做成一个组件,并且这个组件具有独立性,可以不依赖于系统中的其他组件。如一个bearer token的组件,它要使用这个组件的话,也不需要引用anti-CSRF这种机制了。

再进一步的缩小需求范围,加密的数据不需要在系统之外的其他系统中使用,另外处理速度要尽可能的快,因为每一次web请求都会使用加密组件一次或者多次。

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

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

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

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

1、配置应该尽量的简单,默认情况下应该可以零配置,开发人员可以直接运行。

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

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

4、钥应该是受保护的,不会被远程调用到。系统应该有一个自动保护机制并且可以自动应用。

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

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

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

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

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" 来做为公钥。

运行程序,查看结果:

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

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

私钥

私钥存放在哪里呢?

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

2、如果程序寄宿在IIS下,它被保存在HKLM注册表的ACLed特殊注册表键,并且只有工作进程可以访问,它使用windows的DPAPI加密。

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

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

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

一个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中间件等等,对于普通开发人员在编码的时候可能不会用到,但是在做系统分布式部署的时候如果你不了解这个机制可能就会遇到麻烦了(详见蟋蟀博客的这篇文章),所以还是可以期待一下下文,更加深入的了解它,掌握它。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持我们。

时间: 2016-09-09

ASP.NET Core MVC 配置全局路由前缀

ASP.NET Core MVC 配置全局路由前缀 前言 大家好,今天给大家介绍一个 ASP.NET Core MVC 的一个新特性,给全局路由添加统一前缀.严格说其实不算是新特性,不过是Core MVC特有的. 应用背景 不知道大家在做 Web Api 应用程序的时候,有没有遇到过这种场景,就是所有的接口都是以 /api 开头的,也就是我们的api 接口请求地址是像这样的: http://www.example.com/api/order/333 或者是这样的需求 http://www.exa

ASP.NET Core集成微信登录

工具: Visual Studio 2015 update 3 Asp.Net Core 1.0 1 准备工作 申请微信公众平台接口测试帐号,申请网址:(http://mp.weixin.qq.com/debug/cgi-bin/sandbox?t=sandbox/login).申请接口测试号无需公众帐号,可以直接体验和测试公众平台所有高级接口. 1.1 配置接口信息 1.2 修改网页授权信息 点击"修改"后在弹出页面填入你的网站域名: 2 新建网站项目 2.1 选择ASP.NET C

ASP.NET Core配置教程之读取配置信息

提到"配置"二字,我想绝大部分.NET开发人员脑海中会立马浮现出两个特殊文件的身影,那就是我们再熟悉不过的app.config和web.config,多年以来我们已经习惯了将结构化的配置信息定义在这两个文件之中.到了.NET Core的时候,很多我们习以为常的东西都发生了改变,其中也包括定义配置的方式.总的来说,新的配置系统显得更加轻量级,并且具有更好的扩展性,其最大的特点就是支持多样化的数据源.我们可以采用内存的变量作为配置的数据源,也可以直接配置定义在持久化的文件甚至数据库中. 由

asp.net core实现文件上传功能

本文实例为大家分享了单文件上传.多文件上传的功能,供大家参考,具体内容如下 单文件上传  上传文件在Web应用程序中是一个常见的功能.在asp.net core中上传文件并保存在服务器上,是很容易的.下面就来演示一下怎么样在 ASP.NET Core项目中进行文件上传.  首先,创建一个 asp.net core 项目,然后在Controller文件件添加一个HomeController,然后在 Views 文件夹的 Home 文件夹里添加一个 New.cshtml 视图文件.如下图: 添加一个

解决asp.net core在输出中文时乱码的问题

前言 作为一个.NET Web开发者,我最伤心的时候就是项目开发部署时面对Windows Server上贫瘠的解决方案,同样是神器Nginx,Win上的Nginx便始终不如Linux上的,你或许会说"干嘛不用windows自带的NLB呢",那这就是我这个小鸟的从众心理了,君不见Stack Overflow 2016最新架构中,用的负载和缓存技术也都是采用在Linux上已经成熟的解决方案吗.没办法的时候找个适合的解决办法是好事,有办法的时候当然要选择最好的解决办法. 所幸,.ASP.NE

云服务器下搭建ASP.NET Core环境

最近.net core如火如荼,国内这方面环境搭建方面的文档也非常多,但是不少已经是过时的,就算按照那个流程走下去也避免不了一些地方早就不一样了.所以下面我将从头到尾的教大家搭建一次环境,并且成功运行官网的demo. 一.系统环境 本次笔者因为懒的去做虚拟机,所以注册了一个云提供商的试用账户作为本次的主机. 系统: Ubuntu Server 14.04.2 LTS 64bit Mono: 1.0.0-rc1-update1 Coreclr: 1.0.0-rc1-update1 二.正文 1.首

ASP.NET Core 1.0实现邮件发送功能

准备将一些项目迁移到 asp.net core 先从封装类库入手,在遇到邮件发送类时发现在 asp.net core 1.0中并示提供SMTP相关类库,于是网上一搜发现了MailKit 好东西一定要试一下,何况是开源,下面是代码可实现SMTP邮件发送: using MailKit.Net.Smtp; using MailKit.Security; using MimeKit; using System.Threading.Tasks; namespace ConsoleApp1 { public

Linux(Ubuntu)下搭建ASP.NET Core环境

今天来学习一下ASP.NET Core 运行在Ubuntu中.无需安装mono . 环境 Ubuntu 14.04.4 LTS 服务器版 全新安装系统. 下载地址:http://mirrors.neusoft.edu.cn/ubuntu-releases/14.04.4/ubuntu-14.04.4-server-amd64.iso 你也可以下载桌面版安装. 下载地址:http://mirrors.neusoft.edu.cn/ubuntu-releases/14.04.4/ 安装DNVM 首先

ASP.NET Core 数据保护(Data Protection)中篇

前言 上篇主要是对 ASP.NET Core 的 Data Protection 做了一个简单的介绍,本篇主要是介绍一下API及使用方法. API 接口 ASP.NET Core Data Protectio 主要对普通开发人员提供了两个接口,IDataProtectionProvider 和 IDataProtector.  我们先看一下这两个接口的关系: namespace Microsoft.AspNetCore.DataProtection { // // 摘要: // An inter

win10下ASP.NET Core部署环境搭建步骤

随着ASP.NET Core 1.0 rtm的发布,网上有许多相关.net core 相关文章,今刚好有时间也在win10环境上搭建下 ASP.NET Core的部署环境,把过程记录下给大家. 1. 开发运行环境 1> Visual Studio 2015 Update 3* 2> .NET Core 1.0 for Visual Studio (包括asp.net core 模板,其中如果机器上没有.net core sdk会默认安装)地址https://go.microsoft.com/f

win10下VSCode+CMake+Clang+GCC环境搭建教程图解

打算用C/C++把基本的数据结构与算法实现一遍, 为考研做准备, 因为只是想实现算法和数据结构, 就不太想用VisualStudio, 感觉VSCode不错, 遂在网上找了一些教程, 结合自己的需求, 配置一下开发环境. 安装软件 CMake CMake是一个跨平台的自动化建构系统,它使用一个名为 CMakeLists.txt 的文件来描述构建过程; 官网下载安装, 傻瓜式操作; 记得把安装目录下的bin文件添加到系统环境变量, 这个可以在安装的时候勾选, 勾选了就不用自己添加了; 检测是否安装

VS2015 搭建Asp.net core开发环境的方法

前言 随着ASP.NET Core 1.0 rtm的发布,网上有许多相关.net core 相关文章,最近正好有时间就尝试VS2015 搭建Asp.net core开发环境,以下是简单的搭建过程,下面来一起看看吧. 步骤如下 一.首先你得装个vs2015 并且保证已经升级至 update3及以上(此处附上一个vs2015带up3的下载链接: ed2k://|file|cn_visual_studio_enterprise_2015_with_update_3_x86_x64_dvd_892329

详解.Net Core + Angular2 环境搭建

本文介绍了.Net Core + Angular2 环境搭建,具体如下: 环境搭建: 1)node.js版本>5.0,NPM版本>3.0,TypeScript版本>2.0(全装最新版就好了) 2)安装NTVS 1.2(node tools for vs),TSVS dev 1.4(TS for VS) 3)构建package.json,tsconfig.json,gulp.js文件 1.package.json { "name": "template.ang

Python3+Pycharm+PyQt5环境搭建步骤图文详解

搭建环境: 操作系统:Win10 64bit Python版本:3.7 Pycharm:社区免费版 一.Python3.7安装 下载链接:官网https://www.python.org/downloads/windows/或腾讯软件中心下载https://pc.qq.com/detail/5/detail_24685.html或其他站点下载.我下载的是python-3.7.0-amd64. 下载到安装包后打开,如果想安装到默认路径(C盘)的话一直点下一步就可以了,或者自定义安装到其他分区,我的

docker部署Asp.net core应用的完整步骤

1 容器概念 使用Docker前我们首先要简单了解一下容器的概念.MSDN上有一张虚拟机和容器的对比图,很好的展示了虚拟机和容器的区别,如下所示,虚拟机包括应用程序.必需的库或二进制文件以及完整的来宾操作系统,每台虚拟机都有一个单独的内核,我们完全可以把虚拟机看做是一台真实的物理机.容器包括应用程序及其所有依赖项,与其他容器共享 OS 内核,容器在主机操作系统上作为独立进程运行,我们可以把容器看做是一个应用沙盒. 我们经常会遇到"我机器上可以运行"的问题吧,然后部署到其他机器时就遇到了

ASP.NET Core部署前期准备 使用Hyper-V安装Ubuntu Server 16.10

概述 Hyper-V是微软的一款虚拟化产品,和VMWare一样采用的hypervisor技术.它已经被内嵌到Win10系统内,我们只需要进行简单的安装即可.但是前提是要确保你的机器已经启用虚拟化,可以到任务管理器中查看,如下: Ubuntu(乌班图)是一个开源的Linux操作系统,同时为企业提供服务器版本.至于其他发行版本如:CentOS.Debian等,这里不是讨论的重点,本篇是以Ubuntu Server 16.10版本进行安装的.且不说Ubuntu资料多,社区广,单凭它是我大学里边接触到的

Jexus 5.8.2正式发布! 为Asp.Net Core生产环境提供平台支持

Jexus 是一款运行于 Linux 平台,以支持  ASP.NET.PHP 为特色的集高安全性和高性能为一体的 WEB 服务器和反向代理服务器.最新版 5.8.2 已经发布,有如下更新: 1.现在大部分网站已经部署HTTPS,大家对于安全越来越重视,顺应潮流新增HTTPS多证书支持,每个网站都可以配置自己独立的SSL证书,现在有2种方式支持网站部署HTTPS. A.添加全服务器使用的SSL配置:如果需要,可以添加一个ssl配置为所有没有单独配置ssl的网站提供共享,这个配置,对支持泛域名的证书

详解ASP.NET Core部署项目到Ubuntu Server

基于上一篇成功安装Ubuntu Server 16.10的基础上,接下来继续我们ASP.NET Core项目的部署之旅! 只是对于这些年整天和Windows打交道的我,初次使用Linux确实有点费劲. 但是为了.NET Core跨平台的这一重大特性,即使再多的坑,也还是要硬着头皮上的. 不然会有人怀着诧异的眼神问你:你的.NET Core项目还部署到Windows上? 废话不多说,预祝你在十步之内成功部署!<( ̄︶ ̄)[GO!] 一.安装.NET Core SDK 依次输入以下命令即可完成安装,

Windows下Ruby+Watir自动化测试的环境搭建及数据读取

Watir的使用环境搭建 1.watir环境工具安装包: 1) ruby186-26.exe下载地址:http://files.rubyforge.vm.bytemark.co.uk/rubyinstaller/ 2) watir-1.5.2.gem下载地址:http://rubyforge.org/frs/?group_id=104&release_id=28016 3)rubygems-update-1.3.7.gem下载地址:http://rubyforge.org/frs/?group_