Copy SecureString with Length

  • Thread starter Thread starter Brian Stoop
  • Start date Start date
B

Brian Stoop

Hi, I want to copy the first 6 characters of a SecureString to a new
SecureString, leaving the old one unchanged.

The SecureString constructor takes a char pointer and length, but how do I
get a the char pointer from the old SecureString ?


Thanks, B
 
Brian said:
Hi, I want to copy the first 6 characters of a SecureString to a new
SecureString, leaving the old one unchanged.
If at all possible, avoid doing this. Change the code that creates the
original SecureString instead to also produce this string. It's very hard to
operate on SecureStrings after the fact (at least while maintaining security).
The SecureString constructor takes a char pointer and length, but how do I
get a the char pointer from the old SecureString ?
This is quickest, but it requires unsafe code:

SecureString s2;
IntPtr p = IntPtr.Zero;
try {
RuntimeHelpers.PrepareConstrainedRegions();
try { }
finally {
p = Marshal.SecureStringToGlobalAllocUnicode(s);
}
unsafe (char* c = (char*) p) {
s2 = new SecureString(c, 6);
}
} finally {
if (p != IntPtr.Zero) Marshal.ZeroFreeGlobalAllocUnicode(p);
}

Note that allocating is done in a constrained execution region (CER) to
prevent the possibility of an exception occurring between the allocation and
the assignment to p (yes, this is possible, and it would leave a leaked
unsecure copy of the string in memory). This may fire warnings if you're
using MDAs because the CER is technically invalid
(.SecureStringToGlobalAllocUnicode() is not marked with the appropriate
attribute). Still, as far as I can tell it's necessary.
 
thanks.

Jeroen Mostert said:
If at all possible, avoid doing this. Change the code that creates the
original SecureString instead to also produce this string. It's very hard
to operate on SecureStrings after the fact (at least while maintaining
security).

This is quickest, but it requires unsafe code:

SecureString s2;
IntPtr p = IntPtr.Zero;
try {
RuntimeHelpers.PrepareConstrainedRegions();
try { }
finally {
p = Marshal.SecureStringToGlobalAllocUnicode(s);
}
unsafe (char* c = (char*) p) {
s2 = new SecureString(c, 6);
}
} finally {
if (p != IntPtr.Zero) Marshal.ZeroFreeGlobalAllocUnicode(p);
}

Note that allocating is done in a constrained execution region (CER) to
prevent the possibility of an exception occurring between the allocation
and the assignment to p (yes, this is possible, and it would leave a
leaked unsecure copy of the string in memory). This may fire warnings if
you're using MDAs because the CER is technically invalid
(.SecureStringToGlobalAllocUnicode() is not marked with the appropriate
attribute). Still, as far as I can tell it's necessary.
 
Back
Top