Getting password for encryption without storing it in the memory.

P

per9000

Hi all,
I want to create an encryption program and started thinking about not
storing sensitive information in the memory since I guess someone
might steal my computer an scan my memory.

So I wrote this method for getting a password from the console and
converting it to an array of bytes for later use in the encryption
algorithm.

The weak point as I see it is the storage of the password - it will be
stored in the memory as an array of chars/bytes. I fill it with junk
but still: what worries me is what List.ToArray() does - is a new
instance created and then lost somewhere? (see sample below)

* Is there a better way to do this?
* Is the textbox with stars instead of plain text safe (for GUI use
instead of console use)?

Thanks,

Per Erik Strandberg
Linear or Nonlinear optimization in .NET?
see http://tomopt.com/tomnet/

-----

/// <summary>
/// Generate hash value (key) from the console (from the password).
/// </summary>
/// <param name="Message">Message to prompt</param>
/// <param name="one">True if it is the first key, false if second.</
param>
/// <returns>The key: a byte array of length 16 or 32.</returns>
public static byte[] GetKeyFromConsole(string Message, bool one)
{
// we use bytes/chars here - pretty bad since åäö will get lost
List<byte> pass = new List<byte>();

// prompt
Console.Write("{0}>", Message);

// read one key and store in list
char c = Console.ReadKey(true).KeyChar;
while (!(c == Environment.NewLine[0] || c == '\n'))
{
Console.Write('*');
pass.Add((byte)c);
c = Console.ReadKey(true).KeyChar;
}
Console.WriteLine();

byte[] b;


// get hash value of the keypunches
if (one)
{
// first key using sha
// or some secret native hash function
SHA256Managed sha = new SHA256Managed();
b = sha.ComputeHash(pass.ToArray());
sha.Clear();
}
else
{
// second key using md5
// or some secret native hash function
MD5CryptoServiceProvider md = new MD5CryptoServiceProvider();
b = md.ComputeHash(pass.ToArray());
md.Clear();
}

// clear temp char and chararr
c = '*';
for (int i = 0; i < pass.Count; i++)
pass = (byte)'*';

// return hashvalue
return b;
}
 
R

rossum

Hi all,
I want to create an encryption program and started thinking about not
storing sensitive information in the memory since I guess someone
might steal my computer an scan my memory.

So I wrote this method for getting a password from the console and
converting it to an array of bytes for later use in the encryption
algorithm.

The weak point as I see it is the storage of the password - it will be
stored in the memory as an array of chars/bytes. I fill it with junk
but still: what worries me is what List.ToArray() does - is a new
instance created and then lost somewhere? (see sample below)

* Is there a better way to do this?
* Is the textbox with stars instead of plain text safe (for GUI use
instead of console use)?

Thanks,

Per Erik Strandberg
Linear or Nonlinear optimization in .NET?
see http://tomopt.com/tomnet/
This is not an uncommon problem. Unfortunately is is a difficult one
to solve in an operating system that is not built with security on
mind - there is no way to clear the swapfile for instance.

You might like to look at System.Security.SecureString which solves
some of the problems - it is kept encrypted in memory for instance.
The main problem with SecureString is that so few other functions will
accept it as a parameter. For instance I have not found a way to pass
one directly to SHA256 to get a hash value.

Sometimes it is easier to work with System.String and to explicitly
clear it yourself in unsafe code:

unsafe void OverwriteString(string text) {
const char overwriteChar = 'X';
fixed (char* cp = text) {
for (int i = 0; i < text.Length; ++i) {
cp = overwriteChar;
}
}
}

Alternatively you can work with arrays of bytes which are much easier
to clear yourself without having to drop into unsafe code.

rossum
 
J

Jon Skeet [C# MVP]

Sometimes it is easier to work with System.String and to explicitly
clear it yourself in unsafe code:

unsafe void OverwriteString(string text) {
const char overwriteChar = 'X';
fixed (char* cp = text) {
for (int i = 0; i < text.Length; ++i) {
cp = overwriteChar;
}
}
}


Just make sure you never call OverwriteString with a reference which is
interned - otherwise every string literal with the same value will be
clobbered!
 
R

rossum

Sometimes it is easier to work with System.String and to explicitly
clear it yourself in unsafe code:

unsafe void OverwriteString(string text) {
const char overwriteChar = 'X';
fixed (char* cp = text) {
for (int i = 0; i < text.Length; ++i) {
cp = overwriteChar;
}
}
}


Just make sure you never call OverwriteString with a reference which is
interned - otherwise every string literal with the same value will be
clobbered!

Agreed. Things would be a lot easier if SecureString were more
practical to use, then cludges like my OverwriteString would not be
needed. It is frustrating that SecureString provides securityt, but
at the cost of almost all of its usability.

rossum
 
P

per9000

Hi,

SecureString is something new to me - I will make sure I look into it.
Having the string encrypted sounds excellent - I had no idea .NET had
it build it.

Thanks,
Per

-----

Per Erik Strandberg
Linear or Nonlinear optimization in .NET?
see http://tomopt.com/tomnet/

YAB?
see http://www.pererikstrandberg.se/blog/


Sometimes it is easier to work with System.String and to explicitly
clear it yourself in unsafe code:
unsafe void OverwriteString(string text) {
const char overwriteChar = 'X';
fixed (char* cp = text) {
for (int i = 0; i < text.Length; ++i) {
cp = overwriteChar;
}
}
}

Just make sure you never call OverwriteString with a reference which is
interned - otherwise every string literal with the same value will be
clobbered!

Agreed. Things would be a lot easier if SecureString were more
practical to use, then cludges like my OverwriteString would not be
needed. It is frustrating that SecureString provides securityt, but
at the cost of almost all of its usability.

rossum
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top