【问题标题】:Store data securely in memory (password based encryption)将数据安全地存储在内存中(基于密码的加密)
【发布时间】:2019-09-25 06:29:33
【问题描述】:

我必须将密钥存储到内存中。所以出于安全考虑,我们不能直接将加密密钥存储到内存中,我们需要以加密的方式存储密钥。所以我们的想法是我们以加密方式存储密钥,在加密操作时,只需解密密钥并使用它并处置密钥。

所以我们在 BouncyCastle c# 版本 Example 代码中使用基于密码的加密 (PBE) 定义。

代码中的问题是这里的密码是固定的。我必须在运行时生成密码。

存储密钥的步骤:

  • 生成密码
  • 创建临时密钥以加密密钥(安全数据)
  • 保存到内存中

执行加密操作的步骤:

  • 生成密码
  • 创建临时密钥以解密密钥(安全数据)
  • 执行加密操作
  • 处置密钥(安全数据)

【问题讨论】:

    标签: encryption .net-core cryptography aes hsm


    【解决方案1】:

    这是一个想法,因此密码永远不能在本地变量之外未加密地存储:

    using System;
    using System.Security;
    using System.Security.Cryptography;
    using System.Text;
    
    private string _SecureKey;
    
    public bool MemorizePassword { get; set; }
    
    public string Password
    {
      get
      {
        if ( _Password.IsNullOrEmpty() ) return _Password;
        var buf = Encoding.Default.GetBytes(_Password);
        ProtectedMemory.Unprotect(buf, MemoryProtectionScope.SameProcess);
        return Encoding.Default.GetString(Decrypt(buf, _SecureKey.ToString()));
      }
      set
      {
        if ( !MemorizePassword ) 
        { 
          _Password = "";
          return;
        }
        CreateSecureKey();
        if ( value.IsNullOrEmpty() ) 
          _Password = value;
        else
        {
          var buf = Encrypt(Encoding.Default.GetBytes(value), _SecureKey.ToString());
          ProtectedMemory.Protect(buf, MemoryProtectionScope.SameProcess);
          _Password = Encoding.Default.GetString(buf);
        }
      }
    }
    
    private void CreateSecureKey()
    {
      _SecureKey = new SecureString();
      foreach ( char c in Convert.ToBase64String(CreateCryptoKey(64)) )
        _SecureKey.AppendChar(c);
      _SecureKey.MakeReadOnly();
    }
    
    static public byte[] CreateCryptoKey(int length)
    {
      if ( length < 1 ) length = 1;
      byte[] key = new byte[length];
      new RNGCryptoServiceProvider().GetBytes(key);
      return key;
    }
    
    static public byte[] Encrypt(byte[] data, string password)
    {
      return Encrypt(data, password, DefaultCryptoSalt);
    }
    
    static public byte[] Decrypt(byte[] data, string password)
    {
      return Decrypt(data, password, DefaultCryptoSalt);
    }
    
    static public string Encrypt(string str, string password, byte[] salt)
    {
      if ( str.IsNullOrEmpty() ) return str;
      PasswordDeriveBytes p = new PasswordDeriveBytes(password, salt);
      var s = Encrypt(Encoding.Default.GetBytes(str), p.GetBytes(32), p.GetBytes(16));
      return Convert.ToBase64String(s);
    }
    
    static public string Decrypt(string str, string password, byte[] salt)
    {
      if ( str.IsNullOrEmpty() ) return str;
      PasswordDeriveBytes p = new PasswordDeriveBytes(password, salt);
      var s = Decrypt(Convert.FromBase64String(str), p.GetBytes(32), p.GetBytes(16));
      return Encoding.Default.GetString(s);
    }
    
    static public byte[] Encrypt(byte[] data, byte[] key, byte[] iv)
    {
      if ( data == null ) return data;
      using ( MemoryStream m = new MemoryStream() )
      {
        var r = Rijndael.Create().CreateEncryptor(key, iv);
        using ( CryptoStream c = new CryptoStream(m, r, CryptoStreamMode.Write) )
          c.Write(data, 0, data.Length);
        return m.ToArray();
      }
    }
    
    static public byte[] Decrypt(byte[] data, byte[] key, byte[] iv)
    {
      if ( data == null ) return data;
      using ( MemoryStream m = new MemoryStream() )
      {
        var r = Rijndael.Create().CreateDecryptor(key, iv);
        using ( CryptoStream c = new CryptoStream(m, r, CryptoStreamMode.Write) )
          c.Write(data, 0, data.Length);
        return m.ToArray();
      }
    }
    

    特定于您的应用的盐示例(使用 0 到 255 之间的任意随机值):

    byte[] DefaultCryptoSalt = new byte[] { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
    

    【讨论】:

    • 我使用的是 .net 核心,据我所知 ProtectedMemory 仅适用于 windows 平台,因为它使用 windows 本机 DPAPI。
    • 没有看到标签,抱歉。以后会注意的,谢谢。
    • 但是如果可能的话,你可以使用这个想法并将其调整到 .net 核心。
    • 也许是 .Net Core 上可用的 ProtectedData 类:docs.microsoft.com/fr-fr/dotnet/api/…
    • ProtectedData 与 ProtectedMemory 讨论:social.msdn.microsoft.com/Forums/en-US/…
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-11-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-03-23
    • 1970-01-01
    相关资源
    最近更新 更多