最近接到一个任务,加密DotNet项目的配置文件。配置文件里需要加密的地方一共有两块,一个是数据库连接字符串,一个是自定义的所有AppSettings。

一开始接到这个任务我是拒绝的,因为压根不知道怎么加密,印象中的加密方式还停留在MD5。对于啥是对称加密,啥是非对称加密完全不认识。

加密方式

因为用的是DotNet所以打开微软Doc,希望能找到一点关于DotNet加密的说明文档。

其中.Net安全性 <https://docs.microsoft.com/zh-cn/dotnet/standard/security/>
介绍了一些关于加密的方法。

最常用的加密方式

* 对称加密
对称加密,使用单个密钥加密和解密数据(通常被用来加密大数据量的东西)。

* 非对称加密

非对称加密,分为公钥和私钥,利用公钥加密数据,由私钥解密。通常情况下用来保护对称加密的密钥。(在开发过程中发现,用公钥加密一个数据库连接字符串都会由于内容过长而报错)。对于待加密内容比较长的,可以使用分段加密的方式。

数字证书

一开始考虑使用对称方式加密配置文件,但是密钥的存放就是是一个很大的问题,想当然的就打算把密钥放在配置文件里。可是加密的意义何在呢?

所以后来考虑使用非对称方式加密配置文件,利用公钥加密文件,然后利用私钥解密。

存放公钥和私钥的最好工具是数字证书。

通常情况下,数字证书分为两种,一种只有公钥,一种则是有公钥也有私钥。

生成证书

证书其实需要由第三方CA机构来生成的,当然也可以自己生成。

Windows平台下微软提供了两种生成方式:

* 利用微软提供的MakeCert.exe可以生成证书。该工具包含在Windows SDK
<https://developer.microsoft.com/zh-cn/windows/downloads/windows-10-sdk>
中(注意对应版本)。MakeCert文档
<https://docs.microsoft.com/zh-cn/windows/desktop/SecCrypto/makecert>
* 利用PowerShell也是一种不错的选择。PowerShell文档
<https://docs.microsoft.com/zh-cn/previous-versions/windows/powershell-scripting/hh848633(v=wps.640)>
数字证书的存储

看了网上的很多博客,大部分是直接加载本地实体文件,比较高级的是把证书导入到计算机的存储区。

证书存储有两种类型:

* 本地用户
* MY
* Root
* Trust
* CA
* UserDS
* 当前用户
* MY
* Root
* Trust
* CA
* UserDS
本地用户除了MY以外应该都可以被当前用户继承

导入证书
//导入文件方法 private static bool ImportPfxFile(string filePath, string password =
null) { //证书安装到本地存储,根节点 X509Store store = new
X509Store(StoreName.TrustedPeople, StoreLocation.LocalMachine); try {
X509Certificate2 certificate = new X509Certificate2(filePath, password == null
? "" : password, X509KeyStorageFlags.MachineKeySet);
store.Open(OpenFlags.ReadWrite); store.Remove(certificate); //可省略
store.Add(certificate); //File.Delete(filePath); return true; } catch
(System.Exception e) { MessageBox.Show(e.Message); return false; } finally {
store.Close(); } }
注意

*

导入证书的时候注意证书存储标志X509KeyStorageFlags,一般情况下不推荐设置为可导出Exportable,所以利用私钥解密的时候,注意私钥的使用方式。

*
对于证书密码,如果没有直接给null就可以了。

关于给IIS授权的问题

运行环境是IIS,经测试发现直接运行网站是没有权限获取证书的,需要给IIS用户授权才可以。

这个IIS用户给我折腾死了。本来以为给 ASP.NET 授权就可以了,没想到不是的。经过一顿搜索终于明白了,需要授权的是对应程序池的名称。

名称 状态 .NET CLR 版本 托管管道模式 标识 应用程序
.NET v2.0 已启动 v2.0 集成 ApplicationPoolIdentity 0
DefaultAppPool 已启动 v4.0 集成 ApplicationPoolIdentity 4
比如网站的程序池是DefaultAppPool,就需要给DefaultAppPool用户授权。

授权方式一

第一种方式比较简单,利用MMC。

* 命令行打开MMC
* 添加证书节点
* 将其他区的证书托动到个人
* 右键证书==》所有任务==》管理私钥==》添加对应用户即可
* 将证书托回到原来分区
授权方式二

第二种方式需要用到两个工具appcmd.exe和winhttpcertcfg.exe。

appcmd.exe是一个IIS命令行工具,详细文档
<https://docs.microsoft.com/zh-cn/iis/get-started/getting-started-with-iis/getting-started-with-appcmdexe>

appcmd.exe一般会存放在C:\Windows\System32\inetsrv\appcmd.exe

这里的使用方式很简单即通过命令获得IIS所有程序池信息,执行以下命令
C:\Windows\System32\inetsrv\appcmd.exe list apppool //得到如下结果 APPPOOL
"DefaultAppPool" (MgdVersion:v4.0,MgdMode:Integrated,state:Started) APPPOOL
"Classic .NET AppPool" (MgdVersion:v2.0,MgdMode:Classic,state:Started) APPPOOL
".NET v2.0 Classic" (MgdVersion:v2.0,MgdMode:Classic,state:Started) APPPOOL
".NET v2.0" (MgdVersion:v2.0,MgdMode:Integrated,state:Started) APPPOOL ".NET
v4.5 Classic" (MgdVersion:v4.0,MgdMode:Classic,state:Started) APPPOOL ".NET
v4.5" (MgdVersion:v4.0,MgdMode:Integrated,state:Started)
.Net 执行此命令
private Dictionary<string, object> MyCommand(string fileName, string
argument) { try { ProcessStartInfo startInfo = new ProcessStartInfo(fileName) {
CreateNoWindow = true, UseShellExecute = false, RedirectStandardError = true,
RedirectStandardOutput = true, Arguments = argument }; //创建一个进程 Process pc =
new Process(); pc.StartInfo = startInfo; //启动进程 pc.Start(); //准备读出输出流和错误流
List<string> listOutPut = new List<string>(); List<string> listError = new
List<string>(); pc.BeginOutputReadLine(); pc.BeginErrorReadLine();
pc.OutputDataReceived += (ss, ee) => { listOutPut.Add(ee.Data); };
pc.ErrorDataReceived += (ss, ee) => { listError.Add(ee.Data); }; //等待退出
pc.WaitForExit(); //关闭进程 pc.Close(); Dictionary<string, object> dic = new
Dictionary<string, object>(); dic.Add("outPut", listOutPut); dic.Add("error",
listError); return dic; } catch (Exception e) { throw e; } }
通过解析listOutPut可以得到程序池名称。

接下来需要用到证书配置工具winhttpcertcfg.exe 详细文档
<https://docs.microsoft.com/en-us/windows/desktop/WinHttp/winhttpcertcfg-exe--a-certificate-configuration-tool>

利用如下命令即可完成授权
winhttpcertcfg -g -c LOCAL_MACHINE\My -s MyCertificate -a TESTUSER
//LOCAL_MACHINE\My:用户\存储区 //MyCertificate:证书名
//TESTUSER:授权用户名,即listOutPut得到的程序池名称
注意

如果利用appcmd得到程序池名称后执行授权命令,报如下错
Error: No account information was found.
这说明程序池并非活跃状态,访问一下对应网站即可。

友情链接
ioDraw流程图
API参考文档
OK工具箱
云服务器优惠
阿里云优惠券
腾讯云优惠券
华为云优惠券
站点信息
问题反馈
邮箱:ixiaoyang8@qq.com
QQ群:637538335
关注微信