192 lines
6.1 KiB
C#
192 lines
6.1 KiB
C#
using System;
|
|
using System.Runtime.InteropServices;
|
|
using System.Security;
|
|
using System.Text;
|
|
|
|
|
|
namespace Common.Utils
|
|
{
|
|
/// <summary>
|
|
/// An extension class to handle SecureString conversion
|
|
/// </summary>
|
|
internal static class SecureStringExtensions
|
|
{
|
|
public static readonly Encoding ENCODING = Encoding.UTF8;
|
|
|
|
#region methods
|
|
|
|
/// <summary>
|
|
/// Convert the content of the SecureString as an array of bytes
|
|
/// </summary>
|
|
/// <param name="password"></param>
|
|
/// <returns> A Byte Array representation of a secure string </returns>
|
|
public static byte[] ConvertToByteArray(this SecureString password)
|
|
{
|
|
if (password == null)
|
|
{
|
|
throw new SecureStringConversionException("Cannot convert a null password");
|
|
}
|
|
|
|
IntPtr stringTempPass = IntPtr.Zero;
|
|
string convertedPass;
|
|
try
|
|
{
|
|
stringTempPass = Marshal.SecureStringToGlobalAllocUnicode(password);
|
|
convertedPass = Marshal.PtrToStringUni(stringTempPass);
|
|
|
|
if (convertedPass != null)
|
|
return ENCODING.GetBytes(convertedPass);
|
|
else
|
|
return null;
|
|
}
|
|
finally
|
|
{
|
|
Marshal.ZeroFreeGlobalAllocUnicode(stringTempPass);
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Convert the content of a byte array to a secure string
|
|
/// </summary>
|
|
/// <param name="arrayToConvert"></param>
|
|
/// <returns> The representation of the byte array in a secure string </returns>
|
|
public static SecureString ConvertByteArrayToSecureString(this byte[] arrayToConvert)
|
|
{
|
|
IntPtr stringPointer = IntPtr.Zero;
|
|
|
|
if (arrayToConvert.Length == 0)
|
|
throw new ArgumentException("Password is empty");
|
|
stringPointer = Marshal.StringToBSTR(ENCODING.GetString(arrayToConvert));
|
|
|
|
try
|
|
{
|
|
return ConvertToSecureString(Marshal.PtrToStringBSTR(stringPointer));
|
|
}
|
|
|
|
finally
|
|
{
|
|
Marshal.ZeroFreeBSTR(stringPointer);
|
|
GC.Collect();
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Convert a secure string to a char array
|
|
/// </summary>
|
|
/// <param name="password"></param>
|
|
/// <returns> A representation of the secure string in a char array </returns>
|
|
public static char[] ConvertToCharArray(this SecureString password)
|
|
{
|
|
char[] charArray = new char[password.Length];
|
|
IntPtr charPass = IntPtr.Zero;
|
|
|
|
try
|
|
{
|
|
charPass = Marshal.SecureStringToCoTaskMemUnicode(password);
|
|
Marshal.Copy(charPass, charArray, 0, password.Length);
|
|
return charArray;
|
|
}
|
|
finally
|
|
{
|
|
if (charPass != IntPtr.Zero)
|
|
{
|
|
Marshal.ZeroFreeGlobalAllocUnicode(charPass);
|
|
}
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Convert a SecureString to string. Used for compliancy with MSFT WINRM DLL
|
|
/// </summary>
|
|
/// <param name="password"></param>
|
|
/// <returns>a string represetation of a secure string </returns>
|
|
public static string ConvertToString(this SecureString password)
|
|
{
|
|
IntPtr stringPointer = IntPtr.Zero;
|
|
|
|
if (password == null)
|
|
throw new ArgumentNullException("Password is empty");
|
|
stringPointer = Marshal.SecureStringToBSTR(password);
|
|
|
|
try
|
|
{
|
|
return Marshal.PtrToStringBSTR(stringPointer);
|
|
}
|
|
finally
|
|
{
|
|
Marshal.ZeroFreeBSTR(stringPointer);
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Convert a String object to SecureString
|
|
/// </summary>
|
|
/// <param name="password"></param>
|
|
/// <returns>A secure string representation of a string object</returns>
|
|
public static SecureString ConvertToSecureString(this string password)
|
|
{
|
|
var securePass = new SecureString();
|
|
|
|
foreach (var c in password)
|
|
securePass.AppendChar(c);
|
|
|
|
securePass.MakeReadOnly();
|
|
return securePass;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Compare the value of secure string object
|
|
/// </summary>
|
|
/// <param name="password"></param>
|
|
/// <param name="value"></param>
|
|
/// <returns>true/false according to the values equality</returns>
|
|
public static bool ValueEquals(this SecureString password, SecureString value)
|
|
{
|
|
IntPtr passBstr = IntPtr.Zero;
|
|
IntPtr valueBstr = IntPtr.Zero;
|
|
try
|
|
{
|
|
passBstr = Marshal.SecureStringToBSTR(password);
|
|
valueBstr = Marshal.SecureStringToBSTR(value);
|
|
int passLength = Marshal.ReadInt32(passBstr, -4);
|
|
int valueLength = Marshal.ReadInt32(valueBstr, -4);
|
|
|
|
if (passLength != valueLength)
|
|
return false;
|
|
for (int x = 0; x < passLength; ++x)
|
|
{
|
|
byte passByte = Marshal.ReadByte(passBstr, x);
|
|
byte valueByte = Marshal.ReadByte(valueBstr, x);
|
|
if (passByte != valueByte)
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
finally
|
|
{
|
|
if (passBstr != IntPtr.Zero)
|
|
Marshal.ZeroFreeBSTR(passBstr);
|
|
if (valueBstr != IntPtr.Zero)
|
|
Marshal.ZeroFreeBSTR(valueBstr);
|
|
}
|
|
}
|
|
}
|
|
|
|
public class SecureStringConversionException : Exception
|
|
{
|
|
public SecureStringConversionException()
|
|
{
|
|
}
|
|
|
|
public SecureStringConversionException(string message) : base(message)
|
|
{
|
|
}
|
|
|
|
public SecureStringConversionException(string message, Exception innerException) : base(message, innerException)
|
|
{
|
|
}
|
|
}
|
|
}
|
|
|
|
#endregion |