Skip to content

Commit

Permalink
added password validator
Browse files Browse the repository at this point in the history
  • Loading branch information
Haik committed Nov 3, 2023
1 parent 89c0d89 commit e686b91
Show file tree
Hide file tree
Showing 5 changed files with 159 additions and 28 deletions.
42 changes: 42 additions & 0 deletions Pandatech.Crypto.Tests/RandomPasswordTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -39,4 +39,46 @@ public void Generate_ShouldReturnDifferentPasswords()

Assert.NotEqual(password1, password2);
}

[Theory]
[InlineData(7, true, false, true, true)]
[InlineData(4, false, true, false, false)]
[InlineData(5, true, false, false, false)]
[InlineData(13, true, true, false, false)]
[InlineData(25, true, true, true, false)]
[InlineData(35, true, true, true, true)]

public void ValidationTestForGeneratedPasswords(
int length,
bool includeUppercase,
bool includeLowercase,
bool includeDigits,
bool includeSpecialChars)
{
// Generate a random password
var password = RandomPassword.Generate(length, includeUppercase, includeLowercase, includeDigits,
includeSpecialChars);
Assert.True(RandomPassword.Validate(password, length, includeUppercase, includeLowercase, includeDigits,
includeSpecialChars));
}
[Theory]
[InlineData(7, true, false, true, true)]
[InlineData(4, false, true, false, false)]
[InlineData(5, true, false, false, false)]
[InlineData(13, true, true, false, false)]
[InlineData(25, true, true, true, false)]
[InlineData(35, false, true, true, true)]
public void ValidationTestForGeneratedPasswordsOpposite(
int length,
bool includeUppercase,
bool includeLowercase,
bool includeDigits,
bool includeSpecialChars)
{
// Generate a random password
var password = RandomPassword.Generate(length, includeUppercase, includeLowercase, includeDigits,
includeSpecialChars);
Assert.False(RandomPassword.Validate(password, length, !includeUppercase, !includeLowercase, !includeDigits,
!includeSpecialChars));
}
}
4 changes: 2 additions & 2 deletions Pandatech.Crypto/Pandatech.Crypto.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,14 @@
<TargetFramework>net7.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<Version>2.1.5</Version>
<Version>2.1.6</Version>
<Title>Pandatech.Crypto</Title>
<Authors>Pandatech</Authors>
<PackageIcon>pandatech.png</PackageIcon>
<PackageReadmeFile>Readme.md</PackageReadmeFile>
<Description>PandaTech.Crypto is a .NET library simplifying common cryptograhic functions.</Description>
<RepositoryUrl>https://github.com/PandaTechAM/be-lib-pandatech-crypto</RepositoryUrl>
<PackageReleaseNotes>Removed null checking on Aes256 Encrypt/Decrypt</PackageReleaseNotes>
<PackageReleaseNotes>Added password validator</PackageReleaseNotes>
</PropertyGroup>

<ItemGroup>
Expand Down
67 changes: 55 additions & 12 deletions Pandatech.Crypto/RandomPassword.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,18 +10,7 @@ public static class RandomPassword
public static string Generate(int length, bool includeUppercase, bool includeLowercase, bool includeDigits,
bool includeSpecialChars)
{
var typesCount = (includeUppercase ? 1 : 0) + (includeLowercase ? 1 : 0) + (includeDigits ? 1 : 0) +
(includeSpecialChars ? 1 : 0);

if (typesCount == 0)
{
throw new ArgumentException("At least one character set must be selected.");
}

if (length < typesCount)
{
throw new ArgumentException($"Password length must be at least {typesCount}.");
}
var typesCount = ValidateInput(length, includeUppercase, includeLowercase, includeDigits, includeSpecialChars);

var charSet = "";
if (includeUppercase)
Expand Down Expand Up @@ -73,6 +62,59 @@ public static string Generate(int length, bool includeUppercase, bool includeLow
return ShuffleString(password);
}

public static bool Validate(string password, int length, bool includeUppercase, bool includeLowercase,
bool includeDigits,
bool includeSpecialChars)
{
if (password.Length < length)
{
return false;
}

ValidateInput(length, includeUppercase, includeLowercase, includeDigits, includeSpecialChars);

if (includeUppercase && !password.Any(char.IsUpper))
{
return false;
}

if (includeLowercase && !password.Any(char.IsLower))
{
return false;
}

if (includeDigits && !password.Any(char.IsDigit))
{
return false;
}

if (includeSpecialChars && !password.Any(c => SpecialChars.Contains(c)))
{
return false;
}

return true;
}

private static int ValidateInput(int length, bool includeUppercase, bool includeLowercase, bool includeDigits,
bool includeSpecialChars)
{
var typesCount = (includeUppercase ? 1 : 0) + (includeLowercase ? 1 : 0) + (includeDigits ? 1 : 0) +
(includeSpecialChars ? 1 : 0);

if (typesCount == 0)
{
throw new ArgumentException("At least one character set must be selected.");
}

if (length < typesCount)
{
throw new ArgumentException($"Password length must be at least {typesCount}.");
}

return typesCount;
}

private static string ShuffleString(char[] array)
{
var n = array.Length;
Expand All @@ -83,6 +125,7 @@ private static string ShuffleString(char[] array)
var j = randomBuffer[i] % (i + 1);
(array[i], array[j]) = (array[j], array[i]);
}

return new string(array);
}
}
37 changes: 30 additions & 7 deletions Pandatech.Crypto/Readme.md
Original file line number Diff line number Diff line change
@@ -1,20 +1,25 @@
# PandaTech.Crypto

## Introduction

Pandatech.Crypto is a powerful cryptographic utility library backed by 99% test coverage through unit tests. The library
offers an array of static methods for secure data operations, including AES256 encryption and decryption, Argon2Id
password hashing and verification, as well as utilities for generating cryptographic random bytes and passwords.

Designed to work efficiently in containerized environments, the library performs effectively even with limited
resources—hash generation takes under 500ms on a container with 1 vCore and 1GB of RAM.

## Features

* **AES 256-bit Encryption/Decryption:** Encrypt your data and get the IV and encrypted bytes in one array. Decrypt it
back to its original form, seamlessly handling the IV. Note that you have option to encrypt with hash and decrypt
ignoring hash. (for cases where you want to apply filtering on the encrypted data or check uniqueness of the encrypted
data)
* **Argon2Id Hashing:** Perform password hashing and verification with a focus on security and performance, leveraging the Argon2Id algorithm.
* **Argon2Id Hashing:** Perform password hashing and verification with a focus on security and performance, leveraging
the Argon2Id algorithm.
* **SHA-3 Hashing:** Utilize 512-bit SHA-3 hashing for various applications.
* **Random Number/Password Generation:** Generate cryptographic random bytes, AES256 keys, or strong passwords with specific character sets.
* **Random Number/Password Generation:** Generate cryptographic random bytes, AES256 keys, or strong passwords with
specific character sets.
* **Performance Optimized:** Tested to run efficiently in resource-constrained environments.
* **High Test Coverage:** Confidence backed by 99% unit test coverage.

Expand All @@ -26,12 +31,15 @@ Console:
there.

## How to Use

### 1. Configuring Dependency Injection
First, you'll need to configure Aes256 and Argon2Id in your application. To do so, add the following code to your `Program.cs` file:

First, you'll need to configure Aes256 and Argon2Id in your application. To do so, add the following code to
your `Program.cs` file:

```csharp
using Pandatech.Crypto;


// For Aes256
builder.services.AddPandatechCryptoAes256(options =>
{
Expand All @@ -47,28 +55,40 @@ builder.services.AddPandatechCryptoAes256(options =>
options.MemorySize = 128 * 1024;
});
```

### 2. AES256 Class

#### Immutable Configurations

1. **IV**: A random IV is generated for each Encryption, enhancing security.
2. **PaddingMode**: PKCS7

#### Encryption/Decryption methods with hashing

```csharp
byte[] cipherText = aes256.Encrypt("your-plaintext");
string plainText = aes256.Decrypt(cipherText);
```

#### Encryption/Decryption methods without hashing

```csharp
byte[] cipherText = aes256.Encrypt("your-plaintext", false);
string plainText = aes256.Decrypt(cipherText, false);
```

#### Encryption/Decryption methods with custom key (overriding options for one time)

```csharp
string customKey = "your-custom-base64-encoded-key";
byte[] cipherText = aes256.Encrypt("your-plaintext", customKey);
string plainText = aes256.Decrypt(cipherText, customKey);
```

### 2. Argon2id Class

#### Default Configurations

1. **Salt**: A random salt is generated for each password hash, enhancing security.
2. **DegreeOfParallelism**: 8
3. **Iterations**: 5
Expand Down Expand Up @@ -98,7 +118,12 @@ var includeUppercase = true;
var includeLowercase = true;
var includeDigits = true;
var includeSpecialChars = true;

//Method for generating random password
string password = RandomPassword.Generate(16, includeUppercase, includeLowercase, includeDigits, includeSpecialChars);

//Method for validation of password
bool isValid = RandomPassword.Validate(password, 16, includeUppercase, includeLowercase, includeDigits, includeSpecialChars);
```

### 5. Sha3 Class
Expand All @@ -113,6 +138,4 @@ var isHashValid = Sha3.VerifyHash("yourPlainText", sha3Hash);

## License

PandaTech.Crypto is licensed under the MIT License.

Your Security, Our Priority.
PandaTech.Crypto is licensed under the MIT License.
37 changes: 30 additions & 7 deletions Readme.md
Original file line number Diff line number Diff line change
@@ -1,20 +1,25 @@
# PandaTech.Crypto

## Introduction

Pandatech.Crypto is a powerful cryptographic utility library backed by 99% test coverage through unit tests. The library
offers an array of static methods for secure data operations, including AES256 encryption and decryption, Argon2Id
password hashing and verification, as well as utilities for generating cryptographic random bytes and passwords.

Designed to work efficiently in containerized environments, the library performs effectively even with limited
resources—hash generation takes under 500ms on a container with 1 vCore and 1GB of RAM.

## Features

* **AES 256-bit Encryption/Decryption:** Encrypt your data and get the IV and encrypted bytes in one array. Decrypt it
back to its original form, seamlessly handling the IV. Note that you have option to encrypt with hash and decrypt
ignoring hash. (for cases where you want to apply filtering on the encrypted data or check uniqueness of the encrypted
data)
* **Argon2Id Hashing:** Perform password hashing and verification with a focus on security and performance, leveraging the Argon2Id algorithm.
* **Argon2Id Hashing:** Perform password hashing and verification with a focus on security and performance, leveraging
the Argon2Id algorithm.
* **SHA-3 Hashing:** Utilize 512-bit SHA-3 hashing for various applications.
* **Random Number/Password Generation:** Generate cryptographic random bytes, AES256 keys, or strong passwords with specific character sets.
* **Random Number/Password Generation:** Generate cryptographic random bytes, AES256 keys, or strong passwords with
specific character sets.
* **Performance Optimized:** Tested to run efficiently in resource-constrained environments.
* **High Test Coverage:** Confidence backed by 99% unit test coverage.

Expand All @@ -26,12 +31,15 @@ Console:
there.

## How to Use

### 1. Configuring Dependency Injection
First, you'll need to configure Aes256 and Argon2Id in your application. To do so, add the following code to your `Program.cs` file:

First, you'll need to configure Aes256 and Argon2Id in your application. To do so, add the following code to
your `Program.cs` file:

```csharp
using Pandatech.Crypto;


// For Aes256
builder.services.AddPandatechCryptoAes256(options =>
{
Expand All @@ -47,28 +55,40 @@ builder.services.AddPandatechCryptoAes256(options =>
options.MemorySize = 128 * 1024;
});
```

### 2. AES256 Class

#### Immutable Configurations

1. **IV**: A random IV is generated for each Encryption, enhancing security.
2. **PaddingMode**: PKCS7

#### Encryption/Decryption methods with hashing

```csharp
byte[] cipherText = aes256.Encrypt("your-plaintext");
string plainText = aes256.Decrypt(cipherText);
```

#### Encryption/Decryption methods without hashing

```csharp
byte[] cipherText = aes256.Encrypt("your-plaintext", false);
string plainText = aes256.Decrypt(cipherText, false);
```

#### Encryption/Decryption methods with custom key (overriding options for one time)

```csharp
string customKey = "your-custom-base64-encoded-key";
byte[] cipherText = aes256.Encrypt("your-plaintext", customKey);
string plainText = aes256.Decrypt(cipherText, customKey);
```

### 2. Argon2id Class

#### Default Configurations

1. **Salt**: A random salt is generated for each password hash, enhancing security.
2. **DegreeOfParallelism**: 8
3. **Iterations**: 5
Expand Down Expand Up @@ -98,7 +118,12 @@ var includeUppercase = true;
var includeLowercase = true;
var includeDigits = true;
var includeSpecialChars = true;

//Method for generating random password
string password = RandomPassword.Generate(16, includeUppercase, includeLowercase, includeDigits, includeSpecialChars);

//Method for validation of password
bool isValid = RandomPassword.Validate(password, 16, includeUppercase, includeLowercase, includeDigits, includeSpecialChars);
```

### 5. Sha3 Class
Expand All @@ -113,6 +138,4 @@ var isHashValid = Sha3.VerifyHash("yourPlainText", sha3Hash);

## License

PandaTech.Crypto is licensed under the MIT License.

Your Security, Our Priority.
PandaTech.Crypto is licensed under the MIT License.

0 comments on commit e686b91

Please sign in to comment.