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#?
 

TyMac

Member
Joined
Dec 7, 2014
Messages
5
Programming Experience
3-5
Well I can tell you that I'm doing it wrong here:

Code:
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();
            }
        }
 

jmcilhinney

C# Forum Moderator
Staff member
Joined
Apr 23, 2011
Messages
2,350
Location
Sydney, Australia
Programming Experience
10+
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:
Code:
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:
Code:
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?
 

TyMac

Member
Joined
Dec 7, 2014
Messages
5
Programming Experience
3-5
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:
Code:
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:
Code:
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:

Code:
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?
 
Top Bottom