├── XkPassword ├── en.gz ├── StringBuilderExtensions.cs ├── StreamReaderExtensions.cs ├── IRandomSource.cs ├── Padding.cs ├── SystemRandomInt.cs ├── CaseTransformation.cs ├── XkPassword.csproj ├── PublicExtensionMethods │ └── HashSetExtensions.cs └── XkPasswd.cs ├── LICENSE ├── XkPassword.Demo ├── App.config ├── App.xaml.cs ├── Properties │ ├── Settings.settings │ ├── Settings.Designer.cs │ ├── AssemblyInfo.cs │ ├── Resources.Designer.cs │ └── Resources.resx ├── App.xaml ├── XkPassword.Demo.csproj ├── MainWindow.xaml.cs └── MainWindow.xaml ├── LICENSE.XkPassword ├── README.md ├── XkPassword.sln ├── .gitattributes ├── .gitignore └── LICENSE.WordList /XkPassword/en.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/myount/xkpassword/HEAD/XkPassword/en.gz -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Please see LICENSE.XkPassword for the license covering the XkPassword code itself, 2 | and LICENSE.WordList for the license covering the built-in English word list (generated from SCOWL). -------------------------------------------------------------------------------- /XkPassword.Demo/App.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /XkPassword.Demo/App.xaml.cs: -------------------------------------------------------------------------------- 1 | using System.Windows; 2 | 3 | namespace XkPassword.Demo 4 | { 5 | /// 6 | /// Interaction logic for App.xaml 7 | /// 8 | public partial class App : Application 9 | { 10 | } 11 | } -------------------------------------------------------------------------------- /XkPassword.Demo/Properties/Settings.settings: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /XkPassword/StringBuilderExtensions.cs: -------------------------------------------------------------------------------- 1 | using System.Text; 2 | 3 | namespace XkPassword 4 | { 5 | internal static class StringBuilderExtensions 6 | { 7 | public static void Truncate(this StringBuilder builder, int desiredLength) 8 | { 9 | if (builder.Length < desiredLength) 10 | { 11 | return; 12 | } 13 | 14 | builder.Remove(desiredLength, builder.Length - desiredLength); 15 | } 16 | } 17 | } -------------------------------------------------------------------------------- /XkPassword/StreamReaderExtensions.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.IO; 3 | 4 | namespace XkPassword 5 | { 6 | internal static class StreamReaderExtensions 7 | { 8 | /// 9 | /// Reads all lines from a and returns them in an of . 10 | /// 11 | /// The reader. 12 | /// An of of lines available from the StreamReader. 13 | public static IEnumerable ReadAllLines(this StreamReader reader) 14 | { 15 | while (!reader.EndOfStream) 16 | { 17 | yield return reader.ReadLine(); 18 | } 19 | } 20 | } 21 | } -------------------------------------------------------------------------------- /XkPassword/IRandomSource.cs: -------------------------------------------------------------------------------- 1 | namespace XkPassword 2 | { 3 | /// 4 | /// An interface for classes which provide a source of random integers or booleans. 5 | /// 6 | public interface IRandomSource 7 | { 8 | /// 9 | /// Gets the next integer between minValue and maxValue from the random source. 10 | /// 11 | /// The lower bound of the range of possible integers to return. 12 | /// The upper bound, exclusive, of the range of possible integers to return. 13 | /// An integer in the range [minValue..maxValue). 14 | int Next(int minValue, int maxValue); 15 | 16 | /// 17 | /// Returns a randomly chosen true or false value. 18 | /// 19 | /// A randomly chosen true or false value. 20 | bool CoinFlip(); 21 | } 22 | } -------------------------------------------------------------------------------- /XkPassword/Padding.cs: -------------------------------------------------------------------------------- 1 | namespace XkPassword 2 | { 3 | /// 4 | /// An enumeration of possible password padding types. 5 | /// 6 | public enum Padding 7 | { 8 | /// 9 | /// No padding. 10 | /// 11 | None = 0, 12 | 13 | /// 14 | /// Fixed padding: a fixed number of characters will be added to the beginning and/or end of the password according to the configuration. 15 | /// 16 | Fixed = 1, 17 | 18 | /// 19 | /// Adaptive padding: in addition to a fixed number of characters being added to the beginning and/or end of the password according to the 20 | /// configuration, characters will be added to the end of the password to pad it out to a specific length. 21 | /// N.B.: This setting will have no effect if PadToLength is less than or equal to 0. 22 | /// 23 | Adaptive = 2 24 | } 25 | } -------------------------------------------------------------------------------- /XkPassword.Demo/Properties/Settings.Designer.cs: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | // 3 | // This code was generated by a tool. 4 | // Runtime Version:4.0.30319.42000 5 | // 6 | // Changes to this file may cause incorrect behavior and will be lost if 7 | // the code is regenerated. 8 | // 9 | //------------------------------------------------------------------------------ 10 | 11 | namespace XkPassword.Demo.Properties { 12 | 13 | 14 | [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] 15 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "16.3.0.0")] 16 | internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase { 17 | 18 | private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings()))); 19 | 20 | public static Settings Default { 21 | get { 22 | return defaultInstance; 23 | } 24 | } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /XkPassword/SystemRandomInt.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace XkPassword 4 | { 5 | /// 6 | /// The default source of random integers, which simply wraps System.Random. 7 | /// 8 | internal class DefaultRandomSource : IRandomSource 9 | { 10 | private static readonly Random RandomSource = new Random(); 11 | 12 | /// 13 | /// Get the next integer between minValue and maxValue from the random source. 14 | /// 15 | /// The lower bound of the range of possible integers to return. 16 | /// The upper bound, exclusive, of the range of possible integers to return. 17 | /// An integer in the range [minValue..maxValue). 18 | public int Next(int minValue, int maxValue) 19 | { 20 | return RandomSource.Next(minValue, maxValue); 21 | } 22 | 23 | /// 24 | /// Returns a randomly chosen true or false value. 25 | /// 26 | /// A randomly chosen true or false value. 27 | public bool CoinFlip() 28 | { 29 | return Convert.ToBoolean(Next(0, 2)); 30 | } 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /LICENSE.XkPassword: -------------------------------------------------------------------------------- 1 | Copyright (c) 2014, Michael Yount 2 | Copyright (c) 2014, Bart Busscots 3 | All rights reserved. 4 | 5 | Redistribution and use in source and binary forms, with or without 6 | modification, are permitted provided that the following conditions are met: 7 | 8 | * Redistributions of source code must retain the above copyright notice, this 9 | list of conditions and the following disclaimer. 10 | 11 | * Redistributions in binary form must reproduce the above copyright notice, 12 | this list of conditions and the following disclaimer in the documentation 13 | and/or other materials provided with the distribution. 14 | 15 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 16 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 18 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 19 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 20 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 21 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 22 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 23 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 24 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # XkPassword 2 | XkPassword is a C# reimplementation of [Bart Busschots' `xkpasswd.pm`][xkpasswd.pm], a library for generating 3 | secure memorable passwords inspired mainly by [a well-known xkcd comic][xkcd]. 4 | 5 | This library is provided free of charge, under the same license as `xkpasswd.pm`: see LICENSE.XkPassword for details. 6 | 7 | The built-in English wordlist was generated from [SCOWL][scowl], which is made available under an 8 | MIT-style license: see LICENSE.WordList for details. 9 | 10 | [xkpasswd.pm]: http://github.com/bbusschots/xkpasswd.pm 11 | [xkcd]: http://xkcd.com/936/ 12 | [scowl]: http://wordlist.aspell.net/ 13 | 14 | ## Differences between XkPassword and `xkpasswd.pm` 15 | 16 | XkPassword is a reimplementation, not a direct port. I sought only to duplicate the core functionality of 17 | `xkpasswd.pm`. Therefore, XkPassword does not have multiple preset configurations as `xkpasswd.pm` does, 18 | though the `XkPasswd` class's constructor does set defaults similar to the "default" configuration of 19 | `xkpasswd.pm`. It is assumed that the consuming application will provide some capacity for storing and 20 | reusing different configurations. 21 | 22 | # XkPassword.Demo 23 | 24 | XkPassword.Demo is a rudimentary application which demonstrates all capabilities of XkPassword except the 25 | ability to choose a different word list file. It is built using Windows Presentation Foundation and requires 26 | version 4.5 of the .NET Framework. -------------------------------------------------------------------------------- /XkPassword/CaseTransformation.cs: -------------------------------------------------------------------------------- 1 | namespace XkPassword 2 | { 3 | /// 4 | /// An enumeration representing possible word case transformations. 5 | /// 6 | /// N.B.: All transformations are performed using the invariant culture. 7 | public enum CaseTransformation 8 | { 9 | /// 10 | /// Perform no case transformation. 11 | /// 12 | None = 0, 13 | /// 14 | /// Transform word to ALL UPPERCASE. 15 | /// 16 | UpperCase = 1, 17 | /// 18 | /// Transform word to all lowercase. 19 | /// 20 | LowerCase = 2, 21 | /// 22 | /// Capitalize the first letter of the word. 23 | /// 24 | Capitalize = 3, 25 | /// 26 | /// Capitalise the first letter of the word. 27 | /// 28 | /// For British users. 29 | Capitalise = Capitalize, 30 | /// 31 | /// iNVERT THE CASE OF THE WORD. 32 | /// 33 | Invert = 4, 34 | /// 35 | /// AlTeRnAtE tHe CaSe Of ThE wOrD. 36 | /// 37 | Alternate = 5, 38 | /// 39 | /// RAndOmLY capITAliZe thE WorD. 40 | /// 41 | Random = 6, 42 | 43 | /// 44 | /// RANDOMLY capitalize entire WORD 45 | /// 46 | RandomWord = 7 47 | } 48 | } -------------------------------------------------------------------------------- /XkPassword/XkPassword.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | netstandard2.0 5 | XkPassword is C# reimplementation of the xkpasswd.pm Perl module by Bart Busschots, inspired by a well-known webcomic. 6 | Michael Yount 7 | Michael Yount and contributors 8 | 1.2.0 9 | Copyright © 2014-2015 Michael Yount and contributors 10 | 11 | 1.2.0 - Converted to a .NET Standard 2.0 library. 12 | 13 | 1.1.2 - Fixed a bug where word length limits were exclusive rather than inclusive. Added a feature from the original xkpasswd.pm which randomly capitalizes an entire word in the password. Thanks to John Bloom for these contributions. 14 | 15 | 1.1.0 - XkPassword can now use sources of randomness other than the default System.Random: create a class that implements IRandomSource wrapping your preferred source of randomness, and set RandomSource to an instance of it. 16 | https://github.com/myount/xkpassword 17 | password-generator 18 | true 19 | https://github.com/myount/xkpassword 20 | git 21 | LICENSE 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | True 31 | 32 | 33 | 34 | 35 | 36 | -------------------------------------------------------------------------------- /XkPassword/PublicExtensionMethods/HashSetExtensions.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Linq; 3 | 4 | namespace XkPassword.PublicExtensionMethods 5 | { 6 | /// 7 | /// Extension methods for of s that may be useful to consumers of . 8 | /// 9 | public static class HashSetExtensions 10 | { 11 | /// 12 | /// Adds the unique items from an of to the hash set. 13 | /// 14 | /// The hash set. 15 | /// The characters to add to the hash set. 16 | public static void AddCharArray(this HashSet hashSet, IEnumerable charEnumerable) 17 | { 18 | if (hashSet == null) 19 | { 20 | return; 21 | } 22 | 23 | if (charEnumerable == null) 24 | { 25 | return; 26 | } 27 | 28 | foreach (char c in charEnumerable.Distinct()) 29 | { 30 | hashSet.Add(c); 31 | } 32 | } 33 | 34 | /// 35 | /// Clears the hash set and sets its contents to the unique characters from the of . 36 | /// 37 | /// The hash set. 38 | /// The characters to add to the hash set. 39 | public static void FromCharArray(this HashSet hashSet, IEnumerable charEnumerable) 40 | { 41 | if (hashSet == null) 42 | { 43 | return; 44 | } 45 | 46 | if (charEnumerable == null) 47 | { 48 | return; 49 | } 50 | 51 | hashSet.Clear(); 52 | hashSet.AddCharArray(charEnumerable); 53 | } 54 | } 55 | } -------------------------------------------------------------------------------- /XkPassword.sln: -------------------------------------------------------------------------------- 1 | 2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio Version 16 4 | VisualStudioVersion = 16.0.29418.71 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "XkPassword.Demo", "XkPassword.Demo\XkPassword.Demo.csproj", "{5D3772AB-02E3-469A-8464-689573D09079}" 7 | EndProject 8 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Documentation", "Documentation", "{867A2549-C1F2-4036-AC18-DBB537723C97}" 9 | ProjectSection(SolutionItems) = preProject 10 | LICENSE = LICENSE 11 | LICENSE.WordList = LICENSE.WordList 12 | LICENSE.XkPassword = LICENSE.XkPassword 13 | README.md = README.md 14 | EndProjectSection 15 | EndProject 16 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Git Files", "Git Files", "{87D1FD17-E878-414B-B6AD-8B83317F7F72}" 17 | ProjectSection(SolutionItems) = preProject 18 | .gitattributes = .gitattributes 19 | .gitignore = .gitignore 20 | EndProjectSection 21 | EndProject 22 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "XkPassword", "XkPassword\XkPassword.csproj", "{C7B29E5F-0B03-4578-ABC2-702A7199F52A}" 23 | EndProject 24 | Global 25 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 26 | Debug|Any CPU = Debug|Any CPU 27 | Release|Any CPU = Release|Any CPU 28 | EndGlobalSection 29 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 30 | {5D3772AB-02E3-469A-8464-689573D09079}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 31 | {5D3772AB-02E3-469A-8464-689573D09079}.Debug|Any CPU.Build.0 = Debug|Any CPU 32 | {5D3772AB-02E3-469A-8464-689573D09079}.Release|Any CPU.ActiveCfg = Release|Any CPU 33 | {5D3772AB-02E3-469A-8464-689573D09079}.Release|Any CPU.Build.0 = Release|Any CPU 34 | {C7B29E5F-0B03-4578-ABC2-702A7199F52A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 35 | {C7B29E5F-0B03-4578-ABC2-702A7199F52A}.Debug|Any CPU.Build.0 = Debug|Any CPU 36 | {C7B29E5F-0B03-4578-ABC2-702A7199F52A}.Release|Any CPU.ActiveCfg = Release|Any CPU 37 | {C7B29E5F-0B03-4578-ABC2-702A7199F52A}.Release|Any CPU.Build.0 = Release|Any CPU 38 | EndGlobalSection 39 | GlobalSection(SolutionProperties) = preSolution 40 | HideSolutionNode = FALSE 41 | EndGlobalSection 42 | GlobalSection(ExtensibilityGlobals) = postSolution 43 | SolutionGuid = {FDE26E25-D218-4200-80CE-A43E64E49C62} 44 | EndGlobalSection 45 | EndGlobal 46 | -------------------------------------------------------------------------------- /XkPassword.Demo/App.xaml: -------------------------------------------------------------------------------- 1 | 5 | 6 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | -------------------------------------------------------------------------------- /XkPassword.Demo/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.InteropServices; 3 | using System.Windows; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | 9 | [assembly: AssemblyTitle("XkPassword.Demo")] 10 | [assembly: AssemblyDescription("")] 11 | [assembly: AssemblyConfiguration("")] 12 | [assembly: AssemblyCompany("")] 13 | [assembly: AssemblyProduct("XkPassword.Demo")] 14 | [assembly: AssemblyCopyright("Copyright © 2014")] 15 | [assembly: AssemblyTrademark("")] 16 | [assembly: AssemblyCulture("")] 17 | 18 | // Setting ComVisible to false makes the types in this assembly not visible 19 | // to COM components. If you need to access a type in this assembly from 20 | // COM, set the ComVisible attribute to true on that type. 21 | 22 | [assembly: ComVisible(false)] 23 | 24 | //In order to begin building localizable applications, set 25 | //CultureYouAreCodingWith in your .csproj file 26 | //inside a . For example, if you are using US english 27 | //in your source files, set the to en-US. Then uncomment 28 | //the NeutralResourceLanguage attribute below. Update the "en-US" in 29 | //the line below to match the UICulture setting in the project file. 30 | 31 | //[assembly: NeutralResourcesLanguage("en-US", UltimateResourceFallbackLocation.Satellite)] 32 | 33 | [assembly: ThemeInfo( 34 | ResourceDictionaryLocation.None, //where theme specific resource dictionaries are located 35 | //(used if a resource is not found in the page, 36 | // or application resource dictionaries) 37 | ResourceDictionaryLocation.SourceAssembly //where the generic resource dictionary is located 38 | //(used if a resource is not found in the page, 39 | // app, or any theme specific resource dictionaries) 40 | )] 41 | 42 | // Version information for an assembly consists of the following four values: 43 | // 44 | // Major Version 45 | // Minor Version 46 | // Build Number 47 | // Revision 48 | // 49 | // You can specify all the values or you can default the Build and Revision Numbers 50 | // by using the '*' as shown below: 51 | // [assembly: AssemblyVersion("1.0.*")] 52 | 53 | [assembly: AssemblyVersion("1.0.1.*")] 54 | [assembly: AssemblyFileVersion("1.0.1")] -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | ############################################################################### 2 | # Set default behavior to automatically normalize line endings. 3 | ############################################################################### 4 | * text=auto 5 | 6 | ############################################################################### 7 | # Set default behavior for command prompt diff. 8 | # 9 | # This is need for earlier builds of msysgit that does not have it on by 10 | # default for csharp files. 11 | # Note: This is only used by command line 12 | ############################################################################### 13 | #*.cs diff=csharp 14 | 15 | ############################################################################### 16 | # Set the merge driver for project and solution files 17 | # 18 | # Merging from the command prompt will add diff markers to the files if there 19 | # are conflicts (Merging from VS is not affected by the settings below, in VS 20 | # the diff markers are never inserted). Diff markers may cause the following 21 | # file extensions to fail to load in VS. An alternative would be to treat 22 | # these files as binary and thus will always conflict and require user 23 | # intervention with every merge. To do so, just uncomment the entries below 24 | ############################################################################### 25 | #*.sln merge=binary 26 | #*.csproj merge=binary 27 | #*.vbproj merge=binary 28 | #*.vcxproj merge=binary 29 | #*.vcproj merge=binary 30 | #*.dbproj merge=binary 31 | #*.fsproj merge=binary 32 | #*.lsproj merge=binary 33 | #*.wixproj merge=binary 34 | #*.modelproj merge=binary 35 | #*.sqlproj merge=binary 36 | #*.wwaproj merge=binary 37 | 38 | ############################################################################### 39 | # behavior for image files 40 | # 41 | # image files are treated as binary by default. 42 | ############################################################################### 43 | #*.jpg binary 44 | #*.png binary 45 | #*.gif binary 46 | 47 | ############################################################################### 48 | # diff behavior for common document formats 49 | # 50 | # Convert binary document formats to text before diffing them. This feature 51 | # is only available from the command line. Turn it on by uncommenting the 52 | # entries below. 53 | ############################################################################### 54 | #*.doc diff=astextplain 55 | #*.DOC diff=astextplain 56 | #*.docx diff=astextplain 57 | #*.DOCX diff=astextplain 58 | #*.dot diff=astextplain 59 | #*.DOT diff=astextplain 60 | #*.pdf diff=astextplain 61 | #*.PDF diff=astextplain 62 | #*.rtf diff=astextplain 63 | #*.RTF diff=astextplain 64 | -------------------------------------------------------------------------------- /XkPassword.Demo/Properties/Resources.Designer.cs: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | // 3 | // This code was generated by a tool. 4 | // Runtime Version:4.0.30319.42000 5 | // 6 | // Changes to this file may cause incorrect behavior and will be lost if 7 | // the code is regenerated. 8 | // 9 | //------------------------------------------------------------------------------ 10 | 11 | namespace XkPassword.Demo.Properties { 12 | using System; 13 | 14 | 15 | /// 16 | /// A strongly-typed resource class, for looking up localized strings, etc. 17 | /// 18 | // This class was auto-generated by the StronglyTypedResourceBuilder 19 | // class via a tool like ResGen or Visual Studio. 20 | // To add or remove a member, edit your .ResX file then rerun ResGen 21 | // with the /str option, or rebuild your VS project. 22 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "16.0.0.0")] 23 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] 24 | [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] 25 | internal class Resources { 26 | 27 | private static global::System.Resources.ResourceManager resourceMan; 28 | 29 | private static global::System.Globalization.CultureInfo resourceCulture; 30 | 31 | [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] 32 | internal Resources() { 33 | } 34 | 35 | /// 36 | /// Returns the cached ResourceManager instance used by this class. 37 | /// 38 | [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] 39 | internal static global::System.Resources.ResourceManager ResourceManager { 40 | get { 41 | if (object.ReferenceEquals(resourceMan, null)) { 42 | global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("XkPassword.Demo.Properties.Resources", typeof(Resources).Assembly); 43 | resourceMan = temp; 44 | } 45 | return resourceMan; 46 | } 47 | } 48 | 49 | /// 50 | /// Overrides the current thread's CurrentUICulture property for all 51 | /// resource lookups using this strongly typed resource class. 52 | /// 53 | [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] 54 | internal static global::System.Globalization.CultureInfo Culture { 55 | get { 56 | return resourceCulture; 57 | } 58 | set { 59 | resourceCulture = value; 60 | } 61 | } 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | ## Ignore Visual Studio temporary files, build results, and 2 | ## files generated by popular Visual Studio add-ons. 3 | 4 | # User-specific files 5 | *.suo 6 | *.user 7 | *.sln.docstates 8 | 9 | # Build results 10 | 11 | [Dd]ebug/ 12 | [Rr]elease/ 13 | x64/ 14 | build/ 15 | [Bb]in/ 16 | [Oo]bj/ 17 | 18 | # Enable "build/" folder in the NuGet Packages folder since NuGet packages use it for MSBuild targets 19 | !packages/*/build/ 20 | 21 | # MSTest test Results 22 | [Tt]est[Rr]esult*/ 23 | [Bb]uild[Ll]og.* 24 | 25 | *_i.c 26 | *_p.c 27 | *.ilk 28 | *.meta 29 | *.obj 30 | *.pch 31 | *.pdb 32 | *.pgc 33 | *.pgd 34 | *.rsp 35 | *.sbr 36 | *.tlb 37 | *.tli 38 | *.tlh 39 | *.tmp 40 | *.tmp_proj 41 | *.log 42 | *.vspscc 43 | *.vssscc 44 | .builds 45 | *.pidb 46 | *.log 47 | *.scc 48 | *.nupkg 49 | 50 | # Visual C++ cache files 51 | ipch/ 52 | *.aps 53 | *.ncb 54 | *.opensdf 55 | *.sdf 56 | *.cachefile 57 | 58 | # Visual Studio profiler 59 | *.psess 60 | *.vsp 61 | *.vspx 62 | 63 | # Guidance Automation Toolkit 64 | *.gpState 65 | 66 | # ReSharper is a .NET coding add-in 67 | _ReSharper*/ 68 | *.[Rr]e[Ss]harper 69 | 70 | # TeamCity is a build add-in 71 | _TeamCity* 72 | 73 | # DotCover is a Code Coverage Tool 74 | *.dotCover 75 | 76 | # NCrunch 77 | *.ncrunch* 78 | .*crunch*.local.xml 79 | 80 | # Installshield output folder 81 | [Ee]xpress/ 82 | 83 | # DocProject is a documentation generator add-in 84 | DocProject/buildhelp/ 85 | DocProject/Help/*.HxT 86 | DocProject/Help/*.HxC 87 | DocProject/Help/*.hhc 88 | DocProject/Help/*.hhk 89 | DocProject/Help/*.hhp 90 | DocProject/Help/Html2 91 | DocProject/Help/html 92 | 93 | # Click-Once directory 94 | publish/ 95 | 96 | # Publish Web Output 97 | *.Publish.xml 98 | 99 | # NuGet Packages Directory 100 | ## TODO: If you have NuGet Package Restore enabled, uncomment the next line 101 | #packages/ 102 | 103 | # Windows Azure Build Output 104 | csx 105 | *.build.csdef 106 | 107 | # Windows Store app package directory 108 | AppPackages/ 109 | 110 | # Others 111 | sql/ 112 | *.Cache 113 | ClientBin/ 114 | [Ss]tyle[Cc]op.* 115 | ~$* 116 | *~ 117 | *.dbmdl 118 | *.[Pp]ublish.xml 119 | *.pfx 120 | *.publishsettings 121 | 122 | # RIA/Silverlight projects 123 | Generated_Code/ 124 | 125 | # Backup & report files from converting an old project file to a newer 126 | # Visual Studio version. Backup files are not needed, because we have git ;-) 127 | _UpgradeReport_Files/ 128 | Backup*/ 129 | UpgradeLog*.XML 130 | UpgradeLog*.htm 131 | 132 | # SQL Server files 133 | App_Data/*.mdf 134 | App_Data/*.ldf 135 | 136 | 137 | #LightSwitch generated files 138 | GeneratedArtifacts/ 139 | _Pvt_Extensions/ 140 | ModelManifest.xml 141 | 142 | # ========================= 143 | # Windows detritus 144 | # ========================= 145 | 146 | # Windows image file caches 147 | Thumbs.db 148 | ehthumbs.db 149 | 150 | # Folder config file 151 | Desktop.ini 152 | 153 | # Recycle Bin used on file shares 154 | $RECYCLE.BIN/ 155 | 156 | # Mac desktop service store files 157 | .DS_Store 158 | -------------------------------------------------------------------------------- /XkPassword.Demo/XkPassword.Demo.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Debug 6 | AnyCPU 7 | {5D3772AB-02E3-469A-8464-689573D09079} 8 | WinExe 9 | Properties 10 | XkPassword.Demo 11 | XkPassword.Demo 12 | v4.8 13 | 512 14 | {60dc8134-eba5-43b8-bcc9-bb4bc16c2548};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} 15 | 4 16 | 17 | 18 | 19 | AnyCPU 20 | true 21 | full 22 | false 23 | bin\Debug\ 24 | DEBUG;TRACE 25 | prompt 26 | 4 27 | false 28 | 29 | 30 | AnyCPU 31 | pdbonly 32 | true 33 | bin\Release\ 34 | TRACE 35 | prompt 36 | 4 37 | false 38 | 39 | 40 | 41 | 42 | 43 | 44 | 4.0 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | MSBuild:Compile 53 | Designer 54 | 55 | 56 | MSBuild:Compile 57 | Designer 58 | 59 | 60 | App.xaml 61 | Code 62 | 63 | 64 | MainWindow.xaml 65 | Code 66 | 67 | 68 | 69 | 70 | Code 71 | 72 | 73 | True 74 | True 75 | Resources.resx 76 | 77 | 78 | True 79 | Settings.settings 80 | True 81 | 82 | 83 | ResXFileCodeGenerator 84 | Resources.Designer.cs 85 | 86 | 87 | SettingsSingleFileGenerator 88 | Settings.Designer.cs 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | {c7b29e5f-0b03-4578-abc2-702a7199f52a} 98 | XkPassword 99 | 100 | 101 | 102 | 109 | -------------------------------------------------------------------------------- /XkPassword.Demo/Properties/Resources.resx: -------------------------------------------------------------------------------- 1 | 2 | 3 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | text/microsoft-resx 107 | 108 | 109 | 2.0 110 | 111 | 112 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 113 | 114 | 115 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 116 | 117 | -------------------------------------------------------------------------------- /XkPassword.Demo/MainWindow.xaml.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Net.Mime; 3 | using System.Windows; 4 | using System.Windows.Input; 5 | using XkPassword.PublicExtensionMethods; 6 | 7 | namespace XkPassword.Demo 8 | { 9 | /// 10 | /// Interaction logic for MainWindow.xaml 11 | /// 12 | public partial class MainWindow : Window 13 | { 14 | private readonly XkPasswd _generator; 15 | 16 | public MainWindow() 17 | { 18 | this.InitializeComponent(); 19 | _generator = new XkPasswd(); 20 | } 21 | 22 | private void btnGenerate_Click(object sender, RoutedEventArgs e) 23 | { 24 | var replacements = new Dictionary(); 25 | if ((tbReplaceCharacters.Text.Length > 0) && (tbWithCharacters.Text.Length > 0)) 26 | { 27 | if (tbReplaceCharacters.Text.Length < tbWithCharacters.Text.Length) 28 | { 29 | for (int i = 0; i < tbReplaceCharacters.Text.Length; i++) 30 | { 31 | replacements.Add(tbReplaceCharacters.Text[i], tbWithCharacters.Text[i]); 32 | } 33 | } 34 | else 35 | { 36 | for (int i = 0; i < tbWithCharacters.Text.Length; i++) 37 | { 38 | replacements.Add(tbReplaceCharacters.Text[i], tbWithCharacters.Text[i]); 39 | } 40 | } 41 | } 42 | 43 | if (string.IsNullOrWhiteSpace(tbPadLength.Text)) 44 | { 45 | tbPadLength.Text = "0"; 46 | } 47 | 48 | this._generator.SeparatorCharacter = (string.IsNullOrEmpty(this.tbSeparator.Text) 49 | ? null 50 | : (char?)(this.tbSeparator.Text[0])); 51 | this._generator.WordCount = int.Parse(this.tbWordCount.Text); 52 | this._generator.MinWordLength = int.Parse(this.tbMinWordLength.Text); 53 | this._generator.MaxWordLength = int.Parse(this.tbMaxWordLength.Text); 54 | this._generator.PaddingType = (Padding)(this.cbPaddingType.SelectedIndex); 55 | this._generator.PaddingCharacter = (string.IsNullOrEmpty(this.tbPaddingChar.Text) 56 | ? null 57 | : (char?)this.tbPaddingChar.Text[0]); 58 | this._generator.PaddingCharactersBefore = int.Parse(this.tbPadCharsBefore.Text); 59 | this._generator.PaddingCharactersAfter = int.Parse(this.tbPadCharsAfter.Text); 60 | this._generator.PaddingDigitsBefore = int.Parse(this.tbPadBefore.Text); 61 | this._generator.PaddingDigitsAfter = int.Parse(this.tbPadAfter.Text); 62 | this._generator.PadToLength = int.Parse(this.tbPadLength.Text); 63 | this._generator.CaseTransform = (CaseTransformation)(this.cbCaseTransform.SelectedIndex); 64 | this._generator.CharacterSubstitutions = replacements; 65 | 66 | _generator.SymbolAlphabet.FromCharArray((string.IsNullOrEmpty(this.tbSymbolAlphabet.Text) 67 | ? null 68 | : this.tbSymbolAlphabet.Text.ToCharArray())); 69 | _generator.SeparatorAlphabet.FromCharArray((string.IsNullOrEmpty(this.tbSymbolAlphabet.Text) 70 | ? null 71 | : this.tbSymbolAlphabet.Text.ToCharArray())); 72 | this.tbPasswords.Text += _generator.Generate() + '\n'; 73 | this.tbPasswords.ScrollToEnd(); 74 | } 75 | 76 | private void tbMinWordLength_KeyUp(object sender, KeyEventArgs e) 77 | { 78 | int x; 79 | if (!int.TryParse(this.tbMinWordLength.Text, out x)) 80 | { 81 | this.tbMinWordLength.Text = "0"; 82 | } 83 | } 84 | 85 | private void tbMaxWordLength_KeyUp(object sender, KeyEventArgs e) 86 | { 87 | int x; 88 | if (!int.TryParse(this.tbMaxWordLength.Text, out x)) 89 | { 90 | this.tbMaxWordLength.Text = "0"; 91 | } 92 | } 93 | 94 | private void tbPadDigitsBefore_KeyUp(object sender, KeyEventArgs e) 95 | { 96 | int x; 97 | if (!int.TryParse(this.tbPadBefore.Text, out x)) 98 | { 99 | this.tbPadBefore.Text = "0"; 100 | } 101 | } 102 | 103 | private void tbPadDigitsAfter_KeyUp(object sender, KeyEventArgs e) 104 | { 105 | int x; 106 | if (!int.TryParse(this.tbPadAfter.Text, out x)) 107 | { 108 | this.tbPadAfter.Text = "0"; 109 | } 110 | } 111 | 112 | private void tbPadCharsBefore_KeyUp(object sender, KeyEventArgs e) 113 | { 114 | int x; 115 | if (!int.TryParse(this.tbPadCharsBefore.Text, out x)) 116 | { 117 | this.tbPadCharsBefore.Text = "0"; 118 | } 119 | } 120 | 121 | private void tbPadCharsAfter_KeyUp(object sender, KeyEventArgs e) 122 | { 123 | int x; 124 | if (!int.TryParse(this.tbPadCharsAfter.Text, out x)) 125 | { 126 | this.tbPadCharsAfter.Text = "0"; 127 | } 128 | } 129 | 130 | private void tbPadLength_KeyUp(object sender, KeyEventArgs e) 131 | { 132 | int x; 133 | if (!int.TryParse(this.tbPadLength.Text, out x)) 134 | { 135 | this.tbPadLength.Text = "0"; 136 | } 137 | } 138 | 139 | private void tbNumWords_KeyUp(object sender, KeyEventArgs e) 140 | { 141 | int x; 142 | if (!int.TryParse(this.tbWordCount.Text, out x)) 143 | { 144 | this.tbWordCount.Text = "4"; 145 | } 146 | } 147 | } 148 | } -------------------------------------------------------------------------------- /XkPassword.Demo/MainWindow.xaml: -------------------------------------------------------------------------------- 1 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 16 | 17 | 18 | 19 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | None 51 | Fixed 52 | Adaptive 53 | 54 | 55 | 56 | 57 | 58 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | None 90 | ALL UPPERCASE 91 | all lowercase 92 | Capitalize Words 93 | iNVERTED cASE 94 | AlTeRnAtInG CaSe 95 | rANdoMly CAPitaLiZE 96 | RANDOMLY capitalize entire WORD 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 109 | 110 | 111 | -------------------------------------------------------------------------------- /LICENSE.WordList: -------------------------------------------------------------------------------- 1 | The collective work is Copyright 2000-2014 by Kevin Atkinson as well 2 | as any of the copyrights mentioned below: 3 | 4 | Copyright 2000-2014 by Kevin Atkinson 5 | 6 | Permission to use, copy, modify, distribute and sell these word 7 | lists, the associated scripts, the output created from the scripts, 8 | and its documentation for any purpose is hereby granted without fee, 9 | provided that the above copyright notice appears in all copies and 10 | that both that copyright notice and this permission notice appear in 11 | supporting documentation. Kevin Atkinson makes no representations 12 | about the suitability of this array for any purpose. It is provided 13 | "as is" without express or implied warranty. 14 | 15 | Alan Beale also deserves special credit as he has, 16 | in addition to providing the 12Dicts package and being a major 17 | contributor to the ENABLE word list, given me an incredible amount of 18 | feedback and created a number of special lists (those found in the 19 | Supplement) in order to help improve the overall quality of SCOWL. 20 | 21 | The 10 level includes the 1000 most common English words (according to 22 | the Moby (TM) Words II [MWords] package), a subset of the 1000 most 23 | common words on the Internet (again, according to Moby Words II), and 24 | frequently class 16 from Brian Kelk's "UK English Wordlist 25 | with Frequency Classification". 26 | 27 | The MWords package was explicitly placed in the public domain: 28 | 29 | The Moby lexicon project is complete and has 30 | been place into the public domain. Use, sell, 31 | rework, excerpt and use in any way on any platform. 32 | 33 | Placing this material on internal or public servers is 34 | also encouraged. The compiler is not aware of any 35 | export restrictions so freely distribute world-wide. 36 | 37 | You can verify the public domain status by contacting 38 | 39 | Grady Ward 40 | 3449 Martha Ct. 41 | Arcata, CA 95521-4884 42 | 43 | grady@netcom.com 44 | grady@northcoast.com 45 | 46 | The "UK English Wordlist With Frequency Classification" is also in the 47 | Public Domain: 48 | 49 | Date: Sat, 08 Jul 2000 20:27:21 +0100 50 | From: Brian Kelk 51 | 52 | > I was wondering what the copyright status of your "UK English 53 | > Wordlist With Frequency Classification" word list as it seems to 54 | > be lacking any copyright notice. 55 | 56 | There were many many sources in total, but any text marked 57 | "copyright" was avoided. Locally-written documentation was one 58 | source. An earlier version of the list resided in a filespace called 59 | PUBLIC on the University mainframe, because it was considered public 60 | domain. 61 | 62 | Date: Tue, 11 Jul 2000 19:31:34 +0100 63 | 64 | > So are you saying your word list is also in the public domain? 65 | 66 | That is the intention. 67 | 68 | The 20 level includes frequency classes 7-15 from Brian's word list. 69 | 70 | The 35 level includes frequency classes 2-6 and words appearing in at 71 | least 11 of 12 dictionaries as indicated in the 12Dicts package. All 72 | words from the 12Dicts package have had likely inflections added via 73 | my inflection database. 74 | 75 | The 12Dicts package and Supplement is in the Public Domain. 76 | 77 | The WordNet database, which was used in the creation of the 78 | Inflections database, is under the following copyright: 79 | 80 | This software and database is being provided to you, the LICENSEE, 81 | by Princeton University under the following license. By obtaining, 82 | using and/or copying this software and database, you agree that you 83 | have read, understood, and will comply with these terms and 84 | conditions.: 85 | 86 | Permission to use, copy, modify and distribute this software and 87 | database and its documentation for any purpose and without fee or 88 | royalty is hereby granted, provided that you agree to comply with 89 | the following copyright notice and statements, including the 90 | disclaimer, and that the same appear on ALL copies of the software, 91 | database and documentation, including modifications that you make 92 | for internal use or for distribution. 93 | 94 | WordNet 1.6 Copyright 1997 by Princeton University. All rights 95 | reserved. 96 | 97 | THIS SOFTWARE AND DATABASE IS PROVIDED "AS IS" AND PRINCETON 98 | UNIVERSITY MAKES NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR 99 | IMPLIED. BY WAY OF EXAMPLE, BUT NOT LIMITATION, PRINCETON 100 | UNIVERSITY MAKES NO REPRESENTATIONS OR WARRANTIES OF MERCHANT- 101 | ABILITY OR FITNESS FOR ANY PARTICULAR PURPOSE OR THAT THE USE OF THE 102 | LICENSED SOFTWARE, DATABASE OR DOCUMENTATION WILL NOT INFRINGE ANY 103 | THIRD PARTY PATENTS, COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS. 104 | 105 | The name of Princeton University or Princeton may not be used in 106 | advertising or publicity pertaining to distribution of the software 107 | and/or database. Title to copyright in this software, database and 108 | any associated documentation shall at all times remain with 109 | Princeton University and LICENSEE agrees to preserve same. 110 | 111 | The 40 level includes words from Alan's 3esl list found in version 4.0 112 | of his 12dicts package. Like his other stuff the 3esl list is also in the 113 | public domain. 114 | 115 | The 50 level includes Brian's frequency class 1, words appearing 116 | in at least 5 of 12 of the dictionaries as indicated in the 12Dicts 117 | package, and uppercase words in at least 4 of the previous 12 118 | dictionaries. A decent number of proper names is also included: The 119 | top 1000 male, female, and Last names from the 1990 Census report; a 120 | list of names sent to me by Alan Beale; and a few names that I added 121 | myself. Finally a small list of abbreviations not commonly found in 122 | other word lists is included. 123 | 124 | The name files form the Census report is a government document which I 125 | don't think can be copyrighted. 126 | 127 | The file special-jargon.50 uses common.lst and word.lst from the 128 | "Unofficial Jargon File Word Lists" which is derived from "The Jargon 129 | File". All of which is in the Public Domain. This file also contain 130 | a few extra UNIX terms which are found in the file "unix-terms" in the 131 | special/ directory. 132 | 133 | The 55 level includes words from Alan's 2of4brif list found in version 134 | 4.0 of his 12dicts package. Like his other stuff the 2of4brif is also 135 | in the public domain. 136 | 137 | The 60 level includes all words appearing in at least 2 of the 12 138 | dictionaries as indicated by the 12Dicts package. 139 | 140 | The 70 level includes Brian's frequency class 0 and the 74,550 common 141 | dictionary words from the MWords package. The common dictionary words, 142 | like those from the 12Dicts package, have had all likely inflections 143 | added. The 70 level also included the 5desk list from version 4.0 of 144 | the 12Dics package which is in the public domain. 145 | 146 | The 80 level includes the ENABLE word list, all the lists in the 147 | ENABLE supplement package (except for ABLE), the "UK Advanced Cryptics 148 | Dictionary" (UKACD), the list of signature words from the YAWL package, 149 | and the 10,196 places list from the MWords package. 150 | 151 | The ENABLE package, mainted by M\Cooper , 152 | is in the Public Domain: 153 | 154 | The ENABLE master word list, WORD.LST, is herewith formally released 155 | into the Public Domain. Anyone is free to use it or distribute it in 156 | any manner they see fit. No fee or registration is required for its 157 | use nor are "contributions" solicited (if you feel you absolutely 158 | must contribute something for your own peace of mind, the authors of 159 | the ENABLE list ask that you make a donation on their behalf to your 160 | favorite charity). This word list is our gift to the Scrabble 161 | community, as an alternate to "official" word lists. Game designers 162 | may feel free to incorporate the WORD.LST into their games. Please 163 | mention the source and credit us as originators of the list. Note 164 | that if you, as a game designer, use the WORD.LST in your product, 165 | you may still copyright and protect your product, but you may *not* 166 | legally copyright or in any way restrict redistribution of the 167 | WORD.LST portion of your product. This *may* under law restrict your 168 | rights to restrict your users' rights, but that is only fair. 169 | 170 | UKACD, by J Ross Beresford , is under the 171 | following copyright: 172 | 173 | Copyright (c) J Ross Beresford 1993-1999. All Rights Reserved. 174 | 175 | The following restriction is placed on the use of this publication: 176 | if The UK Advanced Cryptics Dictionary is used in a software package 177 | or redistributed in any form, the copyright notice must be 178 | prominently displayed and the text of this document must be included 179 | verbatim. 180 | 181 | There are no other restrictions: I would like to see the list 182 | distributed as widely as possible. 183 | 184 | The 95 level includes the 354,984 single words, 256,772 compound 185 | words, 4,946 female names and the 3,897 male names, and 21,986 names 186 | from the MWords package, ABLE.LST from the ENABLE Supplement, and some 187 | additional words found in my part-of-speech database that were not 188 | found anywhere else. 189 | 190 | Accent information was taken from UKACD. 191 | 192 | My VARCON package was used to create the American, British, and 193 | Canadian word list. 194 | 195 | Since the original word lists used in the VARCON package came 196 | from the Ispell distribution they are under the Ispell copyright: 197 | 198 | Copyright 1993, Geoff Kuenning, Granada Hills, CA 199 | All rights reserved. 200 | 201 | Redistribution and use in source and binary forms, with or without 202 | modification, are permitted provided that the following conditions 203 | are met: 204 | 205 | 1. Redistributions of source code must retain the above copyright 206 | notice, this list of conditions and the following disclaimer. 207 | 2. Redistributions in binary form must reproduce the above copyright 208 | notice, this list of conditions and the following disclaimer in the 209 | documentation and/or other materials provided with the distribution. 210 | 3. All modifications to the source code must be clearly marked as 211 | such. Binary redistributions based on modified source code 212 | must be clearly marked as modified versions in the documentation 213 | and/or other materials provided with the distribution. 214 | (clause 4 removed with permission from Geoff Kuenning) 215 | 5. The name of Geoff Kuenning may not be used to endorse or promote 216 | products derived from this software without specific prior 217 | written permission. 218 | 219 | THIS SOFTWARE IS PROVIDED BY GEOFF KUENNING AND CONTRIBUTORS ``AS 220 | IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 221 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 222 | FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GEOFF 223 | KUENNING OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 224 | INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 225 | BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 226 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 227 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 228 | LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 229 | ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 230 | POSSIBILITY OF SUCH DAMAGE. -------------------------------------------------------------------------------- /XkPassword/XkPasswd.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Globalization; 4 | using System.IO; 5 | using System.IO.Compression; 6 | using System.Linq; 7 | using System.Reflection; 8 | using System.Text; 9 | #if DEBUG 10 | using System.Diagnostics; 11 | 12 | #endif 13 | 14 | namespace XkPassword 15 | { 16 | /// 17 | /// A password generator inspired by a well-known web comic. 18 | /// 19 | public class XkPasswd 20 | { 21 | private int _maxWordLength; 22 | 23 | private int _minWordLength; 24 | 25 | private int _padCharsAfter; 26 | 27 | private int _padCharsBefore; 28 | 29 | private int _padDigitsAfter; 30 | 31 | private int _padDigitsBefore; 32 | 33 | private int _wordCount; 34 | 35 | /// 36 | /// Initializes a new instance of the class. 37 | /// 38 | public XkPasswd() 39 | { 40 | this.WordListPath = "?en.gz"; 41 | this.SymbolAlphabet = new HashSet 42 | { 43 | '!', 44 | '@', 45 | '$', 46 | '%', 47 | '^', 48 | '&', 49 | '*', 50 | '-', 51 | '_', 52 | '+', 53 | '=', 54 | ':', 55 | '|', 56 | '~', 57 | '?' 58 | }; 59 | this.SeparatorAlphabet = null; 60 | this.MinWordLength = 4; 61 | this.MaxWordLength = 8; 62 | this.WordCount = 4; 63 | this.SeparatorCharacter = null; 64 | this.PaddingDigitsAfter = 2; 65 | this.PaddingDigitsBefore = 2; 66 | this.PaddingType = Padding.Fixed; 67 | this.PaddingCharacter = null; 68 | this.PaddingCharactersAfter = 2; 69 | this.PaddingCharactersBefore = 2; 70 | this.PadToLength = 0; 71 | this.CaseTransform = CaseTransformation.Capitalize; 72 | this.CharacterSubstitutions = new Dictionary(); 73 | this.RandomSource = new DefaultRandomSource(); 74 | } 75 | 76 | /// 77 | /// Gets or sets the path to the word list used by this instance of the password generator. 78 | /// 79 | /// 80 | /// A string representing the path to the word list file. If the path starts with "?", it is 81 | /// assumed to refer to a gzipped embedded resource. 82 | /// 83 | public string WordListPath { get; set; } 84 | 85 | /// 86 | /// Gets or sets the set of symbols that may appear in passwords generated by this instance of the password generator. 87 | /// 88 | /// 89 | /// A of s representing the set of symbols that may appear 90 | /// in generated passwords. 91 | /// 92 | public HashSet SymbolAlphabet { get; set; } 93 | 94 | /// 95 | /// Gets or sets the set of symbols that may appear in as separators in passwords generated by this instance of the 96 | /// password generator. 97 | /// If null or empty, the value of will be used. 98 | /// 99 | /// 100 | /// A of s representing the set of symbols that may appear as separators 101 | /// in generated passwords, or null or an empty of to indicate that 102 | /// should be used. 103 | /// 104 | public HashSet SeparatorAlphabet { get; set; } 105 | 106 | /// 107 | /// Gets or sets the minimum length of words that may appear in generated passwords. 108 | /// 109 | /// 110 | /// An integer. 111 | /// 112 | /// Thrown when attempting to set value to less than or equal to 0. 113 | public int MinWordLength 114 | { 115 | get { return (this._minWordLength < this._maxWordLength) ? this._minWordLength : this._maxWordLength; } 116 | set 117 | { 118 | if (value <= 0) 119 | { 120 | throw new ArgumentOutOfRangeException("value", value, "Minimum word length cannot be less than 1"); 121 | } 122 | 123 | this._minWordLength = value; 124 | } 125 | } 126 | 127 | /// 128 | /// Gets or sets the maximum length of words that may appear in generated passwords. 129 | /// 130 | /// 131 | /// An integer. 132 | /// 133 | /// Thrown when attempting to set value to less than or equal to 0. 134 | public int MaxWordLength 135 | { 136 | get { return (this._maxWordLength > this._minWordLength) ? this._maxWordLength : this._minWordLength; } 137 | set 138 | { 139 | if (value <= 0) 140 | { 141 | throw new ArgumentOutOfRangeException("value", value, "Maximum word length cannot be less than 1"); 142 | } 143 | 144 | this._maxWordLength = value; 145 | } 146 | } 147 | 148 | /// 149 | /// Gets or sets the number of words that will appear in generated passwords. 150 | /// 151 | /// 152 | /// A positive integer greater than or equal to 1. 153 | /// 154 | /// Thrown when attempting to set value to less than or equal to 0. 155 | public int WordCount 156 | { 157 | get { return this._wordCount; } 158 | set 159 | { 160 | if (value <= 0) 161 | { 162 | throw new ArgumentOutOfRangeException("value", value, "Word count cannot be less than 1"); 163 | } 164 | this._wordCount = value; 165 | } 166 | } 167 | 168 | /// 169 | /// Gets or sets the specific character to use as a separator in generated passwords. 170 | /// If ASCII NUL ('\0'), no separator will be used. 171 | /// If null, a random separator will be chosen from if set, or 172 | /// . 173 | /// 174 | /// 175 | /// A of . ASCII NUL ('\0') means no separator; a null value means 176 | /// choose randomly 177 | /// from if it is set, or otherwise. 178 | /// 179 | public char? SeparatorCharacter { get; set; } 180 | 181 | /// 182 | /// Gets or sets the number of padding digits that will appear before the words in a generated password. 183 | /// 184 | /// 185 | /// A positive, nonzero integer. 186 | /// 187 | /// Thrown when attempting to set value to less than 0. 188 | public int PaddingDigitsBefore 189 | { 190 | get { return this._padDigitsBefore; } 191 | set 192 | { 193 | if (value < 0) 194 | { 195 | throw new ArgumentOutOfRangeException("value", value, "Cannot have negative number of padding digits"); 196 | } 197 | 198 | this._padDigitsBefore = value; 199 | } 200 | } 201 | 202 | /// 203 | /// Gets or sets the number of padding digits that will appear after the words in a generated password. 204 | /// 205 | /// 206 | /// The padding digits after. 207 | /// 208 | /// Thrown when attempting to set value to less than 0. 209 | public int PaddingDigitsAfter 210 | { 211 | get { return this._padDigitsAfter; } 212 | set 213 | { 214 | if (value < 0) 215 | { 216 | throw new ArgumentOutOfRangeException("value", value, "Cannot have negative number of padding digits"); 217 | } 218 | 219 | this._padDigitsAfter = value; 220 | } 221 | } 222 | 223 | /// 224 | /// Gets or sets the type of padding to use in generated passwords. 225 | /// 226 | /// 227 | /// A member of the enumeration. 228 | /// 229 | public Padding PaddingType { get; set; } 230 | 231 | /// 232 | /// Gets or sets the character that will be used as padding in generated passwords. 233 | /// If ASCII NUL ('\0') or null, a random padding character will be chosen from . 234 | /// 235 | /// 236 | /// A of . ASCII NUL ('\0') or null value means choose randomly from 237 | /// . 238 | /// 239 | public char? PaddingCharacter { get; set; } 240 | 241 | /// 242 | /// Gets or sets the number of padding characters that will appear before the initial padding digits in generated 243 | /// passwords. 244 | /// 245 | /// 246 | /// An integer. 247 | /// 248 | /// Thrown when attempting to set value to less than 0. 249 | public int PaddingCharactersBefore 250 | { 251 | get { return this._padCharsBefore; } 252 | set 253 | { 254 | if (value < 0) 255 | { 256 | throw new ArgumentOutOfRangeException("value", value, "Cannot have negative number of padding characters"); 257 | } 258 | 259 | this._padCharsBefore = value; 260 | } 261 | } 262 | 263 | /// 264 | /// Gets or sets the number of padding characters that will appear after the terminal padding digits in generated 265 | /// passwords. 266 | /// 267 | /// 268 | /// An integer greater than or equal to 0. 269 | /// 270 | /// Thrown when attempting to set value to less than 0. 271 | public int PaddingCharactersAfter 272 | { 273 | get { return this._padCharsAfter; } 274 | set 275 | { 276 | if (value < 0) 277 | { 278 | throw new ArgumentOutOfRangeException("value", value, "Cannot have negative number of padding characters"); 279 | } 280 | 281 | _padCharsAfter = value; 282 | } 283 | } 284 | 285 | /// 286 | /// Gets or sets the length to which to pad generated passwords. Has no effect if is not 287 | /// . 288 | /// 289 | /// 290 | /// A positive, non-zero integer. 291 | /// 292 | public int PadToLength { get; set; } 293 | 294 | /// 295 | /// Gets or sets the case transformation that will be applied to words appearing in generated passwords. 296 | /// 297 | /// 298 | /// A member of the enumeration. 299 | /// 300 | public CaseTransformation CaseTransform { get; set; } 301 | 302 | /// 303 | /// Gets or sets the dictionary of character substitutions to apply to words appearing in generated passwords. 304 | /// 305 | /// 306 | /// A of , with the keys being the characters to 307 | /// replace, and the values being 308 | /// their replacements. 309 | /// 310 | public Dictionary CharacterSubstitutions { get; set; } 311 | 312 | /// 313 | /// Gets or sets an instance of a class that will be used to generate random integers. Any class used for this purpose 314 | /// must implement . 315 | /// 316 | /// 317 | /// A class implementing . 318 | /// 319 | public IRandomSource RandomSource { get; set; } 320 | 321 | /// 322 | /// Randomly selects words between characters and characters 323 | /// in length, inclusive, 324 | /// from the word list. 325 | /// 326 | /// A for the word list. 327 | /// A number of random words meeting the word length limitations specified by the configuration. 328 | private IEnumerable GetRandomWords(StreamReader reader) 329 | { 330 | #if DEBUG 331 | Debug.WriteLine(string.Format("Processing wordlist to get words between {0} and {1} chars", 332 | this.MinWordLength, 333 | this.MaxWordLength)); 334 | Stopwatch sw = Stopwatch.StartNew(); 335 | #endif //DEBUG 336 | 337 | IEnumerable suitableWords = 338 | reader.ReadAllLines() 339 | .Where(w => (w.Length >= this.MinWordLength) && (w.Length <= this.MaxWordLength)) 340 | .ToList(); 341 | 342 | #if DEBUG 343 | sw.Stop(); 344 | Debug.WriteLine(string.Format("Done in {0}", sw.Elapsed)); 345 | #endif //DEBUG 346 | 347 | for (int i = 0; i < this.WordCount; i++) 348 | { 349 | yield return suitableWords.ElementAt(this.RandomSource.Next(0, suitableWords.Count())); 350 | } 351 | } 352 | 353 | /// 354 | /// Transforms the case of a given of of words 355 | /// according to the configured on the generator. 356 | /// 357 | /// The words whose cases are to be transformed. 358 | /// An of of words with their cases transformed. 359 | private IEnumerable TransformCase(IEnumerable words) 360 | { 361 | switch (this.CaseTransform) 362 | { 363 | case CaseTransformation.None: 364 | return words; 365 | case CaseTransformation.UpperCase: 366 | return words.Select(w => w.ToUpperInvariant()); 367 | case CaseTransformation.LowerCase: 368 | return words.Select(w => w.ToLowerInvariant()); 369 | case CaseTransformation.Capitalize: 370 | return words.Select(w => w.Substring(0, 1).ToUpperInvariant() + w.Substring(1)); 371 | case CaseTransformation.Invert: 372 | return words.Select(w => w.Substring(0, 1).ToLowerInvariant() + w.Substring(1).ToUpperInvariant()); 373 | case CaseTransformation.Alternate: 374 | return words.Select(w => 375 | { 376 | char[] wChars = w.ToLowerInvariant().ToCharArray(); 377 | bool startCaps = this.RandomSource.CoinFlip(); 378 | for (int i = 0; i < wChars.Length; i++) 379 | { 380 | if (startCaps) 381 | { 382 | if ((i % 2) == 0) 383 | { 384 | wChars[i] -= ' '; 385 | } 386 | } 387 | else 388 | { 389 | if ((i % 2) != 0) 390 | { 391 | wChars[i] -= ' '; 392 | } 393 | } 394 | } 395 | return new string(wChars); 396 | } 397 | ); 398 | case CaseTransformation.Random: 399 | return 400 | words.Select( 401 | w => 402 | new string( 403 | w.ToUpperInvariant().Select(c => (char)(c + (this.RandomSource.CoinFlip() ? ' ' : '\0'))) 404 | .ToArray())); 405 | case CaseTransformation.RandomWord: 406 | return words.Select(w => this.RandomSource.CoinFlip() ? w.ToUpperInvariant() : w.ToLowerInvariant()); 407 | default: 408 | return words; 409 | } 410 | } 411 | 412 | /// 413 | /// Gets random digits between 0 and 9 inclusive. 414 | /// 415 | /// The number of random digits to return. 416 | /// The number of random digits specified by . 417 | private IEnumerable GetRandomDigits(int num) 418 | { 419 | for (int i = 0; i < num; i++) 420 | { 421 | yield return (char)(this.RandomSource.Next(48, 58)); 422 | } 423 | } 424 | 425 | /// 426 | /// Gets the separator character as a string. 427 | /// 428 | /// 429 | /// The separator character to be used in passwords, as a . If 430 | /// is set, 431 | /// that value is used as follows: no separator (the empty string) if is ASCII NUL 432 | /// ('\0'), 433 | /// otherwise the character in is returned. If that is not set and 434 | /// 435 | /// is set, a character is randomly selected from that. If is not set, a 436 | /// character is randomly 437 | /// selected from . 438 | /// 439 | private string GetSeparatorCharacter() 440 | { 441 | return this.SeparatorCharacter.HasValue 442 | ? (this.SeparatorCharacter.Value == '\0' 443 | ? "" 444 | : this.SeparatorCharacter.Value.ToString(CultureInfo.InvariantCulture)) 445 | : (this.SeparatorAlphabet == null 446 | ? this.SymbolAlphabet.ElementAt(this.RandomSource.Next(0, this.SymbolAlphabet.Count)) 447 | .ToString(CultureInfo.InvariantCulture) 448 | : this.SeparatorAlphabet.ElementAt(this.RandomSource.Next(0, this.SeparatorAlphabet.Count)) 449 | .ToString(CultureInfo.InvariantCulture)); 450 | } 451 | 452 | /// 453 | /// Gets a random symbol from the symbol alphabet. 454 | /// 455 | /// A random symbol from , as a . 456 | private char GetRandomSymbol() 457 | { 458 | return 459 | this.SymbolAlphabet.ElementAt(this.RandomSource.Next(0, this.SymbolAlphabet.Count)); 460 | } 461 | 462 | /// 463 | /// Performs character substitutions on an of according to the 464 | /// substitutions provided in . 465 | /// 466 | /// The words to perform substitutions on. 467 | /// An of of words with characters substituted. 468 | private IEnumerable SubstituteCharacters(IEnumerable words) 469 | { 470 | if (this.CharacterSubstitutions == null) 471 | { 472 | foreach (string w in words) 473 | { 474 | yield return w; 475 | } 476 | } 477 | else 478 | { 479 | foreach (string word in words) 480 | { 481 | string subWord = word; 482 | foreach (var sub in this.CharacterSubstitutions) 483 | { 484 | subWord = word.Replace(sub.Key, sub.Value); 485 | } 486 | yield return subWord; 487 | } 488 | } 489 | } 490 | 491 | /// 492 | /// Generates a password according to the rules configured in this instance. 493 | /// 494 | /// A password matching the configuration options of this instance. 495 | public string Generate() 496 | { 497 | bool hadPaddingChar = this.PaddingCharacter.HasValue && (this.PaddingCharacter.Value != '\0'); 498 | var passwordBuilder = new StringBuilder(); 499 | 500 | using (var reader = new StreamReader( 501 | this.WordListPath.StartsWith("?") 502 | ? (Stream)new GZipStream(Assembly.GetExecutingAssembly() 503 | .GetManifestResourceStream("XkPassword." 504 | + this.WordListPath.Substring(1)), 505 | CompressionMode.Decompress) 506 | : File.Open(this.WordListPath, FileMode.Open, FileAccess.Read, FileShare.Read))) 507 | { 508 | string separator = this.GetSeparatorCharacter(); 509 | IEnumerable randomWords = this.SubstituteCharacters( 510 | (this.CaseTransform 511 | == CaseTransformation.None 512 | ? this.GetRandomWords(reader) 513 | : this.TransformCase(this 514 | .GetRandomWords 515 | (reader)))); 516 | 517 | IEnumerable startPaddingDigits = (this.PaddingDigitsBefore > 0) 518 | ? GetRandomDigits(this.PaddingDigitsBefore) 519 | : new List(), 520 | endPaddingDigits = (this.PaddingDigitsAfter > 0) 521 | ? GetRandomDigits(this.PaddingDigitsAfter) 522 | : new List(); 523 | 524 | passwordBuilder.Append(startPaddingDigits.ToArray()); 525 | if (this.PaddingDigitsBefore > 0) 526 | { 527 | passwordBuilder.Append(separator); 528 | } 529 | passwordBuilder.Append(string.Join(separator, randomWords.ToArray())); 530 | if (this.PaddingDigitsAfter > 0) 531 | { 532 | passwordBuilder.Append(separator); 533 | } 534 | passwordBuilder.Append(endPaddingDigits.ToArray()); 535 | 536 | switch (this.PaddingType) 537 | { 538 | case Padding.None: 539 | break; 540 | case Padding.Fixed: 541 | if (!hadPaddingChar) 542 | { 543 | this.PaddingCharacter = GetRandomSymbol(); 544 | } 545 | 546 | if (this.PaddingCharactersBefore > 0) 547 | { 548 | passwordBuilder.Insert(0, 549 | this.PaddingCharacter.Value.ToString(CultureInfo.InvariantCulture) 550 | + this.SeparatorCharacter, 551 | this.PaddingCharactersBefore); 552 | } 553 | 554 | if (this.PaddingCharactersAfter > 0) 555 | { 556 | passwordBuilder.Append(this.PaddingCharacter.Value, this.PaddingCharactersAfter); 557 | } 558 | 559 | if (!hadPaddingChar) 560 | { 561 | this.PaddingCharacter = null; 562 | } 563 | break; 564 | case Padding.Adaptive: 565 | if (this.PadToLength <= 0) 566 | { 567 | break; 568 | } 569 | 570 | if (!hadPaddingChar) 571 | { 572 | this.PaddingCharacter = GetRandomSymbol(); 573 | } 574 | 575 | if (passwordBuilder.Length < this.PadToLength) 576 | { 577 | passwordBuilder.Append(this.PaddingCharacter.Value, 578 | this.PadToLength - passwordBuilder.Length); 579 | } 580 | else if (passwordBuilder.Length > this.PadToLength) 581 | { 582 | passwordBuilder.Truncate(this.PadToLength); 583 | } 584 | break; 585 | } 586 | } 587 | 588 | return passwordBuilder.ToString(); 589 | } 590 | 591 | /// 592 | /// Generates the specified number of passwords. 593 | /// 594 | /// The number of passwords to generate. 595 | /// An of of passwords. 596 | public IEnumerable Generate(int numPasswords) 597 | { 598 | for (int i = 0; i < numPasswords; i++) 599 | { 600 | yield return this.Generate(); 601 | } 602 | } 603 | } 604 | } --------------------------------------------------------------------------------