Skip to content

Commit

Permalink
Updated AES256 null checking
Browse files Browse the repository at this point in the history
  • Loading branch information
Haik committed Nov 2, 2023
1 parent c1a5eef commit 89c0d89
Show file tree
Hide file tree
Showing 5 changed files with 54 additions and 29 deletions.
15 changes: 7 additions & 8 deletions Pandatech.Crypto.Tests/Aes256Tests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ public void EncryptDecryptWithoutParameter_ShouldReturnOriginalString()
var aes256 = new Aes256(aes256Options);
Environment.SetEnvironmentVariable("AES_KEY", Random.GenerateAes256KeyString());
const string original = "MySensitiveData";
var encrypted = aes256.Encrypt(original,false);
var encrypted = aes256.Encrypt(original, false);
var decrypted = aes256.Decrypt(encrypted, false);

Assert.Equal(original, decrypted);
Expand Down Expand Up @@ -98,7 +98,6 @@ public void EncryptDecryptWithInvalidKey_ShouldThrowException()
const string original = "MySensitiveData";

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

[Fact]
Expand All @@ -113,22 +112,22 @@ public void EncryptDecryptWithShortKey_ShouldThrowException()
}

[Fact]
public void EncryptDecryptWithEmptyText_ShouldThrowException()
public void EncryptDecryptWithEmptyText_ShouldReturnEmptyString()
{
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));
var encrypted = aes256.Encrypt(original, key);
var decrypted = aes256.Decrypt(encrypted, key);
Assert.Equal(original, decrypted);
}

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

Assert.Throws<ArgumentNullException>(() => aes256.Decrypt(null!, key));
Assert.Equal("", aes256.Decrypt(Array.Empty<byte>(), key));
}
}
8 changes: 5 additions & 3 deletions Pandatech.Crypto.Tests/HostBuilderTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,10 @@ public void AddPandatechCryptoAes256_RegistersServicesCorrectly()
var services = new ServiceCollection();

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

// Assert
Expand All @@ -22,7 +23,7 @@ public void AddPandatechCryptoAes256_RegistersServicesCorrectly()
var aes256 = serviceProvider.GetRequiredService<Aes256>();

Assert.NotNull(aes256Options);
Assert.Equal("abd", aes256Options.Key);
Assert.Equal(key, aes256Options.Key);
Assert.NotNull(aes256);
}
[Fact]
Expand All @@ -34,7 +35,8 @@ public void AddPandatechCryptoAes256_RegistersAsSingleton()
// Act
services.AddPandatechCryptoAes256(options =>
{
options.Key = "abd";
options.Key = Random.GenerateAes256KeyString();
});

var serviceProvider = services.BuildServiceProvider();
Expand Down
43 changes: 27 additions & 16 deletions Pandatech.Crypto/Aes256.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,28 +14,37 @@ public Aes256(Aes256Options options)
_options = options ?? throw new ArgumentNullException(nameof(options));
}

public byte[] Encrypt(string plainText, bool addHashToBytes = true)
public byte[] Encrypt(string? plainText, bool addHashToBytes = true)
{
if (string.IsNullOrEmpty(plainText)) return Array.Empty<byte>();
return addHashToBytes ? EncryptWithHash(plainText) : Encrypt(plainText);
}
public byte[] Encrypt(string plainText, string key, bool addHashToBytes = true)

public byte[] Encrypt(string? plainText, string key, bool addHashToBytes = true)
{
ValidateKey(key);
if (string.IsNullOrEmpty(plainText)) return Array.Empty<byte>();
return addHashToBytes ? EncryptWithHash(plainText, key) : Encrypt(plainText, key);
}
public string Decrypt(byte[] cipherText, bool includesHash = true)

public string? Decrypt(byte[] cipherText, bool includesHash = true)
{
if (cipherText.Length == 0) return "";
return includesHash ? DecryptIgnoringHash(cipherText) : Decrypt(cipherText);
}
public string Decrypt(byte[] cipherText, string key, bool bytesIncludeHash = true)

public string? Decrypt(byte[] cipherText, string key, bool bytesIncludeHash = true)
{
ValidateKey(key);
if (cipherText.Length == 0) return "";
return bytesIncludeHash ? DecryptIgnoringHash(cipherText, key) : Decrypt(cipherText, key);
}


private byte[] Encrypt(string plainText, string? key)
{
key ??= _options.Key;
ValidateInputs(plainText, key);
ValidateText(plainText);
using var aesAlg = Aes.Create();
aesAlg.KeySize = KeySize;
aesAlg.Padding = PaddingMode.PKCS7;
Expand All @@ -55,12 +64,12 @@ private byte[] Encrypt(string plainText, string? key)
var result = aesAlg.IV.Concat(encryptedPasswordByte).ToArray();
return result;
}


private string Decrypt(byte[] cipherText, string? key)
{
key ??= _options.Key;
ValidateInputs(cipherText, key);
ValidateCipherText(cipherText);
var iv = cipherText.Take(IvSize).ToArray();
var encrypted = cipherText.Skip(IvSize).ToArray();

Expand Down Expand Up @@ -93,22 +102,24 @@ private string DecryptIgnoringHash(IEnumerable<byte> cipherTextWithHash, string?
return Decrypt(cipherText, key);
}

private static void ValidateInputs(string text, string key)
private static void ValidateKey(string key)
{
if (string.IsNullOrEmpty(text))
throw new ArgumentException("Text cannot be null or empty.");

if (string.IsNullOrEmpty(key) || !IsBase64String(key) || Convert.FromBase64String(key).Length != 32)
throw new ArgumentException("Invalid key.");
}

private static void ValidateInputs(byte[] cipherText, string key)
private static void ValidateText(string text)
{
if (string.IsNullOrEmpty(text) && text != null)
throw new ArgumentException("Text cannot be null or empty.");
}

private static void ValidateCipherText(byte[] cipherText)
{
if (cipherText.Length == 0) return;

if (cipherText == null || cipherText.Length < IvSize)
throw new ArgumentException("Invalid cipher text.");

if (string.IsNullOrEmpty(key) || !IsBase64String(key) || Convert.FromBase64String(key).Length != 32)
throw new ArgumentException("Invalid key.");
}

private static bool IsBase64String(string s)
Expand Down
13 changes: 13 additions & 0 deletions Pandatech.Crypto/HostBuilderExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ public static void AddPandatechCryptoAes256(this IServiceCollection services, Ac
{
var options = new Aes256Options();
configure(options);
ValidateKey(options.Key);
services.AddSingleton(options);
services.AddSingleton<Aes256>();
}
Expand All @@ -19,11 +20,23 @@ public static void AddPandatechCryptoArgon2Id(this IServiceCollection services,
services.AddSingleton(options);
services.AddSingleton<Argon2Id>();
}

private static void ValidateKey(string key)
{
if (string.IsNullOrEmpty(key) || !IsBase64String(key) || Convert.FromBase64String(key).Length != 32)
throw new ArgumentException("Invalid key.");
}

public static void AddPandatechCryptoArgon2Id(this IServiceCollection services)
{
var options = new Argon2IdOptions();
services.AddSingleton(options);
services.AddSingleton<Argon2Id>();
}

private static bool IsBase64String(string s)
{
var buffer = new Span<byte>(new byte[s.Length]);
return Convert.TryFromBase64String(s, buffer, out _);
}
}
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.4</Version>
<Version>2.1.5</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>Added Random Id Generator for internal use</PackageReleaseNotes>
<PackageReleaseNotes>Removed null checking on Aes256 Encrypt/Decrypt</PackageReleaseNotes>
</PropertyGroup>

<ItemGroup>
Expand Down

0 comments on commit 89c0d89

Please sign in to comment.