DNX核心:加密/解密?

时间:2016-01-29 18:00:34

标签: encryption dnx .net-core

我正在将网站移植到dnx core / aspnet5 / mvc6。我需要将密码存储到数据库中的第三方站点(它本质上是一个聚合器)。

在早期版本的mvc中,我使用像RijndaelManaged这样的类来完成此操作。但那些似乎并不存在于dnx核心中。事实上,我还没有找到关于dnx核心中任何通用加密/解密内容的大量文档。

在mvc6站点中加密/解密单个字段值的建议方法是什么?我不想加密整个sql server数据库。

或者,我是否应该考虑使用其他方法来存储访问受密码保护的第三方网站所需的凭据?

2 个答案:

答案 0 :(得分:1)

请参阅DataProtection API documentation

他们的guidance on using it for persistent data protection有点过分,但他们说没有技术上的理由你不能这样做。基本上,为了持久存储受保护的数据,您需要愿意允许使用过期密钥对其进行保护,因为密钥可能会在您保护后过期。

对我而言,使用它似乎是合理的,我在my own project中使用它。

由于IPersistedDataProtector只提供带字节数组的方法,因此我提出了几种扩展方法来从字符串来回转换字节。

public static class DataProtectionExtensions
{
    public static string PersistentUnprotect(
        this IPersistedDataProtector dp,
        string protectedData,
        out bool requiresMigration,
        out bool wasRevoked)
    {
        bool ignoreRevocation = true;
        byte[] protectedBytes = Convert.FromBase64String(protectedData);
        byte[] unprotectedBytes = dp.DangerousUnprotect(protectedBytes, ignoreRevocation, out requiresMigration, out wasRevoked);

        return Encoding.UTF8.GetString(unprotectedBytes);
    }

    public static string PersistentProtect(
        this IPersistedDataProtector dp,
        string clearText)
    {
        byte[] clearBytes = Encoding.UTF8.GetBytes(clearText);
        byte[] protectedBytes = dp.Protect(clearBytes);

        string result = Convert.ToBase64String(protectedBytes);
        return result;

        }

  }

我还创建了一个辅助类,专门用于保护我的SiteSettings对象上的某些属性,然后再将其保存到db。

using cloudscribe.Core.Models;
using Microsoft.AspNet.DataProtection;
using Microsoft.Extensions.Logging;
using System;

namespace cloudscribe.Core.Web.Components
{
    public class SiteDataProtector
    {
        public SiteDataProtector(
        IDataProtectionProvider dataProtectionProvider,
        ILogger<SiteDataProtector> logger)
    {
        rawProtector = dataProtectionProvider.CreateProtector("cloudscribe.Core.Models.SiteSettings");
        log = logger;
    }

    private ILogger log;
    private IDataProtector rawProtector = null;
    private IPersistedDataProtector dataProtector
    {
        get { return rawProtector as IPersistedDataProtector; }
    }

    public void Protect(ISiteSettings site)
    {
        if (site == null) { throw new ArgumentNullException("you must pass in an implementation of ISiteSettings"); }
        if (site.IsDataProtected) { return; }
        if (dataProtector == null) { return; }

        if (site.FacebookAppSecret.Length > 0)
        {
            try
            {
                site.FacebookAppSecret = dataProtector.PersistentProtect(site.FacebookAppSecret);
            }
            catch (System.Security.Cryptography.CryptographicException ex)
            {
                log.LogError("data protection error", ex);
            }
        }

        // ....

        site.IsDataProtected = true;
    }

    public void UnProtect(ISiteSettings site)
    {
        bool requiresMigration = false;
        bool wasRevoked = false;
        if (site == null) { throw new ArgumentNullException("you must pass in an implementation of ISiteSettings"); }
        if (!site.IsDataProtected) { return; }

        if (site.FacebookAppSecret.Length > 0)
        {
            try
            {
                site.FacebookAppSecret = dataProtector.PersistentUnprotect(site.FacebookAppSecret, out requiresMigration, out wasRevoked);
            }
            catch (System.Security.Cryptography.CryptographicException ex)
            {
                log.LogError("data protection error", ex);
            }
            catch (FormatException ex)
            {
                log.LogError("data protection error", ex);
            }
        }

        site.IsDataProtected = false;

        if (requiresMigration || wasRevoked)
        {
            log.LogWarning("DataProtection key wasRevoked or requires migration, save site settings for " + site.SiteName + " to protect with a new key");
        }
    }


    }
 }

如果应用程序需要在数据受到保护后迁移到其他计算机,那么您还需要控制密钥位置,默认情况下会将密钥放在计算机的操作系统密钥环上,因为我理解它很多就像过去的machinekey一样,你可以在web.config中覆盖它以便于移植。 当然,保护钥匙就在你身上。我在项目启动时有这样的代码

 //If you change the key persistence location, the system will no longer automatically encrypt keys 
 // at rest since it doesn’t know whether DPAPI is an appropriate encryption mechanism.
 services.ConfigureDataProtection(configure =>
 {
      string pathToCryptoKeys = appBasePath + Path.DirectorySeparatorChar
            + "dp_keys" + Path.DirectorySeparatorChar;

      // these keys are not encrypted at rest
      // since we have specified a non default location
      // that also makes the key portable so they will still work if we migrate to 
      // a new machine (will they work on different OS? I think so)
      // this is a similar server migration issue as the old machinekey
      // where we specified a machinekey in web.config so it would not change if we 
      // migrate to a new server
      configure.PersistKeysToFileSystem(new DirectoryInfo(pathToCryptoKeys));
   });

因此,在此示例中,我的密钥存储在appRoot / dp_keys中。

答案 1 :(得分:0)

如果你想手动做事;

添加对System.Security.Cryptography.Algorithms

的引用

然后,您可以通过create方法创建每种算法类型的实例。例如;

var aes = System.Security.Cryptography.Aes.Create();