1 /******************************************************************************/
2 /* SlunkCrypt, by LoRd_MuldeR <MuldeR2@GMX.de> */
3 /* This work has been released under the CC0 1.0 Universal license! */
4 /******************************************************************************/
7 using System.Collections.Generic;
8 using System.Diagnostics;
11 using System.Threading.Tasks;
13 namespace com.muldersoft.slunkcrypt.gui.process
15 public static class PasswordGen
17 private static readonly TimeSpan TIMEOUT_MSEC = TimeSpan.FromSeconds(90);
19 private const string COMMAND_PASSWRD = "-p {0:D}";
21 // =============================================================================
23 // =============================================================================
25 public class GenerationFailedException : IOException
27 public GenerationFailedException(string message, Exception innerException) : base(message, innerException)
32 // =============================================================================
34 // =============================================================================
36 public static async Task<string> GeneratePassword(int length)
38 using (FileStream executableFile = ExecutableHelper.GetExecutableFile())
42 string password = await StartProcess(executableFile, length);
43 if (IsWeakPassword(password))
45 throw new InvalidDataException("The generated password string is invalid!");
51 throw new GenerationFailedException("Failed to generate password string!", e);
56 public static bool IsWeakPassword(string password)
59 if (!string.IsNullOrEmpty(password))
61 foreach (char c in password)
65 flags |= char.IsUpper(c) ? 0x2 : 0x1;
69 flags |= char.IsDigit(c) ? 0x8 : 0x4;
73 return (flags != 0xF);
76 // =============================================================================
78 // =============================================================================
80 private static async Task<string> StartProcess(FileStream executableFile, int length)
82 using (Process process = new Process())
84 process.StartInfo.UseShellExecute = false;
85 process.StartInfo.CreateNoWindow = true;
86 process.StartInfo.RedirectStandardOutput = true;
87 process.StartInfo.StandardOutputEncoding = Encoding.UTF8;
88 process.StartInfo.FileName = executableFile.Name;
89 process.StartInfo.Arguments = string.Format(COMMAND_PASSWRD, length);
92 Stack<string> outputLines = await WaitForExit(process, TIMEOUT_MSEC);
94 if (process.ExitCode == 0)
96 while (outputLines.Count > 0)
98 string line = outputLines.Pop();
99 if (line.Length >= length)
109 private static async Task<Stack<string>> WaitForExit(Process process, TimeSpan timeout)
111 Task<Stack<string>> readTask;
112 await Task.WhenAny(readTask = Task.Run(() => ReadOutput(process)), Task.Delay(timeout));
113 if (!process.WaitForExit(125))
116 process.WaitForExit();
118 return await readTask;
121 private static Stack<string> ReadOutput(Process process)
123 Stack<string> result = new Stack<string>();
124 using (StreamReader reader = process.StandardOutput)
127 while ((line = reader.ReadLine()) != null)
130 if (line.Length != 0)
132 result.Push(line.Trim());