Как запретить пользователям и другим приложениям доступ к данным, сохраненным в файле, содержимое которого защищено только паролем? - PullRequest
2 голосов
/ 22 сентября 2019

Итак, я создаю систему управления бизнесом, чтобы файлы проекта были сохранены локально на компьютере, но многие могут получить доступ к компьютеру.Для того, чтобы никто не мог просто открыть файлы и получить доступ ко всем данным, я хочу, чтобы файл мог открываться, просто бросил мое приложение.Для этого я подумал, что для открытия файла будет какой-то постоянный пароль, и я передам поток, так что это единственный способ открыть файл.

Возможно ли это?

что я должен изменить, чтобы сделать это в следующем коде?

Stream SerializeStream = new FileStream(Project_Name, FileMode.Create, FileAccess.ReadWrite, FileShare.ReadWrite)

1 Ответ

0 голосов
/ 22 сентября 2019

Вот некоторые идеи, взятые из моей личной базовой библиотеки, для сохранения / загрузки зашифрованных файлов или объектов и потоков.

using System;
using System.Security;
using System.Security.Cryptography;
using System.Text;

using ( StreamWriter writer = new StreamWriter(filename) )
{
  string password = AskPassword();
  writer.Write(Encrypt(Content, password));
}

using ( StreamReader reader = new StreamReader(filename) )
{
  string password = AskPassword();
  string content = Decrypt(reader.ReadToEnd(), password);
}

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

Вы не можете хранить необработанный пароль в любой переменной (свойствах и / или полях) вне локальных переменных.

public string Password
{
  get
  {
    lock ( locker )
    {
      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
  {
    lock ( locker )
    {
      if ( !MemorizePassword ) 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;
}

Надеюсь, я не забыл что-то еще спроситьit.

Если вы хотите сериализовать и десериализовать зашифрованные объекты, вы можете сделать следующее:

Сохранить:

using ( FileStream f = new FileStream(filename,
                                      FileMode.Create, FileAccess.Write, FileShare.None,
                                      buffersize) )
{
  var cbf = new BinaryFormatter(new CoreSurrogateSelector(),
                                new StreamingContext(StreamingContextStates.All));
  using ( MemoryStream ms = new MemoryStream() )
  {
    cbf.Serialize(ms, obj);
    var buf = ms.GetBuffer();
    if ( compress ) buf = buf.Compress();
    cbf.Serialize(f, Encrypt(buf, password));
  }
}

Загрузить:

using ( FileStream f = new FileStream(filename,
                                      FileMode.Open, FileAccess.Read, FileShare.None,
                                      buffersize) )
{
  BinaryFormatter bf = new BinaryFormatter(new CoreSurrogateSelector(),
                                           new StreamingContext(StreamingContextStates.All));
  byte[] buf = (byte[])bf.Deserialize(f);
  buf = Decrypt(buf, password);
  if ( compress ) buf = buf.Decompress();
  using ( MemoryStream ms = new MemoryStream() )
  {
    ms.Write(buf, 0, buf.Length);
    ms.Position = 0;
    T obj = (T)bf.Deserialize(ms);
    return obj;
  }
}

Если вы хотите использовать сжатие:

using System;
using System.IO;
using System.IO.Compression;
using System.Text;

static public string Compress(this string text)
{
  if ( text.IsNullOrEmpty() ) return text;
  return Convert.ToBase64String(Encoding.Default.GetBytes(text).Compress());
}

static public byte[] Compress(this byte[] buffer)
{
  using ( MemoryStream ms = new MemoryStream() )
  {
    using ( GZipStream zip = new GZipStream(ms, CompressionMode.Compress, true) )
      zip.Write(buffer, 0, buffer.Length);
    ms.Position = 0;
    byte[] compressed = new byte[ms.Length];
    ms.Read(compressed, 0, compressed.Length);
    byte[] gzBuffer = new byte[compressed.Length + 4];
    System.Buffer.BlockCopy(compressed, 0, gzBuffer, 4, compressed.Length);
    System.Buffer.BlockCopy(BitConverter.GetBytes(buffer.Length), 0, gzBuffer, 0, 4);
    return gzBuffer;
  }
}

static public string Decompress(this string text)
{
  return Encoding.Default.GetString(Convert.FromBase64String(text).Decompress());
}

static public byte[] Decompress(this byte[] gzBuffer)
{
  using ( MemoryStream ms = new MemoryStream() )
  {
    int msgLength = BitConverter.ToInt32(gzBuffer, 0);
    ms.Write(gzBuffer, 4, gzBuffer.Length - 4);
    byte[] buffer = new byte[msgLength];
    ms.Position = 0;
    using ( GZipStream zip = new GZipStream(ms, CompressionMode.Decompress) )
      zip.Read(buffer, 0, buffer.Length);
    return buffer;
  }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...