Работа с конфиденциальными данными в памяти - C#
Формулировка задачи:
Здравствуйте. Есть некие данные которые хранятся на диски в зашифрованном виде. Мне нужна как-то с ними работать (чтение, запись и т. п.). Если я расшифрую и загружу эти данные в string, то они будут висеть какое-то в памяти в открытом виде, что нехорошо. Как быть в такой ситуации?
Решение задачи: «Работа с конфиденциальными данными в памяти»
textual
Листинг программы
using System;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices;
using System.Security;
using System.Security.Cryptography;
using System.Text;
namespace ConsoleApplication53
{
class Program
{
static void Main(string[] args)
{
string samplePass = "Hello world!";
using (var md5 = MD5.Create())
{
byte[] originalHash = md5.ComputeHash(Encoding.Unicode.GetBytes(samplePass));
Console.WriteLine(string.Concat(originalHash.Select(x=>x.ToString("X2"))));
var sec = new SecureString();
foreach (char c in samplePass)
{
sec.AppendChar(c);
}
using (var secureStringStream = new SecureStringStream(sec))
{
byte[] arr = md5.ComputeHash(secureStringStream);
Console.WriteLine(string.Concat(arr.Select(x => x.ToString("X2"))));
}
}
}
}
class SecureStringStream : Stream
{
private IntPtr _bstr;
public SecureStringStream(SecureString secureString)
{
_bstr = Marshal.SecureStringToBSTR(secureString);
Length = Marshal.ReadInt32(_bstr, -4);
}
public override int Read(byte[] buffer, int offset, int count)
{
if (Position == Length)
return 0;
buffer[0] = Marshal.ReadByte(_bstr, (int) Position);
Position++;
return 1;
}
public override long Seek(long offset, SeekOrigin origin)
{
switch (origin)
{
case SeekOrigin.Begin:
return Position = offset;
case SeekOrigin.End:
return Position = Length - offset - 1;
case SeekOrigin.Current:
return Position += offset;
}
throw new NotImplementedException();
}
protected override void Dispose(bool disposing)
{
base.Dispose(disposing);
if (_bstr != IntPtr.Zero)
{
Marshal.ZeroFreeBSTR(_bstr);
_bstr = IntPtr.Zero;
}
}
public override void Flush()
{
throw new NotImplementedException();
}
public override void SetLength(long value)
{
throw new NotImplementedException();
}
public override void Write(byte[] buffer, int offset, int count)
{
throw new NotImplementedException();
}
public override bool CanRead { get; } = true;
public override bool CanSeek { get; } = false;
public override bool CanWrite { get; } = false;
public override long Length { get; }
public override long Position { get; set; }
}
}