60

Can this be simplified to a one liner? Feel free to completely rewrite it as long as secureString gets initialized properly.

SecureString secureString = new SecureString ();
foreach (char c in "fizzbuzz".ToCharArray())
{
    secureString.AppendChar (c);
}
2

8 Answers 8

75

Just use NetworkCredential. It has the conversion logic built-in.

SecureString ss = new NetworkCredential("", "fizzbuzz").SecurePassword;

As others have noted, all of these techniques strip the security benefits of SecureString, but in certain situations (such as unit tests) this may be acceptable.

Update:

As noted in the comments, NetworkCredential can also be used to convert a SecureString back to a string.

string s = new NetworkCredential("", ss).Password;
Sign up to request clarification or add additional context in comments.

5 Comments

and it is not available prior .Net 4.0
@JohannesOvermann, what do you mean with both directions? (As far as I can see, NetworkCredential consumes either a plain text password or a SecureString password, but only exposes a plain text password in the former case.)
@CodeFox: I meant that it can be used to translate String -> SecureString and SecureString -> String. I think it always consumes both and always exposes both. But from your question I take it that the SecureString -> String does not work?
@JohannesOvermann, yes - that was my assumption after reading the MSDN documentation of the NetworkCredential class. I have tried it out and I can now confirm your original comment. Thanks again!
@CodeFox: Thanks for trying it out and for confirming that it actually works!
54

You could use Linq:

"fizzbuzz".ToCharArray().ToList().ForEach(p => secureString.AppendChar(p));

5 Comments

I guess I can throw this into an extension method to get what I'm after: processInfo.Password = new SecureSring ().FromString ("fizzbuzz")
You can avoid the extra .ToList() operation with the following: Array.ForEach("fizzbuzz".ToCharArray(), secureString.AppendChar);
You don't have to declare ToCharArray, Linq will automatically enumerate as a char array.
this is still a 2 liner though? You still need to have declared secureString.
At least in later versions of .NET (say, 4.5), this is possible "fizzbuzz".ForEach(secureString.AppendChar)
32

Apart from using unsafe code and a char*, there isn't a (much) better way.

The point here is not to copy SecureString contents to/from normal strings. The constant "fizzbuzz" constant is the security leak here.

7 Comments

Beat me to it -- +1. Plus the additional changes you need to make to allow for unsafe code negates any "savings" on lines of code.
Don't most passwords originate in most software as strings and then need to be converted to a SecureString? Not sure what you mean by "not to copy SecureString contents from normal string". In normal circumstances that would be string password. "fizzbuzz" is just a homage.
Yes, and that greatly reduces the usability of SecureString.
If you're collecting a SecureString from keystrokes, you don't actually have an original string. This, I believe, was the original intent of SecureString.
I've yet to find a Q&A that talks about how to capture string that you want to make secure into the process to begin with. For example, say I fetch a password from user input from a password form control on a windows form. How could I get that input securely? Wouldn't it already be in a string the moment I get it from the control, negating my attempts at securing it? Can I force garbage collection on the string after retrieving it from the control and placing it into my SecureString?
|
19
var s = "fizzbuzz".Aggregate(new SecureString(), (ss, c) => { ss.AppendChar(c); return ss; });

1 Comment

This is very elegant.
19

Slight improvement on Sascha's answer replacing the lambda with a method group

"fizzbuzz".ToCharArray().ToList().ForEach(ss.AppendChar);

Comments

9

Here is a how NetworkCredential class from .NET doing it:

SecureString secureString;
fixed (char* chPtr = plainString)
  secureString = new SecureString(chPtr, plainString.Length);

Ugly but probably the most efficient.

1 Comment

Note that the use of fixed requires an unsafe block, which in turn requires the compiler switch /unsafe.
9

Since SecureString utilizes the IDispose interface. You could actually do it like this.

SecureString secure = new SecureString();
foreach(var character in data.ToCharArray())
    secure.AppendChar(character);

Essentially the data would be a parameter.

If you utilize the using to help alleviate resources; you'll want to be careful about the scope. But this may be a beneficial alternative, depending on usage.

Update:

You could actually do a full method signature:

public static SecureString ConvertStringToSecureString(this string data)
{
     var secure = new SecureString();
     foreach(var character in data.ToCharArray())
         secure.AppendChar(character);

     secure.MakeReadOnly();
     return secure;
     
}

For the decryption you would want to do:

public static string ConvertSecureStringToString(this SecureString data)
{
     var pointer = IntPtr.Zero;
     try
     {
          pointer = Marshal.SecureStringToGlobalAllocUnicode(data);
          return Marshal.PtrToStringUni(pointer);
     }
     finally
     {
          Marshal.ZeroFreeGlobalAllocUnicode(pointer);
     }
}

The following article will give you some additional information as well.

1 Comment

Why didn't MS add this to the framework? The class is completely useless if you can't access the value. Seems like they (MS) either didn't really want people to use SecureString, or are even more inept than I previously have accused.
7

least amount of code because .ToList() is not required for this:

Array.ForEach("fizzbuzz".ToCharArray(), secureString.AppendChar);

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.