I have an application that needs to have the user create a passphrase. As such, there are various rules that need to be tested against the passphrase as it's being entered.
These rules are pretty typical-- the value must be a certain length, have one upper, one lower, include some special characters, etc.
However, since this is a WPF application using a PasswordBox
control, and the resulting value is very sensitive, how can I setup a complexity comparison system that dynamically checks the passphrase as the user is typing?
To be clear, I have a list of all requirements in a text label below the passphrase creation PasswordBox element. As the user types, a validator shows which requirements are met and which ones are still needed. I also have an entropy calculator which give a typical "OK, Good, Strong, Very Strong" indicator once requirements are met. This is why I need to find a way to securely validate the value as the user is typing.
How can I accomplish this without emitting insecure .Net strings?
You can subscribe to PasswordChanged
but don't use Password
property if you care about securely storing your sensetive value. Instead, do this:
private void OnPasswordChanged(object sender, RoutedEventArgs e) {
using (var pwd = ((PasswordBox) sender).SecurePassword) {
int length = pwd.Length;
if (length == 0) {
// string empty, do something
return;
}
bool hasSpecial = false;
bool hasUpper = false;
bool hasLower = false;
bool hasDigit = false;
// etc
// allocate unmanaged memory and copy string there
IntPtr ptr = Marshal.SecureStringToBSTR(pwd);
try {
// each char in that string is 2 bytes, not one (it's UTF-16 string)
for (int i = 0; i < length * 2; i += 2) {
// so use ReadInt16 and convert resulting "short" to char
var ch = Convert.ToChar(Marshal.ReadInt16(ptr + i));
// run your checks
hasSpecial |= IsSpecialChar(ch);
hasUpper |= Char.IsUpper(ch);
hasLower |= Char.IsLower(ch);
hasDigit |= Char.IsDigit(ch);
}
}
finally {
// don't forget to zero memory to remove password from it
Marshal.ZeroFreeBSTR(ptr);
}
}
}
That way you never build .NET string during your validation, and every trace of password is cleared from memory when you finish.