0

I would like to remove a String from the memory of .NET application. Lets say we have a Decryption method, which comes from a 3rd party lib and it returns a String. This is not smart, but there is nothing I can do about it.

String s = SomeComponent.Decrypt("cypherstring")

Now I would copy the content of s into a SecureString to work with. But... how do I get rid of s. I know the GC would collect it here, but if I used that string for a while it would stay. Also I would like to not rely on the GC here, since it might be security related - which requries my code to be deterministic.

My Idea is something like that:

public static SecureString Convert(ref String s)
{
     //copy content of s into SecureString
     //shred s
}

There is no big deal to copy the data into the SecureString, but how do I "destroy" s?

Moerwald
  • 10,448
  • 9
  • 43
  • 83
Jaster
  • 8,255
  • 3
  • 34
  • 60
  • Why do you think copying it will be safer? you already made a new string (s) where the output is copied to... And as soon as its not used again in code it will get GC'd so if its a local variable it will get GC'd pretty fast. – EpicKip Feb 10 '17 at 09:15
  • I suppose you could use a combination of `Marshall.DestroyStructure` and `Marshall.FreeHAlloc` to do what you want, and you could even go nuclear with `GC.Collect`, but I agree with EpicKip that it's probably not necessary, especially if it's a local variable. – Abion47 Feb 10 '17 at 09:18
  • You can at least set s to another value, if you don't want the data to be readable anymore, so even it is not handled by the GC at the moment, there will be nothing left of the original stringcontent –  Feb 10 '17 at 09:18
  • will `SomeComponent.Decrypt("cypherstring").ToCharArray ().ToList ().ForEach ( p => secureString.AppendChar ( p ) );` do? – Gordon Feb 10 '17 at 09:21
  • 1
    @Pedro Not necessarily. If you assign a new value to the string, it won't overwrite the old value. It will allocate new memory for the new value. The old value won't be referenced anywhere, but it's still going to be in memory until garbage collection. – Abion47 Feb 10 '17 at 09:23
  • Yes you're right, sorry, another thought: Isn't the method --> SomeComponent.Decrypt() also creating a string a return the value of it? So even if you can destroy your string, another version of it will still last in memory, til GC is handling it –  Feb 10 '17 at 09:26
  • @Pedro Fair point. If that kind of security is required, then `Decrypt` should return the value in the form of a `ref` or `out` parameter rather than a return value. That being said, it falls under the same category as before, that as an almost certainly local variable it will get garbage collected quickly. – Abion47 Feb 10 '17 at 09:40
  • 2
    Unless you can get the 3rd party onboard, any efforts are almost certainly doomed. Even if you somehow destroy the string, how do you know they've not left a buffer lurking around with the decrypted bytes? – Damien_The_Unbeliever Feb 10 '17 at 09:58
  • I have to assume, the 3rd party lib does the right thing, except for returning it in an unsafe manner. No need to discuss this, since we can't influence this. – Jaster Feb 10 '17 at 14:29
  • @Abion47 how would you do this in the give case? I'm not sure I can destroy managed objects with FeeHAlloc... some sample? – Jaster Feb 10 '17 at 14:29

1 Answers1

0

Use this code:

public static SecureString Convert(ref String s)
{
    //copy content of s into SecureString
    SecureString secureString;
    unsafe
    {
        fixed (char* charArray = s.ToArray())
            secureString = new SecureString(charArray, s.Length);
    }            
    //shred s
    s = null;
    GC.Collect();
    return secureString;
}

Note that the length if string cannot exceeds maximum capacity of SecureString. Maximum capacity of SecureString is 65536

Hossein Golshani
  • 1,847
  • 5
  • 16
  • 27
  • 2
    This probably will not work. From MSDN: "Use this method to try to reclaim memory that is inaccessible. However, using this method does not guarantee that all inaccessible memory in the specified generation is reclaimed." – Gordon Feb 10 '17 at 10:25
  • Added to which, as I mentioned on the other question, you've no idea how many times copies of this string may have ended up in (currently unused) memory in the heap, due to it being "moved" during previous GCs (of course, when we say "moved" during GC, what we actually mean is copied and references updated. The GC doesn't (intentionally) do anything to clean up the previous memory location) – Damien_The_Unbeliever Feb 10 '17 at 13:16