Skip to content

Commit 104ac6b

Browse files
authored
Merge pull request #55 from selfmadecode/unit-tests
Test: Add unit tests for AES encryption and decryption
2 parents 8663485 + 8e8ef52 commit 104ac6b

12 files changed

Lines changed: 406 additions & 129 deletions

File tree

README.md

Lines changed: 6 additions & 83 deletions
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,12 @@ A C# library for encryption and decryption.
55
## Overview
66

77
The SafeCrypt library provides a set of methods for encrypting and decrypting data using various encryption algorithms,
8-
including the Advanced Encryption Standard (AES) and RSA (Rivest–Shamir–Adleman).
8+
including the Advanced Encryption Standard (AES) and RSA (Rivest–Shamir–Adleman).
99
It is designed to be easy to use and can be integrated into C# applications that require secure data transmission or storage.
1010
## Table of Contents
1111

1212
- [Installation](#installation)
13-
- [AES Encryption and Decryption usage](#usage)
13+
- [AES Encryption and Decryption usage](#aes)
1414
- [RSA Encryption and Decryption usage](#rsa)
1515
- [Contributing](#contributing)
1616
- [License](#license)
@@ -34,88 +34,11 @@ To use the SafeCrypt library in your C# project, follow these steps:
3434

3535
Now, you can reference the SafeCrypt library in your C# project.
3636

37-
## Usage
38-
39-
To use the AES encryption in your C# application,
40-
instantiate the `AesEncryption` or `AesDecryption` class and call the provided methods. Here's a simple example:
41-
42-
```csharp
43-
using SafeCrypt.AES;
44-
using SafeCrypt.Models;
45-
46-
class Program
47-
{
48-
static async Task Main()
49-
{
50-
51-
var encryptedData = await Aes.EncryptToBase64StringAsync("Hello, World!", "gdjdtsraewsuteastwerse=="
52-
53-
Console.WriteLine($"Encrypted Data: {encryptedData.EncryptedData}");
54-
Console.WriteLine($"Initialization Vector: {encryptedData.Iv}");
55-
56-
var parameterToDecrypt = new DecryptionParameters
57-
{
58-
DataToDecrypt = encryptedData.EncryptedData,
59-
SecretKey = encryptedData.SecretKey,
60-
IV = encryptedData.IV
61-
62-
};
63-
64-
var data = await Aes.DecryptFromBase64StringAsync(parameterToDecrypt)
65-
66-
Console.WriteLine($"Decrypted Data: {data.DecryptedData}");
67-
Console.WriteLine($"Initialization Vector: {data.Iv}");
68-
}
69-
}
70-
71-
72-
-------------------------------------------------------------------------------------------------------
73-
74-
using SafeCrypt.AES;
75-
using SafeCrypt.Models;
76-
77-
class Program
78-
{
79-
static async Task Main()
80-
{
81-
var dataToEncrypt = "Data to Encrypt";
82-
83-
var iv = "gyrthusdgythisdg";
84-
var secret = "hghjuytsdfraestwsgtere==";
85-
86-
var encryptionParam = new EncryptionParameters
87-
{
88-
DataToEncrypt = dataToEncrypt,
89-
IV = iv,
90-
SecretKey = secret
91-
};
92-
93-
94-
var response = await Aes.EncryptToBase64StringAsync(encryptionParam.DataToEncrypt, secret);
95-
96-
Console.WriteLine(response.EncryptedData);
97-
Console.WriteLine(response.Iv);
98-
Console.WriteLine(response.SecretKey);
99-
100-
101-
102-
var decryptorParam = new DecryptionParameters
103-
{
104-
IV = response.Iv,
105-
SecretKey = secret,
106-
DataToDecrypt = response.EncryptedData
107-
};
108-
109-
110-
var decryptionData = await Aes.DecryptFromBase64StringAsync(decryptorParam);
111-
112-
Console.WriteLine(decryptionData.DecryptedData);
113-
Console.WriteLine(decryptionData.Iv);
114-
Console.WriteLine(decryptionData.SecretKey);
115-
}
116-
}
117-
```
37+
## Aes
38+
To use AES encryption in your C# application, access the static Aes class directly.
39+
Call the provided methods;
11840

41+
Check the [Aes.md](doc/Aes.md) documentation for guidance.
11942

12043
## Rsa
12144
This library provides a straightforward implementation of RSA encryption and decryption in C# using the .NET `RSACryptoServiceProvider`.

SafeCrypt.sln

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,10 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SafeCrypt", "src\SafeCrypt.
1313
EndProject
1414
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SafeCrypt.App", "src\SafeCrypt.Test\SafeCrypt.App.csproj", "{DAD7FFA3-AABC-47FF-BA79-0C9531BFBBE6}"
1515
EndProject
16+
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "SafeCrypt.UnitTests", "SafeCrypt.UnitTests", "{5FC8B106-513E-4B2D-A2C0-2D5B5B76947C}"
17+
EndProject
18+
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SafeCrypt.UnitTests", "src\SafeCrypt.UnitTests\SafeCrypt.UnitTests.csproj", "{5A43627C-68E1-44E3-9866-DE15FE976392}"
19+
EndProject
1620
Global
1721
GlobalSection(SolutionConfigurationPlatforms) = preSolution
1822
Debug|Any CPU = Debug|Any CPU
@@ -27,6 +31,10 @@ Global
2731
{DAD7FFA3-AABC-47FF-BA79-0C9531BFBBE6}.Debug|Any CPU.Build.0 = Debug|Any CPU
2832
{DAD7FFA3-AABC-47FF-BA79-0C9531BFBBE6}.Release|Any CPU.ActiveCfg = Release|Any CPU
2933
{DAD7FFA3-AABC-47FF-BA79-0C9531BFBBE6}.Release|Any CPU.Build.0 = Release|Any CPU
34+
{5A43627C-68E1-44E3-9866-DE15FE976392}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
35+
{5A43627C-68E1-44E3-9866-DE15FE976392}.Debug|Any CPU.Build.0 = Debug|Any CPU
36+
{5A43627C-68E1-44E3-9866-DE15FE976392}.Release|Any CPU.ActiveCfg = Release|Any CPU
37+
{5A43627C-68E1-44E3-9866-DE15FE976392}.Release|Any CPU.Build.0 = Release|Any CPU
3038
EndGlobalSection
3139
GlobalSection(SolutionProperties) = preSolution
3240
HideSolutionNode = FALSE
@@ -36,6 +44,8 @@ Global
3644
{1D91E775-F63F-4537-B81E-B8F9A6480D6D} = {0B7C0C60-9850-4554-AF85-86C0378B6B16}
3745
{AE9FAE54-9854-4F98-A60F-19125CEAA3A8} = {8507D130-9F07-426C-8EE6-0AC714CF72E5}
3846
{DAD7FFA3-AABC-47FF-BA79-0C9531BFBBE6} = {1D91E775-F63F-4537-B81E-B8F9A6480D6D}
47+
{5FC8B106-513E-4B2D-A2C0-2D5B5B76947C} = {0B7C0C60-9850-4554-AF85-86C0378B6B16}
48+
{5A43627C-68E1-44E3-9866-DE15FE976392} = {5FC8B106-513E-4B2D-A2C0-2D5B5B76947C}
3949
EndGlobalSection
4050
GlobalSection(ExtensibilityGlobals) = postSolution
4151
SolutionGuid = {639A4359-2BA4-4F71-9EBF-D6EAB68C84CB}

doc/Aes.md

Lines changed: 172 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,172 @@
1+
# SafeCrypt AES Encryption and Decryption
2+
3+
## Overview
4+
5+
The SafeCrypt library provides a simple and secure implementation of the Advanced Encryption Standard (AES) algorithm for
6+
encryption and decryption in C#.
7+
This document guides you through the basic steps to use AES encryption and decryption methods.
8+
9+
## Table of Contents
10+
11+
- [Usage](#usage)
12+
- [EncryptToHexStringAsync method](#encryptToHexStringAsync-method)
13+
- [Encrypting Data](#encrypting-data)
14+
- [Decrypting Data](#decrypting-data)
15+
- [EncryptToBase64StringAsync method](#encryptToBase64StringAsync-method)
16+
- [Example](#example)
17+
- [EncryptionData Object](#encryptiondata-object)
18+
- [Cipher Modes](#cipher-modes)
19+
- [Contributing](#contributing)
20+
21+
## Usage
22+
23+
### EncryptToHexStringAsync method
24+
25+
#### Encrypting Data
26+
27+
To encrypt data using the AES algorithm in this library, you first need to decide which method you want to use.
28+
The `EncryptToHexStringAsync` method returns a hexadecimal string, while `EncryptToBase64StringAsync` returns a Base64 string.
29+
Follow the steps below to use `EncryptToHexStringAsync`:
30+
31+
1. **Generate an IV Key:** Use the `KeyGenerators.GenerateHexadecimalIVKey()` method to create an Initialization Vector (IV) key. The IV is crucial for secure encryption.
32+
33+
2. **Generate a Secret Key:** Call `KeyGenerators.GenerateAesSecretKey(128)` to generate a secret key with the desired bit size. Supported bit sizes are 128, 192, or 256. Any other value will result in an exception.
34+
35+
3. **Create an EncryptionParameters Model:** Construct an `EncryptionParameters` model, providing the data to be encrypted, IV, and secret key.
36+
37+
4. **Call EncryptToHexStringAsync:** Invoke the `Aes.EncryptToHexStringAsync` method with the `EncryptionParameters` model to encrypt the data. Check for errors in the `Errors` property of the returned `EncryptionData` object.
38+
39+
#### Decrypting Data
40+
41+
To decrypt data encrypted with AES, follow these steps:
42+
43+
1. **Create a DecryptionParameters Model:** Build a `DecryptionParameters` model, providing the encrypted data, IV, and secret key used during encryption.
44+
45+
2. **Call DecryptFromHexStringAsync:** Use the `Aes.DecryptFromHexStringAsync` method with the `DecryptionParameters` model to decrypt the data. Ensure that the provided IV and secret key match those used during encryption.
46+
47+
48+
49+
### EncryptToBase64StringAsync method
50+
To use the EncryptToBase64StringAsync method for encryption, follow these steps:
51+
52+
Generate an Initialization Vector (IV) using the KeyGenerators.GenerateBase64IVKey() method.
53+
Generate a secret key by calling the KeyGenerators.GenerateAesSecretKey(256) method. The parameter for this method accepts the following values: 128, 192, 256. Any value aside from these throws an exception with the message "Invalid key size. Supported sizes are 128, 192, or 256 bits."
54+
To encrypt the data, provide the EncryptionParameters model to the EncryptToBase64StringAsync method, along with an optional cipher mode. The cipher mode defaults to CBC if not specified.
55+
56+
57+
## Example
58+
59+
```csharp
60+
using SafeCrypt.AES;
61+
using SafeCrypt.Helpers;
62+
using SafeCrypt.Models;
63+
64+
// Using the EncryptToHexStringAsync and DecryptFromHexStringAsync methods
65+
66+
var aesIv = KeyGenerators.GenerateHexadecimalIVKey();
67+
var secret = KeyGenerators.GenerateAesSecretKey(256);
68+
69+
var dataToEncrypt = "Hello World";
70+
71+
var data = new EncryptionParameters
72+
{
73+
Data = dataToEncrypt,
74+
IV = aesIv,
75+
SecretKey = secret
76+
};
77+
78+
Console.WriteLine($"Hex Encryption Started");
79+
80+
Console.WriteLine();
81+
Console.WriteLine();
82+
83+
var encryptionResult = await Aes.EncryptToHexStringAsync(data);
84+
85+
if (encryptionResult.Errors.Count > 0)
86+
{
87+
// List errors here
88+
}
89+
90+
Console.WriteLine($"Hex Encrypted data: {encryptionResult.EncryptedData}");
91+
Console.WriteLine($"IV key: {encryptionResult.Iv}");
92+
Console.WriteLine($"Secret key: {encryptionResult.SecretKey}");
93+
94+
Console.WriteLine();
95+
Console.WriteLine();
96+
97+
Console.WriteLine($"Hex Decryption Started");
98+
99+
// Perform decryption using the same IV and secret
100+
var decryptionResult = await Aes.DecryptFromHexStringAsync(new DecryptionParameters
101+
{
102+
Data = encryptionResult.EncryptedData,
103+
IV = aesIv,
104+
SecretKey = secret
105+
});
106+
107+
Console.WriteLine($"Hex Decrypted data: {decryptionResult.DecryptedData}");
108+
Console.WriteLine($"IV key: {decryptionResult.Iv}");
109+
Console.WriteLine($"Secret key: {decryptionResult.SecretKey}");
110+
111+
112+
// Using the EncryptToBase64StringAsync and DecryptFromBase64StringAsync methods
113+
114+
var base64AesIv = KeyGenerators.GenerateBase64IVKey();
115+
116+
var base64dataToEncrypt = new EncryptionParameters
117+
{
118+
Data = dataToEncrypt,
119+
IV = base64AesIv,
120+
SecretKey = secret
121+
};
122+
123+
Console.WriteLine();
124+
Console.WriteLine();
125+
126+
127+
Console.WriteLine($"Base64 Encryption Started");
128+
129+
Console.WriteLine();
130+
Console.WriteLine();
131+
132+
var encryptedResult = await Aes.EncryptToBase64StringAsync(base64dataToEncrypt);
133+
Console.WriteLine($"Base64 Encrypted data: {encryptedResult.EncryptedData}");
134+
Console.WriteLine($"IV key: {encryptedResult.Iv}");
135+
Console.WriteLine($"Secret key: {encryptedResult.SecretKey}");
136+
137+
138+
Console.WriteLine();
139+
Console.WriteLine();
140+
141+
Console.WriteLine($"Base64 Decryption Started");
142+
143+
var decryptionResponse = await Aes.DecryptFromBase64StringAsync(new DecryptionParameters
144+
{
145+
Data = encryptedResult.EncryptedData,
146+
IV = base64AesIv,
147+
SecretKey = secret
148+
});
149+
150+
Console.WriteLine($"Base64 Decrypted data: {decryptionResponse.DecryptedData}");
151+
Console.WriteLine($"IV key: {decryptionResponse.Iv}");
152+
Console.WriteLine($"Secret key: {decryptionResponse.SecretKey}");
153+
```
154+
155+
## EncryptionData Object
156+
157+
The Encryption methods returns an `EncryptionData` object with the following properties:
158+
159+
- `EncryptedData`: Holds the encrypted data as a hexadecimal string.
160+
- `Iv`: The Initialization Vector used for encryption.
161+
- `SecretKey`: The secret key used for encryption.
162+
- `HasError`: If an error occurs during encryption, this property is set to true.
163+
- `Errors`: A list of all errors that occurred during encryption.
164+
165+
## Cipher Modes
166+
167+
By default, the methods uses Cipher Block Chaining (CBC) mode for both encryption and decryption.
168+
If you change the mode during encryption, provide the same mode during decryption.
169+
170+
## Contributing
171+
172+
Contributions to the SafeCrypt library are welcome! Follow the contribution guidelines and feel free to open issues or submit pull requests.

src/SafeCrypt.Lib/Encryption/AesEncryption/Encrypting.cs

Lines changed: 17 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -84,33 +84,41 @@ public static async Task<EncryptionData> EncryptToHexStringAsync(EncryptionParam
8484
/// <exception cref="FormatException">
8585
/// Thrown if the base64secretKey is not a valid Base64-encoded string.
8686
/// </exception>
87-
public static async Task<EncryptionData> EncryptToBase64StringAsync(string dataToBeEncrypted, string base64secretKey, CipherMode mode = CipherMode.CBC)
87+
public static async Task<EncryptionData> EncryptToBase64StringAsync(EncryptionParameters param, CipherMode mode = CipherMode.CBC)
8888
{
8989
// validate is base64
90-
if (!Validators.IsBase64String(base64secretKey))
90+
var responseData = new EncryptionData();
91+
92+
var parameterValidation = ValidateEncryptionParameters(param);
93+
94+
if (parameterValidation.HasError)
9195
{
92-
return null;
96+
return parameterValidation;
9397
}
9498

95-
NullChecks(data: dataToBeEncrypted, base64secretKey);
99+
if (!Validators.IsBase64String(param.SecretKey))
100+
{
101+
AddError(responseData, "Secret Key not base64");
102+
}
96103

97104
// Generate a random 16-byte IV for AES in CBC mode
98-
var aesIv = KeyGenerators.GenerateRandomIVKeyAsBytes(16);
105+
byte[] aesIv = Convert.FromBase64String(param.IV);
106+
99107

100108
var byteEncryptionParameters = new ByteEncryptionParameters
101109
{
102-
SecretKey = Convert.FromBase64String(base64secretKey),
110+
SecretKey = Convert.FromBase64String(param.SecretKey),
103111
IV = aesIv,
104-
Data = dataToBeEncrypted.ConvertToHexString().HexadecimalStringToByteArray()
112+
Data = param.Data.ConvertToHexString().HexadecimalStringToByteArray()
105113
};
106114

107115
var response = await BaseAesEncryption.EncryptAsync(byteEncryptionParameters, mode);
108116

109117
return new EncryptionData
110118
{
111119
EncryptedData = Convert.ToBase64String(response),
112-
Iv = Convert.ToBase64String(aesIv),
113-
SecretKey = base64secretKey
120+
Iv = param.IV,
121+
SecretKey = param.SecretKey
114122
};
115123
}
116124

src/SafeCrypt.Lib/Helpers/Converters.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ public static string ConvertToHexString(this string input)
5858
}
5959

6060
/// <summary>
61-
/// Converts a string to bytes and validates the resulting byte array.
61+
/// Converts a string to byte array.
6262
/// </summary>
6363
/// <param name="input">The input string to convert.</param>
6464
/// <returns>The byte array representation of the input string if valid; otherwise, null.</returns>

src/SafeCrypt.Lib/Helpers/KeyGenerators.cs

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,12 +42,18 @@ public static byte[] GenerateRandomIVKeyAsBytes(int length)
4242
/// <see cref="BitConverter.ToString"/>. Any hyphens in the resulting string are removed
4343
/// using <see cref="string.Replace"/>.
4444
/// </remarks>
45-
public static string GenerateRandomIVKeyAsString()
45+
public static string GenerateHexadecimalIVKey()
4646
{
4747
byte[] randomBytes = GenerateRandomIVKeyAsBytes(16);
4848
return BitConverter.ToString(randomBytes).Replace("-", "");
4949
}
5050

51+
public static string GenerateBase64IVKey()
52+
{
53+
byte[] randomBytes = GenerateRandomIVKeyAsBytes(16);
54+
return Convert.ToBase64String(randomBytes);
55+
}
56+
5157
/// <summary>
5258
/// Generates a valid AES secret key with the specified key size.
5359
/// </summary>

0 commit comments

Comments
 (0)