Skip to content

Commit

Permalink
Update static classes to service
Browse files Browse the repository at this point in the history
  • Loading branch information
Haik committed Oct 31, 2023
1 parent 5ea547f commit 4323961
Show file tree
Hide file tree
Showing 10 changed files with 301 additions and 152 deletions.
62 changes: 38 additions & 24 deletions Pandatech.Crypto.Tests/Aes256Tests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,48 +12,54 @@ public void Generate_ShouldReturnByteArray()
Assert.Equal(length, randomBytes.Length);
}


[Fact]
public void EncryptDecryptWithParameter_ShouldReturnOriginalString()
{
var aes256 = new Aes256(new Aes256Options());

var key = Random.GenerateAes256KeyString();
const string original = "MySensitiveData";
var encrypted = Aes256.Encrypt(original, key);
var decrypted = Aes256.Decrypt(encrypted, key);
var encrypted = aes256.Encrypt(original, key);
var decrypted = aes256.Decrypt(encrypted, key);

Assert.Equal(original, decrypted);
}

[Fact]
public void EncryptDecryptWithoutParameter_ShouldReturnOriginalString()
{
var aes256Options = new Aes256Options { Key = Random.GenerateAes256KeyString() };
var aes256 = new Aes256(aes256Options);
Environment.SetEnvironmentVariable("AES_KEY", Random.GenerateAes256KeyString());
const string original = "MySensitiveData";
var encrypted = Aes256.Encrypt(original);
var decrypted = Aes256.Decrypt(encrypted);
var encrypted = aes256.Encrypt(original);
var decrypted = aes256.Decrypt(encrypted);

Assert.Equal(original, decrypted);
}

[Fact]
public void EncryptWithParameterAndHash_ShouldReturnByteArrayWithHash()
{
var aes256 = new Aes256(new Aes256Options());
var key = Random.GenerateAes256KeyString();
const string original = "MySensitiveData";
var encryptedWithHash = Aes256.EncryptWithHash(original, key);
var encryptedWithHash = aes256.EncryptWithHash(original, key);

Assert.NotNull(encryptedWithHash);
Assert.True(encryptedWithHash.Length > original.Length);
Assert.True(encryptedWithHash.Length > 64);
}

[Fact]
public void EncryptWithoutParameterAndHash_ShouldReturnByteArrayWithHash()
{
var aes256Options = new Aes256Options { Key = Random.GenerateAes256KeyString() };
var aes256 = new Aes256(aes256Options);
Environment.SetEnvironmentVariable("AES_KEY", Random.GenerateAes256KeyString());
const string original = "MySensitiveData";
var encryptedWithHash = Aes256.EncryptWithHash(original);
var encryptedWithHash = aes256.EncryptWithHash(original);

Assert.NotNull(encryptedWithHash);
Assert.True(encryptedWithHash.Length > original.Length);
Assert.True(encryptedWithHash.Length > 64);
Expand All @@ -62,69 +68,77 @@ public void EncryptWithoutParameterAndHash_ShouldReturnByteArrayWithHash()
[Fact]
public void DecryptWithParameterAndIgnoringHash_ShouldReturnOriginalString()
{
var aes256 = new Aes256(new Aes256Options());
var key = Random.GenerateAes256KeyString();
const string original = "MySensitiveData";
var encryptedWithHash = Aes256.EncryptWithHash(original, key);
var decrypted = Aes256.DecryptIgnoringHash(encryptedWithHash, key);
var encryptedWithHash = aes256.EncryptWithHash(original, key);
var decrypted = aes256.DecryptIgnoringHash(encryptedWithHash, key);

Assert.Equal(original, decrypted);
}

[Fact]
public void DecryptWithoutParameterAndIgnoringHash_ShouldReturnOriginalString()
{
var aes256Options = new Aes256Options { Key = Random.GenerateAes256KeyString() };
var aes256 = new Aes256(aes256Options);
Environment.SetEnvironmentVariable("AES_KEY", Random.GenerateAes256KeyString());
const string original = "MySensitiveData";
var encryptedWithHash = Aes256.EncryptWithHash(original);
var decrypted = Aes256.DecryptIgnoringHash(encryptedWithHash);
var encryptedWithHash = aes256.EncryptWithHash(original);
var decrypted = aes256.DecryptIgnoringHash(encryptedWithHash);

Assert.Equal(original, decrypted);
}

[Fact]
public void DecryptIgnoringHashWithInvalidData_ShouldThrowException()
{
var aes256 = new Aes256(new Aes256Options());
const string invalidKey = "InvalidKey";
var invalidData = new byte[50];

Assert.Throws<ArgumentException>(() => Aes256.DecryptIgnoringHash(invalidData, invalidKey));
Assert.Throws<ArgumentException>(() => aes256.DecryptIgnoringHash(invalidData, invalidKey));
}

[Fact]
public void EncryptDecryptWithInvalidKey_ShouldThrowException()
{
var aes256 = new Aes256(new Aes256Options());
const string invalidKey = "InvalidKey";
const string original = "MySensitiveData";

Assert.Throws<ArgumentException>(() => Aes256.Encrypt(original, invalidKey));
Assert.Throws<ArgumentException>(() => Aes256.Decrypt(Array.Empty<byte>(), invalidKey));
Assert.Throws<ArgumentException>(() => aes256.Encrypt(original, invalidKey));
Assert.Throws<ArgumentException>(() => aes256.Decrypt(Array.Empty<byte>(), invalidKey));
}

[Fact]
public void EncryptDecryptWithShortKey_ShouldThrowException()
{
var aes256 = new Aes256(new Aes256Options());
var shortKey = Convert.ToBase64String(new byte[15]); // Less than 256 bits
const string original = "MySensitiveData";

Assert.Throws<ArgumentException>(() => Aes256.Encrypt(original, shortKey));
Assert.Throws<ArgumentException>(() => Aes256.Decrypt(Array.Empty<byte>(), shortKey));
Assert.Throws<ArgumentException>(() => aes256.Encrypt(original, shortKey));
Assert.Throws<ArgumentException>(() => aes256.Decrypt(Array.Empty<byte>(), shortKey));
}

[Fact]
public void EncryptDecryptWithEmptyText_ShouldThrowException()
{
var aes256 = new Aes256(new Aes256Options());
var key = Random.GenerateAes256KeyString();
var original = string.Empty;

Assert.Throws<ArgumentException>(() => Aes256.Encrypt(original, key));
Assert.Throws<ArgumentException>(() => Aes256.Decrypt(Array.Empty<byte>(), key));
Assert.Throws<ArgumentException>(() => aes256.Encrypt(original, key));
Assert.Throws<ArgumentException>(() => aes256.Decrypt(Array.Empty<byte>(), key));
}

[Fact]
public void EncryptDecryptWithNullCipher_ShouldThrowException()
{
var aes256 = new Aes256(new Aes256Options());
var key = Random.GenerateAes256KeyString();

Assert.Throws<ArgumentException>(() => Aes256.Decrypt(null!, key));
Assert.Throws<ArgumentException>(() => aes256.Decrypt(null!, key));
}
}
36 changes: 25 additions & 11 deletions Pandatech.Crypto.Tests/Argon2IdTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,44 +2,58 @@

public class Argon2IdTests
{
[Fact]
public void HashVerify_ShouldFailForDifferentArgonConfigs()
{
var argon2Id = new Argon2Id(new Argon2IdOptions());
var argon2Id2 = new Argon2Id(new Argon2IdOptions { SaltSize = 16, MemorySize = 128, DegreeOfParallelism = 1, Iterations = 1 });
var password = RandomPassword.Generate(32, true, true, true, true);
var hash = argon2Id.HashPassword(password);
Assert.False(argon2Id2.VerifyHash(password, hash));
}

[Fact]
public void HashVerify_ShouldBeValid()
{
var argon2Id = new Argon2Id(new Argon2IdOptions());

var password = RandomPassword.Generate(32, true, true, true, true);
var hash = Argon2Id.HashPassword(password);
var hash = argon2Id.HashPassword(password);

Assert.True(Argon2Id.VerifyHash(password, hash));
Assert.True(argon2Id.VerifyHash(password, hash));
}

[Fact]
public void HashVerify_InvalidPassword_ShouldBeInvalid()
{
var argon2Id = new Argon2Id(new Argon2IdOptions());
var password = RandomPassword.Generate(32, true, true, true, true);
var hash = Argon2Id.HashPassword(password);


var hash = argon2Id.HashPassword(password);
}

[Fact]
public void DifferentPasswords_ShouldHaveDifferentHashes()
{
var argon2Id = new Argon2Id(new Argon2IdOptions());
var password1 = RandomPassword.Generate(32, true, true, true, true);
var password2 = RandomPassword.Generate(32, true, true, true, true);
var hash1 = Argon2Id.HashPassword(password1);
var hash2 = Argon2Id.HashPassword(password2);
var hash1 = argon2Id.HashPassword(password1);
var hash2 = argon2Id.HashPassword(password2);

Assert.NotEqual(hash1, hash2);
}

[Fact]
public void HashPassword_EmptyPassword_ShouldThrowException()
{
Assert.Throws<ArgumentException>(() => Argon2Id.HashPassword(""));
var argon2Id = new Argon2Id(new Argon2IdOptions());
Assert.Throws<ArgumentException>(() => argon2Id.HashPassword(""));
}

[Fact]
public void VerifyHash_NullHash_ShouldThrowException()
{
Assert.Throws<ArgumentException>(() => Argon2Id.VerifyHash("password", null!));
var argon2Id = new Argon2Id(new Argon2IdOptions());
Assert.Throws<ArgumentException>(() => argon2Id.VerifyHash("password", null!));
}
}
92 changes: 92 additions & 0 deletions Pandatech.Crypto.Tests/HostBuilderTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
using Microsoft.Extensions.DependencyInjection;

namespace Pandatech.Crypto.Tests;

public class HostBuilderTests
{
[Fact]
public void AddPandatechCryptoAes256_RegistersServicesCorrectly()
{
// Arrange
var services = new ServiceCollection();

// Act
services.AddPandatechCryptoAes256(options =>
{
options.Key = "abd";
});

// Assert
var serviceProvider = services.BuildServiceProvider();
var aes256Options = serviceProvider.GetRequiredService<Aes256Options>();
var aes256 = serviceProvider.GetRequiredService<Aes256>();

Assert.NotNull(aes256Options);
Assert.Equal("abd", aes256Options.Key);
Assert.NotNull(aes256);
}
[Fact]
public void AddPandatechCryptoAes256_RegistersAsSingleton()
{
// Arrange
var services = new ServiceCollection();

// Act
services.AddPandatechCryptoAes256(options =>
{
options.Key = "abd";
});

var serviceProvider = services.BuildServiceProvider();

// Assert
var aes256Instance1 = serviceProvider.GetRequiredService<Aes256>();
var aes256Instance2 = serviceProvider.GetRequiredService<Aes256>();

Assert.Same(aes256Instance1, aes256Instance2);
}
[Fact]
public void AddPandatechCryptoArgon2Id_RegistersServicesCorrectly()
{
// Arrange
var services = new ServiceCollection();

// Act
services.AddPandatechCryptoArgon2Id(options =>
{
options.Iterations = 4;
// ... other configurations
});

// Assert
var serviceProvider = services.BuildServiceProvider();
var argon2IdOptions = serviceProvider.GetRequiredService<Argon2IdOptions>();
var argon2Id = serviceProvider.GetRequiredService<Argon2Id>();

Assert.NotNull(argon2IdOptions);
Assert.Equal(4, argon2IdOptions.Iterations);
Assert.NotNull(argon2Id);
}
[Fact]
public void AddPandatechCryptoArgon2Id_RegistersAsSingleton()
{
// Arrange
var services = new ServiceCollection();

// Act
services.AddPandatechCryptoArgon2Id(options =>
{
options.Iterations = 4;
// ... other configurations
});

var serviceProvider = services.BuildServiceProvider();

// Assert
var argon2IdInstance1 = serviceProvider.GetRequiredService<Argon2Id>();
var argon2IdInstance2 = serviceProvider.GetRequiredService<Argon2Id>();

Assert.Same(argon2IdInstance1, argon2IdInstance2);
}

}
35 changes: 12 additions & 23 deletions Pandatech.Crypto/Aes256.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,20 +2,21 @@

namespace Pandatech.Crypto;

public static class Aes256
public class Aes256
{
private static readonly string Key = Environment.GetEnvironmentVariable("AES_KEY")!;
private readonly Aes256Options _options;
private const int KeySize = 256;
private const int IvSize = 16;
private const int HashSize = 64;

public static byte[] Encrypt(string plainText)
public Aes256(Aes256Options options)
{
return Encrypt(plainText, Key);
_options = options ?? throw new ArgumentNullException(nameof(options));
}

public static byte[] Encrypt(string plainText, string key)
public byte[] Encrypt(string plainText, string? key = null)
{
key ??= _options.Key;
ValidateInputs(plainText, key);
using var aesAlg = Aes.Create();
aesAlg.KeySize = KeySize;
Expand All @@ -37,13 +38,9 @@ public static byte[] Encrypt(string plainText, string key)
return result;
}

public static string Decrypt(byte[] cipherText)
{
return Decrypt(cipherText, Key);
}

public static string Decrypt(byte[] cipherText, string key)
public string Decrypt(byte[] cipherText, string? key = null)
{
key ??= _options.Key;
ValidateInputs(cipherText, key);
var iv = cipherText.Take(IvSize).ToArray();
var encrypted = cipherText.Skip(IvSize).ToArray();
Expand All @@ -62,25 +59,17 @@ public static string Decrypt(byte[] cipherText, string key)
return srDecrypt.ReadToEnd();
}

public static byte[] EncryptWithHash(string plainText)
{
return EncryptWithHash(plainText, Key);
}

public static byte[] EncryptWithHash(string plainText, string key)
public byte[] EncryptWithHash(string plainText, string? key = null)
{
key ??= _options.Key;
var encryptedBytes = Encrypt(plainText, key);
var hashBytes = Sha3.Hash(plainText);
return hashBytes.Concat(encryptedBytes).ToArray();
}

public static string DecryptIgnoringHash(IEnumerable<byte> cipherTextWithHash)
{
return DecryptIgnoringHash(cipherTextWithHash, Key);
}

public static string DecryptIgnoringHash(IEnumerable<byte> cipherTextWithHash, string key)
public string DecryptIgnoringHash(IEnumerable<byte> cipherTextWithHash, string? key = null)
{
key ??= _options.Key;
var cipherText = cipherTextWithHash.Skip(HashSize).ToArray();
return Decrypt(cipherText, key);
}
Expand Down
Loading

0 comments on commit 4323961

Please sign in to comment.