declare on secure strings

TyMac

Member
Joined
Dec 7, 2014
Messages
5
Programming Experience
3-5
I need to declare a secure string a variable that is located in a text file. In Powershell this is easy:

$password = Get-content "C:\text_file_with_secure_string_in_it.txt" | convertto-securestring

How would I declare this variable correctly in C#?
 
Well I can tell you that I'm doing it wrong here:

C#:
namespace DecryptStrg
{
    class Program
    {
        static void Main(string[] args)
        {
            FileInfo file = new FileInfo("C:\\path\to\\password\\file\\here\\textfile.txt");
            if (!file.Exists)
            {




                SecureString password;
                using (FileStream fs = file.Open(FileMode.OpenOrCreate, FileAccess.ReadWrite, FileShare.ReadWrite))
                {
                    byte[] bytes = new byte[fs.Length];
                    int numBytesToRead = (int)fs.Length;
                    int numBytesRead = 0;
                    while (numBytesToRead > 0)
                    {
                        int n = fs.Read(bytes, numBytesRead, numBytesToRead);
                        if (n == 0)
                            break;


                        numBytesRead += n;
                        numBytesToRead -= n;
                    }
                    password = Encoding.Unicode.GetString(bytes).DecryptString();
                }
                Console.WriteLine(password.ToUnsecureString());
                Console.ReadLine();
            }
        }
 
You're not doing "it" wrong if "it" is what you actually asked for. You asked how to declare the variable and you're doing that just fine right here:
C#:
SecureString password;
The rest of it is inefficient and/or wrong. Firstly, why read the data from the file that way when you can simply call File.ReadAllBytes? Secondly, why read all the Bytes from a file and then use an Encoding object to convert that to a String when you can just call File.ReadAllText?

With regards to the SecureString, this line here:
C#:
password = Encoding.Unicode.GetString(bytes).DecryptString();
is passing a Byte array to Encoding.GetString, which will return a String, and then trying to call DecryptString on the result and assign the result of that to the `password` variable, which is type SecureString. For that to work, you'd have to have DecryptString declared as an extension method that extends the String type and returns a SecureString. Have you declared DecryptString like that?
 
You're not doing "it" wrong if "it" is what you actually asked for. You asked how to declare the variable and you're doing that just fine right here:
C#:
SecureString password;
The rest of it is inefficient and/or wrong. Firstly, why read the data from the file that way when you can simply call File.ReadAllBytes? Secondly, why read all the Bytes from a file and then use an Encoding object to convert that to a String when you can just call File.ReadAllText?

With regards to the SecureString, this line here:
C#:
password = Encoding.Unicode.GetString(bytes).DecryptString();
is passing a Byte array to Encoding.GetString, which will return a String, and then trying to call DecryptString on the result and assign the result of that to the `password` variable, which is type SecureString. For that to work, you'd have to have DecryptString declared as an extension method that extends the String type and returns a SecureString. Have you declared DecryptString like that?

Yes:

C#:
static class Extensions
	{
		
		public static SecureString DecryptString(this string source)
		{
			if (source == null)
				return null;


			SecureString result = new SecureString();


			try
			{
				var decrypted = ProtectedData.Unprotect(Convert.FromBase64String(source), entropy, DataProtectionScope.CurrentUser);
				result = Encoding.Unicode.GetString(decrypted).ToSecureString();
			}
			catch
			{
				result = new SecureString();
			}
			return result;
		}


		public static string ToUnsecureString(this SecureString source)
		{
			if (source == null)
				return null;


			var ptr = Marshal.SecureStringToBSTR(source);


			try
			{
				return Marshal.PtrToStringBSTR(ptr);
			}
			finally
			{
				Marshal.ZeroFreeBSTR(ptr);
			}
		}
	}

Does that look correct?
 
Back
Top Bottom