From: Meron LAVIE on
I am writing some encryption utilities. Obviously, I am interested in
ensuring that no trace of the clear, unencrypted data will be left in
memory. Therefore, I dutifully called RtlZeroMemory via pinvoke. This works
fine on byte[] (the source clear data), but when I try it on a String, all
sorts of memory corruption ensues and even VisualStudio itself starts acting
stange (buttons dissapear, etc).

Please find below my code. Any suggestions would be appreciated.

Lavie

[code]
/// <summary>

/// Sets properties for a SymmetricAlgorithm

/// </summary>

/// <param name="symmetricAlgorithm">SymmetricAlgorithm whose properties
should be set</param>

/// <param name="password">Password - WARNING: this methods trounces the
passwords with zeros</param>

private static void SetEncryptionAlgorithmProperties(SymmetricAlgorithm
symmetricAlgorithm, string password)

{

GCHandle gchPassword = GCHandle.Alloc(password, GCHandleType.Pinned);

PasswordDeriveBytes pdb = new PasswordDeriveBytes(password, SALT);


symmetricAlgorithm.Key =
pdb.GetBytes(symmetricAlgorithm.LegalKeySizes[0].MinSize / BITS_IN_BYTE);

symmetricAlgorithm.IV =
pdb.GetBytes(symmetricAlgorithm.LegalBlockSizes[0].MinSize / BITS_IN_BYTE);

// Trounce the password!

Helper.ZeroMemory(gchPassword.AddrOfPinnedObject(),
(uint)(password.Length*2));

gchPassword.Free();

}

[/code]



[code]

/// <summary>

/// Zero memory (fill with zeros)

/// </summary>

/// <param name="destinationObject">Address of object in memory, at which
trouncing should commence</param>

/// <param name="length">How many bytes to trounce</param>

/// <returns>Did trouncing succeed</returns>

[DllImport("KERNEL32.DLL", EntryPoint = "RtlZeroMemory", SetLastError=true)]

public static extern bool ZeroMemory(IntPtr destinationObject, uint length);

[code]

From: Patrice on
It reminds of a SecureString class I never used but that could be usefull in
your case :
http://msdn.microsoft.com/en-us/library/system.security.securestring.aspx

I gave a quick look and it looks like it is used in association with classes
in the Marshalling namespace allowing to get and clear the value hold in an
unmanaged buffer...

If you still use ZeroMemory I would double check how string are stored.
First they are reference types so that address you get could be those of the
string pointer rather than the actual data plus the string length is perhaps
stored somewhere.

My approach would be first to try to read the string data to make sure the
method used to get at the string location is correct.
--
Patrice


"Meron LAVIE" <lavie(a)net2vision.net.il> a �crit dans le message de
news:F9D3AED3-6573-496D-BD45-1C59C8898C3C(a)microsoft.com...
>I am writing some encryption utilities. Obviously, I am interested in
>ensuring that no trace of the clear, unencrypted data will be left in
>memory. Therefore, I dutifully called RtlZeroMemory via pinvoke. This works
>fine on byte[] (the source clear data), but when I try it on a String, all
>sorts of memory corruption ensues and even VisualStudio itself starts
>acting stange (buttons dissapear, etc).
>
> Please find below my code. Any suggestions would be appreciated.
>
> Lavie
>
> [code]
> /// <summary>
>
> /// Sets properties for a SymmetricAlgorithm
>
> /// </summary>
>
> /// <param name="symmetricAlgorithm">SymmetricAlgorithm whose properties
> should be set</param>
>
> /// <param name="password">Password - WARNING: this methods trounces the
> passwords with zeros</param>
>
> private static void SetEncryptionAlgorithmProperties(SymmetricAlgorithm
> symmetricAlgorithm, string password)
>
> {
>
> GCHandle gchPassword = GCHandle.Alloc(password, GCHandleType.Pinned);
>
> PasswordDeriveBytes pdb = new PasswordDeriveBytes(password, SALT);
>
>
> symmetricAlgorithm.Key =
> pdb.GetBytes(symmetricAlgorithm.LegalKeySizes[0].MinSize / BITS_IN_BYTE);
>
> symmetricAlgorithm.IV =
> pdb.GetBytes(symmetricAlgorithm.LegalBlockSizes[0].MinSize /
> BITS_IN_BYTE);
>
> // Trounce the password!
>
> Helper.ZeroMemory(gchPassword.AddrOfPinnedObject(),
> (uint)(password.Length*2));
>
> gchPassword.Free();
>
> }
>
> [/code]
>
>
>
> [code]
>
> /// <summary>
>
> /// Zero memory (fill with zeros)
>
> /// </summary>
>
> /// <param name="destinationObject">Address of object in memory, at which
> trouncing should commence</param>
>
> /// <param name="length">How many bytes to trounce</param>
>
> /// <returns>Did trouncing succeed</returns>
>
> [DllImport("KERNEL32.DLL", EntryPoint = "RtlZeroMemory",
> SetLastError=true)]
>
> public static extern bool ZeroMemory(IntPtr destinationObject, uint
> length);
>
> [code]
>

From: Patrice on
Great to see it solved.. One more reason to be always as close as possible
to the actual code even in test code (sucha s suign variables rather than
constants even if the variable is filled with a test value).
--
Patrice

From: MarkusSchaber on
Hi, Meron,

On 30 Nov., 11:00, "Meron LAVIE" <la...(a)net2vision.net.il> wrote:
> I am writing some encryption utilities. Obviously, I am interested in
> ensuring that no trace of the clear, unencrypted data will be left in
> memory. Therefore, I dutifully called RtlZeroMemory via pinvoke. This works
> fine on byte[] (the source clear data), but when I try it on a String, all
> sorts of memory corruption ensues and even VisualStudio itself starts acting
> stange (buttons dissapear, etc).

Without taking special precautions like pinning etc, this won't work
reliably with .NET as the garbage collector is free to relocate (->
copy) objects at will. So even by breaking the immutability of strings
by zeroing out the internal buffer (which can lead to lots of ugly
evil things), you cannot guarantee that you removed every trace from
memory.

Markus
From: Tom Shelton on
On 2009-11-30, Meron LAVIE <lavie(a)net2vision.net.il> wrote:
> I am writing some encryption utilities. Obviously, I am interested in
> ensuring that no trace of the clear, unencrypted data will be left in
> memory. Therefore, I dutifully called RtlZeroMemory via pinvoke. This works
> fine on byte[] (the source clear data), but when I try it on a String, all
> sorts of memory corruption ensues and even VisualStudio itself starts acting
> stange (buttons dissapear, etc).
>
> Please find below my code. Any suggestions would be appreciated.
>
> Lavie
>
> [code]
> /// <summary>
>
> /// Sets properties for a SymmetricAlgorithm
>
> /// </summary>
>
> /// <param name="symmetricAlgorithm">SymmetricAlgorithm whose properties
> should be set</param>
>
> /// <param name="password">Password - WARNING: this methods trounces the
> passwords with zeros</param>
>
> private static void SetEncryptionAlgorithmProperties(SymmetricAlgorithm
> symmetricAlgorithm, string password)
>
> {
>
> GCHandle gchPassword = GCHandle.Alloc(password, GCHandleType.Pinned);
>
> PasswordDeriveBytes pdb = new PasswordDeriveBytes(password, SALT);
>
>
> symmetricAlgorithm.Key =
> pdb.GetBytes(symmetricAlgorithm.LegalKeySizes[0].MinSize / BITS_IN_BYTE);
>
> symmetricAlgorithm.IV =
> pdb.GetBytes(symmetricAlgorithm.LegalBlockSizes[0].MinSize / BITS_IN_BYTE);
>
> // Trounce the password!
>
> Helper.ZeroMemory(gchPassword.AddrOfPinnedObject(),
> (uint)(password.Length*2));
>
> gchPassword.Free();
>
> }
>
> [/code]
>
>
>
> [code]
>
> /// <summary>
>
> /// Zero memory (fill with zeros)
>
> /// </summary>
>
> /// <param name="destinationObject">Address of object in memory, at which
> trouncing should commence</param>
>
> /// <param name="length">How many bytes to trounce</param>
>
> /// <returns>Did trouncing succeed</returns>
>
> [DllImport("KERNEL32.DLL", EntryPoint = "RtlZeroMemory", SetLastError=true)]
>
> public static extern bool ZeroMemory(IntPtr destinationObject, uint length);
>
> [code]
>

I'm no expert on it - but have you looked at System.Secuirty.SecureString?

--
Tom Shelton