Compare commits
No commits in common. "b6a1d6a9d07a9e0666659540b25a64c56e148869" and "a30e502bc4554127e3181d6a620a1f71502a2ac3" have entirely different histories.
b6a1d6a9d0
...
a30e502bc4
5 changed files with 17 additions and 296 deletions
|
@ -1,58 +0,0 @@
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Text;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
|
|
||||||
namespace CapyKit.Attributes
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Custom attribute for formatting values in a specific way.
|
|
||||||
/// </summary>
|
|
||||||
[AttributeUsage(AttributeTargets.Property)]
|
|
||||||
public class ValueFormatAttribute : Attribute
|
|
||||||
{
|
|
||||||
#region Properties
|
|
||||||
|
|
||||||
/// <summary> Gets or sets the format to use for formatting the value. </summary>
|
|
||||||
/// <value> The format string used to format the value. </value>
|
|
||||||
public string Format { get; private set; }
|
|
||||||
|
|
||||||
#endregion Properties
|
|
||||||
|
|
||||||
#region Constructors
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Default constructor. Initializes a new instance of the <see cref="ValueFormatAttribute"/>
|
|
||||||
/// class with an empty format string.
|
|
||||||
/// </summary>
|
|
||||||
public ValueFormatAttribute()
|
|
||||||
{
|
|
||||||
this.Format = string.Empty;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Constructor. Initializes a new instance of the <see cref="ValueFormatAttribute"/> class with
|
|
||||||
/// the specified format string.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="format"> The format string used to format the value. </param>
|
|
||||||
public ValueFormatAttribute(string format)
|
|
||||||
{
|
|
||||||
this.Format = format;
|
|
||||||
}
|
|
||||||
|
|
||||||
#endregion Constructors
|
|
||||||
|
|
||||||
#region Methods
|
|
||||||
|
|
||||||
/// <summary> Gets a parameterized formatted string for the specified index. </summary>
|
|
||||||
/// <param name="index"> (Optional) Zero-based index of the item in the string to format. </param>
|
|
||||||
/// <returns> A formatted string with the specified index and format. </returns>
|
|
||||||
public string GetFormatParameterizedString(int index = 0)
|
|
||||||
{
|
|
||||||
return "{" + index + ":" + this.Format + "}";
|
|
||||||
}
|
|
||||||
|
|
||||||
#endregion Methods
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,23 +0,0 @@
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Text;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
|
|
||||||
namespace CapyKit
|
|
||||||
{
|
|
||||||
public class EncryptedValue<T>
|
|
||||||
{
|
|
||||||
#region Members
|
|
||||||
|
|
||||||
//
|
|
||||||
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
#region Properties
|
|
||||||
|
|
||||||
public T Value { get; set; }
|
|
||||||
|
|
||||||
#endregion
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,44 +0,0 @@
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Runtime.InteropServices.ObjectiveC;
|
|
||||||
using System.Text;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
|
|
||||||
namespace CapyKit.Helpers
|
|
||||||
{
|
|
||||||
public class EncryptionHelper
|
|
||||||
{
|
|
||||||
#region Members
|
|
||||||
|
|
||||||
private string encryptionKey;
|
|
||||||
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
#region Constructors
|
|
||||||
|
|
||||||
public EncryptionHelper(string encryptionKey)
|
|
||||||
{
|
|
||||||
this.encryptionKey = encryptionKey;
|
|
||||||
}
|
|
||||||
|
|
||||||
#endregion
|
|
||||||
}
|
|
||||||
|
|
||||||
public interface IEncryptionAlgorithm
|
|
||||||
{
|
|
||||||
#region Properties
|
|
||||||
|
|
||||||
string AlgorithmName { get; }
|
|
||||||
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
#region Methods
|
|
||||||
|
|
||||||
EncryptedValue<T> Encrypt<T>(object obj, params object[] args);
|
|
||||||
|
|
||||||
T Decrypt<T>(EncryptedValue<T> encryptedValue, params object[] args);
|
|
||||||
|
|
||||||
#endregion
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -15,8 +15,8 @@ namespace CapyKit.Helpers
|
||||||
{
|
{
|
||||||
#region Members
|
#region Members
|
||||||
|
|
||||||
/// <summary> Default size to use when generating a new salt. </summary>
|
/// <summary> Default size of the generated salt. </summary>
|
||||||
private const int SALT_SIZE = 32;
|
private const int saltSize = 32;
|
||||||
|
|
||||||
/// <summary> A string of all the lower case characters. </summary>
|
/// <summary> A string of all the lower case characters. </summary>
|
||||||
internal const string LOWER_CASE_CHARACTERS = "abcdefghijklmnopqrstuvwxyz";
|
internal const string LOWER_CASE_CHARACTERS = "abcdefghijklmnopqrstuvwxyz";
|
||||||
|
@ -35,131 +35,25 @@ namespace CapyKit.Helpers
|
||||||
#region Methods
|
#region Methods
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Compares an unencrypted <paramref name="password"/> with a stored, encrypted <paramref name="existingPassword"/>.
|
/// Compares an unencrypted <paramref name="providedPassword"/> with a stored, encrypted
|
||||||
/// This method uses the specified password algorithm type <typeparamref name="T"/> to retrieve the hashed version
|
/// <paramref name="existingPassword"/>.
|
||||||
/// of the <paramref name="password"/> and then compares it with the <paramref name="existingPassword"/>.
|
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <typeparam name="T">The type of the password hashing algorithm.</typeparam>
|
/// <param name="providedPassword"> The provided password, unencrypted. </param>
|
||||||
/// <param name="existingPassword">The existing, encrypted password.</param>
|
/// <param name="existingPassword"> The existing, encrypted password. </param>
|
||||||
/// <param name="password">The unencrypted password to be compared.</param>
|
|
||||||
/// <param name="salt">The salt value used in password hashing.</param>
|
|
||||||
/// <param name="args">Additional arguments required for constructing the password algorithm instance.</param>
|
|
||||||
/// <returns>
|
/// <returns>
|
||||||
/// <see langword="true"/> if hash comparison succeeds, <see langword="false"/> if it fails.
|
/// <see langword="true"/> if hash comparison succeeds, <see langword="false"/> if it fails.
|
||||||
/// </returns>
|
/// </returns>
|
||||||
public static bool CompareHashedPassword<T>(Password existingPassword, string password, byte[] salt, params object[] args)
|
public static bool CompareHashedPassword(string providedPassword, string existingPassword)
|
||||||
{
|
{
|
||||||
var providedPassword = typeof(SecurityHelper)
|
throw new NotImplementedException();
|
||||||
.GetMethod("GetPassword")
|
|
||||||
?.MakeGenericMethod(typeof(T))
|
|
||||||
?.Invoke(null, new object[] { password, salt, args });
|
|
||||||
|
|
||||||
return existingPassword.Equals(providedPassword);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary> Hashes an unencrypted password. </summary>
|
||||||
/// Compares an unencrypted <paramref name="password"/> with a stored, encrypted <paramref name="existingPassword"/>.
|
/// <param name="password"> The password. </param>
|
||||||
/// This method uses the specified <paramref name="algorithm"/> to retrieve the hashed version
|
/// <returns> The hashed password. </returns>
|
||||||
/// of the <paramref name="password"/> and then compares it with the <paramref name="existingPassword"/>.
|
public static string HashPassword(string password)
|
||||||
/// </summary>
|
|
||||||
/// <param name="existingPassword">The existing, encrypted password.</param>
|
|
||||||
/// <param name="password">The unencrypted password to be compared.</param>
|
|
||||||
/// <param name="salt">The salt value used in password hashing.</param>
|
|
||||||
/// <param name="algorithm">The password hashing algorithm.</param>
|
|
||||||
/// <param name="args">Additional arguments required for constructing the password algorithm instance.</param>
|
|
||||||
/// <returns>
|
|
||||||
/// <see langword="true"/> if hash comparison succeeds, <see langword="false"/> if it fails.
|
|
||||||
/// </returns>
|
|
||||||
public static bool CompareHashedPassword(Password existingPassword, string password, byte[] salt, IPasswordAlgorithm algorithm, params object[] args)
|
|
||||||
{
|
{
|
||||||
var algorithmType = algorithm.GetType();
|
throw new NotImplementedException();
|
||||||
|
|
||||||
var providedPassword = typeof(SecurityHelper)
|
|
||||||
.GetMethod("GetPassword")
|
|
||||||
?.MakeGenericMethod(algorithmType)
|
|
||||||
?.Invoke(null, new object[] { password, salt, args });
|
|
||||||
|
|
||||||
return existingPassword.Equals(providedPassword);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Retrieves a <see cref="Password"/> object using the specified password and generates a random salt value.
|
|
||||||
/// Then it uses that salt to call the overloaded <see cref="GetPassword{T}(string, byte[], object[])"/> method with the given password and
|
|
||||||
/// the generated salt as arguments.
|
|
||||||
/// </summary>
|
|
||||||
/// <typeparam name="T"> The type of <see cref="IPasswordAlgorithm"/> implementation to use. </typeparam>
|
|
||||||
/// <param name="password"> The plaintext password to be hashed. </param>
|
|
||||||
/// <param name="args">
|
|
||||||
/// Optional constructor arguments for the <see cref="IPasswordAlgorithm"/> implementation
|
|
||||||
/// instance.
|
|
||||||
/// </param>
|
|
||||||
/// <returns>
|
|
||||||
/// A new <see cref="Password"/> object with the given password and a randomly generated salt, as well as an
|
|
||||||
/// instance of <typeparamref name="T"/> created using any optional constructor arguments provided.
|
|
||||||
/// </returns>
|
|
||||||
/// <seealso cref="SecurityHelper.SALT_SIZE"/>
|
|
||||||
public static Password GetPassword<T>(string password, params object[] args)
|
|
||||||
{
|
|
||||||
var salt = SecurityHelper.GetRandomBytes(SecurityHelper.SALT_SIZE);
|
|
||||||
return GetPassword<T>(password, salt, args);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Retrieves a <see cref="Password"/> object using the specified password, salt, and optional
|
|
||||||
/// constructor arguments.
|
|
||||||
/// </summary>
|
|
||||||
/// <remarks>
|
|
||||||
/// This method uses reflection to find a constructor for the specified password algorithm type (<typeparamref name="T"/>).
|
|
||||||
/// It emits an error event if a suitable constructor is not found or if there is an error invoking the constructor.
|
|
||||||
/// </remarks>
|
|
||||||
/// <typeparam name="T">
|
|
||||||
/// The type of <see cref="IPasswordAlgorithm"/> implementation to use.
|
|
||||||
/// </typeparam>
|
|
||||||
/// <param name="password"> The plaintext password to be hashed. </param>
|
|
||||||
/// <param name="salt">
|
|
||||||
/// A random value used as an additional input to the one-way function that hashes data, a
|
|
||||||
/// password or passphrase. This is used to make each output different for the same input
|
|
||||||
/// thus adding security.
|
|
||||||
/// </param>
|
|
||||||
/// <param name="args">
|
|
||||||
/// Optional constructor arguments for the <see cref="IPasswordAlgorithm"/> implementation
|
|
||||||
/// instance.
|
|
||||||
/// </param>
|
|
||||||
/// <returns>
|
|
||||||
/// A new <see cref="Password"/> object with the given password and salt, as well as an instance
|
|
||||||
/// of <typeparamref name="T"/> created using the provided constructor arguments.
|
|
||||||
/// </returns>
|
|
||||||
public static Password GetPassword<T>(string password, byte[] salt, params object[] args) where T : IPasswordAlgorithm
|
|
||||||
{
|
|
||||||
var allArgs = args.Prepend(salt).Prepend(password).ToArray(); // Prepend in reverse order so that password precedes salt.
|
|
||||||
var argTypes = allArgs.Select(arg => arg.GetType()).ToArray();
|
|
||||||
var algorithmConstructor = typeof(T).GetConstructor(argTypes);
|
|
||||||
|
|
||||||
if (algorithmConstructor == null)
|
|
||||||
{
|
|
||||||
CapyEventReporter.EmitEvent(EventLevel.Error, "Cannot find a constructor for {0} that matches the given arguments: {1}",
|
|
||||||
args: new[]
|
|
||||||
{
|
|
||||||
typeof(T).Name,
|
|
||||||
string.Join(",", argTypes.Select(arg => arg.Name))
|
|
||||||
});
|
|
||||||
return default(Password);
|
|
||||||
}
|
|
||||||
|
|
||||||
var passwordInstance = (T)algorithmConstructor.Invoke(allArgs);
|
|
||||||
|
|
||||||
if (passwordInstance == null)
|
|
||||||
{
|
|
||||||
CapyEventReporter.EmitEvent(EventLevel.Error, "There was an error invoking the constructor for {0} with the given arguments: {1}",
|
|
||||||
args: new[]
|
|
||||||
{
|
|
||||||
typeof(T).Name,
|
|
||||||
string.Join(",", allArgs)
|
|
||||||
});
|
|
||||||
return default(Password);
|
|
||||||
}
|
|
||||||
|
|
||||||
return new Password(password, salt, passwordInstance, args);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -201,7 +95,7 @@ namespace CapyKit.Helpers
|
||||||
/// </returns>
|
/// </returns>
|
||||||
public static Password Pbkdf2(string password)
|
public static Password Pbkdf2(string password)
|
||||||
{
|
{
|
||||||
var salt = SecurityHelper.GetRandomBytes(SALT_SIZE);
|
var salt = SecurityHelper.GetRandomBytes(saltSize);
|
||||||
var pwd = new Password(password, salt, Password.Pbkdf2Algorithm);
|
var pwd = new Password(password, salt, Password.Pbkdf2Algorithm);
|
||||||
|
|
||||||
return pwd;
|
return pwd;
|
||||||
|
@ -292,11 +186,6 @@ namespace CapyKit.Helpers
|
||||||
return buffer;
|
return buffer;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Static method that returns a valid character composition based on the given ValidCharacterCollection parameters.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="validCharacters">An array of ValidCharacterCollection enumeration values representing the desired character sets.</param>
|
|
||||||
/// <returns>A string containing all the characters from the specified character sets.</returns>
|
|
||||||
private static string GetValidCharacterComposition(params ValidCharacterCollection[] validCharacters)
|
private static string GetValidCharacterComposition(params ValidCharacterCollection[] validCharacters)
|
||||||
{
|
{
|
||||||
var composition = new StringBuilder();
|
var composition = new StringBuilder();
|
||||||
|
|
|
@ -16,7 +16,7 @@ namespace CapyKit
|
||||||
{
|
{
|
||||||
#region Members
|
#region Members
|
||||||
|
|
||||||
private static Lazy<Pbkdf2Algorithm> pbkdf2Algorithm = new Lazy<Pbkdf2Algorithm>(() => new Pbkdf2Algorithm());
|
private static Lazy<Pbkdf2Algorithm> algorithm = new Lazy<Pbkdf2Algorithm>(() => new Pbkdf2Algorithm());
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
|
@ -37,19 +37,13 @@ namespace CapyKit
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public IPasswordAlgorithm Algorithm { get; private set; }
|
public IPasswordAlgorithm Algorithm { get; private set; }
|
||||||
|
|
||||||
#region Preconfigued Password Algorithms
|
|
||||||
|
|
||||||
/// <summary> Gets the preconfigured PBKDF2 algorithm. </summary>
|
|
||||||
/// <value> The preconfigured PBKDF2 algorithm. </value>
|
|
||||||
public static Pbkdf2Algorithm Pbkdf2Algorithm
|
public static Pbkdf2Algorithm Pbkdf2Algorithm
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
return pbkdf2Algorithm.Value;
|
return algorithm.Value;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
|
@ -70,25 +64,6 @@ namespace CapyKit
|
||||||
|
|
||||||
#region Methods
|
#region Methods
|
||||||
|
|
||||||
/// <inheritdoc/>
|
|
||||||
public override bool Equals(object? obj)
|
|
||||||
{
|
|
||||||
if(obj == null) return false; // The object is null, and this object is not.
|
|
||||||
|
|
||||||
if(ReferenceEquals(this, obj)) return true; // The object is literally this object.
|
|
||||||
|
|
||||||
var objPassword = obj as Password;
|
|
||||||
|
|
||||||
if (objPassword == null)
|
|
||||||
{
|
|
||||||
return base.Equals(obj); // Objects aren't the same type. We can fall back to the default comparison.
|
|
||||||
}
|
|
||||||
|
|
||||||
return this.Algorithm.AlgorithmName == objPassword.Algorithm.AlgorithmName
|
|
||||||
&& this.Hash == objPassword.Hash
|
|
||||||
&& this.Salt == objPassword.Salt;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <inheritdoc/>
|
/// <inheritdoc/>
|
||||||
public override string ToString()
|
public override string ToString()
|
||||||
{
|
{
|
||||||
|
@ -96,24 +71,6 @@ namespace CapyKit
|
||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region Operators
|
|
||||||
|
|
||||||
/// <inheritdoc/>
|
|
||||||
public static bool operator ==(Password a, Password b)
|
|
||||||
{
|
|
||||||
return ReferenceEquals(a, b) // Literally the same object.
|
|
||||||
|| (ReferenceEquals(a, null) && ReferenceEquals(b,null)) // Both are null
|
|
||||||
|| a.Equals(b); // Both are not null but not the same object.
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <inheritdoc/>
|
|
||||||
public static bool operator !=(Password a, Password b)
|
|
||||||
{
|
|
||||||
return !(a == b);
|
|
||||||
}
|
|
||||||
|
|
||||||
#endregion
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue