Skip to content

Instantly share code, notes, and snippets.

@BlueDoge
Created April 27, 2023 23:05
Show Gist options
  • Save BlueDoge/ceb7ca03dd7612b37be46cee99a05fc0 to your computer and use it in GitHub Desktop.
Save BlueDoge/ceb7ca03dd7612b37be46cee99a05fc0 to your computer and use it in GitHub Desktop.
Some secure string wizardry
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Security;
using System.Runtime.InteropServices;
namespace BlueDogeTools.AWS.Framework.Utilities
{
public static class SecureStringExtentions
{
public static T UseDecryptedSecureString<T>(this SecureString secureString, Func<string, T> action)
{
var length = secureString.Length;
var sourcePtr = IntPtr.Zero;
// Create an empty string of the correct size and pin it so the collector can't copy it all over the place.
var plainString = new string('\0', length);
var plainStringHandler = GCHandle.Alloc(plainString, GCHandleType.Pinned);
var insecureStringPointer = plainStringHandler.AddrOfPinnedObject();
try
{
// Create a basic string of the secure string.
sourcePtr = Marshal.SecureStringToBSTR(secureString);
// loop through the basic string and populate the managed string
for (var i = 0; i < secureString.Length; i++)
{
var unicodeChar = Marshal.ReadInt16(sourcePtr, i * 2);
Marshal.WriteInt16(insecureStringPointer, i * 2, unicodeChar);
}
return action(plainString);
}
finally
{
// clear the managed string and then unpin for GC
Marshal.Copy(new byte[length * 2], 0, insecureStringPointer, length * 2);
plainStringHandler.Free();
// free and clear the basic string
Marshal.ZeroFreeBSTR(sourcePtr);
}
}
public static void UseDecryptedSecureString(this SecureString secureString, Action<string> action)
{
UseDecryptedSecureString(secureString, s =>
{
action(s);
return 0;
});
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment