Безопасное хранение данных в памяти (шифрование на основе пароля) - PullRequest
0 голосов
/ 25 сентября 2019

Я должен сохранить ключ в памяти.Так как из соображений безопасности мы не можем напрямую хранить криптографический ключ в памяти, нам нужно хранить ключ в зашифрованном виде.Таким образом, идея заключается в том, что мы храним ключ в зашифрованном виде, а во время операции шифрования просто расшифровываем ключ, используем его и удаляем ключ.

Поэтому мы используем определение на основе пароля (PBE), определенное в BouncyCastlec # версия Пример код.

Проблема в коде заключается в том, что здесь установлен пароль.Я должен сгенерировать пароль во время выполнения.

Действия по сохранению ключа:

  • Создание пароля
  • Создание временного ключа для шифрования ключа (защищенные данные)
  • Сохранение в памяти

Шаги для выполнения операции шифрования:

  • Создание пароля
  • Создание временного ключа для расшифровки ключа (защищенные данные)
  • выполнение шифрованияоперация
  • Утилизация ключа (защищенные данные)

1 Ответ

1 голос
/ 25 сентября 2019

Вот идея, чтобы пароль никогда не мог храниться в незашифрованном виде вне локальных переменных:

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 };
...