140 lines
4.9 KiB
C#
140 lines
4.9 KiB
C#
|
/******************************************************************************/
|
|||
|
/* SlunkCrypt, by LoRd_MuldeR <MuldeR2@GMX.de> */
|
|||
|
/* This work has been released under the CC0 1.0 Universal license! */
|
|||
|
/******************************************************************************/
|
|||
|
|
|||
|
using System;
|
|||
|
using System.Collections.Generic;
|
|||
|
using System.Diagnostics;
|
|||
|
using System.IO;
|
|||
|
using System.Text;
|
|||
|
using System.Threading.Tasks;
|
|||
|
|
|||
|
namespace com.muldersoft.slunkcrypt.gui.process
|
|||
|
{
|
|||
|
public static class PasswordGen
|
|||
|
{
|
|||
|
private static readonly TimeSpan TIMEOUT_MSEC = TimeSpan.FromSeconds(90);
|
|||
|
|
|||
|
private const string COMMAND_PASSWRD = "-p {0:D}";
|
|||
|
|
|||
|
// =============================================================================
|
|||
|
// Exception classes
|
|||
|
// =============================================================================
|
|||
|
|
|||
|
public class GenerationFailedException : IOException
|
|||
|
{
|
|||
|
public GenerationFailedException(string message, Exception innerException) : base(message, innerException)
|
|||
|
{
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
// =============================================================================
|
|||
|
// Public methods
|
|||
|
// =============================================================================
|
|||
|
|
|||
|
public static async Task<string> GeneratePassword(int length)
|
|||
|
{
|
|||
|
using (FileStream executableFile = ExecutableHelper.GetExecutableFile())
|
|||
|
{
|
|||
|
try
|
|||
|
{
|
|||
|
string password = await StartProcess(executableFile, length);
|
|||
|
if (IsWeakPassword(password))
|
|||
|
{
|
|||
|
throw new InvalidDataException("The generated password string is invalid!");
|
|||
|
}
|
|||
|
return password;
|
|||
|
}
|
|||
|
catch (Exception e)
|
|||
|
{
|
|||
|
throw new GenerationFailedException("Failed to generate password string!", e);
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
public static bool IsWeakPassword(string password)
|
|||
|
{
|
|||
|
int flags = 0;
|
|||
|
if (!string.IsNullOrEmpty(password))
|
|||
|
{
|
|||
|
foreach (char c in password)
|
|||
|
{
|
|||
|
if (char.IsLetter(c))
|
|||
|
{
|
|||
|
flags |= char.IsUpper(c) ? 0x2 : 0x1;
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
flags |= char.IsDigit(c) ? 0x8 : 0x4;
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
return (flags != 0xF);
|
|||
|
}
|
|||
|
|
|||
|
// =============================================================================
|
|||
|
// Internal methods
|
|||
|
// =============================================================================
|
|||
|
|
|||
|
private static async Task<string> StartProcess(FileStream executableFile, int length)
|
|||
|
{
|
|||
|
using (Process process = new Process())
|
|||
|
{
|
|||
|
process.StartInfo.UseShellExecute = false;
|
|||
|
process.StartInfo.CreateNoWindow = true;
|
|||
|
process.StartInfo.RedirectStandardOutput = true;
|
|||
|
process.StartInfo.StandardOutputEncoding = Encoding.UTF8;
|
|||
|
process.StartInfo.FileName = executableFile.Name;
|
|||
|
process.StartInfo.Arguments = string.Format(COMMAND_PASSWRD, length);
|
|||
|
process.Start();
|
|||
|
|
|||
|
Stack<string> outputLines = await WaitForExit(process, TIMEOUT_MSEC);
|
|||
|
|
|||
|
if (process.ExitCode == 0)
|
|||
|
{
|
|||
|
while (outputLines.Count > 0)
|
|||
|
{
|
|||
|
string line = outputLines.Pop();
|
|||
|
if (line.Length >= length)
|
|||
|
{
|
|||
|
return line;
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
return string.Empty;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
private static async Task<Stack<string>> WaitForExit(Process process, TimeSpan timeout)
|
|||
|
{
|
|||
|
Task<Stack<string>> readTask;
|
|||
|
await Task.WhenAny(readTask = Task.Run(() => ReadOutput(process)), Task.Delay(timeout));
|
|||
|
if (!process.WaitForExit(125))
|
|||
|
{
|
|||
|
process.Kill();
|
|||
|
process.WaitForExit();
|
|||
|
}
|
|||
|
return await readTask;
|
|||
|
}
|
|||
|
|
|||
|
private static Stack<string> ReadOutput(Process process)
|
|||
|
{
|
|||
|
Stack<string> result = new Stack<string>();
|
|||
|
using (StreamReader reader = process.StandardOutput)
|
|||
|
{
|
|||
|
string line;
|
|||
|
while ((line = reader.ReadLine()) != null)
|
|||
|
{
|
|||
|
line = line.Trim();
|
|||
|
if (line.Length != 0)
|
|||
|
{
|
|||
|
result.Push(line.Trim());
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
return result;
|
|||
|
}
|
|||
|
}
|
|||
|
}
|