I'm not 100% on the effectiveness of this, but I implemented an extension method to SecureString
based on the solution in this article.
$TypeDefinition = @"
using System;
using System.Runtime.InteropServices;
using System.Security;
public static class ExtensionMethods
{
public static string ConvertToUnsecureString(this SecureString securePassword)
{
if (securePassword == null)
throw new ArgumentNullException("securePassword");
IntPtr unmanagedString = IntPtr.Zero;
try
{
unmanagedString = Marshal.SecureStringToGlobalAllocUnicode(securePassword);
return Marshal.PtrToStringUni(unmanagedString);
}
finally
{
Marshal.ZeroFreeGlobalAllocUnicode(unmanagedString);
}
}
}
"@
$TypeParams = @{
MemberName = 'ConvertToUnsecureString'
MemberType = 'ScriptMethod'
TypeName = 'System.Security.SecureString'
Value = {
[ExtensionMethods]::ConvertToUnsecureString($this)
}
}
Add-Type -CompilerParameters $CompilerParams -TypeDefinition $TypeDefinition
Update-TypeData @TypeParams
SecureStringToGlobalAllocUnicode
copies a SecureString
into unmanaged memory, and PtrToStringUni
holds a copy of that unmanaged string until the pointer to it is freed by ZeroFreeGlobalAllocUnicode
.
It seems relatively secure, but I'm curious what someone more versed in C# thinks.