GUI: Added button to generate a random password to the "Encrypt" tab.

This commit is contained in:
LoRd_MuldeR 2021-05-08 17:55:16 +02:00
parent 502e92ee09
commit 61fa41c888
Signed by: mulder
GPG Key ID: 2B5913365F57E03F
10 changed files with 312 additions and 16 deletions

View File

@ -35,7 +35,7 @@
#define MODE_TEST 5
static const size_t RCMD_PWDLEN_LENGTH = 12U;
static const size_t DFLT_PWDLEN_LENGTH = 20U;
static const size_t DFLT_PWDLEN_LENGTH = 24U;
static const CHR* const ENV_PASSWORD = T("SLUNK_PASSPHRASE");
static const CHR* const ENV_KEEPFILE = T("SLUNK_KEEP_INCOMPLETE");

View File

@ -0,0 +1,12 @@
<UserControl x:Class="com.muldersoft.slunkcrypt.gui.ctrls.ImageButton"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
mc:Ignorable="d"
d:DesignHeight="450" d:DesignWidth="800">
<Button x:Name="Button">
<Image Margin="4,0,4,0" Style="{StaticResource GrayOutIfDisabled}" Stretch="None" Name="ButtonImage"/>
</Button>
</UserControl>

View File

@ -0,0 +1,54 @@
/******************************************************************************/
/* SlunkCrypt, by LoRd_MuldeR <MuldeR2@GMX.de> */
/* This work has been released under the CC0 1.0 Universal license! */
/******************************************************************************/
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
namespace com.muldersoft.slunkcrypt.gui.ctrls
{
/// <summary>
/// Interaction logic for ImageToggleButton.xaml
/// </summary>
public partial class ImageButton : UserControl
{
public event RoutedEventHandler Clicked;
public ImageButton()
{
InitializeComponent();
Button.Click += ButtonClicked;
}
public ImageSource ImageSource
{
get
{
return ButtonImage.Source;
}
set
{
ButtonImage.Source = value;
}
}
public string ButtonToolTip
{
get
{
return ButtonImage.ToolTip as string;
}
set
{
ButtonImage.ToolTip = value;
}
}
private void ButtonClicked(object sender, RoutedEventArgs e)
{
Clicked?.Invoke(this, e);
}
}
}

View File

@ -62,6 +62,30 @@ namespace com.muldersoft.slunkcrypt.gui.ctrls
}
}
public string ToolTipDefault
{
get
{
return Image_Default.ToolTip as string;
}
set
{
Image_Default.ToolTip = value;
}
}
public string ToolTipChecked
{
get
{
return Image_Checked.ToolTip as string;
}
set
{
Image_Checked.ToolTip = value;
}
}
private void OnCheckedChanged(object sender, RoutedEventArgs e)
{
NotifyPropertyChanged("IsChecked");

View File

@ -87,6 +87,17 @@ namespace com.muldersoft.slunkcrypt.gui.ctrls
{
return IsRevealed ? Edit_Normal.Text : Edit_Hidden.Password;
}
set
{
if (IsRevealed)
{
Edit_Normal.Text = string.IsNullOrEmpty(value) ? string.Empty : value;
}
else
{
Edit_Hidden.Password = string.IsNullOrEmpty(value) ? string.Empty : value;
}
}
}
public void Clear()

BIN
gui/Resources/Refresh.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 674 B

View File

@ -70,6 +70,9 @@
<Compile Include="Controls\Hyperlink.xaml.cs">
<DependentUpon>Hyperlink.xaml</DependentUpon>
</Compile>
<Compile Include="Controls\ImageButton.xaml.cs">
<DependentUpon>ImageButton.xaml</DependentUpon>
</Compile>
<Compile Include="Controls\ImageToggleButton.xaml.cs">
<DependentUpon>ImageToggleButton.xaml</DependentUpon>
</Compile>
@ -79,6 +82,7 @@
<Compile Include="Process\SlunkCryptRunner.cs" />
<Compile Include="Utilities\BusyManager.cs" />
<Compile Include="Utilities\PathUtils.cs" />
<Compile Include="Utilities\SecureRandom.cs" />
<Compile Include="Utilities\SystemMenu.cs" />
<Compile Include="Utilities\VisibilityConverter.cs" />
<Compile Include="Utilities\FontSizeConverter.cs" />
@ -88,6 +92,10 @@
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
</Page>
<Page Include="Controls\ImageButton.xaml">
<Generator>MSBuild:Compile</Generator>
<SubType>Designer</SubType>
</Page>
<Page Include="Controls\ImageToggleButton.xaml">
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
@ -175,6 +183,9 @@
<ItemGroup>
<Resource Include="Resources\Tab_LogFile.png" />
</ItemGroup>
<ItemGroup>
<Resource Include="Resources\Refresh.png" />
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.

View File

@ -27,6 +27,7 @@
<BitmapImage x:Key="ImageSource_Eye1" UriSource="Resources/Eye_1.png"/>
<BitmapImage x:Key="ImageSource_Eye2" UriSource="Resources/Eye_2.png"/>
<BitmapImage x:Key="ImageSource_Info" UriSource="Resources/Info.png"/>
<BitmapImage x:Key="ImageSource_Refresh" UriSource="Resources/Refresh.png"/>
<BitmapImage x:Key="ImageSource_Start" UriSource="Resources/Start.png"/>
<BitmapImage x:Key="ImageSource_TabHd1" UriSource="Resources/Tab_Encrypt.png"/>
<BitmapImage x:Key="ImageSource_TabHd2" UriSource="Resources/Tab_Decrypt.png"/>
@ -92,7 +93,8 @@
</DockPanel>
<TextBlock FontWeight="SemiBold" Text="Passphrase:" Margin="0,10,0,0"/>
<DockPanel Margin="0,5,0,0">
<ctrls:ImageToggleButton DockPanel.Dock="Right" Margin="3,0,0,0" x:Name="Button_Encrypt_Toggle" ImageSourceDefault="{StaticResource ImageSource_Eye1}" ImageSourceChecked="{StaticResource ImageSource_Eye2}"/>
<ctrls:ImageToggleButton DockPanel.Dock="Right" Margin="3,0,0,0" x:Name="Button_Encrypt_Toggle" ImageSourceDefault="{StaticResource ImageSource_Eye1}" ImageSourceChecked="{StaticResource ImageSource_Eye2}" ToolTipDefault="Show password" ToolTipChecked="Hide password"/>
<ctrls:ImageButton DockPanel.Dock="Right" Margin="3,0,0,0" Clicked="Button_GeneratePasswd_Click" ImageSource="{StaticResource ImageSource_Refresh}" ButtonToolTip="Generate random password"/>
<ctrls:PasswordToggleBox DockPanel.Dock="Left" EditPadding="3,5,3,5" x:Name="Edit_Encrypt_Password" EditFontFamily="{StaticResource Monospace}" IsRevealed="{Binding IsChecked, ElementName=Button_Encrypt_Toggle}" PasswordChar="*" MaxLength="{x:Static local:SlunkCryptGUI.MAX_PASSWD_LENGTH}" Entered="Edit_Password_Entered"/>
</DockPanel>
</StackPanel>
@ -127,7 +129,7 @@
</DockPanel>
<TextBlock FontWeight="SemiBold" Text="Passphrase:" Margin="0,10,0,0"/>
<DockPanel Margin="0,5,0,0">
<ctrls:ImageToggleButton DockPanel.Dock="Right" Margin="3,0,0,0" x:Name="Button_Decrypt_Toggle" ImageSourceDefault="{StaticResource ImageSource_Eye1}" ImageSourceChecked="{StaticResource ImageSource_Eye2}"/>
<ctrls:ImageToggleButton DockPanel.Dock="Right" Margin="3,0,0,0" x:Name="Button_Decrypt_Toggle" ImageSourceDefault="{StaticResource ImageSource_Eye1}" ImageSourceChecked="{StaticResource ImageSource_Eye2}" ToolTipDefault="Show password" ToolTipChecked="Hide password"/>
<ctrls:PasswordToggleBox DockPanel.Dock="Left" EditPadding="3,5,3,5" x:Name="Edit_Decrypt_Password" EditFontFamily="{StaticResource Monospace}" IsRevealed="{Binding IsChecked, ElementName=Button_Decrypt_Toggle}" PasswordChar="*" MaxLength="{x:Static local:SlunkCryptGUI.MAX_PASSWD_LENGTH}" Entered="Edit_Password_Entered"/>
</DockPanel>
</StackPanel>

View File

@ -35,7 +35,7 @@ namespace com.muldersoft.slunkcrypt.gui
private delegate Task<bool> SlunkProcessor(string inputFile, string outputFile, string password);
public event PropertyChangedEventHandler PropertyChanged;
public const int MIN_PASSWD_LENGTH = 8, REC_PASSWD_LENGTH = 12, MAX_PASSWD_LENGTH = 256, MAX_PATH = 259;
public const int MIN_PASSWD_LENGTH = 8, REC_PASSWD_LENGTH = 12, GEN_PASSWD_LENGTH = 24, MAX_PASSWD_LENGTH = 256, MAX_PATH = 259;
private readonly Lazy<string> m_about = new Lazy<string>(CreateAboutText);
private readonly Random m_random = new Random();
@ -48,7 +48,7 @@ namespace com.muldersoft.slunkcrypt.gui
private volatile bool m_busyFlag = false, m_checksumError = false, m_processReceived = false, m_checked = false;
private volatile SlunkCryptRunner m_processRunner = null;
private const string ASCII_CHARS = "!\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~";
private const string ASCII_CHARS = "!#$%&()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~";
// =============================================================================
// Constructor
@ -139,6 +139,18 @@ namespace com.muldersoft.slunkcrypt.gui
}
}
private async void Button_GeneratePasswd_Click(object sender, RoutedEventArgs e)
{
using (BusyManager busy = new BusyManager(this))
{
Edit_Encrypt_Password.Password = string.Empty;
Task<string> password = Task.Run(() => GenerateRandomString(GEN_PASSWD_LENGTH));
await Task.WhenAll(password, Task.Delay(500));
Button_Encrypt_Toggle.IsChecked = true;
Edit_Encrypt_Password.Password = password.Result;
}
}
private async void Button_Start_Click(object sender, RoutedEventArgs e)
{
if (!IsBusy)
@ -869,6 +881,30 @@ namespace com.muldersoft.slunkcrypt.gui
return (flags != 0xF);
}
private static string GenerateRandomString(int length)
{
if (length > 0)
{
char[] asciiChars = ASCII_CHARS.ToCharArray();
using (SecureRandom secureRandom = new SecureRandom())
{
string result;
do
{
StringBuilder builder = new StringBuilder();
for (int i = 0; i < length; ++i)
{
builder.Append(asciiChars[secureRandom.NextUInt32() % ((uint)asciiChars.Length)]);
}
result = builder.ToString();
}
while ((!char.IsLetterOrDigit(result[0])) || (!char.IsLetterOrDigit(result[result.Length - 1])) || IsWeakPassword(result));
return result;
}
}
return string.Empty;
}
private static void SetFocusAndSelectAll(FrameworkElement element)
{
TextBox textBox;

View File

@ -0,0 +1,146 @@
/******************************************************************************/
/* SlunkCrypt, by LoRd_MuldeR <MuldeR2@GMX.de> */
/* This work has been released under the CC0 1.0 Universal license! */
/******************************************************************************/
using System;
using System.IO;
using System.Security.Cryptography;
namespace com.muldersoft.slunkcrypt.gui.utils
{
class SecureRandom : IDisposable
{
private volatile bool m_disposed = false;
private readonly RNGCryptoServiceProvider m_provider;
private readonly byte[] m_tempBuffer = new byte[256];
private int m_offset = int.MaxValue;
// =============================================================================
// Constructor
// =============================================================================
public SecureRandom()
{
try
{
m_provider = new RNGCryptoServiceProvider();
}
catch (Exception e)
{
throw new IOException("Failed to create RNGCryptoServiceProvider instance!", e);
}
}
~SecureRandom()
{
Dispose();
}
// =============================================================================
// Public methods
// =============================================================================
public int NextInt32()
{
if (m_disposed)
{
throw new ObjectDisposedException("SecureRandom");
}
EnsureBytesAvailable(sizeof(int));
int value = BitConverter.ToInt32(m_tempBuffer, m_offset);
m_offset += sizeof(int);
return value;
}
public uint NextUInt32()
{
if (m_disposed)
{
throw new ObjectDisposedException("SecureRandom");
}
EnsureBytesAvailable(sizeof(uint));
uint value = BitConverter.ToUInt32(m_tempBuffer, m_offset);
m_offset += sizeof(uint);
return value;
}
public long NextInt64()
{
if (m_disposed)
{
throw new ObjectDisposedException("SecureRandom");
}
EnsureBytesAvailable(sizeof(long));
long value = BitConverter.ToInt64(m_tempBuffer, m_offset);
m_offset += sizeof(long);
return value;
}
public ulong NextUInt64()
{
if (m_disposed)
{
throw new ObjectDisposedException("SecureRandom");
}
EnsureBytesAvailable(sizeof(ulong));
ulong value = BitConverter.ToUInt64(m_tempBuffer, m_offset);
m_offset += sizeof(ulong);
return value;
}
public void Dispose()
{
if (!m_disposed)
{
m_disposed = true;
GC.SuppressFinalize(this);
try
{
FillArray(m_tempBuffer, 0);
}
finally
{
try
{
m_provider.Dispose();
}
catch { }
}
}
}
// =============================================================================
// Internal methods
// =============================================================================
private void EnsureBytesAvailable(int length)
{
if ((m_offset >= m_tempBuffer.Length) || ((m_tempBuffer.Length - m_offset) < length))
{
try
{
m_provider.GetBytes(m_tempBuffer);
m_offset = 0;
}
catch (Exception e)
{
throw new IOException("Failed to generated random bytes!", e);
}
}
}
private static void FillArray(byte[] array, byte value)
{
if (!ReferenceEquals(array, null))
{
for (int i = 0; i < array.Length; ++i)
{
array[i] = value;
}
}
}
}
}