.NetCore分布式部署中的DataProtection密钥安全性
2019-01-12 16:24
429 查看
在.NetCore中默认使用DataProtection来保护数据,例如Cooike等。一般情况下DataProtection生成的密钥会被加密后存储,例如默认的文件存储
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 AES public 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
相关文章推荐
- .NetCore 分布式日志收集Exceptionless 在Windows下本地安装部署及应用实例
- hive是不是要分布式部署?要不要安装多个?
- J2EE分布式框架--开发环境部署
- hadoop2.5.1集群部署(完全分布式)
- [Error]分布式部署SCOM安装报错——Report Services实例无效
- Linux的企业-Hadoop(namenode,yarn 的高可用)Hbase 分布式部署
- Hadoop2 伪分布式部署
- 分布式部署下的报表调用 API调用 权限问题以及性能方案
- Tensorflow 分布式部署简介
- 白话tensorflow分布式部署和开发
- SolrCloud 分布式集群部署步骤
- 部署SQL Server Analysis Service (分析服务): 帳戶名稱與安全性識別碼無法對應
- Apache Kafka笔记(五):消息模式、分布式部署等细节
- 集群是否足以替代分布式部署,是大家争论的焦点
- Apache Kafka笔记(五):消息模式、分布式部署等细节
- 【云星数据---大数据部集群署系列004】:zookeeper分布式部署方案
- 单机版solr6.3和分布式solr6.3的安装部署
- Hadoop-2.5.1 分布式部署,Centos7
- 分布式部署 ArcSDE 和 Oracle 服务
- flume伪分布式部署和测试