History

GSF.Core: 1) Fixed an issue with the cryptographically strong random number generator where there was a 1 in 4 billion chance it would generate the maximum number in the specified range of numbers. 2) Modified CollectionExtensions.Scramble() overloads to allow scrambling of arrays. 3) Added the PasswordGenerator class to allow customized random password generation.

GSF.Security: Updated SecurityProviderUtility.GeneratePassword to use the PasswordGenerator class. GSF.InstallerActions: Added a custom action to generate a random password.

StephenCWills committed 11 years ago

Commit ebbecae1 parent cf7845b8 files · +379 −80Browse files

Unified · Split

8 files
  1. Source/Libraries/GSF.Core/Collections/CollectionExtensions.cs +3 −3
  2. Source/Libraries/GSF.Core/GSF.Core.csproj +2 −0
  3. Source/Libraries/GSF.Core/Security/Cryptography/CharacterGroup.cs +115 −0
  4. Source/Libraries/GSF.Core/Security/Cryptography/PasswordGenerator.cs +195 −0
  5. Source/Libraries/GSF.Core/Security/Cryptography/Random.cs +38 −38
  6. Source/Libraries/GSF.InstallerActions/CustomActions.cs +23 −0
  7. Source/Libraries/GSF.InstallerActions/GSF.InstallerActions.csproj +1 −0
  8. Source/Libraries/GSF.Security/SecurityProviderUtility.cs +2 −39
Source/Libraries/GSF.Core/Collections/CollectionExtensions.cs+3−3
@@ -790,7 +790,7 @@ namespace GSF.Collections · 789 unmodified lines
790 /// <remarks>This function uses a cryptographically strong random number generator to perform the scramble.</remarks>790 /// <remarks>This function uses a cryptographically strong random number generator to perform the scramble.</remarks>
791 public static void Scramble<TSource>(this IList<TSource> source)791 public static void Scramble<TSource>(this IList<TSource> source)
792 {792 {
793 if (source.IsReadOnly)793 if (source.IsReadOnly && !(source is TSource[]))
794 throw new ArgumentException("Cannot modify items in a read only list");794 throw new ArgumentException("Cannot modify items in a read only list");
795 795
796 int x, y;796 int x, y;
@@ -821,7 +821,7 @@ namespace GSF.Collections · 24 unmodified lines
821 /// <remarks>This function uses the <see cref="System.Random"/> generator to perform the scramble using a sequence that is repeatable.</remarks>821 /// <remarks>This function uses the <see cref="System.Random"/> generator to perform the scramble using a sequence that is repeatable.</remarks>
822 public static void Scramble<TSource>(this IList<TSource> source, int seed)822 public static void Scramble<TSource>(this IList<TSource> source, int seed)
823 {823 {
824 if (source.IsReadOnly)824 if (source.IsReadOnly && !(source is TSource[]))
825 throw new ArgumentException("Cannot modify items in a read only list");825 throw new ArgumentException("Cannot modify items in a read only list");
826 826
827 System.Random random = new System.Random(seed);827 System.Random random = new System.Random(seed);
@@ -852,7 +852,7 @@ namespace GSF.Collections · 24 unmodified lines
852 /// <remarks>This function uses the <see cref="System.Random"/> generator to perform the unscramble using a sequence that is repeatable.</remarks>852 /// <remarks>This function uses the <see cref="System.Random"/> generator to perform the unscramble using a sequence that is repeatable.</remarks>
853 public static void Unscramble<TSource>(this IList<TSource> source, int seed)853 public static void Unscramble<TSource>(this IList<TSource> source, int seed)
854 {854 {
855 if (source.IsReadOnly)855 if (source.IsReadOnly && !(source is TSource[]))
856 throw new ArgumentException("Cannot modify items in a read only list");856 throw new ArgumentException("Cannot modify items in a read only list");
857 857
858 System.Random random = new System.Random(seed);858 System.Random random = new System.Random(seed);
Source/Libraries/GSF.Core/GSF.Core.csproj+2−0
@@ -361,7 +361,9 @@ · 360 unmodified lines
361 <Compile Include="ReusableObjectPool.cs" />361 <Compile Include="ReusableObjectPool.cs" />
362 <Compile Include="Scheduling\NamespaceDoc.cs" />362 <Compile Include="Scheduling\NamespaceDoc.cs" />
363 <Compile Include="Searching\AsyncSearcher.cs" />363 <Compile Include="Searching\AsyncSearcher.cs" />
364 <Compile Include="Security\Cryptography\CharacterGroup.cs" />
364 <Compile Include="Security\Cryptography\NamespaceDoc.cs" />365 <Compile Include="Security\Cryptography\NamespaceDoc.cs" />
366 <Compile Include="Security\Cryptography\PasswordGenerator.cs" />
365 <Compile Include="Security\Cryptography\Random.cs" />367 <Compile Include="Security\Cryptography\Random.cs" />
366 <Compile Include="Reflection\AssemblyExtensions.cs" />368 <Compile Include="Reflection\AssemblyExtensions.cs" />
367 <Compile Include="Reflection\AssemblyInfo.cs" />369 <Compile Include="Reflection\AssemblyInfo.cs" />
Source/Libraries/GSF.Core/Security/Cryptography/CharacterGroup.cs+115−0
@@ -0,0 +1,115 @@
1//******************************************************************************************************
2// CharacterGroup.cs - Gbtc
3//
4// Copyright © 2015, Grid Protection Alliance. All Rights Reserved.
5//
6// Licensed to the Grid Protection Alliance (GPA) under one or more contributor license agreements. See
7// the NOTICE file distributed with this work for additional information regarding copyright ownership.
8// The GPA licenses this file to you under the MIT License (MIT), the "License"; you may
9// not use this file except in compliance with the License. You may obtain a copy of the License at:
10//
11// http://opensource.org/licenses/MIT
12//
13// Unless agreed to in writing, the subject software distributed under the License is distributed on an
14// "AS-IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. Refer to the
15// License for the specific language governing permissions and limitations.
16//
17// Code Modification History:
18// ----------------------------------------------------------------------------------------------------
19// 10/27/2015 - Stephen C. Wills
20// Generated original version of source code.
21//
22//******************************************************************************************************
23
24using System;
25
26namespace GSF.Security.Cryptography
27{
28 /// <summary>
29 /// Defines a group of characters that can
30 /// appear in an automatically generated password.
31 /// </summary>
32 public class CharacterGroup
33 {
34 #region [ Members ]
35
36 // Fields
37 private string m_characters;
38 private int m_minOccurrence;
39
40 #endregion
41
42 #region [ Constructors ]
43
44 /// <summary>
45 /// Creates a new instance of the <see cref="CharacterGroup"/> class.
46 /// </summary>
47 public CharacterGroup()
48 : this(" ")
49 {
50 }
51
52 /// <summary>
53 /// Creates a new instance of the <see cref="CharacterGroup"/> class.
54 /// </summary>
55 /// <param name="characters">String representing the characters in the character group.</param>
56 public CharacterGroup(string characters)
57 : this(characters, 0)
58 {
59 }
60
61 /// <summary>
62 /// Creates a new instance of the <see cref="CharacterGroup"/> class.
63 /// </summary>
64 /// <param name="characters">String representing the characters in the character group.</param>
65 /// <param name="minOccurrence">The minimum number of occurrences of this character group in the password.</param>
66 public CharacterGroup(string characters, int minOccurrence)
67 {
68 Characters = characters;
69 MinOccurrence = minOccurrence;
70 }
71
72 #endregion
73
74 #region [ Properties ]
75
76 /// <summary>
77 /// The collection of characters in the character group.
78 /// </summary>
79 public string Characters
80 {
81 get
82 {
83 return m_characters;
84 }
85 set
86 {
87 if (string.IsNullOrEmpty(value))
88 throw new ArgumentException("Character group must have at least one character.", nameof(value));
89
90 m_characters = value;
91 }
92 }
93
94 /// <summary>
95 /// The minimum number of occurrences of any of the
96 /// characters in this character group in the password.
97 /// </summary>
98 public int MinOccurrence
99 {
100 get
101 {
102 return m_minOccurrence;
103 }
104 set
105 {
106 if (value < 0)
107 throw new ArgumentOutOfRangeException(nameof(value));
108
109 m_minOccurrence = value;
110 }
111 }
112
113 #endregion
114 }
115}
Source/Libraries/GSF.Core/Security/Cryptography/PasswordGenerator.cs+195−0
@@ -0,0 +1,195 @@
1//******************************************************************************************************
2// PasswordGenerator.cs - Gbtc
3//
4// Copyright © 2015, Grid Protection Alliance. All Rights Reserved.
5//
6// Licensed to the Grid Protection Alliance (GPA) under one or more contributor license agreements. See
7// the NOTICE file distributed with this work for additional information regarding copyright ownership.
8// The GPA licenses this file to you under the MIT License (MIT), the "License"; you may
9// not use this file except in compliance with the License. You may obtain a copy of the License at:
10//
11// http://opensource.org/licenses/MIT
12//
13// Unless agreed to in writing, the subject software distributed under the License is distributed on an
14// "AS-IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. Refer to the
15// License for the specific language governing permissions and limitations.
16//
17// Code Modification History:
18// ----------------------------------------------------------------------------------------------------
19// 10/27/2015 - Stephen C. Wills
20// Generated original version of source code.
21//
22//******************************************************************************************************
23
24using System;
25using System.Collections.Generic;
26using System.Linq;
27using GSF.Collections;
28
29namespace GSF.Security.Cryptography
30{
31 /// <summary>
32 /// Generates random passwords.
33 /// </summary>
34 public class PasswordGenerator
35 {
36 #region [ Members ]
37
38 // Fields
39 private List<CharacterGroup> m_characterGroups;
40
41 #endregion
42
43 #region [ Constructors ]
44
45 /// <summary>
46 /// Creates a new instance of the <see cref="PasswordGenerator"/> class.
47 /// </summary>
48 public PasswordGenerator()
49 : this(DefaultCharacterGroups)
50 {
51 }
52
53 /// <summary>
54 /// Creates a new instance of the <see cref="PasswordGenerator"/> class.
55 /// </summary>
56 /// <param name="characterGroups">The list of character groups used to generate passwords.</param>
57 public PasswordGenerator(IEnumerable<CharacterGroup> characterGroups)
58 {
59 m_characterGroups = new List<CharacterGroup>(characterGroups);
60 }
61
62 #endregion
63
64 #region [ Properties ]
65
66 /// <summary>
67 /// Gets the collection of character groups used by this <see cref="PasswordGenerator"/>.
68 /// </summary>
69 public List<CharacterGroup> CharacterGroups
70 {
71 get
72 {
73 return m_characterGroups;
74 }
75 }
76
77 /// <summary>
78 /// Gets a string representing the total collection
79 /// of characters across all character groups.
80 /// </summary>
81 public string AllCharacters
82 {
83 get
84 {
85 return new string(m_characterGroups
86 .SelectMany(characterGroup => characterGroup.Characters)
87 .ToArray());
88 }
89 }
90
91 /// <summary>
92 /// Gets the absolute minimum length of password that can be
93 /// generated by the <see cref="PasswordGenerator"/> based
94 /// on the minimum occurrence of each character group.
95 /// </summary>
96 public int MinLength
97 {
98 get
99 {
100 return m_characterGroups.Sum(characterGroup => characterGroup.MinOccurrence);
101 }
102 }
103
104 #endregion
105
106 #region [ Methods ]
107
108 /// <summary>
109 /// Generates a random password with 8 characters or
110 /// <see cref="MinLength"/> if it is greater than 8 characters.
111 /// </summary>
112 /// <returns>A randomly generated password.</returns>
113 public string GeneratePassword()
114 {
115 return GeneratePassword(Math.Max(8, MinLength));
116 }
117
118 /// <summary>
119 /// Generates a password with length between the given
120 /// <paramref name="minLength"/> and <paramref name="maxLength"/>.
121 /// </summary>
122 /// <param name="minLength">The minimum length of the generated password.</param>
123 /// <param name="maxLength">The maximum length of the generated password.</param>
124 /// <returns>A randomly generated password.</returns>
125 public string GeneratePassword(int minLength, int maxLength)
126 {
127 if (minLength > maxLength)
128 throw new ArgumentException("minLength must be less than or equal to maxLength");
129
130 return GeneratePassword(Random.Int32Between(minLength, maxLength + 1));
131 }
132
133 /// <summary>
134 /// Generates a password with the given length.
135 /// </summary>
136 /// <param name="length">The length of the password to be generated.</param>
137 /// <returns>A randomly generated password.</returns>
138 public string GeneratePassword(int length)
139 {
140 List<CharacterGroup> characterGroups;
141 char[] passwordChars;
142
143 if (length < MinLength)
144 throw new ArgumentOutOfRangeException(nameof(length), $"The length of the generated password must be at least {MinLength} characters.");
145
146 // Create a collection of character groups the size of the password to be generated.
147 // The number of times a character group appears in this collection is equal to the
148 // minimum number of occurrences of that character group. An AllCharacters group is
149 // created to fill in the characters not accounted for by the other character groups.
150 characterGroups = m_characterGroups
151 .SelectMany(characterGroup => Enumerable.Repeat(characterGroup, characterGroup.MinOccurrence))
152 .Concat(Enumerable.Repeat(new CharacterGroup(AllCharacters), length - MinLength))
153 .ToList();
154
155 passwordChars = new char[length];
156
157 for (int i = 0; i < length; i++)
158 {
159 // Pull a random character from the character group into the password
160 CharacterGroup characterGroup = characterGroups[i];
161 int index = Random.Int32Between(0, characterGroup.Characters.Length);
162 passwordChars[i] = characterGroup.Characters[index];
163 }
164
165 // Scramble the generated set of characters
166 passwordChars.Scramble();
167
168 return new string(passwordChars);
169 }
170
171 #endregion
172
173 #region [ Static ]
174
175 // Static Fields
176
177 /// <summary>
178 /// Default set of character groups used by the <see cref="PasswordGenerator"/>.
179 /// </summary>
180 public static readonly IReadOnlyList<CharacterGroup> DefaultCharacterGroups = new List<CharacterGroup>()
181 {
182 new CharacterGroup() { Characters = "abcdefghijklmnopqrstuvwxyz", MinOccurrence = 1 },
183 new CharacterGroup() { Characters = "ABCDEFGHIJKLMNOPQRSTUVWXYZ", MinOccurrence = 1 },
184 new CharacterGroup() { Characters = "0123456789", MinOccurrence = 1 },
185 new CharacterGroup() { Characters = "~!@#$%^&*-_=+;:,.?", MinOccurrence = 1 }
186 };
187
188 /// <summary>
189 /// Defines the default password generator.
190 /// </summary>
191 public static readonly PasswordGenerator Default = new PasswordGenerator();
192
193 #endregion
194 }
195}
Source/Libraries/GSF.Core/Security/Cryptography/Random.cs+38−38
@@ -39,19 +39,19 @@ namespace GSF.Security.Cryptography · 38 unmodified lines
39 /// </summary>39 /// </summary>
40 public static class Random40 public static class Random
41 {41 {
42 private static readonly RNGCryptoServiceProvider s_randomNumberGenerator = new RNGCryptoServiceProvider();42 private static readonly RNGCryptoServiceProvider RandomNumberGenerator = new RNGCryptoServiceProvider();
43 43
44 /// <summary>44 /// <summary>
45 /// Generates a cryptographically strong double-precision floating-point random number between zero and one.45 /// Generates a cryptographically strong double-precision floating-point random number between zero and one.
46 /// </summary>46 /// </summary>
47 /// <exception cref="System.Security.Cryptography.CryptographicException">The cryptographic service provider (CSP) cannot be acquired.</exception>47 /// <exception cref="CryptographicException">The cryptographic service provider (CSP) cannot be acquired.</exception>
48 public static double Number48 public static double Number
49 {49 {
50 get50 get
51 {51 {
52 unchecked52 unchecked
53 {53 {
54 return (double)UInt32 / (double)uint.MaxValue;54 return UInt32 / (uint.MaxValue + 1.0D);
55 }55 }
56 }56 }
57 }57 }
@@ -59,14 +59,14 @@ namespace GSF.Security.Cryptography · 1 unmodified line
59 /// <summary>59 /// <summary>
60 /// Generates a cryptographically strong random decimal between zero and one.60 /// Generates a cryptographically strong random decimal between zero and one.
61 /// </summary>61 /// </summary>
62 /// <exception cref="System.Security.Cryptography.CryptographicException">The cryptographic service provider (CSP) cannot be acquired.</exception>62 /// <exception cref="CryptographicException">The cryptographic service provider (CSP) cannot be acquired.</exception>
63 public static decimal Decimal63 public static decimal Decimal
64 {64 {
65 get65 get
66 {66 {
67 unchecked67 unchecked
68 {68 {
69 return (decimal)UInt64 / (decimal)ulong.MaxValue;69 return UInt64 / (ulong.MaxValue + 1.0M);
70 }70 }
71 }71 }
72 }72 }
@@ -76,7 +76,7 @@ namespace GSF.Security.Cryptography · 3 unmodified lines
76 /// </summary>76 /// </summary>
77 /// <param name="startNumber">A <see cref="double"/> that is the low end of our range.</param>77 /// <param name="startNumber">A <see cref="double"/> that is the low end of our range.</param>
78 /// <param name="stopNumber">A <see cref="double"/> that is the high end of our range.</param>78 /// <param name="stopNumber">A <see cref="double"/> that is the high end of our range.</param>
79 /// <exception cref="System.Security.Cryptography.CryptographicException">The cryptographic service provider (CSP) cannot be acquired.</exception>79 /// <exception cref="CryptographicException">The cryptographic service provider (CSP) cannot be acquired.</exception>
80 /// <returns>A <see cref="double"/> that is generated between the <paramref name="startNumber"/> and the <paramref name="stopNumber"/>, or an excception.</returns>80 /// <returns>A <see cref="double"/> that is generated between the <paramref name="startNumber"/> and the <paramref name="stopNumber"/>, or an excception.</returns>
81 public static double Between(double startNumber, double stopNumber)81 public static double Between(double startNumber, double stopNumber)
82 {82 {
@@ -94,24 +94,24 @@ namespace GSF.Security.Cryptography · 11 unmodified lines
94 /// <para>The length of the byte array determines how many cryptographically strong random bytes are produced.</para>94 /// <para>The length of the byte array determines how many cryptographically strong random bytes are produced.</para>
95 /// <para>This method is thread safe.</para>95 /// <para>This method is thread safe.</para>
96 /// </remarks>96 /// </remarks>
97 /// <exception cref="System.Security.Cryptography.CryptographicException">The cryptographic service provider (CSP) cannot be acquired.</exception>97 /// <exception cref="CryptographicException">The cryptographic service provider (CSP) cannot be acquired.</exception>
98 /// <exception cref="System.ArgumentNullException">buffer is null.</exception>98 /// <exception cref="ArgumentNullException">buffer is null.</exception>
99 public static void GetBytes(byte[] buffer)99 public static void GetBytes(byte[] buffer)
100 {100 {
101 s_randomNumberGenerator.GetBytes(buffer);101 RandomNumberGenerator.GetBytes(buffer);
102 }102 }
103 103
104 /// <summary>104 /// <summary>
105 /// Generates a cryptographically strong random boolean (i.e., a coin toss).105 /// Generates a cryptographically strong random boolean (i.e., a coin toss).
106 /// </summary>106 /// </summary>
107 /// <exception cref="System.Security.Cryptography.CryptographicException">The cryptographic service provider (CSP) cannot be acquired.</exception>107 /// <exception cref="CryptographicException">The cryptographic service provider (CSP) cannot be acquired.</exception>
108 public static bool Boolean108 public static bool Boolean
109 {109 {
110 get110 get
111 {111 {
112 byte[] value = new byte[1];112 byte[] value = new byte[1];
113 113
114 s_randomNumberGenerator.GetBytes(value);114 RandomNumberGenerator.GetBytes(value);
115 115
116 return value[0] % 2 == 0;116 return value[0] % 2 == 0;
117 }117 }
@@ -120,14 +120,14 @@ namespace GSF.Security.Cryptography · 2 unmodified lines
120 /// <summary>120 /// <summary>
121 /// Generates a cryptographically strong 8-bit random integer.121 /// Generates a cryptographically strong 8-bit random integer.
122 /// </summary>122 /// </summary>
123 /// <exception cref="System.Security.Cryptography.CryptographicException">The cryptographic service provider (CSP) cannot be acquired.</exception>123 /// <exception cref="CryptographicException">The cryptographic service provider (CSP) cannot be acquired.</exception>
124 public static byte Byte124 public static byte Byte
125 {125 {
126 get126 get
127 {127 {
128 byte[] value = new byte[1];128 byte[] value = new byte[1];
129 129
130 s_randomNumberGenerator.GetBytes(value);130 RandomNumberGenerator.GetBytes(value);
131 131
132 return value[0];132 return value[0];
133 }133 }
@@ -136,7 +136,7 @@ namespace GSF.Security.Cryptography · 2 unmodified lines
136 /// <summary>136 /// <summary>
137 /// Generates a cryptographically strong 8-bit random integer between specified values.137 /// Generates a cryptographically strong 8-bit random integer between specified values.
138 /// </summary>138 /// </summary>
139 /// <exception cref="System.Security.Cryptography.CryptographicException">The cryptographic service provider (CSP) cannot be acquired.</exception>139 /// <exception cref="CryptographicException">The cryptographic service provider (CSP) cannot be acquired.</exception>
140 /// <param name="startNumber">A <see cref="byte"/> that is the low end of our range.</param>140 /// <param name="startNumber">A <see cref="byte"/> that is the low end of our range.</param>
141 /// <param name="stopNumber">A <see cref="byte"/> that is the high end of our range.</param>141 /// <param name="stopNumber">A <see cref="byte"/> that is the high end of our range.</param>
142 /// <returns>A <see cref="byte"/> that is generated between the <paramref name="startNumber"/> and the <paramref name="stopNumber"/>.</returns>142 /// <returns>A <see cref="byte"/> that is generated between the <paramref name="startNumber"/> and the <paramref name="stopNumber"/>.</returns>
@@ -151,14 +151,14 @@ namespace GSF.Security.Cryptography · 8 unmodified lines
151 /// <summary>151 /// <summary>
152 /// Generates a cryptographically strong 16-bit random integer.152 /// Generates a cryptographically strong 16-bit random integer.
153 /// </summary>153 /// </summary>
154 /// <exception cref="System.Security.Cryptography.CryptographicException">The cryptographic service provider (CSP) cannot be acquired.</exception>154 /// <exception cref="CryptographicException">The cryptographic service provider (CSP) cannot be acquired.</exception>
155 public static short Int16155 public static short Int16
156 {156 {
157 get157 get
158 {158 {
159 byte[] value = new byte[2];159 byte[] value = new byte[2];
160 160
161 s_randomNumberGenerator.GetBytes(value);161 RandomNumberGenerator.GetBytes(value);
162 162
163 return BitConverter.ToInt16(value, 0);163 return BitConverter.ToInt16(value, 0);
164 }164 }
@@ -167,7 +167,7 @@ namespace GSF.Security.Cryptography · 2 unmodified lines
167 /// <summary>167 /// <summary>
168 /// Generates a cryptographically strong 16-bit random integer between specified values.168 /// Generates a cryptographically strong 16-bit random integer between specified values.
169 /// </summary>169 /// </summary>
170 /// <exception cref="System.Security.Cryptography.CryptographicException">The cryptographic service provider (CSP) cannot be acquired.</exception>170 /// <exception cref="CryptographicException">The cryptographic service provider (CSP) cannot be acquired.</exception>
171 /// <param name="startNumber">A <see cref="short"/> that is the low end of our range.</param>171 /// <param name="startNumber">A <see cref="short"/> that is the low end of our range.</param>
172 /// <param name="stopNumber">A <see cref="short"/> that is the high end of our range.</param>172 /// <param name="stopNumber">A <see cref="short"/> that is the high end of our range.</param>
173 /// <returns>A <see cref="short"/> that is generated between the <paramref name="startNumber"/> and the <paramref name="stopNumber"/>.</returns>173 /// <returns>A <see cref="short"/> that is generated between the <paramref name="startNumber"/> and the <paramref name="stopNumber"/>.</returns>
@@ -182,14 +182,14 @@ namespace GSF.Security.Cryptography · 8 unmodified lines
182 /// <summary>182 /// <summary>
183 /// Generates a cryptographically strong unsigned 16-bit random integer.183 /// Generates a cryptographically strong unsigned 16-bit random integer.
184 /// </summary>184 /// </summary>
185 /// <exception cref="System.Security.Cryptography.CryptographicException">The cryptographic service provider (CSP) cannot be acquired.</exception>185 /// <exception cref="CryptographicException">The cryptographic service provider (CSP) cannot be acquired.</exception>
186 public static ushort UInt16186 public static ushort UInt16
187 {187 {
188 get188 get
189 {189 {
190 byte[] value = new byte[2];190 byte[] value = new byte[2];
191 191
192 s_randomNumberGenerator.GetBytes(value);192 RandomNumberGenerator.GetBytes(value);
193 193
194 return BitConverter.ToUInt16(value, 0);194 return BitConverter.ToUInt16(value, 0);
195 }195 }
@@ -198,7 +198,7 @@ namespace GSF.Security.Cryptography · 2 unmodified lines
198 /// <summary>198 /// <summary>
199 /// Generates a cryptographically strong unsigned 16-bit random integer between specified values.199 /// Generates a cryptographically strong unsigned 16-bit random integer between specified values.
200 /// </summary>200 /// </summary>
201 /// <exception cref="System.Security.Cryptography.CryptographicException">The cryptographic service provider (CSP) cannot be acquired.</exception>201 /// <exception cref="CryptographicException">The cryptographic service provider (CSP) cannot be acquired.</exception>
202 /// <param name="startNumber">A <see cref="ushort"/> that is the low end of our range.</param>202 /// <param name="startNumber">A <see cref="ushort"/> that is the low end of our range.</param>
203 /// <param name="stopNumber">A <see cref="ushort"/> that is the high end of our range.</param>203 /// <param name="stopNumber">A <see cref="ushort"/> that is the high end of our range.</param>
204 /// <returns>A <see cref="ushort"/> that is generated between the <paramref name="startNumber"/> and the <paramref name="stopNumber"/>.</returns>204 /// <returns>A <see cref="ushort"/> that is generated between the <paramref name="startNumber"/> and the <paramref name="stopNumber"/>.</returns>
@@ -213,14 +213,14 @@ namespace GSF.Security.Cryptography · 8 unmodified lines
213 /// <summary>213 /// <summary>
214 /// Generates a cryptographically strong 24-bit random integer.214 /// Generates a cryptographically strong 24-bit random integer.
215 /// </summary>215 /// </summary>
216 /// <exception cref="System.Security.Cryptography.CryptographicException">The cryptographic service provider (CSP) cannot be acquired.</exception>216 /// <exception cref="CryptographicException">The cryptographic service provider (CSP) cannot be acquired.</exception>
217 public static Int24 Int24217 public static Int24 Int24
218 {218 {
219 get219 get
220 {220 {
221 byte[] value = new byte[3];221 byte[] value = new byte[3];
222 222
223 s_randomNumberGenerator.GetBytes(value);223 RandomNumberGenerator.GetBytes(value);
224 224
225 return Int24.GetValue(value, 0);225 return Int24.GetValue(value, 0);
226 }226 }
@@ -229,7 +229,7 @@ namespace GSF.Security.Cryptography · 2 unmodified lines
229 /// <summary>229 /// <summary>
230 /// Generates a cryptographically strong 24-bit random integer between specified values.230 /// Generates a cryptographically strong 24-bit random integer between specified values.
231 /// </summary>231 /// </summary>
232 /// <exception cref="System.Security.Cryptography.CryptographicException">The cryptographic service provider (CSP) cannot be acquired.</exception>232 /// <exception cref="CryptographicException">The cryptographic service provider (CSP) cannot be acquired.</exception>
233 /// <param name="startNumber">A <see cref="Int24"/> that is the low end of our range.</param>233 /// <param name="startNumber">A <see cref="Int24"/> that is the low end of our range.</param>
234 /// <param name="stopNumber">A <see cref="Int24"/> that is the high end of our range.</param>234 /// <param name="stopNumber">A <see cref="Int24"/> that is the high end of our range.</param>
235 /// <returns>A <see cref="Int24"/> that is generated between the <paramref name="startNumber"/> and the <paramref name="stopNumber"/>.</returns>235 /// <returns>A <see cref="Int24"/> that is generated between the <paramref name="startNumber"/> and the <paramref name="stopNumber"/>.</returns>
@@ -244,14 +244,14 @@ namespace GSF.Security.Cryptography · 8 unmodified lines
244 /// <summary>244 /// <summary>
245 /// Generates a cryptographically strong unsigned 24-bit random integer.245 /// Generates a cryptographically strong unsigned 24-bit random integer.
246 /// </summary>246 /// </summary>
247 /// <exception cref="System.Security.Cryptography.CryptographicException">The cryptographic service provider (CSP) cannot be acquired.</exception>247 /// <exception cref="CryptographicException">The cryptographic service provider (CSP) cannot be acquired.</exception>
248 public static UInt24 UInt24248 public static UInt24 UInt24
249 {249 {
250 get250 get
251 {251 {
252 byte[] value = new byte[3];252 byte[] value = new byte[3];
253 253
254 s_randomNumberGenerator.GetBytes(value);254 RandomNumberGenerator.GetBytes(value);
255 255
256 return UInt24.GetValue(value, 0);256 return UInt24.GetValue(value, 0);
257 }257 }
@@ -260,7 +260,7 @@ namespace GSF.Security.Cryptography · 2 unmodified lines
260 /// <summary>260 /// <summary>
261 /// Generates a cryptographically strong unsigned 24-bit random integer between specified values.261 /// Generates a cryptographically strong unsigned 24-bit random integer between specified values.
262 /// </summary>262 /// </summary>
263 /// <exception cref="System.Security.Cryptography.CryptographicException">The cryptographic service provider (CSP) cannot be acquired.</exception>263 /// <exception cref="CryptographicException">The cryptographic service provider (CSP) cannot be acquired.</exception>
264 /// <param name="startNumber">A <see cref="UInt24"/> that is the low end of our range.</param>264 /// <param name="startNumber">A <see cref="UInt24"/> that is the low end of our range.</param>
265 /// <param name="stopNumber">A <see cref="UInt24"/> that is the high end of our range.</param>265 /// <param name="stopNumber">A <see cref="UInt24"/> that is the high end of our range.</param>
266 /// <returns>A <see cref="UInt24"/> that is generated between the <paramref name="startNumber"/> and the <paramref name="stopNumber"/>.</returns>266 /// <returns>A <see cref="UInt24"/> that is generated between the <paramref name="startNumber"/> and the <paramref name="stopNumber"/>.</returns>
@@ -275,14 +275,14 @@ namespace GSF.Security.Cryptography · 8 unmodified lines
275 /// <summary>275 /// <summary>
276 /// Generates a cryptographically strong 32-bit random integer.276 /// Generates a cryptographically strong 32-bit random integer.
277 /// </summary>277 /// </summary>
278 /// <exception cref="System.Security.Cryptography.CryptographicException">The cryptographic service provider (CSP) cannot be acquired.</exception>278 /// <exception cref="CryptographicException">The cryptographic service provider (CSP) cannot be acquired.</exception>
279 public static int Int32279 public static int Int32
280 {280 {
281 get281 get
282 {282 {
283 byte[] value = new byte[4];283 byte[] value = new byte[4];
284 284
285 s_randomNumberGenerator.GetBytes(value);285 RandomNumberGenerator.GetBytes(value);
286 286
287 return BitConverter.ToInt32(value, 0);287 return BitConverter.ToInt32(value, 0);
288 }288 }
@@ -291,7 +291,7 @@ namespace GSF.Security.Cryptography · 2 unmodified lines
291 /// <summary>291 /// <summary>
292 /// Generates a cryptographically strong 32-bit random integer between specified values.292 /// Generates a cryptographically strong 32-bit random integer between specified values.
293 /// </summary>293 /// </summary>
294 /// <exception cref="System.Security.Cryptography.CryptographicException">The cryptographic service provider (CSP) cannot be acquired.</exception>294 /// <exception cref="CryptographicException">The cryptographic service provider (CSP) cannot be acquired.</exception>
295 /// <param name="startNumber">A <see cref="int"/> that is the low end of our range.</param>295 /// <param name="startNumber">A <see cref="int"/> that is the low end of our range.</param>
296 /// <param name="stopNumber">A <see cref="int"/> that is the high end of our range.</param>296 /// <param name="stopNumber">A <see cref="int"/> that is the high end of our range.</param>
297 /// <returns>A <see cref="int"/> that is generated between the <paramref name="startNumber"/> and the <paramref name="stopNumber"/>.</returns>297 /// <returns>A <see cref="int"/> that is generated between the <paramref name="startNumber"/> and the <paramref name="stopNumber"/>.</returns>
@@ -306,14 +306,14 @@ namespace GSF.Security.Cryptography · 8 unmodified lines
306 /// <summary>306 /// <summary>
307 /// Generates a cryptographically strong unsigned 32-bit random integer.307 /// Generates a cryptographically strong unsigned 32-bit random integer.
308 /// </summary>308 /// </summary>
309 /// <exception cref="System.Security.Cryptography.CryptographicException">The cryptographic service provider (CSP) cannot be acquired.</exception>309 /// <exception cref="CryptographicException">The cryptographic service provider (CSP) cannot be acquired.</exception>
310 public static uint UInt32310 public static uint UInt32
311 {311 {
312 get312 get
313 {313 {
314 byte[] value = new byte[4];314 byte[] value = new byte[4];
315 315
316 s_randomNumberGenerator.GetBytes(value);316 RandomNumberGenerator.GetBytes(value);
317 317
318 return BitConverter.ToUInt32(value, 0);318 return BitConverter.ToUInt32(value, 0);
319 }319 }
@@ -322,7 +322,7 @@ namespace GSF.Security.Cryptography · 2 unmodified lines
322 /// <summary>322 /// <summary>
323 /// Generates a cryptographically strong unsigned 32-bit random integer between specified values.323 /// Generates a cryptographically strong unsigned 32-bit random integer between specified values.
324 /// </summary>324 /// </summary>
325 /// <exception cref="System.Security.Cryptography.CryptographicException">The cryptographic service provider (CSP) cannot be acquired.</exception>325 /// <exception cref="CryptographicException">The cryptographic service provider (CSP) cannot be acquired.</exception>
326 /// <param name="startNumber">A <see cref="uint"/> that is the low end of our range.</param>326 /// <param name="startNumber">A <see cref="uint"/> that is the low end of our range.</param>
327 /// <param name="stopNumber">A <see cref="uint"/> that is the high end of our range.</param>327 /// <param name="stopNumber">A <see cref="uint"/> that is the high end of our range.</param>
328 /// <returns>A <see cref="uint"/> that is generated between the <paramref name="startNumber"/> and the <paramref name="stopNumber"/>.</returns>328 /// <returns>A <see cref="uint"/> that is generated between the <paramref name="startNumber"/> and the <paramref name="stopNumber"/>.</returns>
@@ -337,14 +337,14 @@ namespace GSF.Security.Cryptography · 8 unmodified lines
337 /// <summary>337 /// <summary>
338 /// Generates a cryptographically strong 64-bit random integer.338 /// Generates a cryptographically strong 64-bit random integer.
339 /// </summary>339 /// </summary>
340 /// <exception cref="System.Security.Cryptography.CryptographicException">The cryptographic service provider (CSP) cannot be acquired.</exception>340 /// <exception cref="CryptographicException">The cryptographic service provider (CSP) cannot be acquired.</exception>
341 public static long Int64341 public static long Int64
342 {342 {
343 get343 get
344 {344 {
345 byte[] value = new byte[8];345 byte[] value = new byte[8];
346 346
347 s_randomNumberGenerator.GetBytes(value);347 RandomNumberGenerator.GetBytes(value);
348 348
349 return BitConverter.ToInt64(value, 0);349 return BitConverter.ToInt64(value, 0);
350 }350 }
@@ -353,7 +353,7 @@ namespace GSF.Security.Cryptography · 2 unmodified lines
353 /// <summary>353 /// <summary>
354 /// Generates a cryptographically strong 64-bit random integer between specified values.354 /// Generates a cryptographically strong 64-bit random integer between specified values.
355 /// </summary>355 /// </summary>
356 /// <exception cref="System.Security.Cryptography.CryptographicException">The cryptographic service provider (CSP) cannot be acquired.</exception>356 /// <exception cref="CryptographicException">The cryptographic service provider (CSP) cannot be acquired.</exception>
357 /// <param name="startNumber">A <see cref="long"/> that is the low end of our range.</param>357 /// <param name="startNumber">A <see cref="long"/> that is the low end of our range.</param>
358 /// <param name="stopNumber">A <see cref="long"/> that is the high end of our range.</param>358 /// <param name="stopNumber">A <see cref="long"/> that is the high end of our range.</param>
359 /// <returns>A <see cref="long"/> that is generated between the <paramref name="startNumber"/> and the <paramref name="stopNumber"/>.</returns>359 /// <returns>A <see cref="long"/> that is generated between the <paramref name="startNumber"/> and the <paramref name="stopNumber"/>.</returns>
@@ -368,14 +368,14 @@ namespace GSF.Security.Cryptography · 8 unmodified lines
368 /// <summary>368 /// <summary>
369 /// Generates a cryptographically strong unsigned 64-bit random integer.369 /// Generates a cryptographically strong unsigned 64-bit random integer.
370 /// </summary>370 /// </summary>
371 /// <exception cref="System.Security.Cryptography.CryptographicException">The cryptographic service provider (CSP) cannot be acquired.</exception>371 /// <exception cref="CryptographicException">The cryptographic service provider (CSP) cannot be acquired.</exception>
372 public static ulong UInt64372 public static ulong UInt64
373 {373 {
374 get374 get
375 {375 {
376 byte[] value = new byte[8];376 byte[] value = new byte[8];
377 377
378 s_randomNumberGenerator.GetBytes(value);378 RandomNumberGenerator.GetBytes(value);
379 379
380 return BitConverter.ToUInt64(value, 0);380 return BitConverter.ToUInt64(value, 0);
381 }381 }
@@ -384,7 +384,7 @@ namespace GSF.Security.Cryptography · 2 unmodified lines
384 /// <summary>384 /// <summary>
385 /// Generates a cryptographically strong unsigned 64-bit random integer between specified values.385 /// Generates a cryptographically strong unsigned 64-bit random integer between specified values.
386 /// </summary>386 /// </summary>
387 /// <exception cref="System.Security.Cryptography.CryptographicException">The cryptographic service provider (CSP) cannot be acquired.</exception>387 /// <exception cref="CryptographicException">The cryptographic service provider (CSP) cannot be acquired.</exception>
388 /// <param name="startNumber">A <see cref="ulong"/> that is the low end of our range.</param>388 /// <param name="startNumber">A <see cref="ulong"/> that is the low end of our range.</param>
389 /// <param name="stopNumber">A <see cref="ulong"/> that is the high end of our range.</param>389 /// <param name="stopNumber">A <see cref="ulong"/> that is the high end of our range.</param>
390 /// <returns>A <see cref="ulong"/> that is generated between the <paramref name="startNumber"/> and the <paramref name="stopNumber"/>.</returns>390 /// <returns>A <see cref="ulong"/> that is generated between the <paramref name="startNumber"/> and the <paramref name="stopNumber"/>.</returns>
Source/Libraries/GSF.InstallerActions/CustomActions.cs+23−0
@@ -38,6 +38,7 @@ using System.Xml.Linq; · 37 unmodified lines
38using GSF.Data;38using GSF.Data;
39using GSF.Identity;39using GSF.Identity;
40using GSF.Interop;40using GSF.Interop;
41using GSF.Security.Cryptography;
41using GSF.ServiceProcess;42using GSF.ServiceProcess;
42using Microsoft.Deployment.WindowsInstaller;43using Microsoft.Deployment.WindowsInstaller;
43 44
@@ -370,6 +371,28 @@ namespace GSF.InstallerActions · 326 unmodified lines
370 return ActionResult.Success;371 return ActionResult.Success;
371 }372 }
372 373
374 /// <summary>
375 /// Tests a connection to a database server.
376 /// </summary>
377 /// <param name="session">Session object containing data from the installer.</param>
378 /// <returns>Result of the custom action.</returns>
379 [CustomAction]
380 public static ActionResult PasswordGenerationAction(Session session)
381 {
382 int passwordLength;
383
384 session.Log("Begin PasswordGenerationAction");
385
386 if (int.TryParse(session["GENPASSWORDLENGTH"], out passwordLength))
387 session["GENERATEDPASSWORD"] = PasswordGenerator.Default.GeneratePassword(passwordLength);
388 else
389 session["GENERATEDPASSWORD"] = PasswordGenerator.Default.GeneratePassword();
390
391 session.Log("End PasswordGenerationAction");
392
393 return ActionResult.Success;
394 }
395
373 /// <summary>396 /// <summary>
374 /// Tests a connection to a database server.397 /// Tests a connection to a database server.
375 /// </summary>398 /// </summary>
Source/Libraries/GSF.InstallerActions/GSF.InstallerActions.csproj+1−0
@@ -78,6 +78,7 @@ · 77 unmodified lines
78 <Reference Include="System.Core" />78 <Reference Include="System.Core" />
79 <Reference Include="System.IO.Compression" />79 <Reference Include="System.IO.Compression" />
80 <Reference Include="System.IO.Compression.FileSystem" />80 <Reference Include="System.IO.Compression.FileSystem" />
81 <Reference Include="System.Web" />
81 <Reference Include="System.Windows" />82 <Reference Include="System.Windows" />
82 <Reference Include="System.Windows.Forms" />83 <Reference Include="System.Windows.Forms" />
83 <Reference Include="System.Xml.Linq" />84 <Reference Include="System.Xml.Linq" />
Source/Libraries/GSF.Security/SecurityProviderUtility.cs+2−39
@@ -215,46 +215,9 @@ namespace GSF.Security · 214 unmodified lines
215 public static string GeneratePassword(int length)215 public static string GeneratePassword(int length)
216 {216 {
217 if (length < 8)217 if (length < 8)
218 throw new ArgumentException("Value must be at least 8", "length");218 throw new ArgumentException("Value must be at least 8", nameof(length));
219 219
220 // ASCII character ranges:220 return PasswordGenerator.Default.GeneratePassword(length);
221 // Lower case - 97 to 122
222 // Upper case - 65 to 90
223 // Special character - 33 to 47
224 // Digits - 48 to 57
225
226 int cursor = 0;
227 int lower = Random.Int32Between(1, length / 2);
228 int upper = Random.Int32Between(1, (length - lower) / 2);
229 int special = Random.Int32Between(1, (length - (lower + upper)) / 2);
230 int digits = length - (lower + upper + special);
231 char[] password = new char[length];
232 for (int i = 0; i < lower; i++)
233 {
234 password[cursor] = (char)Random.Int32Between(97, 122);
235 cursor++;
236 }
237 for (int i = 0; i < upper; i++)
238 {
239 password[cursor] = (char)Random.Int32Between(65, 90);
240 cursor++;
241 }
242 for (int i = 0; i < special; i++)
243 {
244 password[cursor] = (char)Random.Int32Between(33, 47);
245 cursor++;
246 }
247 for (int i = 0; i < digits; i++)
248 {
249 password[cursor] = (char)Random.Int32Between(48, 57);
250 cursor++;
251 }
252
253 // Scramble for more randomness.
254 List<char> scrambledPassword = new List<char>(password);
255 scrambledPassword.Scramble();
256
257 return new string(scrambledPassword.ToArray());
258 }221 }
259 222
260 /// <summary>223 /// <summary>

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t