.NetCore分布式部署中的DataProtection密钥安全性
在.NetCore中默认使用DataProtection来保护数据,例如Cooike等。一般情况下DataProtection生成的密钥会被加密后存储,例如默认的文件存储
可以看到使用了Windows DPAPI加密。
但是如果更改默认设置例如使用的外部存储如redis则此时密钥默认是不加密的
微软说明如下
警告密钥未加密,这个时候如果redis被破解,系统的密钥也就泄漏了。
微软提供了2个接口IXmlEncryptor,IXmlDecryptor来实现密钥的加密解密,下面使用AES来简单现实,也可以替换为任何加密方式
namespace Microsoft.AspNetCore.DataProtection {/// <summary>/// Extensions for configuring data protection using an <see cref="IDataProtectionBuilder"/>./// </summary>public static class DataProtectionBuilderExtensions{/// <summary>/// Configures keys to be encrypted with AES before being persisted to/// storage./// </summary>/// <param name="builder">The <see cref="IDataProtectionBuilder"/>.</param>/// use on the local machine, 'false' if the key should only be decryptable by the current/// Windows user account.</param>/// <returns>A reference to the <see cref="IDataProtectionBuilder" /> after this operation has completed.</returns>public static IDataProtectionBuilder ProtectKeysWithAES(this IDataProtectionBuilder builder){if (builder == null){throw new ArgumentNullException(nameof(builder));}builder.Services.AddSingleton<IConfigureOptions<KeyManagementOptions>>(services =>{//var loggerFactory = services.GetService<ILoggerFactory>() ?? NullLoggerFactory.Instance;return new ConfigureOptions<KeyManagementOptions>(options =>{options.XmlEncryptor = new AesXmlEncryptor();});});return builder;}}/// <summary>/// An <see cref="IXmlEncryptor"/> that encrypts XML elements with a Aes encryptor./// </summary>sealed class AesXmlEncryptor : IXmlEncryptor{/// <summary>/// Encrypts the specified <see cref="XElement"/> with a null encryptor, i.e.,/// by returning the original value of <paramref name="plaintextElement"/> unencrypted./// </summary>/// <param name="plaintextElement">The plaintext to echo back.</param>/// <returns>/// An <see cref="EncryptedXmlInfo"/> that contains the null-encrypted value of/// <paramref name="plaintextElement"/> along with information about how to/// decrypt it./// </returns>public EncryptedXmlInfo Encrypt(XElement plaintextElement){if (plaintextElement == null){throw new ArgumentNullException(nameof(plaintextElement));}// <encryptedKey>// <!-- This key is encrypted with {provider}. -->// <value>{base64}</value>// </encryptedKey>var Jsonxmlstr =JsonConvert.SerializeObject(plaintextElement);var EncryptedData = EncryptHelper.AESEncrypt(Jsonxmlstr, "b587be32-0420-4eb1-89c6-01bb999e18fe");var newElement = new XElement("encryptedKey",new XComment(" This key is encrypted with AES."),new XElement("value",EncryptedData));return new EncryptedXmlInfo(newElement, typeof(AesXmlDecryptor));}}/// <summary>/// An <see cref="IXmlDecryptor"/> that decrypts XML elements with a Aes decryptor./// </summary>sealed class AesXmlDecryptor : IXmlDecryptor{/// <summary>/// Decrypts the specified XML element./// </summary>/// <param name="encryptedElement">An encrypted XML element.</param>/// <returns>The decrypted form of <paramref name="encryptedElement"/>.</returns>public XElement Decrypt(XElement encryptedElement){if (encryptedElement == null){throw new ArgumentNullException(nameof(encryptedElement));}// <encryptedKey>// <!-- This key is encrypted with {provider}. -->// <value>{base64}</value>// </encryptedKey>var EncryptedData=(string)encryptedElement.Element("value");var Jsonxmlstr = EncryptHelper.AESDecrypt(EncryptedData, "b587be32-0420-4eb1-89c6-01bb999e18fe");// Return a clone of the single child node.return JsonConvert.DeserializeObject<XElement>(Jsonxmlstr);}}#region AESpublic class EncryptHelper{static readonly byte[] AES_IV = { 0x12, 0x34, 0x56, 0x78, 0x90, 0xAB, 0xCD, 0xEF, 0x12, 0x34, 0x56, 0x78, 0x90, 0xAB, 0xCD, 0xEF };/// <summary>/// AES加密算法/// </summary>/// <param name="encryptString">加密前字符串</param>/// <param name="keytype">秘钥</param>/// <returns></returns>public static string AESEncrypt(string encryptString, string encryptKey){if (string.IsNullOrWhiteSpace(encryptString)) return null;if (string.IsNullOrWhiteSpace(encryptKey)) return null;encryptKey = encryptKey.PadRight(32, ' ');byte[] keyBytes = Encoding.UTF8.GetBytes(encryptKey.Substring(0, 32));using (AesCryptoServiceProvider aesAlg = new AesCryptoServiceProvider()){aesAlg.Key = keyBytes;aesAlg.IV = AES_IV;ICryptoTransform encryptor = aesAlg.CreateEncryptor(aesAlg.Key, aesAlg.IV);using (MemoryStream msEncrypt = new MemoryStream()){using (CryptoStream csEncrypt = new CryptoStream(msEncrypt, encryptor, CryptoStreamMode.Write)){using (StreamWriter swEncrypt = new StreamWriter(csEncrypt)){swEncrypt.Write(encryptString);}byte[] bytes = msEncrypt.ToArray();return Convert.ToBase64String(bytes).Replace('+', '-').Replace('/', '_');}}}}/// <summary>/// AES解密算法/// </summary>/// <param name="decryptString">解密前的字符串</param>/// <param name="keytype">秘钥</param>/// <returns></returns>public static string AESDecrypt(string decryptString, string decryptKey){if (string.IsNullOrWhiteSpace(decryptString)) return null;decryptString = decryptString.Replace('-', '+').Replace('_', '/');if (string.IsNullOrWhiteSpace(decryptKey)) return null;decryptKey = decryptKey.PadRight(32, ' ');byte[] keyBytes = Encoding.UTF8.GetBytes(decryptKey.Substring(0, 32));Byte[] inputBytes = Convert.FromBase64String(decryptString);using (AesCryptoServiceProvider aesAlg = new AesCryptoServiceProvider()){aesAlg.Key = keyBytes;aesAlg.IV = AES_IV;ICryptoTransform decryptor = aesAlg.CreateDecryptor(aesAlg.Key, aesAlg.IV);using (MemoryStream msEncrypt = new MemoryStream(inputBytes)){using (CryptoStream csEncrypt = new CryptoStream(msEncrypt, decryptor, CryptoStreamMode.Read)){using (StreamReader srEncrypt = new StreamReader(csEncrypt)){return srEncrypt.ReadToEnd();}}}}}}#endregion }
View Code
调用也很简单.ProtectKeysWithAES()即可
services.AddDataProtection().SetApplicationName("DataProtection").PersistKeysToStackExchangeRedis(ConnectionMultiplexer.Connect(RedisConnection), "DataProtection-Keys").ProtectKeysWithAES();
加密后的密钥如下
注:在生成密钥之前要删除之前的密钥,不然会使用旧密钥而不生成新的密钥直到密钥过期。
对于AES所使用密钥也要进行保护,可以使用第三方密钥存储库如Azure 密钥保管库,或者也可以使用X509证书来来加密。
github https://github.com/saber-wang/DataProtection
转载于:https://www.cnblogs.com/nasha/p/10260158.html
.NetCore分布式部署中的DataProtection密钥安全性相关推荐
- .Net Core分布式部署中的DataProtection密钥安全性
在.NetCore中默认使用DataProtection来保护数据,例如Cooike等.一般情况下DataProtection生成的密钥会被加密后存储,例如默认的文件存储 可以看到使用了Windows ...
- .net Forms身份验证不能用在应用的分布式部署中吗?
参照网上的一些方法,使用Forms身份验证对应用进行分布式部署,发现没有成功. 应用部署的两台内网服务器:192.168.1.19,192.168.1.87,使用Nginx做负载分配,配置完全相同:每 ...
- 集群部署中解决定时任务重复执行的问题-redis分布式锁应用
背景描述 有小伙伴私信我,关于存在定时任务的项目在集群环境下部署如何解决重复执行的问题,PS:定时任务没有单独拆分. 概述:之前的项目都是单机器部署,所以定时任务不会重复消费,只会执行一次.而在集群环 ...
- 保障K8s部署中的安全性
开发人员需要了解如何在容器化应用程序中嵌入控件,以及如何启用运行时保护机制以阻止黑客访问容器化系统. Kubernetes是当前流行和常用的容器编排工具之一.Kubernetes工作负载就像简单的ng ...
- 技术分享 | 在GreatDB分布式部署模式中使用Chaos Mesh做混沌测试
GreatSQL社区原创内容未经授权不得随意使用,转载请联系小编并注明来源. 1. 需求背景与万里安全数据库软件GreatDB分布式部署模式介绍 1.1 需求背景 混沌测试是检测分布式系统不确定性.建 ...
- 【SpringBoot】18、SpringBoot中使用Session共享实现分布式部署
前言:我们知道,在单体项目中,我们将用户信息存在 session 中,那么在该 session 过期之前,我们都可以从 session 中获取到用户信息,通过登录拦截,进行操作 但是分布式部署的时候, ...
- 完全分布式部署Hadoop
完全分布式部署 Hadoop 分析: 1)准备 3 台客户机(关闭防火墙.静态 ip.主机名称) 2)安装 jdk 3)配置环境变量 4)安装 hadoop 5)配置环境变量 6)安装 ssh 7)配 ...
- SCOM 2012知识分享-26:分布式部署要点总结
适应平台:System Center 2012 R2 Operations Manager+Windows Server 2012 R2 Update+SQL Server 2012 SP1 ---- ...
- 使用zipKin构建NetCore分布式链路跟踪
本文主要讲解使用ZipKin构建NetCore分布式链路跟踪 场景 因为最近公司业务量增加,而项目也需要增大部署数量,K8S中Pod基本都扩容了一倍,新增了若干物理机,部分物理机网络通信存在问题,导致 ...
- Hadoop全分布式部署 - CentOS(结尾附视频)
写在前面:博主是一只经过实战开发历练后投身培训事业的"小山猪",昵称取自动画片<狮子王>中的"彭彭",总是以乐观.积极的心态对待周边的事物.本人的技 ...
最新文章
- redis(一) 安装以及基本数据类型操作
- 【深度】北大王奕森:对抗机器学习的鲁棒、隐私和架构
- 【mysql】mysql的数据库主从2(双主双从)
- 没有为类型定义方法怎么办_拼多多开店没有流量怎么办?有什么方法?新手必看!...
- python数据挖掘资料
- 火炬之光使用了哪些技术
- 设计类的五个原则_内容设计的5个原则
- 今天梦幻诛仙服务器维护多久,《梦幻诛仙》6月10日体验服务器维护公告
- 云虚机php.ini在,虚拟主机php.ini在哪
- Linux服务器集群系统(二)——LVS集群的体系结构
- openstack单元測试用组件一览
- 学习总结-《父与子的编程之旅》chapter 18
- oracle 常用统计函数,Oracle常用的统计函数
- 并发原理及php高并发解决方案
- tomcat8下载安装教程
- 射频天线设计-窄带阻抗匹配电路设计
- PHP 合成图片并在图片上加文字
- 《Kotin 极简教程》第14章 使用 Kotlin DSL
- 投石科技“龙卷风”模拟装置
- 究竟什么是CRM(客户关系管理系统)呢?