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 #define MODE_TEST 5
static const size_t RCMD_PWDLEN_LENGTH = 12U; 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_PASSWORD = T("SLUNK_PASSPHRASE");
static const CHR* const ENV_KEEPFILE = T("SLUNK_KEEP_INCOMPLETE"); 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) private void OnCheckedChanged(object sender, RoutedEventArgs e)
{ {
NotifyPropertyChanged("IsChecked"); NotifyPropertyChanged("IsChecked");

View File

@ -87,6 +87,17 @@ namespace com.muldersoft.slunkcrypt.gui.ctrls
{ {
return IsRevealed ? Edit_Normal.Text : Edit_Hidden.Password; 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() 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"> <Compile Include="Controls\Hyperlink.xaml.cs">
<DependentUpon>Hyperlink.xaml</DependentUpon> <DependentUpon>Hyperlink.xaml</DependentUpon>
</Compile> </Compile>
<Compile Include="Controls\ImageButton.xaml.cs">
<DependentUpon>ImageButton.xaml</DependentUpon>
</Compile>
<Compile Include="Controls\ImageToggleButton.xaml.cs"> <Compile Include="Controls\ImageToggleButton.xaml.cs">
<DependentUpon>ImageToggleButton.xaml</DependentUpon> <DependentUpon>ImageToggleButton.xaml</DependentUpon>
</Compile> </Compile>
@ -79,6 +82,7 @@
<Compile Include="Process\SlunkCryptRunner.cs" /> <Compile Include="Process\SlunkCryptRunner.cs" />
<Compile Include="Utilities\BusyManager.cs" /> <Compile Include="Utilities\BusyManager.cs" />
<Compile Include="Utilities\PathUtils.cs" /> <Compile Include="Utilities\PathUtils.cs" />
<Compile Include="Utilities\SecureRandom.cs" />
<Compile Include="Utilities\SystemMenu.cs" /> <Compile Include="Utilities\SystemMenu.cs" />
<Compile Include="Utilities\VisibilityConverter.cs" /> <Compile Include="Utilities\VisibilityConverter.cs" />
<Compile Include="Utilities\FontSizeConverter.cs" /> <Compile Include="Utilities\FontSizeConverter.cs" />
@ -88,6 +92,10 @@
<SubType>Designer</SubType> <SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator> <Generator>MSBuild:Compile</Generator>
</Page> </Page>
<Page Include="Controls\ImageButton.xaml">
<Generator>MSBuild:Compile</Generator>
<SubType>Designer</SubType>
</Page>
<Page Include="Controls\ImageToggleButton.xaml"> <Page Include="Controls\ImageToggleButton.xaml">
<SubType>Designer</SubType> <SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator> <Generator>MSBuild:Compile</Generator>
@ -175,6 +183,9 @@
<ItemGroup> <ItemGroup>
<Resource Include="Resources\Tab_LogFile.png" /> <Resource Include="Resources\Tab_LogFile.png" />
</ItemGroup> </ItemGroup>
<ItemGroup>
<Resource Include="Resources\Refresh.png" />
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" /> <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it. <!-- 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. Other similar extension points exist, see Microsoft.Common.targets.

View File

@ -20,17 +20,18 @@
PreviewKeyDown="Window_PreviewKeyDown"> PreviewKeyDown="Window_PreviewKeyDown">
<Window.Resources> <Window.Resources>
<BitmapImage x:Key="ImageSource_Banner" UriSource="Resources/Banner.png"/> <BitmapImage x:Key="ImageSource_Banner" UriSource="Resources/Banner.png"/>
<BitmapImage x:Key="ImageSource_Browse" UriSource="Resources/Browse.png"/> <BitmapImage x:Key="ImageSource_Browse" UriSource="Resources/Browse.png"/>
<BitmapImage x:Key="ImageSource_Cancel" UriSource="Resources/Cancel.png"/> <BitmapImage x:Key="ImageSource_Cancel" UriSource="Resources/Cancel.png"/>
<BitmapImage x:Key="ImageSource_Exit" UriSource="Resources/Exit.png"/> <BitmapImage x:Key="ImageSource_Exit" UriSource="Resources/Exit.png"/>
<BitmapImage x:Key="ImageSource_Eye1" UriSource="Resources/Eye_1.png"/> <BitmapImage x:Key="ImageSource_Eye1" UriSource="Resources/Eye_1.png"/>
<BitmapImage x:Key="ImageSource_Eye2" UriSource="Resources/Eye_2.png"/> <BitmapImage x:Key="ImageSource_Eye2" UriSource="Resources/Eye_2.png"/>
<BitmapImage x:Key="ImageSource_Info" UriSource="Resources/Info.png"/> <BitmapImage x:Key="ImageSource_Info" UriSource="Resources/Info.png"/>
<BitmapImage x:Key="ImageSource_Start" UriSource="Resources/Start.png"/> <BitmapImage x:Key="ImageSource_Refresh" UriSource="Resources/Refresh.png"/>
<BitmapImage x:Key="ImageSource_TabHd1" UriSource="Resources/Tab_Encrypt.png"/> <BitmapImage x:Key="ImageSource_Start" UriSource="Resources/Start.png"/>
<BitmapImage x:Key="ImageSource_TabHd2" UriSource="Resources/Tab_Decrypt.png"/> <BitmapImage x:Key="ImageSource_TabHd1" UriSource="Resources/Tab_Encrypt.png"/>
<BitmapImage x:Key="ImageSource_TabHd3" UriSource="Resources/Tab_LogFile.png"/> <BitmapImage x:Key="ImageSource_TabHd2" UriSource="Resources/Tab_Decrypt.png"/>
<BitmapImage x:Key="ImageSource_TabHd3" UriSource="Resources/Tab_LogFile.png"/>
<FontFamily x:Key="Monospace">pack://application:,,,/Resources/Fonts/#Hack</FontFamily> <FontFamily x:Key="Monospace">pack://application:,,,/Resources/Fonts/#Hack</FontFamily>
<utils:FontSizeConverter x:Key="SlightlySmallFont" Ratio="0.875"/> <utils:FontSizeConverter x:Key="SlightlySmallFont" Ratio="0.875"/>
<utils:FontSizeConverter x:Key="SlightlyLargerFont" Ratio="1.125"/> <utils:FontSizeConverter x:Key="SlightlyLargerFont" Ratio="1.125"/>
@ -92,7 +93,8 @@
</DockPanel> </DockPanel>
<TextBlock FontWeight="SemiBold" Text="Passphrase:" Margin="0,10,0,0"/> <TextBlock FontWeight="SemiBold" Text="Passphrase:" Margin="0,10,0,0"/>
<DockPanel Margin="0,5,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"/> <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> </DockPanel>
</StackPanel> </StackPanel>
@ -127,7 +129,7 @@
</DockPanel> </DockPanel>
<TextBlock FontWeight="SemiBold" Text="Passphrase:" Margin="0,10,0,0"/> <TextBlock FontWeight="SemiBold" Text="Passphrase:" Margin="0,10,0,0"/>
<DockPanel Margin="0,5,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"/> <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> </DockPanel>
</StackPanel> </StackPanel>

View File

@ -35,7 +35,7 @@ namespace com.muldersoft.slunkcrypt.gui
private delegate Task<bool> SlunkProcessor(string inputFile, string outputFile, string password); private delegate Task<bool> SlunkProcessor(string inputFile, string outputFile, string password);
public event PropertyChangedEventHandler PropertyChanged; 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 Lazy<string> m_about = new Lazy<string>(CreateAboutText);
private readonly Random m_random = new Random(); 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 bool m_busyFlag = false, m_checksumError = false, m_processReceived = false, m_checked = false;
private volatile SlunkCryptRunner m_processRunner = null; private volatile SlunkCryptRunner m_processRunner = null;
private const string ASCII_CHARS = "!\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~"; private const string ASCII_CHARS = "!#$%&()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~";
// ============================================================================= // =============================================================================
// Constructor // 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) private async void Button_Start_Click(object sender, RoutedEventArgs e)
{ {
if (!IsBusy) if (!IsBusy)
@ -869,6 +881,30 @@ namespace com.muldersoft.slunkcrypt.gui
return (flags != 0xF); 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) private static void SetFocusAndSelectAll(FrameworkElement element)
{ {
TextBox textBox; 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;
}
}
}
}
}