Skip to content

Instantly share code, notes, and snippets.

@pierre3
Created October 5, 2013 12:46
Show Gist options
  • Save pierre3/6840538 to your computer and use it in GitHub Desktop.
Save pierre3/6840538 to your computer and use it in GitHub Desktop.
[WPF]PasswordBoxのセキュアなパスワードSecurePasswordにバインドしたい ref: http://qiita.com/pierusan2010/items/5d4ceb28ee18cd4e3853
public static class SecureStringEx
{
public static bool Equals(this SecureString a, SecureString b)
{
if (a == null && b == null)
{ return true; }
if (a == null || b == null)
{ return false; }
if (a.Length != b.Length)
{ return false; }
var aPtr = Marshal.SecureStringToBSTR(a);
var bPtr = Marshal.SecureStringToBSTR(b);
try
{
return Enumerable.Range(0, a.Length)
.All(i => Marshal.ReadInt16(aPtr, i) == Marshal.ReadInt16(bPtr, i));
}
finally
{
Marshal.ZeroFreeBSTR(aPtr);
Marshal.ZeroFreeBSTR(bPtr);
}
}
}
public static class SecureStringEx
{
public static void CopyFromBSTR(this SecureString self, IntPtr bstr, int count)
{
self.Clear();
var chars = Enumerable.Range(0, count)
.Select(i => (char)Marshal.ReadInt16(bstr, i * 2));
foreach (var c in chars)
{
self.AppendChar(c);
}
}
}
using System.Runtime.InteropServices;
using System.Security;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Interactivity;
public class SecurePasswordBindingBehavior : Behavior<PasswordBox>
{
public SecureString SecurePassword
{
get { return (SecureString)GetValue(SecurePasswordProperty); }
set { SetValue(SecurePasswordProperty, value); }
}
public static readonly DependencyProperty SecurePasswordProperty =
DependencyProperty.Register("SecurePassword",
typeof(SecureString),
typeof(SecurePasswordBindingBehavior),
new PropertyMetadata(new SecureString(), SecurePasswordPropertyChanged));
private static void SecurePasswordPropertyChanged(DependencyObject d,
DependencyPropertyChangedEventArgs e)
{
var behavior = d as SecurePasswordBindingBehavior;
if (d == null)
{ return; }
var passwordBox = behavior.AssociatedObject as PasswordBox;
if (passwordBox == null)
{ return; }
var newPassword = e.NewValue as SecureString;
if (newPassword == null)
{ return; }
var oldPassword = e.OldValue as SecureString;
if (newPassword.Equals(oldPassword))
{ return; }
var bstr = Marshal.SecureStringToBSTR(newPassword);
try
{
passwordBox.SecurePassword.CopyFromBSTR(bstr, newPassword.Length);
}
finally
{
Marshal.ZeroFreeBSTR(bstr);
}
}
protected override void OnAttached()
{
base.OnAttached();
AssociatedObject.PasswordChanged += PasswordBox_PasswordChanged;
}
protected override void OnDetaching()
{
AssociatedObject.PasswordChanged -= PasswordBox_PasswordChanged;
base.OnDetaching();
}
private void PasswordBox_PasswordChanged(object sender, RoutedEventArgs e)
{
SecurePassword = AssociatedObject.SecurePassword.Copy();
}
}
<Window
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"
Title="Input Password" Height="420" Width="800">
<Grid>
<PasswordBox Width="120" PasswordChar="*">
<i:Interaction.Behaviors>
<my:SecurePasswordBindingBehavior
SecurePassword="{Binding SecurePassword, Mode=TwoWay}"/>
</i:Interaction.Behaviors>
</PasswordBox>
</Grid>
</Window>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment