diff --git a/README.md b/README.md index 6965cd2..a27e036 100644 --- a/README.md +++ b/README.md @@ -4,14 +4,14 @@ A C# library for encryption and decryption. ## Overview -The Encryption library provides a set of methods for encrypting and decrypting data using the Advanced Encryption Standard (AES) algorithm, and other algorithm. It is designed to be easy to use and can be integrated into C# applications that require secure data transmission or storage. - +The SafeCrypt library provides a set of methods for encrypting and decrypting data using various encryption algorithms, +including the Advanced Encryption Standard (AES) and RSA (Rivest�Shamir�Adleman). +It is designed to be easy to use and can be integrated into C# applications that require secure data transmission or storage. ## Table of Contents - [Installation](#installation) -- [Usage](#usage) -- [API Reference](#api-reference) -- [Examples](#examples) +- [AES Encryption and Decryption usage](#usage) +- [RSA Encryption and Decryption usage](#rsa) - [Contributing](#contributing) - [License](#license) @@ -34,9 +34,10 @@ To use the SafeCrypt library in your C# project, follow these steps: Now, you can reference the SafeCrypt library in your C# project. -## Basic Usage +## Usage -To use the library in your C# application, instantiate the `AesEncryption` or `AesDecryption` class and call the provided methods. Here's a simple example: +To use the AES encryption in your C# application, +instantiate the `AesEncryption` or `AesDecryption` class and call the provided methods. Here's a simple example: ```csharp using SafeCrypt.AESDecryption; @@ -122,6 +123,14 @@ class Program } ``` + +## Rsa +This library provides a straightforward implementation of RSA encryption and decryption in C# using the .NET `RSACryptoServiceProvider`. +It includes methods for generating RSA key pairs, encrypting data with a public key, and decrypting data with a private key. + +For more details on RSA Encryption, check the [Rsa.md](doc/Rsa.md) document. + + ## Contributing If you would like to contribute to the development of the SafeCrypt library, follow these steps: diff --git a/doc/Rsa.md b/doc/Rsa.md new file mode 100644 index 0000000..0d9a2d0 --- /dev/null +++ b/doc/Rsa.md @@ -0,0 +1,90 @@ +# RSA Encryption and Decryption + +## Overview + +This library provides a straightforward implementation of RSA encryption and decryption in C# using the .NET `RSACryptoServiceProvider`. +It includes methods for generating RSA key pairs, encrypting data with a public key, and decrypting data with a private key. + +## Table of Contents + +- [Usage](#usage) + - [Generate RSA Keys](#generate-rsa-keys) + - [Encrypt and Decrypt using RSA](#encrypt-and-decrypt-using-rsa) + +## Usage + +### Generate RSA Keys + +```csharp +using SafeCrypt.Helpers; +using SafeCrypt.RsaEncryption; + +var rsaKeyPair = KeyGenerators.GenerateRsaKeys(2048); + +string rsaPublicKey = rsaKeyPair.Item1; +string rsaPrivateKey = rsaKeyPair.Item2; + +Console.WriteLine($"Public Key: {rsaPublicKey}"); +Console.WriteLine($"Private Key: {rsaPrivateKey}"); +``` + +### Encrypt and Decrypt using RSA + +```csharp + using SafeCrypt.RsaEncryption; + + // Encrypt + string originalData = "Hello, RSA Encryption!"; + + var encryptionModel = new RsaEncryptionParameters + { + DataToEncrypt = originalData, + PublicKey = rsaPublicKey, + }; + + var encryptedData = await Rsa.EncryptAsync(encryptionModel); + + Console.WriteLine($"Original Data: {originalData}"); + Console.WriteLine("Encrypted Data: " + BitConverter.ToString(encryptedData.EncryptedData)); + + // Convert encrypted byte array to Base64 string + string encryptedDataConvertedString = Convert.ToBase64String(encryptedData.EncryptedData); + + // Convert string back to byte array for decryption + byte[] convertedBytes = Convert.FromBase64String(encryptedDataConvertedString); + + bool arraysAreEqual = StructuralComparisons.StructuralEqualityComparer.Equals(encryptedData.EncryptedData, convertedBytes); + Console.WriteLine("Original and converted byte arrays are equal: " + arraysAreEqual); // should return true + + + + // Decrypt + var decryptionModel = new RsaDecryptionParameters + { + DataToDecrypt = convertedBytes, // encryptedData.EncryptedData + PrivateKey = rsaPrivateKey, + }; + + var decryptedData = await Rsa.DecryptAsync(decryptionModel); + + // if Error occurs during encryption + if (decryptedData.Errors.Count > 0) + { + Console.WriteLine("Decryption Errors:"); + foreach (var error in decryptedData.Errors) + { + Console.WriteLine(error); + } + } + else + { + Console.WriteLine($"Decrypted Data: {decryptedData.DecryptedData}"); + } + +// Note: The return type from Rsa.EncryptAsync is `EncryptionResult`, and Rsa.DecryptAsync is `DecryptionResult`. +// Both models include a list of errors encountered during encryption/decryption. + +``` +## Contributing + +Contributions are welcome! Feel free to open issues, submit pull requests, or provide feedback. \ No newline at end of file diff --git a/src/SafeCrypt.Lib/Encryption/RsaEncryption/Models/Encrypt/RsaEncryptionParameters.cs b/src/SafeCrypt.Lib/Encryption/RsaEncryption/Models/Encrypt/RsaEncryptionParameters.cs new file mode 100644 index 0000000..d688ff6 --- /dev/null +++ b/src/SafeCrypt.Lib/Encryption/RsaEncryption/Models/Encrypt/RsaEncryptionParameters.cs @@ -0,0 +1,34 @@ +using System.ComponentModel.DataAnnotations; + +namespace SafeCrypt.RsaEncryption +{ + public sealed class RsaEncryptionParameters : IEncryptionData + { + /// + /// Gets or sets the public key for RSA encryption. + /// + [Required] + public string PublicKey { get; set; } + + /// + /// Gets or sets the data to be encrypted using RSA. + /// + [Required] + public string DataToEncrypt { get; set; } + } + + public sealed class RsaDecryptionParameters + { + /// + /// Gets or sets the public key for RSA encryption. + /// + [Required] + public string PrivateKey { get; set; } + + /// + /// Gets or sets the data to be encrypted using RSA. + /// + [Required] + public byte[] DataToDecrypt { get; set; } + } +} diff --git a/src/SafeCrypt.Lib/Encryption/RsaEncryption/Models/RsaEncryptionResult.cs b/src/SafeCrypt.Lib/Encryption/RsaEncryption/Models/RsaEncryptionResult.cs new file mode 100644 index 0000000..95d21d8 --- /dev/null +++ b/src/SafeCrypt.Lib/Encryption/RsaEncryption/Models/RsaEncryptionResult.cs @@ -0,0 +1,94 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace SafeCrypt.RsaEncryption.Models +{ + public class RsaEncryptionResult + { + /// + /// Gets or sets the encrypted data. + /// + public byte[] EncryptedData { get; set; } + + /// + /// Gets or sets the list of errors encountered during encryption. + /// + public List Errors { get; set; } + + /// + /// Initializes a new instance of the class. + /// + public RsaEncryptionResult() + { + Errors = new List(); + } + } + + public class RsaDecryptionResult + { + /// + /// Gets or sets the encrypted data. + /// + public byte[] DecryptedData { get; set; } + + /// + /// Gets or sets the list of errors encountered during encryption. + /// + public List Errors { get; set; } + + ///// + ///// Gets or sets the public key used for encryption. + ///// + //public string PublicKey { get; set; } + + /// + /// Gets or sets the private key used for encryption. + /// + public string PrivateKey { get; set; } + + /// + /// Initializes a new instance of the class. + /// + public RsaDecryptionResult() + { + Errors = new List(); + } + } + + public class EncryptionResult + { + /// + /// Gets or sets the list of errors encountered during encryption. + /// + public List Errors { get; set; } + + /// + /// Gets or sets the encrypted data. + /// + public byte[] EncryptedData { get; set; } + + public EncryptionResult() + { + Errors = new List(); + } + } + + public class DecryptionResult + { + /// + /// Gets or sets the list of errors encountered during encryption. + /// + public List Errors { get; set; } + + /// + /// Gets or sets the encrypted data. + /// + public string DecryptedData { get; set; } + + public DecryptionResult() + { + Errors = new List(); + } + } +} diff --git a/src/SafeCrypt.Lib/Encryption/RsaEncryption/Rsa.cs b/src/SafeCrypt.Lib/Encryption/RsaEncryption/Rsa.cs new file mode 100644 index 0000000..22963f4 --- /dev/null +++ b/src/SafeCrypt.Lib/Encryption/RsaEncryption/Rsa.cs @@ -0,0 +1,75 @@ +using System; +using System.Text; +using System.Threading.Tasks; +using SafeCrypt.RsaEncryption.Models; + +namespace SafeCrypt.RsaEncryption +{ + + + public static class Rsa + { + /// + /// Asynchronously encrypts the specified data using RSA encryption. + /// + /// The parameters for RSA encryption. + /// An containing the encrypted data, and errors (if any). + public static async Task EncryptAsync(RsaEncryptionParameters model) + { + var result = new EncryptionResult(); + + if(string.IsNullOrWhiteSpace(model.DataToEncrypt)) + { + result.Errors.Add($"Data cannot be null {nameof(model.DataToEncrypt)}"); + return result; + } + + if (string.IsNullOrWhiteSpace(model.PublicKey)) + { + result.Errors.Add($"PublicKey cannot be null {nameof(model.PublicKey)}"); + return result; + } + + // asynchronously perform RSA encryption + var data = await RsaEncryption.EncryptAsync(model.DataToEncrypt, model.PublicKey); + + if(data.Errors.Count > 0) + { + result.Errors.AddRange(data.Errors); + return result; + } + + result.EncryptedData = data.EncryptedData; + return result; + } + + public static async Task DecryptAsync(RsaDecryptionParameters model) + { + var result = new DecryptionResult(); + + if(model.DataToDecrypt == null) + { + result.Errors.Add($"DataToDecrypt cannot be null {nameof(model.DataToDecrypt)}"); + return result; + } + + if (string.IsNullOrWhiteSpace(model.PrivateKey)) + { + result.Errors.Add($"PrivateKey cannot be null {nameof(model.PrivateKey)}"); + return result; + } + + // asynchronously perform RSA encryption + var data = await RsaEncryption.DecryptAsync(model.DataToDecrypt, model.PrivateKey); + + if (data.Errors.Count > 0) + { + result.Errors.AddRange(data.Errors); + return result; + } + + result.DecryptedData = Encoding.UTF8.GetString(data.DecryptedData); + return result; + } + } +} diff --git a/src/SafeCrypt.Lib/Encryption/RsaEncryption/RsaEncryption.cs b/src/SafeCrypt.Lib/Encryption/RsaEncryption/RsaEncryption.cs new file mode 100644 index 0000000..a5cd195 --- /dev/null +++ b/src/SafeCrypt.Lib/Encryption/RsaEncryption/RsaEncryption.cs @@ -0,0 +1,89 @@ +using System.Security.Cryptography; +using System.Text; +using System; +using System.Threading.Tasks; +using SafeCrypt.RsaEncryption.Models; + +namespace SafeCrypt.RsaEncryption +{ + internal static class RsaEncryption + { + /// + /// Asynchronously encrypts the provided data using the RSA (Rivest–Shamir–Adleman) algorithm. + /// + /// The data to be encrypted. + /// The public key used for encryption. + /// + /// A task representing the asynchronous operation that, upon completion, + /// returns an containing the encrypted data. + /// + /// + /// This method uses the RSA algorithm to encrypt the input data with the provided public key. + /// The encryption is performed asynchronously using . + /// + /// The data to be encrypted. + /// The public key used for encryption. + /// + /// A task representing the asynchronous operation that, upon completion, + /// returns an containing the encrypted data. + /// + internal static async Task EncryptAsync(string data, string publicKey) + { + var result = new RsaEncryptionResult(); + + try + { + var encryptedData = await Task.Run(() => + { + using (var rsa = new RSACryptoServiceProvider()) + { + rsa.FromXmlString(publicKey); + byte[] dataBytes = Encoding.UTF8.GetBytes(data); + return rsa.Encrypt(dataBytes, false); + } + }); + + result.EncryptedData = encryptedData; + } + catch (Exception ex) + { + result.Errors.Add(ex.Message); + } + + return result; + } + + /// + /// Decrypts data using RSA private key. + /// + /// The encrypted data. + /// The RSA private key. + /// The decrypted data. + internal static async Task DecryptAsync(byte[] encryptedData, string privateKey) + { + var result = new RsaDecryptionResult(); + + try + { + var decryptedData = await Task.Run(() => + { + using (var rsa = new RSACryptoServiceProvider()) + { + rsa.FromXmlString(privateKey); + byte[] dataBytes = encryptedData; + return rsa.Decrypt(encryptedData, false); + } + }); + + result.DecryptedData = decryptedData; + + } + catch (Exception ex) + { + result.Errors.Add(ex.Message); + } + + return result; + } + } +} diff --git a/src/SafeCrypt.Lib/Helpers/KeyGenerators.cs b/src/SafeCrypt.Lib/Helpers/KeyGenerators.cs index 44a2c5a..3625465 100644 --- a/src/SafeCrypt.Lib/Helpers/KeyGenerators.cs +++ b/src/SafeCrypt.Lib/Helpers/KeyGenerators.cs @@ -67,5 +67,33 @@ public static string GenerateAesSecretKey(int keySize) return Convert.ToBase64String(aesAlg.Key); } } + + /// + /// Generates a pair of RSA public and private keys with the specified key size. + /// + /// The size of the key pair (e.g., 1024, 2048 bits). + /// + /// A containing the generated RSA public and private keys. + /// Item1 represents the public key, and Item2 represents the private key. + /// + /// + /// The generated keys are in XML format. The public key does not include the private key, + /// while the private key includes both public and private components. + /// + /// The size of the key pair (e.g., 1024, 2048 bits). + /// A tuple containing the generated RSA public and private keys. + /// + /// Thrown if an error occurs during key generation. + /// + public static Tuple GenerateRsaKeys(int keySize) + { + using (var rsa = new RSACryptoServiceProvider(keySize)) + { + string publicKey = rsa.ToXmlString(false); // Don't include private key + string privateKey = rsa.ToXmlString(true); // Include private key + + return new Tuple(publicKey, privateKey); + } + } } } diff --git a/src/SafeCrypt.Lib/Interface/IEncryptionData.cs b/src/SafeCrypt.Lib/Interface/IEncryptionData.cs new file mode 100644 index 0000000..b0418df --- /dev/null +++ b/src/SafeCrypt.Lib/Interface/IEncryptionData.cs @@ -0,0 +1,7 @@ +namespace SafeCrypt +{ + internal interface IEncryptionData + { + string DataToEncrypt { get; set; } + } +} diff --git a/src/SafeCrypt.Lib/SafeCrypt.csproj b/src/SafeCrypt.Lib/SafeCrypt.csproj index cf1749e..2368bc6 100644 --- a/src/SafeCrypt.Lib/SafeCrypt.csproj +++ b/src/SafeCrypt.Lib/SafeCrypt.csproj @@ -15,27 +15,26 @@ README.md True MitLicense.txt - SafeCrypt Library - Release Notes - Version 1.0.1 + SafeCrypt Library - Release Notes - Version 1.0.2 -This release (version 1.0.1) includes updates to the documentation and namespace changes. We have improved the README document to provide more comprehensive information about the library and made adjustments to the namespaces for better organization. +We are excited to announce the latest version of SafeCrypt (v1.0.2), featuring a significant enhancement to our encryption methods. In this release, all encryption operations are now asynchronous, providing improved performance and responsiveness. -Changes - -- Updated README document with detailed usage instructions, API references, and contribution guidelines. -- Made changes to namespaces for better organization and clarity in the codebase. +What's New: +Async Encryption and Decryption: +We have made all encryption methods asynchronous to better align with modern programming practices and enhance the overall responsiveness of SafeCrypt. Bug Fixes No bug fixes in this release. Upgrade Command: -dotnet add package SafeCrypt --version 1.0.1 +dotnet add package SafeCrypt --version 1.0.2 Feedback and Contributions: We appreciate your feedback and contributions! If you encounter any issues or have suggestions, please create an issue on GitHub: https://github.com/selfmadecode/SafeCrypt/issues Thank you for using the SafeCrypt Library! - 1.0.1 + 1.0.2 diff --git a/src/SafeCrypt.Test/Program.cs b/src/SafeCrypt.Test/Program.cs index 79b733e..8c3518c 100644 --- a/src/SafeCrypt.Test/Program.cs +++ b/src/SafeCrypt.Test/Program.cs @@ -36,5 +36,4 @@ Console.WriteLine($"IV key: {decryptionData.Iv}"); Console.WriteLine($"Secret key: {decryptionData.SecretKey}"); - -Console.WriteLine("Hello, World!"); +Console.ReadLine(); diff --git a/src/SafeCrypt.Test/Usage/RsaUsage.cs b/src/SafeCrypt.Test/Usage/RsaUsage.cs new file mode 100644 index 0000000..b9bb1ad --- /dev/null +++ b/src/SafeCrypt.Test/Usage/RsaUsage.cs @@ -0,0 +1,54 @@ +using SafeCrypt.Helpers; +using SafeCrypt.RsaEncryption; +using System.Collections; + +namespace SafeCrypt.App.Usage; + +internal class RsaUsage +{ + internal protected async void Usage() + { + // Example: Generate RSA keys + var rsaKeyPair = KeyGenerators.GenerateRsaKeys(2048); + + string rsaPublicKey = rsaKeyPair.Item1; + string rsaPrivateKey = rsaKeyPair.Item2; + + Console.WriteLine($"pubic key {rsaPublicKey}"); + Console.WriteLine($"private key {rsaPrivateKey}"); + + // Example: Encrypt and Decrypt using RSA + string originalData = "Hello, RSA Encryption!"; + + var enModel = new RsaEncryptionParameters + { + DataToEncrypt = originalData, + PublicKey = rsaPublicKey, + }; + + var encryptedData = await Rsa.EncryptAsync(enModel); + + Console.WriteLine($"Original Data: {originalData}"); + + Console.WriteLine("Original byte array: " + BitConverter.ToString(encryptedData.EncryptedData)); + string EncryptedDataconvertedString = Convert.ToBase64String(encryptedData.EncryptedData); + + byte[] convertedBytes = Convert.FromBase64String(EncryptedDataconvertedString); + + Console.WriteLine("Converted back to byte array: " + BitConverter.ToString(convertedBytes)); + bool arraysAreEqual = StructuralComparisons.StructuralEqualityComparer.Equals(encryptedData.EncryptedData, convertedBytes); + Console.WriteLine("Original and converted byte arrays are equal: " + arraysAreEqual); + + // Decrypting + var decryptionModel = new RsaDecryptionParameters + { + DataToDecrypt = convertedBytes, + PrivateKey = rsaPrivateKey + }; + + var decryptedData = await Rsa.DecryptAsync(decryptionModel); + Console.WriteLine($"{decryptedData.DecryptedData}"); + + Console.ReadLine(); + } +}