From d4b7091f021e8065e539364bb0cbabe8eaf4649c Mon Sep 17 00:00:00 2001 From: Ilya Rastrorguev Date: Fri, 8 Mar 2024 18:26:01 +0500 Subject: [PATCH] Add first release of Crypto Library Initial Crypto Modules and Hashing, CryptoController and CryptoFile classes --- DevsDaddy/Shared/CryptoLibrary/Core.meta | 3 + .../CryptoLibrary/Core/ICryptoProvider.cs | 36 + .../Core/ICryptoProvider.cs.meta | 3 + .../CryptoLibrary/Core/IProviderOptions.cs | 7 + .../Core/IProviderOptions.cs.meta | 3 + .../Shared/CryptoLibrary/CryptoController.cs | 72 ++ .../CryptoLibrary/CryptoController.cs.meta | 3 + DevsDaddy/Shared/CryptoLibrary/CryptoFile.cs | 180 +++++ .../Shared/CryptoLibrary/CryptoFile.cs.meta | 3 + .../Shared/CryptoLibrary/CryptoLibrary.asmdef | 3 + .../CryptoLibrary/CryptoLibrary.asmdef.meta | 7 + .../Shared/CryptoLibrary/CryptoModule.cs | 7 + .../Shared/CryptoLibrary/CryptoModule.cs.meta | 3 + DevsDaddy/Shared/CryptoLibrary/Modules.meta | 8 + .../Shared/CryptoLibrary/Modules/AES.meta | 3 + .../Modules/AES/AESEncryptionOptions.cs | 20 + .../Modules/AES/AESEncryptionOptions.cs.meta | 3 + .../CryptoLibrary/Modules/AES/AESProvider.cs | 120 +++ .../Modules/AES/AESProvider.cs.meta | 3 + .../Shared/CryptoLibrary/Modules/Base64.meta | 3 + .../Modules/Base64/Base64EncryptionOptions.cs | 11 + .../Base64/Base64EncryptionOptions.cs.meta | 3 + .../Modules/Base64/Base64Provider.cs | 66 ++ .../Modules/Base64/Base64Provider.cs.meta | 3 + .../CryptoLibrary/Modules/BlowFish.meta | 3 + .../BlowFish/BlowfishEncryptionOptions.cs | 12 + .../BlowfishEncryptionOptions.cs.meta | 3 + .../Modules/BlowFish/BlowfishProvider.cs | 458 +++++++++++ .../Modules/BlowFish/BlowfishProvider.cs.meta | 3 + .../Shared/CryptoLibrary/Modules/Crc32.meta | 3 + .../Modules/Crc32/CRC32EncryptionOptions.cs | 11 + .../Crc32/CRC32EncryptionOptions.cs.meta | 3 + .../Modules/Crc32/CRC32Provider.cs | 65 ++ .../Modules/Crc32/CRC32Provider.cs.meta | 3 + .../CryptoLibrary/Modules/Crc32/Crc32.cs | 110 +++ .../CryptoLibrary/Modules/Crc32/Crc32.cs.meta | 3 + .../Shared/CryptoLibrary/Modules/DES.meta | 3 + .../Modules/DES/DESEncryptionOptions.cs | 12 + .../Modules/DES/DESEncryptionOptions.cs.meta | 3 + .../CryptoLibrary/Modules/DES/DESProvider.cs | 98 +++ .../Modules/DES/DESProvider.cs.meta | 3 + .../Shared/CryptoLibrary/Modules/MD5.meta | 3 + .../Modules/MD5/MD5EncryptionOptions.cs | 11 + .../Modules/MD5/MD5EncryptionOptions.cs.meta | 3 + .../CryptoLibrary/Modules/MD5/MD5Provider.cs | 77 ++ .../Modules/MD5/MD5Provider.cs.meta | 3 + .../Shared/CryptoLibrary/Modules/PBKDF2.meta | 3 + .../Modules/PBKDF2/PBKDF2EncryptionOptions.cs | 14 + .../PBKDF2/PBKDF2EncryptionOptions.cs.meta | 3 + .../Modules/PBKDF2/PBKDF2Provider.cs | 126 +++ .../Modules/PBKDF2/PBKDF2Provider.cs.meta | 3 + .../CryptoLibrary/Modules/RIPEMD-160.meta | 3 + .../Modules/RIPEMD-160/RIPEMD160.cs | 17 + .../Modules/RIPEMD-160/RIPEMD160.cs.meta | 3 + .../Modules/RIPEMD-160/RIPEMD160Managed.cs | 444 +++++++++++ .../RIPEMD-160/RIPEMD160Managed.cs.meta | 3 + .../RIPEMD-160/RipemdEncryptionOptions.cs | 11 + .../RipemdEncryptionOptions.cs.meta | 3 + .../Modules/RIPEMD-160/RipemdProvider.cs | 65 ++ .../Modules/RIPEMD-160/RipemdProvider.cs.meta | 3 + .../Shared/CryptoLibrary/Modules/RSA.meta | 3 + .../Modules/RSA/RSAEncryptionOptions.cs | 14 + .../Modules/RSA/RSAEncryptionOptions.cs.meta | 3 + .../CryptoLibrary/Modules/RSA/RSAProvider.cs | 86 ++ .../Modules/RSA/RSAProvider.cs.meta | 3 + .../Shared/CryptoLibrary/Modules/SHA.meta | 3 + .../CryptoLibrary/Modules/SHA/SHA1Provider.cs | 77 ++ .../Modules/SHA/SHA1Provider.cs.meta | 3 + .../Modules/SHA/SHA256Provider.cs | 77 ++ .../Modules/SHA/SHA256Provider.cs.meta | 3 + .../Modules/SHA/SHA512Provider.cs | 77 ++ .../Modules/SHA/SHA512Provider.cs.meta | 3 + .../Modules/SHA/SHAEncryptionOptions.cs | 11 + .../Modules/SHA/SHAEncryptionOptions.cs.meta | 3 + .../CryptoLibrary/Modules/TripleDES.meta | 3 + .../TripleDES/TripleDESEncryptionOptions.cs | 16 + .../TripleDESEncryptionOptions.cs.meta | 3 + .../Modules/TripleDES/TripleDESProvider.cs | 87 ++ .../TripleDES/TripleDESProvider.cs.meta | 3 + .../Shared/CryptoLibrary/Modules/Twofish.meta | 3 + .../CryptoLibrary/Modules/Twofish/Twofish.cs | 749 ++++++++++++++++++ .../Modules/Twofish/Twofish.cs.meta | 3 + .../Twofish/TwofishEncryptionOptions.cs | 18 + .../Twofish/TwofishEncryptionOptions.cs.meta | 3 + .../Modules/Twofish/TwofishProvider.cs | 94 +++ .../Modules/Twofish/TwofishProvider.cs.meta | 3 + .../Shared/CryptoLibrary/Modules/XOR.meta | 3 + .../Modules/XOR/XOREncryptionOptions.cs | 12 + .../Modules/XOR/XOREncryptionOptions.cs.meta | 3 + .../CryptoLibrary/Modules/XOR/XORProvider.cs | 86 ++ .../Modules/XOR/XORProvider.cs.meta | 3 + .../Shared/CryptoLibrary/Modules/xxHash.meta | 3 + .../Modules/xxHash/xxHashEncryptionOptions.cs | 20 + .../xxHash/xxHashEncryptionOptions.cs.meta | 3 + .../Modules/xxHash/xxHashProvider.cs | 124 +++ .../Modules/xxHash/xxHashProvider.cs.meta | 3 + DevsDaddy/Shared/CryptoLibrary/Preview.png | Bin 0 -> 227447 bytes .../Shared/CryptoLibrary/Preview.png.meta | 114 +++ README.md | 112 ++- 99 files changed, 4002 insertions(+), 2 deletions(-) create mode 100644 DevsDaddy/Shared/CryptoLibrary/Core.meta create mode 100644 DevsDaddy/Shared/CryptoLibrary/Core/ICryptoProvider.cs create mode 100644 DevsDaddy/Shared/CryptoLibrary/Core/ICryptoProvider.cs.meta create mode 100644 DevsDaddy/Shared/CryptoLibrary/Core/IProviderOptions.cs create mode 100644 DevsDaddy/Shared/CryptoLibrary/Core/IProviderOptions.cs.meta create mode 100644 DevsDaddy/Shared/CryptoLibrary/CryptoController.cs create mode 100644 DevsDaddy/Shared/CryptoLibrary/CryptoController.cs.meta create mode 100644 DevsDaddy/Shared/CryptoLibrary/CryptoFile.cs create mode 100644 DevsDaddy/Shared/CryptoLibrary/CryptoFile.cs.meta create mode 100644 DevsDaddy/Shared/CryptoLibrary/CryptoLibrary.asmdef create mode 100644 DevsDaddy/Shared/CryptoLibrary/CryptoLibrary.asmdef.meta create mode 100644 DevsDaddy/Shared/CryptoLibrary/CryptoModule.cs create mode 100644 DevsDaddy/Shared/CryptoLibrary/CryptoModule.cs.meta create mode 100644 DevsDaddy/Shared/CryptoLibrary/Modules.meta create mode 100644 DevsDaddy/Shared/CryptoLibrary/Modules/AES.meta create mode 100644 DevsDaddy/Shared/CryptoLibrary/Modules/AES/AESEncryptionOptions.cs create mode 100644 DevsDaddy/Shared/CryptoLibrary/Modules/AES/AESEncryptionOptions.cs.meta create mode 100644 DevsDaddy/Shared/CryptoLibrary/Modules/AES/AESProvider.cs create mode 100644 DevsDaddy/Shared/CryptoLibrary/Modules/AES/AESProvider.cs.meta create mode 100644 DevsDaddy/Shared/CryptoLibrary/Modules/Base64.meta create mode 100644 DevsDaddy/Shared/CryptoLibrary/Modules/Base64/Base64EncryptionOptions.cs create mode 100644 DevsDaddy/Shared/CryptoLibrary/Modules/Base64/Base64EncryptionOptions.cs.meta create mode 100644 DevsDaddy/Shared/CryptoLibrary/Modules/Base64/Base64Provider.cs create mode 100644 DevsDaddy/Shared/CryptoLibrary/Modules/Base64/Base64Provider.cs.meta create mode 100644 DevsDaddy/Shared/CryptoLibrary/Modules/BlowFish.meta create mode 100644 DevsDaddy/Shared/CryptoLibrary/Modules/BlowFish/BlowfishEncryptionOptions.cs create mode 100644 DevsDaddy/Shared/CryptoLibrary/Modules/BlowFish/BlowfishEncryptionOptions.cs.meta create mode 100644 DevsDaddy/Shared/CryptoLibrary/Modules/BlowFish/BlowfishProvider.cs create mode 100644 DevsDaddy/Shared/CryptoLibrary/Modules/BlowFish/BlowfishProvider.cs.meta create mode 100644 DevsDaddy/Shared/CryptoLibrary/Modules/Crc32.meta create mode 100644 DevsDaddy/Shared/CryptoLibrary/Modules/Crc32/CRC32EncryptionOptions.cs create mode 100644 DevsDaddy/Shared/CryptoLibrary/Modules/Crc32/CRC32EncryptionOptions.cs.meta create mode 100644 DevsDaddy/Shared/CryptoLibrary/Modules/Crc32/CRC32Provider.cs create mode 100644 DevsDaddy/Shared/CryptoLibrary/Modules/Crc32/CRC32Provider.cs.meta create mode 100644 DevsDaddy/Shared/CryptoLibrary/Modules/Crc32/Crc32.cs create mode 100644 DevsDaddy/Shared/CryptoLibrary/Modules/Crc32/Crc32.cs.meta create mode 100644 DevsDaddy/Shared/CryptoLibrary/Modules/DES.meta create mode 100644 DevsDaddy/Shared/CryptoLibrary/Modules/DES/DESEncryptionOptions.cs create mode 100644 DevsDaddy/Shared/CryptoLibrary/Modules/DES/DESEncryptionOptions.cs.meta create mode 100644 DevsDaddy/Shared/CryptoLibrary/Modules/DES/DESProvider.cs create mode 100644 DevsDaddy/Shared/CryptoLibrary/Modules/DES/DESProvider.cs.meta create mode 100644 DevsDaddy/Shared/CryptoLibrary/Modules/MD5.meta create mode 100644 DevsDaddy/Shared/CryptoLibrary/Modules/MD5/MD5EncryptionOptions.cs create mode 100644 DevsDaddy/Shared/CryptoLibrary/Modules/MD5/MD5EncryptionOptions.cs.meta create mode 100644 DevsDaddy/Shared/CryptoLibrary/Modules/MD5/MD5Provider.cs create mode 100644 DevsDaddy/Shared/CryptoLibrary/Modules/MD5/MD5Provider.cs.meta create mode 100644 DevsDaddy/Shared/CryptoLibrary/Modules/PBKDF2.meta create mode 100644 DevsDaddy/Shared/CryptoLibrary/Modules/PBKDF2/PBKDF2EncryptionOptions.cs create mode 100644 DevsDaddy/Shared/CryptoLibrary/Modules/PBKDF2/PBKDF2EncryptionOptions.cs.meta create mode 100644 DevsDaddy/Shared/CryptoLibrary/Modules/PBKDF2/PBKDF2Provider.cs create mode 100644 DevsDaddy/Shared/CryptoLibrary/Modules/PBKDF2/PBKDF2Provider.cs.meta create mode 100644 DevsDaddy/Shared/CryptoLibrary/Modules/RIPEMD-160.meta create mode 100644 DevsDaddy/Shared/CryptoLibrary/Modules/RIPEMD-160/RIPEMD160.cs create mode 100644 DevsDaddy/Shared/CryptoLibrary/Modules/RIPEMD-160/RIPEMD160.cs.meta create mode 100644 DevsDaddy/Shared/CryptoLibrary/Modules/RIPEMD-160/RIPEMD160Managed.cs create mode 100644 DevsDaddy/Shared/CryptoLibrary/Modules/RIPEMD-160/RIPEMD160Managed.cs.meta create mode 100644 DevsDaddy/Shared/CryptoLibrary/Modules/RIPEMD-160/RipemdEncryptionOptions.cs create mode 100644 DevsDaddy/Shared/CryptoLibrary/Modules/RIPEMD-160/RipemdEncryptionOptions.cs.meta create mode 100644 DevsDaddy/Shared/CryptoLibrary/Modules/RIPEMD-160/RipemdProvider.cs create mode 100644 DevsDaddy/Shared/CryptoLibrary/Modules/RIPEMD-160/RipemdProvider.cs.meta create mode 100644 DevsDaddy/Shared/CryptoLibrary/Modules/RSA.meta create mode 100644 DevsDaddy/Shared/CryptoLibrary/Modules/RSA/RSAEncryptionOptions.cs create mode 100644 DevsDaddy/Shared/CryptoLibrary/Modules/RSA/RSAEncryptionOptions.cs.meta create mode 100644 DevsDaddy/Shared/CryptoLibrary/Modules/RSA/RSAProvider.cs create mode 100644 DevsDaddy/Shared/CryptoLibrary/Modules/RSA/RSAProvider.cs.meta create mode 100644 DevsDaddy/Shared/CryptoLibrary/Modules/SHA.meta create mode 100644 DevsDaddy/Shared/CryptoLibrary/Modules/SHA/SHA1Provider.cs create mode 100644 DevsDaddy/Shared/CryptoLibrary/Modules/SHA/SHA1Provider.cs.meta create mode 100644 DevsDaddy/Shared/CryptoLibrary/Modules/SHA/SHA256Provider.cs create mode 100644 DevsDaddy/Shared/CryptoLibrary/Modules/SHA/SHA256Provider.cs.meta create mode 100644 DevsDaddy/Shared/CryptoLibrary/Modules/SHA/SHA512Provider.cs create mode 100644 DevsDaddy/Shared/CryptoLibrary/Modules/SHA/SHA512Provider.cs.meta create mode 100644 DevsDaddy/Shared/CryptoLibrary/Modules/SHA/SHAEncryptionOptions.cs create mode 100644 DevsDaddy/Shared/CryptoLibrary/Modules/SHA/SHAEncryptionOptions.cs.meta create mode 100644 DevsDaddy/Shared/CryptoLibrary/Modules/TripleDES.meta create mode 100644 DevsDaddy/Shared/CryptoLibrary/Modules/TripleDES/TripleDESEncryptionOptions.cs create mode 100644 DevsDaddy/Shared/CryptoLibrary/Modules/TripleDES/TripleDESEncryptionOptions.cs.meta create mode 100644 DevsDaddy/Shared/CryptoLibrary/Modules/TripleDES/TripleDESProvider.cs create mode 100644 DevsDaddy/Shared/CryptoLibrary/Modules/TripleDES/TripleDESProvider.cs.meta create mode 100644 DevsDaddy/Shared/CryptoLibrary/Modules/Twofish.meta create mode 100644 DevsDaddy/Shared/CryptoLibrary/Modules/Twofish/Twofish.cs create mode 100644 DevsDaddy/Shared/CryptoLibrary/Modules/Twofish/Twofish.cs.meta create mode 100644 DevsDaddy/Shared/CryptoLibrary/Modules/Twofish/TwofishEncryptionOptions.cs create mode 100644 DevsDaddy/Shared/CryptoLibrary/Modules/Twofish/TwofishEncryptionOptions.cs.meta create mode 100644 DevsDaddy/Shared/CryptoLibrary/Modules/Twofish/TwofishProvider.cs create mode 100644 DevsDaddy/Shared/CryptoLibrary/Modules/Twofish/TwofishProvider.cs.meta create mode 100644 DevsDaddy/Shared/CryptoLibrary/Modules/XOR.meta create mode 100644 DevsDaddy/Shared/CryptoLibrary/Modules/XOR/XOREncryptionOptions.cs create mode 100644 DevsDaddy/Shared/CryptoLibrary/Modules/XOR/XOREncryptionOptions.cs.meta create mode 100644 DevsDaddy/Shared/CryptoLibrary/Modules/XOR/XORProvider.cs create mode 100644 DevsDaddy/Shared/CryptoLibrary/Modules/XOR/XORProvider.cs.meta create mode 100644 DevsDaddy/Shared/CryptoLibrary/Modules/xxHash.meta create mode 100644 DevsDaddy/Shared/CryptoLibrary/Modules/xxHash/xxHashEncryptionOptions.cs create mode 100644 DevsDaddy/Shared/CryptoLibrary/Modules/xxHash/xxHashEncryptionOptions.cs.meta create mode 100644 DevsDaddy/Shared/CryptoLibrary/Modules/xxHash/xxHashProvider.cs create mode 100644 DevsDaddy/Shared/CryptoLibrary/Modules/xxHash/xxHashProvider.cs.meta create mode 100644 DevsDaddy/Shared/CryptoLibrary/Preview.png create mode 100644 DevsDaddy/Shared/CryptoLibrary/Preview.png.meta diff --git a/DevsDaddy/Shared/CryptoLibrary/Core.meta b/DevsDaddy/Shared/CryptoLibrary/Core.meta new file mode 100644 index 0000000..e370632 --- /dev/null +++ b/DevsDaddy/Shared/CryptoLibrary/Core.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: e79982a065cc4bc4943d1db4ba896ae3 +timeCreated: 1709889672 \ No newline at end of file diff --git a/DevsDaddy/Shared/CryptoLibrary/Core/ICryptoProvider.cs b/DevsDaddy/Shared/CryptoLibrary/Core/ICryptoProvider.cs new file mode 100644 index 0000000..c31101a --- /dev/null +++ b/DevsDaddy/Shared/CryptoLibrary/Core/ICryptoProvider.cs @@ -0,0 +1,36 @@ +namespace DevsDaddy.Shared.CryptoLibrary.Core +{ + /// + /// Base Crypto-Provider Interface + /// + public interface ICryptoProvider + { + /// + /// Decrypt String Data + /// + /// + /// + string DecryptString(string encryptedString); + + /// + /// Decrypt Binary Data + /// + /// + /// + byte[] DecryptBinary(byte[] encryptedBinary); + + /// + /// Encrypt String + /// + /// + /// + string EncryptString(string decryptedString); + + /// + /// Encrypt Binary + /// + /// + /// + byte[] EncryptBinary(byte[] decryptedBinary); + } +} \ No newline at end of file diff --git a/DevsDaddy/Shared/CryptoLibrary/Core/ICryptoProvider.cs.meta b/DevsDaddy/Shared/CryptoLibrary/Core/ICryptoProvider.cs.meta new file mode 100644 index 0000000..5568ba4 --- /dev/null +++ b/DevsDaddy/Shared/CryptoLibrary/Core/ICryptoProvider.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: b2dfd16ad84e46dcb349978d4d7332c3 +timeCreated: 1709889459 \ No newline at end of file diff --git a/DevsDaddy/Shared/CryptoLibrary/Core/IProviderOptions.cs b/DevsDaddy/Shared/CryptoLibrary/Core/IProviderOptions.cs new file mode 100644 index 0000000..eac8100 --- /dev/null +++ b/DevsDaddy/Shared/CryptoLibrary/Core/IProviderOptions.cs @@ -0,0 +1,7 @@ +namespace DevsDaddy.Shared.CryptoLibrary.Core +{ + /// + /// Provider Options Interface + /// + public interface IProviderOptions { } +} \ No newline at end of file diff --git a/DevsDaddy/Shared/CryptoLibrary/Core/IProviderOptions.cs.meta b/DevsDaddy/Shared/CryptoLibrary/Core/IProviderOptions.cs.meta new file mode 100644 index 0000000..34fd312 --- /dev/null +++ b/DevsDaddy/Shared/CryptoLibrary/Core/IProviderOptions.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 8334da39a9004bf5811d44dc29eaf43c +timeCreated: 1709889484 \ No newline at end of file diff --git a/DevsDaddy/Shared/CryptoLibrary/CryptoController.cs b/DevsDaddy/Shared/CryptoLibrary/CryptoController.cs new file mode 100644 index 0000000..c9730f5 --- /dev/null +++ b/DevsDaddy/Shared/CryptoLibrary/CryptoController.cs @@ -0,0 +1,72 @@ +using DevsDaddy.Shared.CryptoLibrary.Core; +using DevsDaddy.Shared.CryptoLibrary.Modules.AES; + +namespace DevsDaddy.Shared.CryptoLibrary +{ + public static class CryptoController + { + // Default Provider + private static ICryptoProvider defaultProvider = new AESProvider(); + + /// + /// Set Default Crypto Provider + /// + /// + public static void SetDefaultProvider(ICryptoProvider provider) { + defaultProvider = provider; + } + + /// + /// Decrypt Encrypted Plain-Text using provided Crypto-provider or Default Crypto-provider + /// + /// + /// + /// + public static string Decrypt(string encryptedString, ICryptoProvider provider = null) { + if (provider == null) provider = defaultProvider; + return provider.DecryptString(encryptedString); + } + + /// + /// Decrypt encrypted byte array using provided Crypto-provider or Default Crypto-provider + /// + /// + /// + /// + public static byte[] Decrypt(byte[] encryptedArray, ICryptoProvider provider) { + if (provider == null) provider = defaultProvider; + return provider.DecryptBinary(encryptedArray); + } + + /// + /// Encrypt plain-text using provided Crypto-provider or Default Crypto-provider + /// + /// + /// + /// + public static string Encrypt(string plainText, ICryptoProvider provider = null) { + if (provider == null) provider = defaultProvider; + return provider.EncryptString(plainText); + } + + /// + /// Encrypt binary array using provided Crypto-provider or Default Crypto-provider + /// + /// + /// + /// + public static byte[] Encrypt(byte[] decryptedArray, ICryptoProvider provider = null) { + if (provider == null) provider = defaultProvider; + return provider.EncryptBinary(decryptedArray); + } + + public static void Test() { + CryptoFile.SetDefaultProvider(new AESProvider(new AESEncryptionOptions { + cryptoKey = "key" + })); + + string decryptedText = CryptoFile.ReadText("path_to_encrypted_file"); + bool writtenFile = CryptoFile.WriteText("path_to_encrypted_file", decryptedText); + } + } +} \ No newline at end of file diff --git a/DevsDaddy/Shared/CryptoLibrary/CryptoController.cs.meta b/DevsDaddy/Shared/CryptoLibrary/CryptoController.cs.meta new file mode 100644 index 0000000..7f46321 --- /dev/null +++ b/DevsDaddy/Shared/CryptoLibrary/CryptoController.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 586014d07f2f4e3ab3881a37a1ee4e47 +timeCreated: 1709889696 \ No newline at end of file diff --git a/DevsDaddy/Shared/CryptoLibrary/CryptoFile.cs b/DevsDaddy/Shared/CryptoLibrary/CryptoFile.cs new file mode 100644 index 0000000..d735d44 --- /dev/null +++ b/DevsDaddy/Shared/CryptoLibrary/CryptoFile.cs @@ -0,0 +1,180 @@ +using System; +using System.IO; +using System.Text; +using System.Threading.Tasks; +using DevsDaddy.Shared.CryptoLibrary.Core; +using DevsDaddy.Shared.CryptoLibrary.Modules.AES; +using UnityEngine; + +namespace DevsDaddy.Shared.CryptoLibrary +{ + public static class CryptoFile + { + // Default Provider + private static ICryptoProvider defaultProvider = new AESProvider(); + + /// + /// Set Default Crypto Provider + /// + /// + public static void SetDefaultProvider(ICryptoProvider provider) { + defaultProvider = provider; + } + + /// + /// Write Text file to path with encrypted plain-text using provided / default crypto-provider + /// + /// + /// + /// + /// + public static bool WriteText(string path, string plainText, ICryptoProvider provider = null) { + try { + if (provider == null) provider = defaultProvider; + string encryptedText = provider.EncryptString(plainText); + File.WriteAllText(path, encryptedText); + return true; + } + catch (Exception ex) { + Debug.LogError(ex); + return false; + } + } + + /// + /// Write Binary File to path encrypted byte array using provided / default crypto-provider + /// + /// + /// + /// + /// + public static bool WriteBinary(string path, byte[] byteArray, ICryptoProvider provider = null) { + try { + if (provider == null) provider = defaultProvider; + byte[] encryptedText = provider.EncryptBinary(byteArray); + File.WriteAllBytes(path, encryptedText); + return true; + } + catch (Exception ex) { + Debug.LogError(ex); + return false; + } + } + + /// + /// Read encrypted file and returns decrypted plain-text using provided / default crypto-provider + /// + /// + /// + /// + public static async Task ReadTextAsync(string path, ICryptoProvider provider = null) { + try { + if (provider == null) provider = defaultProvider; + string encryptedText = await File.ReadAllTextAsync(path); + string decryptedText = provider.DecryptString(encryptedText); + return decryptedText; + } + catch (Exception ex) { + Debug.LogError(ex); + return null; + } + } + + /// + /// Read encrypted binary file and returns decrypted byte array using provided / default crypto-provider + /// + /// + /// + /// + public static async Task ReadBinaryAsync(string path, ICryptoProvider provider = null) { + try { + if (provider == null) provider = defaultProvider; + byte[] encryptedData = await File.ReadAllBytesAsync(path); + byte[] decryptedData = provider.DecryptBinary(encryptedData); + return decryptedData; + } + catch (Exception ex) { + Debug.LogError(ex); + return null; + } + } + + /// + /// Write Text file to path with encrypted plain-text using provided / default crypto-provider + /// + /// + /// + /// + /// + public static async Task WriteTextAsync(string path, string plainText, ICryptoProvider provider = null) { + try { + if (provider == null) provider = defaultProvider; + string encryptedText = provider.EncryptString(plainText); + await File.WriteAllTextAsync(path, encryptedText); + return true; + } + catch (Exception ex) { + Debug.LogError(ex); + return false; + } + } + + /// + /// Write Binary File to path encrypted byte array using provided / default crypto-provider + /// + /// + /// + /// + /// + public static async Task WriteBinaryAsync(string path, byte[] byteArray, ICryptoProvider provider = null) { + try { + if (provider == null) provider = defaultProvider; + byte[] encryptedText = provider.EncryptBinary(byteArray); + await File.WriteAllBytesAsync(path, encryptedText); + return true; + } + catch (Exception ex) { + Debug.LogError(ex); + return false; + } + } + + /// + /// Read encrypted file and returns decrypted plain-text using provided / default crypto-provider + /// + /// + /// + /// + public static string ReadText(string path, ICryptoProvider provider = null) { + try { + if (provider == null) provider = defaultProvider; + string encryptedText = File.ReadAllText(path); + string decryptedText = provider.DecryptString(encryptedText); + return decryptedText; + } + catch (Exception ex) { + Debug.LogError(ex); + return null; + } + } + + /// + /// Read encrypted binary file and returns decrypted byte array using provided / default crypto-provider + /// + /// + /// + /// + public static byte[] ReadBinary(string path, ICryptoProvider provider = null) { + try { + if (provider == null) provider = defaultProvider; + byte[] encryptedData = File.ReadAllBytes(path); + byte[] decryptedData = provider.DecryptBinary(encryptedData); + return decryptedData; + } + catch (Exception ex) { + Debug.LogError(ex); + return null; + } + } + } +} \ No newline at end of file diff --git a/DevsDaddy/Shared/CryptoLibrary/CryptoFile.cs.meta b/DevsDaddy/Shared/CryptoLibrary/CryptoFile.cs.meta new file mode 100644 index 0000000..5b9fcb5 --- /dev/null +++ b/DevsDaddy/Shared/CryptoLibrary/CryptoFile.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 3b53aedd0664478da9df35f3cf683c18 +timeCreated: 1709889703 \ No newline at end of file diff --git a/DevsDaddy/Shared/CryptoLibrary/CryptoLibrary.asmdef b/DevsDaddy/Shared/CryptoLibrary/CryptoLibrary.asmdef new file mode 100644 index 0000000..f41f8c8 --- /dev/null +++ b/DevsDaddy/Shared/CryptoLibrary/CryptoLibrary.asmdef @@ -0,0 +1,3 @@ +{ + "name": "CryptoLibrary" +} diff --git a/DevsDaddy/Shared/CryptoLibrary/CryptoLibrary.asmdef.meta b/DevsDaddy/Shared/CryptoLibrary/CryptoLibrary.asmdef.meta new file mode 100644 index 0000000..4f95962 --- /dev/null +++ b/DevsDaddy/Shared/CryptoLibrary/CryptoLibrary.asmdef.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 2576790177f6d514d97155b443dfc070 +AssemblyDefinitionImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/DevsDaddy/Shared/CryptoLibrary/CryptoModule.cs b/DevsDaddy/Shared/CryptoLibrary/CryptoModule.cs new file mode 100644 index 0000000..fd05ca6 --- /dev/null +++ b/DevsDaddy/Shared/CryptoLibrary/CryptoModule.cs @@ -0,0 +1,7 @@ +namespace DevsDaddy.Shared.CryptoLibrary +{ + public enum CryptoModule + { + + } +} \ No newline at end of file diff --git a/DevsDaddy/Shared/CryptoLibrary/CryptoModule.cs.meta b/DevsDaddy/Shared/CryptoLibrary/CryptoModule.cs.meta new file mode 100644 index 0000000..0c15863 --- /dev/null +++ b/DevsDaddy/Shared/CryptoLibrary/CryptoModule.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: b0c71a10e117439f93a15473c317dc03 +timeCreated: 1709889714 \ No newline at end of file diff --git a/DevsDaddy/Shared/CryptoLibrary/Modules.meta b/DevsDaddy/Shared/CryptoLibrary/Modules.meta new file mode 100644 index 0000000..ae9aef4 --- /dev/null +++ b/DevsDaddy/Shared/CryptoLibrary/Modules.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: d1f1668f543df7e4eae8debf0d7dcfba +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/DevsDaddy/Shared/CryptoLibrary/Modules/AES.meta b/DevsDaddy/Shared/CryptoLibrary/Modules/AES.meta new file mode 100644 index 0000000..d0b00b8 --- /dev/null +++ b/DevsDaddy/Shared/CryptoLibrary/Modules/AES.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 2efc1c50b6ae4d659b53ee3428cc8c93 +timeCreated: 1709889626 \ No newline at end of file diff --git a/DevsDaddy/Shared/CryptoLibrary/Modules/AES/AESEncryptionOptions.cs b/DevsDaddy/Shared/CryptoLibrary/Modules/AES/AESEncryptionOptions.cs new file mode 100644 index 0000000..11f8199 --- /dev/null +++ b/DevsDaddy/Shared/CryptoLibrary/Modules/AES/AESEncryptionOptions.cs @@ -0,0 +1,20 @@ +using System.Security.Cryptography; +using System.Text; +using DevsDaddy.Shared.CryptoLibrary.Core; + +namespace DevsDaddy.Shared.CryptoLibrary.Modules.AES +{ + [System.Serializable] + public class AESEncryptionOptions : IProviderOptions + { + public int bufferKeySize = 32; + public int blockSize = 256; + public int keySize = 256; + + public string cryptoKey = "AESPassword"; + public Encoding encoding = Encoding.UTF8; + + public CipherMode cipherMode = CipherMode.CBC; + public PaddingMode paddingMode = PaddingMode.PKCS7; + } +} \ No newline at end of file diff --git a/DevsDaddy/Shared/CryptoLibrary/Modules/AES/AESEncryptionOptions.cs.meta b/DevsDaddy/Shared/CryptoLibrary/Modules/AES/AESEncryptionOptions.cs.meta new file mode 100644 index 0000000..4299bf0 --- /dev/null +++ b/DevsDaddy/Shared/CryptoLibrary/Modules/AES/AESEncryptionOptions.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: a102000f019449dfaf93ff3b1485a75a +timeCreated: 1709890300 \ No newline at end of file diff --git a/DevsDaddy/Shared/CryptoLibrary/Modules/AES/AESProvider.cs b/DevsDaddy/Shared/CryptoLibrary/Modules/AES/AESProvider.cs new file mode 100644 index 0000000..ae10fba --- /dev/null +++ b/DevsDaddy/Shared/CryptoLibrary/Modules/AES/AESProvider.cs @@ -0,0 +1,120 @@ +using System; +using System.Collections.Generic; +using System.Security.Cryptography; +using DevsDaddy.Shared.CryptoLibrary.Core; + +namespace DevsDaddy.Shared.CryptoLibrary.Modules.AES +{ + /// + /// AES Encryption Provider. + /// Using for encrypt/decrypt plain text or byte arrays + /// + public class AESProvider : ICryptoProvider + { + private AESEncryptionOptions _options; + + /// + /// AES Cryptography Provider + /// + /// + public AESProvider(AESEncryptionOptions options = null) { + _options = options ?? new AESEncryptionOptions(); + } + + /// + /// Decrypt AES-encrypted base-64 string to plain-text + /// + /// + /// + public string DecryptString(string encryptedString) { + byte[] decrypted = DecryptBinary(Convert.FromBase64String(encryptedString)); + return _options.encoding.GetString(decrypted); + } + + /// + /// Decrypt AES-encrypted binary + /// + /// + /// + public byte[] DecryptBinary(byte[] encryptedBinary) { + RijndaelManaged rij = setupRijndaelManaged; + + List compile = new List(encryptedBinary); + + // First 32 bytes are salt. + List salt = compile.GetRange(0, _options.bufferKeySize); + // Second 32 bytes are IV. + List iv = compile.GetRange(_options.bufferKeySize, _options.bufferKeySize); + rij.IV = iv.ToArray(); + + Rfc2898DeriveBytes deriveBytes = new Rfc2898DeriveBytes(_options.cryptoKey, salt.ToArray()); + byte[] bufferKey = deriveBytes.GetBytes(_options.bufferKeySize); // Convert 32 bytes of salt to password + rij.Key = bufferKey; + + byte[] plain = compile.GetRange(_options.bufferKeySize * 2, compile.Count - (_options.bufferKeySize * 2)).ToArray(); + + using (ICryptoTransform decrypt = rij.CreateDecryptor(rij.Key, rij.IV)) + { + byte[] dest = decrypt.TransformFinalBlock(plain, 0, plain.Length); + return dest; + } + } + + /// + /// Encrypt plain-text to AES-encrypted base-64 string + /// + /// + /// + public string EncryptString(string decryptedString) { + byte[] encrypted = EncryptBinary(_options.encoding.GetBytes(decryptedString)); + return Convert.ToBase64String(encrypted); + } + + /// + /// Encrypt byte array to AES-encrypted byte array + /// + /// + /// + public byte[] EncryptBinary(byte[] decryptedBinary) { + RijndaelManaged rij = setupRijndaelManaged; + + // A pseudorandom number is newly generated based on the inputted password + Rfc2898DeriveBytes deriveBytes = new Rfc2898DeriveBytes(_options.cryptoKey, _options.bufferKeySize); + // The missing parts are specified in advance to fill in 0 length + byte[] salt = new byte[_options.bufferKeySize]; + // Rfc2898DeriveBytes gets an internally generated salt + salt = deriveBytes.Salt; + // The 32-byte data extracted from the generated pseudorandom number is used as a password + byte[] bufferKey = deriveBytes.GetBytes(_options.bufferKeySize); + + rij.Key = bufferKey; + rij.GenerateIV(); + + using (ICryptoTransform encrypt = rij.CreateEncryptor(rij.Key, rij.IV)) + { + byte[] dest = encrypt.TransformFinalBlock(decryptedBinary, 0, decryptedBinary.Length); + // first 32 bytes of salt and second 32 bytes of IV for the first 64 bytes + List compile = new List(salt); + compile.AddRange(rij.IV); + compile.AddRange(dest); + return compile.ToArray(); + } + } + + /// + /// Setup Manager for AES + /// + private RijndaelManaged setupRijndaelManaged + { + get + { + RijndaelManaged rij = new RijndaelManaged(); + rij.BlockSize = _options.blockSize; + rij.KeySize = _options.keySize; + rij.Mode = _options.cipherMode; + rij.Padding = _options.paddingMode; + return rij; + } + } + } +} \ No newline at end of file diff --git a/DevsDaddy/Shared/CryptoLibrary/Modules/AES/AESProvider.cs.meta b/DevsDaddy/Shared/CryptoLibrary/Modules/AES/AESProvider.cs.meta new file mode 100644 index 0000000..4f22a5d --- /dev/null +++ b/DevsDaddy/Shared/CryptoLibrary/Modules/AES/AESProvider.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 1f5f2cf3f4814af28f6d8b51353d90b6 +timeCreated: 1709889798 \ No newline at end of file diff --git a/DevsDaddy/Shared/CryptoLibrary/Modules/Base64.meta b/DevsDaddy/Shared/CryptoLibrary/Modules/Base64.meta new file mode 100644 index 0000000..a4f90af --- /dev/null +++ b/DevsDaddy/Shared/CryptoLibrary/Modules/Base64.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 6a9b5fa32f0f4013b1d98a5a89d4b7c7 +timeCreated: 1709889648 \ No newline at end of file diff --git a/DevsDaddy/Shared/CryptoLibrary/Modules/Base64/Base64EncryptionOptions.cs b/DevsDaddy/Shared/CryptoLibrary/Modules/Base64/Base64EncryptionOptions.cs new file mode 100644 index 0000000..f89be3a --- /dev/null +++ b/DevsDaddy/Shared/CryptoLibrary/Modules/Base64/Base64EncryptionOptions.cs @@ -0,0 +1,11 @@ +using System.Text; +using DevsDaddy.Shared.CryptoLibrary.Core; + +namespace DevsDaddy.Shared.CryptoLibrary.Modules.Base64 +{ + [System.Serializable] + public class Base64EncryptionOptions : IProviderOptions + { + public Encoding encoding = Encoding.UTF8; + } +} \ No newline at end of file diff --git a/DevsDaddy/Shared/CryptoLibrary/Modules/Base64/Base64EncryptionOptions.cs.meta b/DevsDaddy/Shared/CryptoLibrary/Modules/Base64/Base64EncryptionOptions.cs.meta new file mode 100644 index 0000000..cea1850 --- /dev/null +++ b/DevsDaddy/Shared/CryptoLibrary/Modules/Base64/Base64EncryptionOptions.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: c3484dc302e545a993986d2e3fe21c31 +timeCreated: 1709890394 \ No newline at end of file diff --git a/DevsDaddy/Shared/CryptoLibrary/Modules/Base64/Base64Provider.cs b/DevsDaddy/Shared/CryptoLibrary/Modules/Base64/Base64Provider.cs new file mode 100644 index 0000000..f169a48 --- /dev/null +++ b/DevsDaddy/Shared/CryptoLibrary/Modules/Base64/Base64Provider.cs @@ -0,0 +1,66 @@ +using System; +using DevsDaddy.Shared.CryptoLibrary.Core; + +namespace DevsDaddy.Shared.CryptoLibrary.Modules.Base64 +{ + /// + /// Base64 Encryption Provider. + /// Using for encrypt/decrypt plain text or byte arrays + /// + public class Base64Provider : ICryptoProvider + { + private Base64EncryptionOptions _options; + + /// + /// Base64 Encryption Provider + /// + /// + public Base64Provider(Base64EncryptionOptions options = null) { + _options = options ?? new Base64EncryptionOptions(); + } + + /// + /// Decrypt Base64 string to plain text + /// + /// + /// + public string DecryptString(string encryptedString) { + byte[] decodedBytes = Convert.FromBase64String (encryptedString); + string decodedText = _options.encoding.GetString (decodedBytes); + return decodedText; + } + + /// + /// Decrypt Base64 byte array to decrypted byte array + /// + /// + /// + public byte[] DecryptBinary(byte[] encryptedBinary) { + string encoded = _options.encoding.GetString(encryptedBinary); + byte[] decodedBytes = Convert.FromBase64String(encoded); + return decodedBytes; + } + + /// + /// Encrypt plain-text to base64 string + /// + /// + /// + public string EncryptString(string decryptedString) { + byte[] bytesToEncode = _options.encoding.GetBytes (decryptedString); + string encodedText = Convert.ToBase64String (bytesToEncode); + return encodedText; + } + + /// + /// Encrypt byte array to Base64 binary + /// + /// + /// + public byte[] EncryptBinary(byte[] decryptedBinary) { + string encodedText = Convert.ToBase64String(decryptedBinary); + byte[] encodedBytes = _options.encoding.GetBytes (encodedText); + return encodedBytes; + } + } +} \ No newline at end of file diff --git a/DevsDaddy/Shared/CryptoLibrary/Modules/Base64/Base64Provider.cs.meta b/DevsDaddy/Shared/CryptoLibrary/Modules/Base64/Base64Provider.cs.meta new file mode 100644 index 0000000..96f7b1e --- /dev/null +++ b/DevsDaddy/Shared/CryptoLibrary/Modules/Base64/Base64Provider.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: e306f37400714c7aad8a32136af895eb +timeCreated: 1709890384 \ No newline at end of file diff --git a/DevsDaddy/Shared/CryptoLibrary/Modules/BlowFish.meta b/DevsDaddy/Shared/CryptoLibrary/Modules/BlowFish.meta new file mode 100644 index 0000000..84ab5f7 --- /dev/null +++ b/DevsDaddy/Shared/CryptoLibrary/Modules/BlowFish.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: d79d2dc5556347c094e744ba1e21c395 +timeCreated: 1709897312 \ No newline at end of file diff --git a/DevsDaddy/Shared/CryptoLibrary/Modules/BlowFish/BlowfishEncryptionOptions.cs b/DevsDaddy/Shared/CryptoLibrary/Modules/BlowFish/BlowfishEncryptionOptions.cs new file mode 100644 index 0000000..bf05e37 --- /dev/null +++ b/DevsDaddy/Shared/CryptoLibrary/Modules/BlowFish/BlowfishEncryptionOptions.cs @@ -0,0 +1,12 @@ +using System.Text; +using DevsDaddy.Shared.CryptoLibrary.Core; + +namespace DevsDaddy.Shared.CryptoLibrary.Modules.BlowFish +{ + [System.Serializable] + public class BlowfishEncryptionOptions : IProviderOptions + { + public Encoding encoding = Encoding.UTF8; + public string cryptoKey = "MyCryptoKey"; + } +} \ No newline at end of file diff --git a/DevsDaddy/Shared/CryptoLibrary/Modules/BlowFish/BlowfishEncryptionOptions.cs.meta b/DevsDaddy/Shared/CryptoLibrary/Modules/BlowFish/BlowfishEncryptionOptions.cs.meta new file mode 100644 index 0000000..bb51178 --- /dev/null +++ b/DevsDaddy/Shared/CryptoLibrary/Modules/BlowFish/BlowfishEncryptionOptions.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 970075a8bcf84b42849dec0e3b47117e +timeCreated: 1709901465 \ No newline at end of file diff --git a/DevsDaddy/Shared/CryptoLibrary/Modules/BlowFish/BlowfishProvider.cs b/DevsDaddy/Shared/CryptoLibrary/Modules/BlowFish/BlowfishProvider.cs new file mode 100644 index 0000000..5b81797 --- /dev/null +++ b/DevsDaddy/Shared/CryptoLibrary/Modules/BlowFish/BlowfishProvider.cs @@ -0,0 +1,458 @@ +using DevsDaddy.Shared.CryptoLibrary.Core; +using System; +using System.IO; +using System.Text; + +namespace DevsDaddy.Shared.CryptoLibrary.Modules.BlowFish +{ + /// + /// Blowfish Crypto Provider + /// + public class BlowfishProvider : ICryptoProvider + { + private BlowfishEncryptionOptions _options; + + const int N = 16; + const int KEYBYTES = 8; + + static uint[] _P = + { + 0x243f6a88, 0x85a308d3, 0x13198a2e, 0x03707344, 0xa4093822, 0x299f31d0, + 0x082efa98, 0xec4e6c89, 0x452821e6, 0x38d01377, 0xbe5466cf, 0x34e90c6c, + 0xc0ac29b7, 0xc97c50dd, 0x3f84d5b5, 0xb5470917, 0x9216d5d9, 0x8979fb1b + }; + static uint[,] _S = + { + { + 0xd1310ba6, 0x98dfb5ac, 0x2ffd72db, 0xd01adfb7, 0xb8e1afed, 0x6a267e96, + 0xba7c9045, 0xf12c7f99, 0x24a19947, 0xb3916cf7, 0x0801f2e2, 0x858efc16, + 0x636920d8, 0x71574e69, 0xa458fea3, 0xf4933d7e, 0x0d95748f, 0x728eb658, + 0x718bcd58, 0x82154aee, 0x7b54a41d, 0xc25a59b5, 0x9c30d539, 0x2af26013, + 0xc5d1b023, 0x286085f0, 0xca417918, 0xb8db38ef, 0x8e79dcb0, 0x603a180e, + 0x6c9e0e8b, 0xb01e8a3e, 0xd71577c1, 0xbd314b27, 0x78af2fda, 0x55605c60, + 0xe65525f3, 0xaa55ab94, 0x57489862, 0x63e81440, 0x55ca396a, 0x2aab10b6, + 0xb4cc5c34, 0x1141e8ce, 0xa15486af, 0x7c72e993, 0xb3ee1411, 0x636fbc2a, + 0x2ba9c55d, 0x741831f6, 0xce5c3e16, 0x9b87931e, 0xafd6ba33, 0x6c24cf5c, + 0x7a325381, 0x28958677, 0x3b8f4898, 0x6b4bb9af, 0xc4bfe81b, 0x66282193, + 0x61d809cc, 0xfb21a991, 0x487cac60, 0x5dec8032, 0xef845d5d, 0xe98575b1, + 0xdc262302, 0xeb651b88, 0x23893e81, 0xd396acc5, 0x0f6d6ff3, 0x83f44239, + 0x2e0b4482, 0xa4842004, 0x69c8f04a, 0x9e1f9b5e, 0x21c66842, 0xf6e96c9a, + 0x670c9c61, 0xabd388f0, 0x6a51a0d2, 0xd8542f68, 0x960fa728, 0xab5133a3, + 0x6eef0b6c, 0x137a3be4, 0xba3bf050, 0x7efb2a98, 0xa1f1651d, 0x39af0176, + 0x66ca593e, 0x82430e88, 0x8cee8619, 0x456f9fb4, 0x7d84a5c3, 0x3b8b5ebe, + 0xe06f75d8, 0x85c12073, 0x401a449f, 0x56c16aa6, 0x4ed3aa62, 0x363f7706, + 0x1bfedf72, 0x429b023d, 0x37d0d724, 0xd00a1248, 0xdb0fead3, 0x49f1c09b, + 0x075372c9, 0x80991b7b, 0x25d479d8, 0xf6e8def7, 0xe3fe501a, 0xb6794c3b, + 0x976ce0bd, 0x04c006ba, 0xc1a94fb6, 0x409f60c4, 0x5e5c9ec2, 0x196a2463, + 0x68fb6faf, 0x3e6c53b5, 0x1339b2eb, 0x3b52ec6f, 0x6dfc511f, 0x9b30952c, + 0xcc814544, 0xaf5ebd09, 0xbee3d004, 0xde334afd, 0x660f2807, 0x192e4bb3, + 0xc0cba857, 0x45c8740f, 0xd20b5f39, 0xb9d3fbdb, 0x5579c0bd, 0x1a60320a, + 0xd6a100c6, 0x402c7279, 0x679f25fe, 0xfb1fa3cc, 0x8ea5e9f8, 0xdb3222f8, + 0x3c7516df, 0xfd616b15, 0x2f501ec8, 0xad0552ab, 0x323db5fa, 0xfd238760, + 0x53317b48, 0x3e00df82, 0x9e5c57bb, 0xca6f8ca0, 0x1a87562e, 0xdf1769db, + 0xd542a8f6, 0x287effc3, 0xac6732c6, 0x8c4f5573, 0x695b27b0, 0xbbca58c8, + 0xe1ffa35d, 0xb8f011a0, 0x10fa3d98, 0xfd2183b8, 0x4afcb56c, 0x2dd1d35b, + 0x9a53e479, 0xb6f84565, 0xd28e49bc, 0x4bfb9790, 0xe1ddf2da, 0xa4cb7e33, + 0x62fb1341, 0xcee4c6e8, 0xef20cada, 0x36774c01, 0xd07e9efe, 0x2bf11fb4, + 0x95dbda4d, 0xae909198, 0xeaad8e71, 0x6b93d5a0, 0xd08ed1d0, 0xafc725e0, + 0x8e3c5b2f, 0x8e7594b7, 0x8ff6e2fb, 0xf2122b64, 0x8888b812, 0x900df01c, + 0x4fad5ea0, 0x688fc31c, 0xd1cff191, 0xb3a8c1ad, 0x2f2f2218, 0xbe0e1777, + 0xea752dfe, 0x8b021fa1, 0xe5a0cc0f, 0xb56f74e8, 0x18acf3d6, 0xce89e299, + 0xb4a84fe0, 0xfd13e0b7, 0x7cc43b81, 0xd2ada8d9, 0x165fa266, 0x80957705, + 0x93cc7314, 0x211a1477, 0xe6ad2065, 0x77b5fa86, 0xc75442f5, 0xfb9d35cf, + 0xebcdaf0c, 0x7b3e89a0, 0xd6411bd3, 0xae1e7e49, 0x00250e2d, 0x2071b35e, + 0x226800bb, 0x57b8e0af, 0x2464369b, 0xf009b91e, 0x5563911d, 0x59dfa6aa, + 0x78c14389, 0xd95a537f, 0x207d5ba2, 0x02e5b9c5, 0x83260376, 0x6295cfa9, + 0x11c81968, 0x4e734a41, 0xb3472dca, 0x7b14a94a, 0x1b510052, 0x9a532915, + 0xd60f573f, 0xbc9bc6e4, 0x2b60a476, 0x81e67400, 0x08ba6fb5, 0x571be91f, + 0xf296ec6b, 0x2a0dd915, 0xb6636521, 0xe7b9f9b6, 0xff34052e, 0xc5855664, + 0x53b02d5d, 0xa99f8fa1, 0x08ba4799, 0x6e85076a + }, + { + 0x4b7a70e9, 0xb5b32944, 0xdb75092e, 0xc4192623, 0xad6ea6b0, 0x49a7df7d, + 0x9cee60b8, 0x8fedb266, 0xecaa8c71, 0x699a17ff, 0x5664526c, 0xc2b19ee1, + 0x193602a5, 0x75094c29, 0xa0591340, 0xe4183a3e, 0x3f54989a, 0x5b429d65, + 0x6b8fe4d6, 0x99f73fd6, 0xa1d29c07, 0xefe830f5, 0x4d2d38e6, 0xf0255dc1, + 0x4cdd2086, 0x8470eb26, 0x6382e9c6, 0x021ecc5e, 0x09686b3f, 0x3ebaefc9, + 0x3c971814, 0x6b6a70a1, 0x687f3584, 0x52a0e286, 0xb79c5305, 0xaa500737, + 0x3e07841c, 0x7fdeae5c, 0x8e7d44ec, 0x5716f2b8, 0xb03ada37, 0xf0500c0d, + 0xf01c1f04, 0x0200b3ff, 0xae0cf51a, 0x3cb574b2, 0x25837a58, 0xdc0921bd, + 0xd19113f9, 0x7ca92ff6, 0x94324773, 0x22f54701, 0x3ae5e581, 0x37c2dadc, + 0xc8b57634, 0x9af3dda7, 0xa9446146, 0x0fd0030e, 0xecc8c73e, 0xa4751e41, + 0xe238cd99, 0x3bea0e2f, 0x3280bba1, 0x183eb331, 0x4e548b38, 0x4f6db908, + 0x6f420d03, 0xf60a04bf, 0x2cb81290, 0x24977c79, 0x5679b072, 0xbcaf89af, + 0xde9a771f, 0xd9930810, 0xb38bae12, 0xdccf3f2e, 0x5512721f, 0x2e6b7124, + 0x501adde6, 0x9f84cd87, 0x7a584718, 0x7408da17, 0xbc9f9abc, 0xe94b7d8c, + 0xec7aec3a, 0xdb851dfa, 0x63094366, 0xc464c3d2, 0xef1c1847, 0x3215d908, + 0xdd433b37, 0x24c2ba16, 0x12a14d43, 0x2a65c451, 0x50940002, 0x133ae4dd, + 0x71dff89e, 0x10314e55, 0x81ac77d6, 0x5f11199b, 0x043556f1, 0xd7a3c76b, + 0x3c11183b, 0x5924a509, 0xf28fe6ed, 0x97f1fbfa, 0x9ebabf2c, 0x1e153c6e, + 0x86e34570, 0xeae96fb1, 0x860e5e0a, 0x5a3e2ab3, 0x771fe71c, 0x4e3d06fa, + 0x2965dcb9, 0x99e71d0f, 0x803e89d6, 0x5266c825, 0x2e4cc978, 0x9c10b36a, + 0xc6150eba, 0x94e2ea78, 0xa5fc3c53, 0x1e0a2df4, 0xf2f74ea7, 0x361d2b3d, + 0x1939260f, 0x19c27960, 0x5223a708, 0xf71312b6, 0xebadfe6e, 0xeac31f66, + 0xe3bc4595, 0xa67bc883, 0xb17f37d1, 0x018cff28, 0xc332ddef, 0xbe6c5aa5, + 0x65582185, 0x68ab9802, 0xeecea50f, 0xdb2f953b, 0x2aef7dad, 0x5b6e2f84, + 0x1521b628, 0x29076170, 0xecdd4775, 0x619f1510, 0x13cca830, 0xeb61bd96, + 0x0334fe1e, 0xaa0363cf, 0xb5735c90, 0x4c70a239, 0xd59e9e0b, 0xcbaade14, + 0xeecc86bc, 0x60622ca7, 0x9cab5cab, 0xb2f3846e, 0x648b1eaf, 0x19bdf0ca, + 0xa02369b9, 0x655abb50, 0x40685a32, 0x3c2ab4b3, 0x319ee9d5, 0xc021b8f7, + 0x9b540b19, 0x875fa099, 0x95f7997e, 0x623d7da8, 0xf837889a, 0x97e32d77, + 0x11ed935f, 0x16681281, 0x0e358829, 0xc7e61fd6, 0x96dedfa1, 0x7858ba99, + 0x57f584a5, 0x1b227263, 0x9b83c3ff, 0x1ac24696, 0xcdb30aeb, 0x532e3054, + 0x8fd948e4, 0x6dbc3128, 0x58ebf2ef, 0x34c6ffea, 0xfe28ed61, 0xee7c3c73, + 0x5d4a14d9, 0xe864b7e3, 0x42105d14, 0x203e13e0, 0x45eee2b6, 0xa3aaabea, + 0xdb6c4f15, 0xfacb4fd0, 0xc742f442, 0xef6abbb5, 0x654f3b1d, 0x41cd2105, + 0xd81e799e, 0x86854dc7, 0xe44b476a, 0x3d816250, 0xcf62a1f2, 0x5b8d2646, + 0xfc8883a0, 0xc1c7b6a3, 0x7f1524c3, 0x69cb7492, 0x47848a0b, 0x5692b285, + 0x095bbf00, 0xad19489d, 0x1462b174, 0x23820e00, 0x58428d2a, 0x0c55f5ea, + 0x1dadf43e, 0x233f7061, 0x3372f092, 0x8d937e41, 0xd65fecf1, 0x6c223bdb, + 0x7cde3759, 0xcbee7460, 0x4085f2a7, 0xce77326e, 0xa6078084, 0x19f8509e, + 0xe8efd855, 0x61d99735, 0xa969a7aa, 0xc50c06c2, 0x5a04abfc, 0x800bcadc, + 0x9e447a2e, 0xc3453484, 0xfdd56705, 0x0e1e9ec9, 0xdb73dbd3, 0x105588cd, + 0x675fda79, 0xe3674340, 0xc5c43465, 0x713e38d8, 0x3d28f89e, 0xf16dff20, + 0x153e21e7, 0x8fb03d4a, 0xe6e39f2b, 0xdb83adf7 + }, + { + 0xe93d5a68, 0x948140f7, 0xf64c261c, 0x94692934, 0x411520f7, 0x7602d4f7, + 0xbcf46b2e, 0xd4a20068, 0xd4082471, 0x3320f46a, 0x43b7d4b7, 0x500061af, + 0x1e39f62e, 0x97244546, 0x14214f74, 0xbf8b8840, 0x4d95fc1d, 0x96b591af, + 0x70f4ddd3, 0x66a02f45, 0xbfbc09ec, 0x03bd9785, 0x7fac6dd0, 0x31cb8504, + 0x96eb27b3, 0x55fd3941, 0xda2547e6, 0xabca0a9a, 0x28507825, 0x530429f4, + 0x0a2c86da, 0xe9b66dfb, 0x68dc1462, 0xd7486900, 0x680ec0a4, 0x27a18dee, + 0x4f3ffea2, 0xe887ad8c, 0xb58ce006, 0x7af4d6b6, 0xaace1e7c, 0xd3375fec, + 0xce78a399, 0x406b2a42, 0x20fe9e35, 0xd9f385b9, 0xee39d7ab, 0x3b124e8b, + 0x1dc9faf7, 0x4b6d1856, 0x26a36631, 0xeae397b2, 0x3a6efa74, 0xdd5b4332, + 0x6841e7f7, 0xca7820fb, 0xfb0af54e, 0xd8feb397, 0x454056ac, 0xba489527, + 0x55533a3a, 0x20838d87, 0xfe6ba9b7, 0xd096954b, 0x55a867bc, 0xa1159a58, + 0xcca92963, 0x99e1db33, 0xa62a4a56, 0x3f3125f9, 0x5ef47e1c, 0x9029317c, + 0xfdf8e802, 0x04272f70, 0x80bb155c, 0x05282ce3, 0x95c11548, 0xe4c66d22, + 0x48c1133f, 0xc70f86dc, 0x07f9c9ee, 0x41041f0f, 0x404779a4, 0x5d886e17, + 0x325f51eb, 0xd59bc0d1, 0xf2bcc18f, 0x41113564, 0x257b7834, 0x602a9c60, + 0xdff8e8a3, 0x1f636c1b, 0x0e12b4c2, 0x02e1329e, 0xaf664fd1, 0xcad18115, + 0x6b2395e0, 0x333e92e1, 0x3b240b62, 0xeebeb922, 0x85b2a20e, 0xe6ba0d99, + 0xde720c8c, 0x2da2f728, 0xd0127845, 0x95b794fd, 0x647d0862, 0xe7ccf5f0, + 0x5449a36f, 0x877d48fa, 0xc39dfd27, 0xf33e8d1e, 0x0a476341, 0x992eff74, + 0x3a6f6eab, 0xf4f8fd37, 0xa812dc60, 0xa1ebddf8, 0x991be14c, 0xdb6e6b0d, + 0xc67b5510, 0x6d672c37, 0x2765d43b, 0xdcd0e804, 0xf1290dc7, 0xcc00ffa3, + 0xb5390f92, 0x690fed0b, 0x667b9ffb, 0xcedb7d9c, 0xa091cf0b, 0xd9155ea3, + 0xbb132f88, 0x515bad24, 0x7b9479bf, 0x763bd6eb, 0x37392eb3, 0xcc115979, + 0x8026e297, 0xf42e312d, 0x6842ada7, 0xc66a2b3b, 0x12754ccc, 0x782ef11c, + 0x6a124237, 0xb79251e7, 0x06a1bbe6, 0x4bfb6350, 0x1a6b1018, 0x11caedfa, + 0x3d25bdd8, 0xe2e1c3c9, 0x44421659, 0x0a121386, 0xd90cec6e, 0xd5abea2a, + 0x64af674e, 0xda86a85f, 0xbebfe988, 0x64e4c3fe, 0x9dbc8057, 0xf0f7c086, + 0x60787bf8, 0x6003604d, 0xd1fd8346, 0xf6381fb0, 0x7745ae04, 0xd736fccc, + 0x83426b33, 0xf01eab71, 0xb0804187, 0x3c005e5f, 0x77a057be, 0xbde8ae24, + 0x55464299, 0xbf582e61, 0x4e58f48f, 0xf2ddfda2, 0xf474ef38, 0x8789bdc2, + 0x5366f9c3, 0xc8b38e74, 0xb475f255, 0x46fcd9b9, 0x7aeb2661, 0x8b1ddf84, + 0x846a0e79, 0x915f95e2, 0x466e598e, 0x20b45770, 0x8cd55591, 0xc902de4c, + 0xb90bace1, 0xbb8205d0, 0x11a86248, 0x7574a99e, 0xb77f19b6, 0xe0a9dc09, + 0x662d09a1, 0xc4324633, 0xe85a1f02, 0x09f0be8c, 0x4a99a025, 0x1d6efe10, + 0x1ab93d1d, 0x0ba5a4df, 0xa186f20f, 0x2868f169, 0xdcb7da83, 0x573906fe, + 0xa1e2ce9b, 0x4fcd7f52, 0x50115e01, 0xa70683fa, 0xa002b5c4, 0x0de6d027, + 0x9af88c27, 0x773f8641, 0xc3604c06, 0x61a806b5, 0xf0177a28, 0xc0f586e0, + 0x006058aa, 0x30dc7d62, 0x11e69ed7, 0x2338ea63, 0x53c2dd94, 0xc2c21634, + 0xbbcbee56, 0x90bcb6de, 0xebfc7da1, 0xce591d76, 0x6f05e409, 0x4b7c0188, + 0x39720a3d, 0x7c927c24, 0x86e3725f, 0x724d9db9, 0x1ac15bb4, 0xd39eb8fc, + 0xed545578, 0x08fca5b5, 0xd83d7cd3, 0x4dad0fc4, 0x1e50ef5e, 0xb161e6f8, + 0xa28514d9, 0x6c51133c, 0x6fd5c7e7, 0x56e14ec4, 0x362abfce, 0xddc6c837, + 0xd79a3234, 0x92638212, 0x670efa8e, 0x406000e0 + }, + { + 0x3a39ce37, 0xd3faf5cf, 0xabc27737, 0x5ac52d1b, 0x5cb0679e, 0x4fa33742, + 0xd3822740, 0x99bc9bbe, 0xd5118e9d, 0xbf0f7315, 0xd62d1c7e, 0xc700c47b, + 0xb78c1b6b, 0x21a19045, 0xb26eb1be, 0x6a366eb4, 0x5748ab2f, 0xbc946e79, + 0xc6a376d2, 0x6549c2c8, 0x530ff8ee, 0x468dde7d, 0xd5730a1d, 0x4cd04dc6, + 0x2939bbdb, 0xa9ba4650, 0xac9526e8, 0xbe5ee304, 0xa1fad5f0, 0x6a2d519a, + 0x63ef8ce2, 0x9a86ee22, 0xc089c2b8, 0x43242ef6, 0xa51e03aa, 0x9cf2d0a4, + 0x83c061ba, 0x9be96a4d, 0x8fe51550, 0xba645bd6, 0x2826a2f9, 0xa73a3ae1, + 0x4ba99586, 0xef5562e9, 0xc72fefd3, 0xf752f7da, 0x3f046f69, 0x77fa0a59, + 0x80e4a915, 0x87b08601, 0x9b09e6ad, 0x3b3ee593, 0xe990fd5a, 0x9e34d797, + 0x2cf0b7d9, 0x022b8b51, 0x96d5ac3a, 0x017da67d, 0xd1cf3ed6, 0x7c7d2d28, + 0x1f9f25cf, 0xadf2b89b, 0x5ad6b472, 0x5a88f54c, 0xe029ac71, 0xe019a5e6, + 0x47b0acfd, 0xed93fa9b, 0xe8d3c48d, 0x283b57cc, 0xf8d56629, 0x79132e28, + 0x785f0191, 0xed756055, 0xf7960e44, 0xe3d35e8c, 0x15056dd4, 0x88f46dba, + 0x03a16125, 0x0564f0bd, 0xc3eb9e15, 0x3c9057a2, 0x97271aec, 0xa93a072a, + 0x1b3f6d9b, 0x1e6321f5, 0xf59c66fb, 0x26dcf319, 0x7533d928, 0xb155fdf5, + 0x03563482, 0x8aba3cbb, 0x28517711, 0xc20ad9f8, 0xabcc5167, 0xccad925f, + 0x4de81751, 0x3830dc8e, 0x379d5862, 0x9320f991, 0xea7a90c2, 0xfb3e7bce, + 0x5121ce64, 0x774fbe32, 0xa8b6e37e, 0xc3293d46, 0x48de5369, 0x6413e680, + 0xa2ae0810, 0xdd6db224, 0x69852dfd, 0x09072166, 0xb39a460a, 0x6445c0dd, + 0x586cdecf, 0x1c20c8ae, 0x5bbef7dd, 0x1b588d40, 0xccd2017f, 0x6bb4e3bb, + 0xdda26a7e, 0x3a59ff45, 0x3e350a44, 0xbcb4cdd5, 0x72eacea8, 0xfa6484bb, + 0x8d6612ae, 0xbf3c6f47, 0xd29be463, 0x542f5d9e, 0xaec2771b, 0xf64e6370, + 0x740e0d8d, 0xe75b1357, 0xf8721671, 0xaf537d5d, 0x4040cb08, 0x4eb4e2cc, + 0x34d2466a, 0x0115af84, 0xe1b00428, 0x95983a1d, 0x06b89fb4, 0xce6ea048, + 0x6f3f3b82, 0x3520ab82, 0x011a1d4b, 0x277227f8, 0x611560b1, 0xe7933fdc, + 0xbb3a792b, 0x344525bd, 0xa08839e1, 0x51ce794b, 0x2f32c9b7, 0xa01fbac9, + 0xe01cc87e, 0xbcc7d1f6, 0xcf0111c3, 0xa1e8aac7, 0x1a908749, 0xd44fbd9a, + 0xd0dadecb, 0xd50ada38, 0x0339c32a, 0xc6913667, 0x8df9317c, 0xe0b12b4f, + 0xf79e59b7, 0x43f5bb3a, 0xf2d519ff, 0x27d9459c, 0xbf97222c, 0x15e6fc2a, + 0x0f91fc71, 0x9b941525, 0xfae59361, 0xceb69ceb, 0xc2a86459, 0x12baa8d1, + 0xb6c1075e, 0xe3056a0c, 0x10d25065, 0xcb03a442, 0xe0ec6e0e, 0x1698db3b, + 0x4c98a0be, 0x3278e964, 0x9f1f9532, 0xe0d392df, 0xd3a0342b, 0x8971f21e, + 0x1b0a7441, 0x4ba3348c, 0xc5be7120, 0xc37632d8, 0xdf359f8d, 0x9b992f2e, + 0xe60b6f47, 0x0fe3f11d, 0xe54cda54, 0x1edad891, 0xce6279cf, 0xcd3e7e6f, + 0x1618b166, 0xfd2c1d05, 0x848fd2c5, 0xf6fb2299, 0xf523f357, 0xa6327623, + 0x93a83531, 0x56cccd02, 0xacf08162, 0x5a75ebb5, 0x6e163697, 0x88d273cc, + 0xde966292, 0x81b949d0, 0x4c50901b, 0x71c65614, 0xe6c6c7bd, 0x327a140a, + 0x45e1d006, 0xc3f27b9a, 0xc9aa53fd, 0x62a80f00, 0xbb25bfe2, 0x35bdd2f6, + 0x71126905, 0xb2040222, 0xb6cbcf7c, 0xcd769c2b, 0x53113ec0, 0x1640e3d3, + 0x38abbd60, 0x2547adf0, 0xba38209c, 0xf746ce76, 0x77afa1c5, 0x20756060, + 0x85cbfe4e, 0x8ae88dd8, 0x7aaaf9b0, 0x4cf9aa7e, 0x1948c25c, 0x02fb8a8c, + 0x01c36ae4, 0xd6ebe1f9, 0x90d4f869, 0xa65cdea0, 0x3f09252d, 0xc208e69f, + 0xb74e6132, 0xce77e25b, 0x578fdfe3, 0x3ac372e6 + } + }; + + uint[] P; + uint[,] S; + + /// + /// Blowfish Provider + /// + /// + public BlowfishProvider(BlowfishEncryptionOptions options) { + _options = options ?? new BlowfishEncryptionOptions(); + + byte[] key = _options.encoding.GetBytes(_options.cryptoKey); + + short i; + short j; + short k; + uint data; + uint datal; + uint datar; + + P = _P.Clone() as uint[]; + S = _S.Clone() as uint[,]; + + j = 0; + for (i = 0; i < N + 2; ++i) + { + data = 0x00000000; + for (k = 0; k < 4; ++k) + { + data = (data << 8) | key[j]; + j++; + if (j >= key.Length) + { + j = 0; + } + } + P[i] = P[i] ^ data; + } + + datal = 0x00000000; + datar = 0x00000000; + + for (i = 0; i < N + 2; i += 2) + { + Encipher(ref datal, ref datar); + P[i] = datal; + P[i + 1] = datar; + } + + for (i = 0; i < 4; ++i) + { + for (j = 0; j < 256; j += 2) + { + Encipher(ref datal, ref datar); + + S[i, j] = datal; + S[i, j + 1] = datar; + } + } + } + + private uint F(uint x) + { + ushort a; + ushort b; + ushort c; + ushort d; + uint y; + + d = (ushort)(x & 0x00FF); + x >>= 8; + c = (ushort)(x & 0x00FF); + x >>= 8; + b = (ushort)(x & 0x00FF); + x >>= 8; + a = (ushort)(x & 0x00FF); + //y = ((S[0][a] + S[1][b]) ^ S[2][c]) + S[3][d]; + y = S[0, a] + S[1, b]; + y = y ^ S[2, c]; + y = y + S[3, d]; + + return y; + } + + private void Encipher(byte[] data, int length) + { + uint xl, xr; + if ((length % 8) != 0) + throw new Exception("Invalid Length"); + for (int i = 0; i < length; i += 8) + { + // Encode the data in 8 byte blocks. + xl = (uint)((data[i] << 24) | (data[i + 1] << 16) | (data[i + 2] << 8) | data[i + 3]); + xr = (uint)((data[i + 4] << 24) | (data[i + 5] << 16) | (data[i + 6] << 8) | data[i + 7]); + Encipher(ref xl, ref xr); + // Now Replace the data. + data[i] = (byte)(xl >> 24); + data[i + 1] = (byte)(xl >> 16); + data[i + 2] = (byte)(xl >> 8); + data[i + 3] = (byte)(xl); + data[i + 4] = (byte)(xr >> 24); + data[i + 5] = (byte)(xr >> 16); + data[i + 6] = (byte)(xr >> 8); + data[i + 7] = (byte)(xr); + } + } + + private void Encipher(ref uint xl, ref uint xr) + { + uint Xl; + uint Xr; + uint temp; + short i; + + Xl = xl; + Xr = xr; + + for (i = 0; i < N; ++i) + { + Xl = Xl ^ P[i]; + Xr = F(Xl) ^ Xr; + + temp = Xl; + Xl = Xr; + Xr = temp; + } + + temp = Xl; + Xl = Xr; + Xr = temp; + + Xr = Xr ^ P[N]; + Xl = Xl ^ P[N + 1]; + + xl = Xl; + xr = Xr; + } + + private String Encipher(String data) + { + byte[] b = _options.encoding.GetBytes(data); + Encipher(b, b.Length); + return Convert.ToBase64String(b); + } + + private void Decipher(byte[] data, int length) + { + uint xl, xr; + if ((length % 8) != 0) + throw new Exception("Invalid Length"); + for (int i = 0; i < length; i += 8) + { + // Encode the data in 8 byte blocks. + xl = (uint)((data[i] << 24) | (data[i + 1] << 16) | (data[i + 2] << 8) | data[i + 3]); + xr = (uint)((data[i + 4] << 24) | (data[i + 5] << 16) | (data[i + 6] << 8) | data[i + 7]); + Decipher(ref xl, ref xr); + // Now Replace the data. + data[i] = (byte)(xl >> 24); + data[i + 1] = (byte)(xl >> 16); + data[i + 2] = (byte)(xl >> 8); + data[i + 3] = (byte)(xl); + data[i + 4] = (byte)(xr >> 24); + data[i + 5] = (byte)(xr >> 16); + data[i + 6] = (byte)(xr >> 8); + data[i + 7] = (byte)(xr); + } + } + + private void Decipher(ref uint xl, ref uint xr) + { + uint Xl; + uint Xr; + uint temp; + short i; + + Xl = xl; + Xr = xr; + + for (i = N + 1; i > 1; --i) + { + Xl = Xl ^ P[i]; + Xr = F(Xl) ^ Xr; + + /* Exchange Xl and Xr */ + temp = Xl; + Xl = Xr; + Xr = temp; + } + + /* Exchange Xl and Xr */ + temp = Xl; + Xl = Xr; + Xr = temp; + + Xr = Xr ^ P[1]; + Xl = Xl ^ P[0]; + + xl = Xl; + xr = Xr; + } + + private String Decipher(String data) + { + byte[] b = Convert.FromBase64String(data); + Decipher(b, b.Length); + + return _options.encoding.GetString(b); + } + + /// + /// Decrypt text using Blowfish Provider + /// + /// + /// + public string DecryptString(string encryptedString) { + return Decipher(encryptedString); + } + + /// + /// Decrypt byte array using Blowfish Provider + /// + /// + /// + public byte[] DecryptBinary(byte[] encryptedBinary) { + byte[] decrypted = new byte[encryptedBinary.Length]; + Array.Copy(encryptedBinary, decrypted, encryptedBinary.Length); + Decipher(decrypted, decrypted.Length); + return decrypted; + } + + /// + /// Encode plain-text using Blowfish Provider + /// + /// + /// + public string EncryptString(string decryptedString) { + return Encipher(decryptedString); + } + + /// + /// Encrypt Binary using Blowfish Provider + /// + /// + /// + public byte[] EncryptBinary(byte[] decryptedBinary) { + byte[] encrypted = new byte[decryptedBinary.Length]; + Array.Copy(decryptedBinary, encrypted, decryptedBinary.Length); + Decipher(encrypted, encrypted.Length); + return encrypted; + } + } +} \ No newline at end of file diff --git a/DevsDaddy/Shared/CryptoLibrary/Modules/BlowFish/BlowfishProvider.cs.meta b/DevsDaddy/Shared/CryptoLibrary/Modules/BlowFish/BlowfishProvider.cs.meta new file mode 100644 index 0000000..551d4f7 --- /dev/null +++ b/DevsDaddy/Shared/CryptoLibrary/Modules/BlowFish/BlowfishProvider.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: c50802061af74e20ab21681d6addd0c1 +timeCreated: 1709901452 \ No newline at end of file diff --git a/DevsDaddy/Shared/CryptoLibrary/Modules/Crc32.meta b/DevsDaddy/Shared/CryptoLibrary/Modules/Crc32.meta new file mode 100644 index 0000000..3c1bed3 --- /dev/null +++ b/DevsDaddy/Shared/CryptoLibrary/Modules/Crc32.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 7a00b48dbb944ac0a2d68a7beb1f4d74 +timeCreated: 1709901092 \ No newline at end of file diff --git a/DevsDaddy/Shared/CryptoLibrary/Modules/Crc32/CRC32EncryptionOptions.cs b/DevsDaddy/Shared/CryptoLibrary/Modules/Crc32/CRC32EncryptionOptions.cs new file mode 100644 index 0000000..8bf0dac --- /dev/null +++ b/DevsDaddy/Shared/CryptoLibrary/Modules/Crc32/CRC32EncryptionOptions.cs @@ -0,0 +1,11 @@ +using System.Text; +using DevsDaddy.Shared.CryptoLibrary.Core; + +namespace DevsDaddy.Shared.CryptoLibrary.Modules.Crc32 +{ + [System.Serializable] + public class CRC32EncryptionOptions : IProviderOptions + { + public Encoding encoding = Encoding.UTF8; + } +} \ No newline at end of file diff --git a/DevsDaddy/Shared/CryptoLibrary/Modules/Crc32/CRC32EncryptionOptions.cs.meta b/DevsDaddy/Shared/CryptoLibrary/Modules/Crc32/CRC32EncryptionOptions.cs.meta new file mode 100644 index 0000000..50383dd --- /dev/null +++ b/DevsDaddy/Shared/CryptoLibrary/Modules/Crc32/CRC32EncryptionOptions.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: c88999e508ec47fda502137b21747ede +timeCreated: 1709901131 \ No newline at end of file diff --git a/DevsDaddy/Shared/CryptoLibrary/Modules/Crc32/CRC32Provider.cs b/DevsDaddy/Shared/CryptoLibrary/Modules/Crc32/CRC32Provider.cs new file mode 100644 index 0000000..ea87a5d --- /dev/null +++ b/DevsDaddy/Shared/CryptoLibrary/Modules/Crc32/CRC32Provider.cs @@ -0,0 +1,65 @@ +using System; +using DevsDaddy.Shared.CryptoLibrary.Core; + +namespace DevsDaddy.Shared.CryptoLibrary.Modules.Crc32 +{ + /// + /// CRC32 Hash Provider + /// + public class CRC32Provider : ICryptoProvider + { + // Provider Options + private CRC32EncryptionOptions _options; + + /// + /// CRC32 Hash Provider + /// + /// + public CRC32Provider(CRC32EncryptionOptions options = null) { + _options = options ?? new CRC32EncryptionOptions(); + } + + /// + /// Decrypt String (Not Supported for hashing) + /// + /// + /// + /// + public string DecryptString(string encryptedString) { + throw new Exception($"Failed to decrypt text, because {this.GetType()} doesn't support decryption."); + } + + /// + /// Decrypt Binary (Not Supported for hashing) + /// + /// + /// + /// + public byte[] DecryptBinary(byte[] encryptedBinary) { + throw new Exception($"Failed to decrypt text, because {this.GetType()} doesn't support decryption."); + } + + /// + /// Get CRC32 of Plain Text + /// + /// + /// + public string EncryptString(string decryptedString) { + byte[] encrypted = EncryptBinary(_options.encoding.GetBytes(decryptedString)); + return Convert.ToBase64String(encrypted); + } + + /// + /// Encrypt Binary + /// + /// + /// + public byte[] EncryptBinary(byte[] decryptedBinary) { + using (Crc32 crc = new Crc32()) + { + byte[] hashBytes = crc.ComputeHash(decryptedBinary); + return hashBytes; + } + } + } +} \ No newline at end of file diff --git a/DevsDaddy/Shared/CryptoLibrary/Modules/Crc32/CRC32Provider.cs.meta b/DevsDaddy/Shared/CryptoLibrary/Modules/Crc32/CRC32Provider.cs.meta new file mode 100644 index 0000000..04c2af4 --- /dev/null +++ b/DevsDaddy/Shared/CryptoLibrary/Modules/Crc32/CRC32Provider.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 32e98cf987fa4d4ba5950846eccf09d8 +timeCreated: 1709901123 \ No newline at end of file diff --git a/DevsDaddy/Shared/CryptoLibrary/Modules/Crc32/Crc32.cs b/DevsDaddy/Shared/CryptoLibrary/Modules/Crc32/Crc32.cs new file mode 100644 index 0000000..e59da9e --- /dev/null +++ b/DevsDaddy/Shared/CryptoLibrary/Modules/Crc32/Crc32.cs @@ -0,0 +1,110 @@ +using System; +using System.Security.Cryptography; +using System.IO; + +namespace DevsDaddy.Shared.CryptoLibrary.Modules.Crc32 +{ + public class Crc32 : HashAlgorithm + { + public const UInt32 DefaultPolynomial = 0xedb88320; + public const UInt32 DefaultSeed = 0xffffffff; + + private UInt32 hash; + private UInt32 seed; + private UInt32[] table; + private static UInt32[] defaultTable; + + public Crc32() { + table = InitializeTable(DefaultPolynomial); + seed = DefaultSeed; + Initialize(); + } + + public Crc32(UInt32 polynomial, UInt32 seed) { + table = InitializeTable(polynomial); + this.seed = seed; + Initialize(); + } + + public override void Initialize() { + hash = seed; + } + + protected override void HashCore(byte[] buffer, int start, int length) { + hash = CalculateHash(table, hash, buffer, start, length); + } + + protected override byte[] HashFinal() { + byte[] hashBuffer = UInt32ToBigEndianBytes(~hash); + this.HashValue = hashBuffer; + return hashBuffer; + } + + public override int HashSize { + get { return 32; } + } + + public static UInt32 Compute(byte[] buffer) { + return ~CalculateHash(InitializeTable(DefaultPolynomial), DefaultSeed, buffer, 0, buffer.Length); + } + + public static UInt32 Compute(UInt32 seed, byte[] buffer) { + return ~CalculateHash(InitializeTable(DefaultPolynomial), seed, buffer, 0, buffer.Length); + } + + public static UInt32 Compute(UInt32 polynomial, UInt32 seed, byte[] buffer) { + return ~CalculateHash(InitializeTable(polynomial), seed, buffer, 0, buffer.Length); + } + + private static UInt32[] InitializeTable(UInt32 polynomial) { + if (polynomial == DefaultPolynomial && defaultTable != null) + return defaultTable; + + UInt32[] createTable = new UInt32[256]; + for (int i = 0; i < 256; i++) + { + UInt32 entry = (UInt32)i; + for (int j = 0; j < 8; j++) + if ((entry & 1) == 1) + entry = (entry >> 1) ^ polynomial; + else + entry = entry >> 1; + createTable[i] = entry; + } + + if (polynomial == DefaultPolynomial) + defaultTable = createTable; + + return createTable; + } + + private static UInt32 CalculateHash(UInt32[] table, UInt32 seed, byte[] buffer, int start, int size) { + UInt32 crc = seed; + for (int i = start; i < size; i++) + unchecked + { + crc = (crc >> 8) ^ table[buffer[i] ^ crc & 0xff]; + } + return crc; + } + + private byte[] UInt32ToBigEndianBytes(UInt32 x) { + return new byte[] { + (byte)((x >> 24) & 0xff), + (byte)((x >> 16) & 0xff), + (byte)((x >> 8) & 0xff), + (byte)(x & 0xff) + }; + } + + public string Get(string FilePath) { + Crc32 crc32 = new Crc32(); + String hash = String.Empty; + + using (FileStream fs = File.Open(FilePath, FileMode.Open)) + foreach (byte b in crc32.ComputeHash(fs)) hash += b.ToString("x2").ToLower(); + + return hash; + } + } +} \ No newline at end of file diff --git a/DevsDaddy/Shared/CryptoLibrary/Modules/Crc32/Crc32.cs.meta b/DevsDaddy/Shared/CryptoLibrary/Modules/Crc32/Crc32.cs.meta new file mode 100644 index 0000000..f82784a --- /dev/null +++ b/DevsDaddy/Shared/CryptoLibrary/Modules/Crc32/Crc32.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 5b306395bd914c1ea1be614cf0fffbe6 +timeCreated: 1709901203 \ No newline at end of file diff --git a/DevsDaddy/Shared/CryptoLibrary/Modules/DES.meta b/DevsDaddy/Shared/CryptoLibrary/Modules/DES.meta new file mode 100644 index 0000000..91c04de --- /dev/null +++ b/DevsDaddy/Shared/CryptoLibrary/Modules/DES.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 7331c9adf98140a99fa8d992ae7f851c +timeCreated: 1709891836 \ No newline at end of file diff --git a/DevsDaddy/Shared/CryptoLibrary/Modules/DES/DESEncryptionOptions.cs b/DevsDaddy/Shared/CryptoLibrary/Modules/DES/DESEncryptionOptions.cs new file mode 100644 index 0000000..5b720b8 --- /dev/null +++ b/DevsDaddy/Shared/CryptoLibrary/Modules/DES/DESEncryptionOptions.cs @@ -0,0 +1,12 @@ +using System.Text; +using DevsDaddy.Shared.CryptoLibrary.Core; + +namespace DevsDaddy.Shared.CryptoLibrary.Modules.DES +{ + [System.Serializable] + public class DESEncryptionOptions : IProviderOptions + { + public string cryptoKey = "ABCDEFGH"; + public Encoding encoding = Encoding.UTF8; + } +} \ No newline at end of file diff --git a/DevsDaddy/Shared/CryptoLibrary/Modules/DES/DESEncryptionOptions.cs.meta b/DevsDaddy/Shared/CryptoLibrary/Modules/DES/DESEncryptionOptions.cs.meta new file mode 100644 index 0000000..46f2417 --- /dev/null +++ b/DevsDaddy/Shared/CryptoLibrary/Modules/DES/DESEncryptionOptions.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 7d4e5d2be20b40d284b39199847a26f0 +timeCreated: 1709891855 \ No newline at end of file diff --git a/DevsDaddy/Shared/CryptoLibrary/Modules/DES/DESProvider.cs b/DevsDaddy/Shared/CryptoLibrary/Modules/DES/DESProvider.cs new file mode 100644 index 0000000..974936f --- /dev/null +++ b/DevsDaddy/Shared/CryptoLibrary/Modules/DES/DESProvider.cs @@ -0,0 +1,98 @@ +using System; +using System.IO; +using System.Security.Cryptography; +using DevsDaddy.Shared.CryptoLibrary.Core; + +namespace DevsDaddy.Shared.CryptoLibrary.Modules.DES +{ + /// + /// DES Encryption Provider. + /// Using for encrypt/decrypt plain text or byte arrays + /// + public class DESProvider : ICryptoProvider + { + // Encryption Options + private DESEncryptionOptions _options; + + /// + /// DES Encryption Provider + /// + /// + public DESProvider(DESEncryptionOptions options = null) { + _options = options ?? new DESEncryptionOptions(); + } + + /// + /// Decrypt encrypted string to plain text using DES + /// + /// + /// + public string DecryptString(string encryptedString) { + byte[] txtByteData = Convert.FromBase64String(encryptedString); + byte[] decoded = DecryptBinary(txtByteData); + return _options.encoding.GetString(decoded); + } + + /// + /// Decrypt encrypted byte array to decrypted byte array using DES + /// + /// + /// + public byte[] DecryptBinary(byte[] encryptedBinary) { + byte[] keyByteData = _options.encoding.GetBytes(_options.cryptoKey); + + DESCryptoServiceProvider DEScryptoProvider = new DESCryptoServiceProvider(); + ICryptoTransform trnsfrm = DEScryptoProvider.CreateDecryptor(keyByteData, keyByteData); + CryptoStreamMode mode = CryptoStreamMode.Write; + + //Set up Stream & Write Encript data + MemoryStream mStream = new MemoryStream(); + CryptoStream cStream = new CryptoStream(mStream, trnsfrm, mode); + cStream.Write(encryptedBinary, 0, encryptedBinary.Length); + cStream.FlushFinalBlock(); + + //Read Ecncrypted Data From Memory Stream + byte[] result = new byte[mStream.Length]; + mStream.Position = 0; + mStream.Read(result, 0, result.Length); + + return result; + } + + /// + /// Encrypt plain-text using DES + /// + /// + /// + public string EncryptString(string decryptedString) { + byte[] txtByteData = _options.encoding.GetBytes(decryptedString); + byte[] encoded = EncryptBinary(txtByteData); + return Convert.ToBase64String(encoded); + } + + /// + /// Encrypt byte-array using DES + /// + /// + /// + public byte[] EncryptBinary(byte[] decryptedBinary) { + byte[] keyByteData = _options.encoding.GetBytes(_options.cryptoKey); + DESCryptoServiceProvider DEScryptoProvider = new DESCryptoServiceProvider(); + ICryptoTransform trnsfrm = DEScryptoProvider.CreateEncryptor(keyByteData, keyByteData); + CryptoStreamMode mode = CryptoStreamMode.Write; + + //Set up Stream & Write Encript data + MemoryStream mStream = new MemoryStream(); + CryptoStream cStream = new CryptoStream(mStream, trnsfrm, mode); + cStream.Write(decryptedBinary, 0, decryptedBinary.Length); + cStream.FlushFinalBlock(); + + //Read Ecncrypted Data From Memory Stream + byte[] result = new byte[mStream.Length]; + mStream.Position = 0; + mStream.Read(result, 0, result.Length); + + return result; + } + } +} \ No newline at end of file diff --git a/DevsDaddy/Shared/CryptoLibrary/Modules/DES/DESProvider.cs.meta b/DevsDaddy/Shared/CryptoLibrary/Modules/DES/DESProvider.cs.meta new file mode 100644 index 0000000..54e1d37 --- /dev/null +++ b/DevsDaddy/Shared/CryptoLibrary/Modules/DES/DESProvider.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: f97ecf2e80fd4695be93a4faf86a6b0f +timeCreated: 1709891843 \ No newline at end of file diff --git a/DevsDaddy/Shared/CryptoLibrary/Modules/MD5.meta b/DevsDaddy/Shared/CryptoLibrary/Modules/MD5.meta new file mode 100644 index 0000000..2549996 --- /dev/null +++ b/DevsDaddy/Shared/CryptoLibrary/Modules/MD5.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 709b5e3fc5ab4a628f158df4ea242698 +timeCreated: 1709889633 \ No newline at end of file diff --git a/DevsDaddy/Shared/CryptoLibrary/Modules/MD5/MD5EncryptionOptions.cs b/DevsDaddy/Shared/CryptoLibrary/Modules/MD5/MD5EncryptionOptions.cs new file mode 100644 index 0000000..92c1df4 --- /dev/null +++ b/DevsDaddy/Shared/CryptoLibrary/Modules/MD5/MD5EncryptionOptions.cs @@ -0,0 +1,11 @@ +using System.Text; +using DevsDaddy.Shared.CryptoLibrary.Core; + +namespace DevsDaddy.Shared.CryptoLibrary.Modules.MD5 +{ + [System.Serializable] + public class MD5EncryptionOptions : IProviderOptions + { + public Encoding encoding = Encoding.UTF8; + } +} \ No newline at end of file diff --git a/DevsDaddy/Shared/CryptoLibrary/Modules/MD5/MD5EncryptionOptions.cs.meta b/DevsDaddy/Shared/CryptoLibrary/Modules/MD5/MD5EncryptionOptions.cs.meta new file mode 100644 index 0000000..a13a066 --- /dev/null +++ b/DevsDaddy/Shared/CryptoLibrary/Modules/MD5/MD5EncryptionOptions.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 8de0da8afd9b4da5b2d8c8bd995ce70f +timeCreated: 1709894165 \ No newline at end of file diff --git a/DevsDaddy/Shared/CryptoLibrary/Modules/MD5/MD5Provider.cs b/DevsDaddy/Shared/CryptoLibrary/Modules/MD5/MD5Provider.cs new file mode 100644 index 0000000..1f5a5b5 --- /dev/null +++ b/DevsDaddy/Shared/CryptoLibrary/Modules/MD5/MD5Provider.cs @@ -0,0 +1,77 @@ +using System; +using System.Text; +using DevsDaddy.Shared.CryptoLibrary.Core; + +namespace DevsDaddy.Shared.CryptoLibrary.Modules.MD5 +{ + /// + /// MD5 Hash Provider (No Decryption, Only Encryption) + /// + public class MD5Provider : ICryptoProvider + { + // Provider Options + private MD5EncryptionOptions _options; + + /// + /// MD5 Hashing Provider + /// + /// + public MD5Provider(MD5EncryptionOptions options = null) { + _options = options ?? new MD5EncryptionOptions(); + } + + /// + /// Decrypt String (Not Supported for hashing) + /// + /// + /// + /// + public string DecryptString(string encryptedString) { + throw new Exception($"Failed to decrypt text, because {this.GetType()} doesn't support decryption."); + } + + /// + /// Decrypt Binary (Not Supported for hashing) + /// + /// + /// + /// + public byte[] DecryptBinary(byte[] encryptedBinary) { + throw new Exception($"Failed to decrypt text, because {this.GetType()} doesn't support decryption."); + } + + /// + /// Encrypt plain-text and returns MD5 hash + /// + /// + /// + public string EncryptString(string decryptedString) { + using (System.Security.Cryptography.MD5 md5 = System.Security.Cryptography.MD5.Create()) + { + byte[] inputBytes = _options.encoding.GetBytes(decryptedString); + byte[] hashBytes = md5.ComputeHash(inputBytes); + + // Convert the byte array to hexadecimal string + StringBuilder sb = new StringBuilder(); + for (int i = 0; i < hashBytes.Length; i++) + { + sb.Append(hashBytes[i].ToString("X2")); + } + return sb.ToString(); + } + } + + /// + /// Encrypt byte array and return MD5 hashed byte array + /// + /// + /// + public byte[] EncryptBinary(byte[] decryptedBinary) { + using (System.Security.Cryptography.MD5 md5 = System.Security.Cryptography.MD5.Create()) + { + byte[] hashBytes = md5.ComputeHash(decryptedBinary); + return hashBytes; + } + } + } +} \ No newline at end of file diff --git a/DevsDaddy/Shared/CryptoLibrary/Modules/MD5/MD5Provider.cs.meta b/DevsDaddy/Shared/CryptoLibrary/Modules/MD5/MD5Provider.cs.meta new file mode 100644 index 0000000..d4e9cfc --- /dev/null +++ b/DevsDaddy/Shared/CryptoLibrary/Modules/MD5/MD5Provider.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: ee97b4162c6c4e1cb68e88ab196c2028 +timeCreated: 1709894172 \ No newline at end of file diff --git a/DevsDaddy/Shared/CryptoLibrary/Modules/PBKDF2.meta b/DevsDaddy/Shared/CryptoLibrary/Modules/PBKDF2.meta new file mode 100644 index 0000000..997b845 --- /dev/null +++ b/DevsDaddy/Shared/CryptoLibrary/Modules/PBKDF2.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 34c2bd6fc94d4b1c9f8d55f1e3ea6f93 +timeCreated: 1709898865 \ No newline at end of file diff --git a/DevsDaddy/Shared/CryptoLibrary/Modules/PBKDF2/PBKDF2EncryptionOptions.cs b/DevsDaddy/Shared/CryptoLibrary/Modules/PBKDF2/PBKDF2EncryptionOptions.cs new file mode 100644 index 0000000..b7f3680 --- /dev/null +++ b/DevsDaddy/Shared/CryptoLibrary/Modules/PBKDF2/PBKDF2EncryptionOptions.cs @@ -0,0 +1,14 @@ +using System.Text; +using DevsDaddy.Shared.CryptoLibrary.Core; + +namespace DevsDaddy.Shared.CryptoLibrary.Modules.PBKDF2 +{ + [System.Serializable] + public class PBKDF2EncryptionOptions : IProviderOptions + { + public bool autoRegenerateSalt = true; + public Encoding encoding = Encoding.UTF8; + public int hashIterations = 100000; + public int saltSize = 34; + } +} \ No newline at end of file diff --git a/DevsDaddy/Shared/CryptoLibrary/Modules/PBKDF2/PBKDF2EncryptionOptions.cs.meta b/DevsDaddy/Shared/CryptoLibrary/Modules/PBKDF2/PBKDF2EncryptionOptions.cs.meta new file mode 100644 index 0000000..7e11cb9 --- /dev/null +++ b/DevsDaddy/Shared/CryptoLibrary/Modules/PBKDF2/PBKDF2EncryptionOptions.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 5913aff3da074d73bf59d501328a333e +timeCreated: 1709898878 \ No newline at end of file diff --git a/DevsDaddy/Shared/CryptoLibrary/Modules/PBKDF2/PBKDF2Provider.cs b/DevsDaddy/Shared/CryptoLibrary/Modules/PBKDF2/PBKDF2Provider.cs new file mode 100644 index 0000000..673313c --- /dev/null +++ b/DevsDaddy/Shared/CryptoLibrary/Modules/PBKDF2/PBKDF2Provider.cs @@ -0,0 +1,126 @@ +using System; +using System.Security.Cryptography; +using DevsDaddy.Shared.CryptoLibrary.Core; + +namespace DevsDaddy.Shared.CryptoLibrary.Modules.PBKDF2 +{ + /// + /// PBKDF2 Hashing Provider + /// + public class PBKDF2Provider : ICryptoProvider + { + // Provider Options + private PBKDF2EncryptionOptions _options; + private string currentSalt; + + /// + /// PBKDF2 Provider + /// + /// + public PBKDF2Provider(PBKDF2EncryptionOptions options = null) { + _options = options ?? new PBKDF2EncryptionOptions(); + } + + /// + /// Decrypt String (Not Supported for hashing) + /// + /// + /// + /// + public string DecryptString(string encryptedString) { + throw new Exception($"Failed to decrypt text, because {this.GetType()} doesn't support decryption."); + } + + /// + /// Decrypt Binary (Not Supported for hashing) + /// + /// + /// + /// + public byte[] DecryptBinary(byte[] encryptedBinary) { + throw new Exception($"Failed to decrypt text, because {this.GetType()} doesn't support decryption."); + } + + /// + /// Get PBKDF2 Hash from plain-text + /// + /// + /// + public string EncryptString(string decryptedString) { + if (string.IsNullOrEmpty(currentSalt) || _options.autoRegenerateSalt) GenerateSalt(); + return calculateHash(_options.hashIterations, decryptedString); + } + + /// + /// Get PBKDF2 Hash from byte array + /// + /// + /// + public byte[] EncryptBinary(byte[] decryptedBinary) { + if (string.IsNullOrEmpty(currentSalt) || _options.autoRegenerateSalt) GenerateSalt(); + return calculateHash(_options.hashIterations, decryptedBinary); + } + + /// + /// Generate Hash Salt + /// + /// + /// + public string GenerateSalt() + { + if (_options.saltSize < 1) + throw new InvalidOperationException(string.Format("Cannot generate a salt of size {0}, use a value greater than 1, recommended: 16", _options.saltSize)); + + var rand = RandomNumberGenerator.Create(); + var ret = new byte[_options.saltSize]; + rand.GetBytes(ret); + + currentSalt = string.Format("{0}.{1}", _options.hashIterations, Convert.ToBase64String(ret)); + return currentSalt; + } + + /// + /// Calculate Text Hash + /// + /// + /// + /// + private string calculateHash(int iteration, string text) + { + byte[] saltBytes = _options.encoding.GetBytes(currentSalt); + var pbkdf2 = new Rfc2898DeriveBytes(text, saltBytes, iteration); + var key = pbkdf2.GetBytes(64); + return Convert.ToBase64String(key); + } + + /// + /// Calculate Binary Hash + /// + /// + /// + /// + private byte[] calculateHash(int iteration, byte[] data) { + byte[] saltBytes = _options.encoding.GetBytes(currentSalt); + var pbkdf2 = new Rfc2898DeriveBytes(data, saltBytes, iteration); + var key = pbkdf2.GetBytes(64); + return key; + } + + /// + /// Expand Salt + /// + /// + private void expandSalt() + { + try + { + var i = currentSalt.IndexOf('.'); + _options.hashIterations = int.Parse(currentSalt.Substring(0, i), System.Globalization.NumberStyles.Number); + } + catch (Exception) + { + throw new FormatException("The salt was not in an expected format of {int}.{string}"); + } + } + } +} \ No newline at end of file diff --git a/DevsDaddy/Shared/CryptoLibrary/Modules/PBKDF2/PBKDF2Provider.cs.meta b/DevsDaddy/Shared/CryptoLibrary/Modules/PBKDF2/PBKDF2Provider.cs.meta new file mode 100644 index 0000000..7c2ee68 --- /dev/null +++ b/DevsDaddy/Shared/CryptoLibrary/Modules/PBKDF2/PBKDF2Provider.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: b5d0e6204e3048ee9720ecfc78f8e958 +timeCreated: 1709898883 \ No newline at end of file diff --git a/DevsDaddy/Shared/CryptoLibrary/Modules/RIPEMD-160.meta b/DevsDaddy/Shared/CryptoLibrary/Modules/RIPEMD-160.meta new file mode 100644 index 0000000..6a270fb --- /dev/null +++ b/DevsDaddy/Shared/CryptoLibrary/Modules/RIPEMD-160.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 9592fbdc5acf4a61b4e6717e1596b69b +timeCreated: 1709897338 \ No newline at end of file diff --git a/DevsDaddy/Shared/CryptoLibrary/Modules/RIPEMD-160/RIPEMD160.cs b/DevsDaddy/Shared/CryptoLibrary/Modules/RIPEMD-160/RIPEMD160.cs new file mode 100644 index 0000000..0d5d8b7 --- /dev/null +++ b/DevsDaddy/Shared/CryptoLibrary/Modules/RIPEMD-160/RIPEMD160.cs @@ -0,0 +1,17 @@ +namespace DevsDaddy.Shared.CryptoLibrary.Modules.RIPEMD_160 +{ + public abstract class RIPEMD160 : System.Security.Cryptography.HashAlgorithm + { + public RIPEMD160() { } + + public new static RIPEMD160 Create() + { + return new RIPEMD160Managed(); + } + + public new static RIPEMD160 Create(string hashname) + { + return new RIPEMD160Managed(); + } + } +} \ No newline at end of file diff --git a/DevsDaddy/Shared/CryptoLibrary/Modules/RIPEMD-160/RIPEMD160.cs.meta b/DevsDaddy/Shared/CryptoLibrary/Modules/RIPEMD-160/RIPEMD160.cs.meta new file mode 100644 index 0000000..12d7793 --- /dev/null +++ b/DevsDaddy/Shared/CryptoLibrary/Modules/RIPEMD-160/RIPEMD160.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: c31d9ebcea784ab18e1443e8656abe00 +timeCreated: 1709898451 \ No newline at end of file diff --git a/DevsDaddy/Shared/CryptoLibrary/Modules/RIPEMD-160/RIPEMD160Managed.cs b/DevsDaddy/Shared/CryptoLibrary/Modules/RIPEMD-160/RIPEMD160Managed.cs new file mode 100644 index 0000000..a60a4ff --- /dev/null +++ b/DevsDaddy/Shared/CryptoLibrary/Modules/RIPEMD-160/RIPEMD160Managed.cs @@ -0,0 +1,444 @@ +using System; +using System.Linq; +using System.Text; + +namespace DevsDaddy.Shared.CryptoLibrary.Modules.RIPEMD_160 +{ + public class RIPEMD160Managed : RIPEMD160 + { + static public UInt32 ReadUInt32(byte[] buffer, long offset) + { + return + (Convert.ToUInt32(buffer[3 + offset]) << 24) | + (Convert.ToUInt32(buffer[2 + offset]) << 16) | + (Convert.ToUInt32(buffer[1 + offset]) << 8) | + (Convert.ToUInt32(buffer[0 + offset])); + } + + static UInt32 RotateLeft(UInt32 value, int bits) + { + return (value << bits) | (value >> (32 - bits)); + } + + static UInt32 F(UInt32 x, UInt32 y, UInt32 z) + { + return x ^ y ^ z; + } + + static UInt32 G(UInt32 x, UInt32 y, UInt32 z) + { + return (x & y) | (~x & z); + } + + static UInt32 H(UInt32 x, UInt32 y, UInt32 z) + { + return (x | ~y) ^ z; + } + + static UInt32 I(UInt32 x, UInt32 y, UInt32 z) + { + return (x & z) | (y & ~z); + } + + static UInt32 J(UInt32 x, UInt32 y, UInt32 z) + { + return x ^ (y | ~z); + } + + static void FF(ref UInt32 a, UInt32 b, ref UInt32 c, UInt32 d, UInt32 e, UInt32 x, int s) + { + a += F(b, c, d) + x; + a = RotateLeft(a, s) + e; + c = RotateLeft(c, 10); + } + + static void GG(ref UInt32 a, UInt32 b, ref UInt32 c, UInt32 d, UInt32 e, UInt32 x, int s) + { + a += G(b, c, d) + x + (UInt32)0x5a827999; + a = RotateLeft(a, s) + e; + c = RotateLeft(c, 10); + } + + static void HH(ref UInt32 a, UInt32 b, ref UInt32 c, UInt32 d, UInt32 e, UInt32 x, int s) + { + a += H(b, c, d) + x + (UInt32)0x6ed9eba1; + a = RotateLeft(a, s) + e; + c = RotateLeft(c, 10); + } + + static void II(ref UInt32 a, UInt32 b, ref UInt32 c, UInt32 d, UInt32 e, UInt32 x, int s) + { + a += I(b, c, d) + x + (UInt32)0x8f1bbcdc; + a = RotateLeft(a, s) + e; + c = RotateLeft(c, 10); + } + + static void JJ(ref UInt32 a, UInt32 b, ref UInt32 c, UInt32 d, UInt32 e, UInt32 x, int s) + { + a += J(b, c, d) + x + (UInt32)0xa953fd4e; + a = RotateLeft(a, s) + e; + c = RotateLeft(c, 10); + } + + static void FFF(ref UInt32 a, UInt32 b, ref UInt32 c, UInt32 d, UInt32 e, UInt32 x, int s) + { + a += F(b, c, d) + x; + a = RotateLeft(a, s) + e; + c = RotateLeft(c, 10); + } + + static void GGG(ref UInt32 a, UInt32 b, ref UInt32 c, UInt32 d, UInt32 e, UInt32 x, int s) + { + a += G(b, c, d) + x + (UInt32)0x7a6d76e9; + a = RotateLeft(a, s) + e; + c = RotateLeft(c, 10); + } + + static void HHH(ref UInt32 a, UInt32 b, ref UInt32 c, UInt32 d, UInt32 e, UInt32 x, int s) + { + a += H(b, c, d) + x + (UInt32)0x6d703ef3; + a = RotateLeft(a, s) + e; + c = RotateLeft(c, 10); + } + + static void III(ref UInt32 a, UInt32 b, ref UInt32 c, UInt32 d, UInt32 e, UInt32 x, int s) + { + a += I(b, c, d) + x + (UInt32)0x5c4dd124; + a = RotateLeft(a, s) + e; + c = RotateLeft(c, 10); + } + + static void JJJ(ref UInt32 a, UInt32 b, ref UInt32 c, UInt32 d, UInt32 e, UInt32 x, int s) + { + a += J(b, c, d) + x + (UInt32)0x50a28be6; + a = RotateLeft(a, s) + e; + c = RotateLeft(c, 10); + } + + static public void MDinit(ref UInt32[] MDbuf) + { + MDbuf[0] = (UInt32)0x67452301; + MDbuf[1] = (UInt32)0xefcdab89; + MDbuf[2] = (UInt32)0x98badcfe; + MDbuf[3] = (UInt32)0x10325476; + MDbuf[4] = (UInt32)0xc3d2e1f0; + } + + static public void compress(ref UInt32[] MDbuf, UInt32[] X) + { + UInt32 aa = MDbuf[0]; + UInt32 bb = MDbuf[1]; + UInt32 cc = MDbuf[2]; + UInt32 dd = MDbuf[3]; + UInt32 ee = MDbuf[4]; + UInt32 aaa = MDbuf[0]; + UInt32 bbb = MDbuf[1]; + UInt32 ccc = MDbuf[2]; + UInt32 ddd = MDbuf[3]; + UInt32 eee = MDbuf[4]; + + /* round 1 */ + FF(ref aa, bb, ref cc, dd, ee, X[0], 11); + FF(ref ee, aa, ref bb, cc, dd, X[1], 14); + FF(ref dd, ee, ref aa, bb, cc, X[2], 15); + FF(ref cc, dd, ref ee, aa, bb, X[3], 12); + FF(ref bb, cc, ref dd, ee, aa, X[4], 5); + FF(ref aa, bb, ref cc, dd, ee, X[5], 8); + FF(ref ee, aa, ref bb, cc, dd, X[6], 7); + FF(ref dd, ee, ref aa, bb, cc, X[7], 9); + FF(ref cc, dd, ref ee, aa, bb, X[8], 11); + FF(ref bb, cc, ref dd, ee, aa, X[9], 13); + FF(ref aa, bb, ref cc, dd, ee, X[10], 14); + FF(ref ee, aa, ref bb, cc, dd, X[11], 15); + FF(ref dd, ee, ref aa, bb, cc, X[12], 6); + FF(ref cc, dd, ref ee, aa, bb, X[13], 7); + FF(ref bb, cc, ref dd, ee, aa, X[14], 9); + FF(ref aa, bb, ref cc, dd, ee, X[15], 8); + + /* round 2 */ + GG(ref ee, aa, ref bb, cc, dd, X[7], 7); + GG(ref dd, ee, ref aa, bb, cc, X[4], 6); + GG(ref cc, dd, ref ee, aa, bb, X[13], 8); + GG(ref bb, cc, ref dd, ee, aa, X[1], 13); + GG(ref aa, bb, ref cc, dd, ee, X[10], 11); + GG(ref ee, aa, ref bb, cc, dd, X[6], 9); + GG(ref dd, ee, ref aa, bb, cc, X[15], 7); + GG(ref cc, dd, ref ee, aa, bb, X[3], 15); + GG(ref bb, cc, ref dd, ee, aa, X[12], 7); + GG(ref aa, bb, ref cc, dd, ee, X[0], 12); + GG(ref ee, aa, ref bb, cc, dd, X[9], 15); + GG(ref dd, ee, ref aa, bb, cc, X[5], 9); + GG(ref cc, dd, ref ee, aa, bb, X[2], 11); + GG(ref bb, cc, ref dd, ee, aa, X[14], 7); + GG(ref aa, bb, ref cc, dd, ee, X[11], 13); + GG(ref ee, aa, ref bb, cc, dd, X[8], 12); + + /* round 3 */ + HH(ref dd, ee, ref aa, bb, cc, X[3], 11); + HH(ref cc, dd, ref ee, aa, bb, X[10], 13); + HH(ref bb, cc, ref dd, ee, aa, X[14], 6); + HH(ref aa, bb, ref cc, dd, ee, X[4], 7); + HH(ref ee, aa, ref bb, cc, dd, X[9], 14); + HH(ref dd, ee, ref aa, bb, cc, X[15], 9); + HH(ref cc, dd, ref ee, aa, bb, X[8], 13); + HH(ref bb, cc, ref dd, ee, aa, X[1], 15); + HH(ref aa, bb, ref cc, dd, ee, X[2], 14); + HH(ref ee, aa, ref bb, cc, dd, X[7], 8); + HH(ref dd, ee, ref aa, bb, cc, X[0], 13); + HH(ref cc, dd, ref ee, aa, bb, X[6], 6); + HH(ref bb, cc, ref dd, ee, aa, X[13], 5); + HH(ref aa, bb, ref cc, dd, ee, X[11], 12); + HH(ref ee, aa, ref bb, cc, dd, X[5], 7); + HH(ref dd, ee, ref aa, bb, cc, X[12], 5); + + /* round 4 */ + II(ref cc, dd, ref ee, aa, bb, X[1], 11); + II(ref bb, cc, ref dd, ee, aa, X[9], 12); + II(ref aa, bb, ref cc, dd, ee, X[11], 14); + II(ref ee, aa, ref bb, cc, dd, X[10], 15); + II(ref dd, ee, ref aa, bb, cc, X[0], 14); + II(ref cc, dd, ref ee, aa, bb, X[8], 15); + II(ref bb, cc, ref dd, ee, aa, X[12], 9); + II(ref aa, bb, ref cc, dd, ee, X[4], 8); + II(ref ee, aa, ref bb, cc, dd, X[13], 9); + II(ref dd, ee, ref aa, bb, cc, X[3], 14); + II(ref cc, dd, ref ee, aa, bb, X[7], 5); + II(ref bb, cc, ref dd, ee, aa, X[15], 6); + II(ref aa, bb, ref cc, dd, ee, X[14], 8); + II(ref ee, aa, ref bb, cc, dd, X[5], 6); + II(ref dd, ee, ref aa, bb, cc, X[6], 5); + II(ref cc, dd, ref ee, aa, bb, X[2], 12); + + /* round 5 */ + JJ(ref bb, cc, ref dd, ee, aa, X[4], 9); + JJ(ref aa, bb, ref cc, dd, ee, X[0], 15); + JJ(ref ee, aa, ref bb, cc, dd, X[5], 5); + JJ(ref dd, ee, ref aa, bb, cc, X[9], 11); + JJ(ref cc, dd, ref ee, aa, bb, X[7], 6); + JJ(ref bb, cc, ref dd, ee, aa, X[12], 8); + JJ(ref aa, bb, ref cc, dd, ee, X[2], 13); + JJ(ref ee, aa, ref bb, cc, dd, X[10], 12); + JJ(ref dd, ee, ref aa, bb, cc, X[14], 5); + JJ(ref cc, dd, ref ee, aa, bb, X[1], 12); + JJ(ref bb, cc, ref dd, ee, aa, X[3], 13); + JJ(ref aa, bb, ref cc, dd, ee, X[8], 14); + JJ(ref ee, aa, ref bb, cc, dd, X[11], 11); + JJ(ref dd, ee, ref aa, bb, cc, X[6], 8); + JJ(ref cc, dd, ref ee, aa, bb, X[15], 5); + JJ(ref bb, cc, ref dd, ee, aa, X[13], 6); + + /* parallel round 1 */ + JJJ(ref aaa, bbb, ref ccc, ddd, eee, X[5], 8); + JJJ(ref eee, aaa, ref bbb, ccc, ddd, X[14], 9); + JJJ(ref ddd, eee, ref aaa, bbb, ccc, X[7], 9); + JJJ(ref ccc, ddd, ref eee, aaa, bbb, X[0], 11); + JJJ(ref bbb, ccc, ref ddd, eee, aaa, X[9], 13); + JJJ(ref aaa, bbb, ref ccc, ddd, eee, X[2], 15); + JJJ(ref eee, aaa, ref bbb, ccc, ddd, X[11], 15); + JJJ(ref ddd, eee, ref aaa, bbb, ccc, X[4], 5); + JJJ(ref ccc, ddd, ref eee, aaa, bbb, X[13], 7); + JJJ(ref bbb, ccc, ref ddd, eee, aaa, X[6], 7); + JJJ(ref aaa, bbb, ref ccc, ddd, eee, X[15], 8); + JJJ(ref eee, aaa, ref bbb, ccc, ddd, X[8], 11); + JJJ(ref ddd, eee, ref aaa, bbb, ccc, X[1], 14); + JJJ(ref ccc, ddd, ref eee, aaa, bbb, X[10], 14); + JJJ(ref bbb, ccc, ref ddd, eee, aaa, X[3], 12); + JJJ(ref aaa, bbb, ref ccc, ddd, eee, X[12], 6); + + /* parallel round 2 */ + III(ref eee, aaa, ref bbb, ccc, ddd, X[6], 9); + III(ref ddd, eee, ref aaa, bbb, ccc, X[11], 13); + III(ref ccc, ddd, ref eee, aaa, bbb, X[3], 15); + III(ref bbb, ccc, ref ddd, eee, aaa, X[7], 7); + III(ref aaa, bbb, ref ccc, ddd, eee, X[0], 12); + III(ref eee, aaa, ref bbb, ccc, ddd, X[13], 8); + III(ref ddd, eee, ref aaa, bbb, ccc, X[5], 9); + III(ref ccc, ddd, ref eee, aaa, bbb, X[10], 11); + III(ref bbb, ccc, ref ddd, eee, aaa, X[14], 7); + III(ref aaa, bbb, ref ccc, ddd, eee, X[15], 7); + III(ref eee, aaa, ref bbb, ccc, ddd, X[8], 12); + III(ref ddd, eee, ref aaa, bbb, ccc, X[12], 7); + III(ref ccc, ddd, ref eee, aaa, bbb, X[4], 6); + III(ref bbb, ccc, ref ddd, eee, aaa, X[9], 15); + III(ref aaa, bbb, ref ccc, ddd, eee, X[1], 13); + III(ref eee, aaa, ref bbb, ccc, ddd, X[2], 11); + + /* parallel round 3 */ + HHH(ref ddd, eee, ref aaa, bbb, ccc, X[15], 9); + HHH(ref ccc, ddd, ref eee, aaa, bbb, X[5], 7); + HHH(ref bbb, ccc, ref ddd, eee, aaa, X[1], 15); + HHH(ref aaa, bbb, ref ccc, ddd, eee, X[3], 11); + HHH(ref eee, aaa, ref bbb, ccc, ddd, X[7], 8); + HHH(ref ddd, eee, ref aaa, bbb, ccc, X[14], 6); + HHH(ref ccc, ddd, ref eee, aaa, bbb, X[6], 6); + HHH(ref bbb, ccc, ref ddd, eee, aaa, X[9], 14); + HHH(ref aaa, bbb, ref ccc, ddd, eee, X[11], 12); + HHH(ref eee, aaa, ref bbb, ccc, ddd, X[8], 13); + HHH(ref ddd, eee, ref aaa, bbb, ccc, X[12], 5); + HHH(ref ccc, ddd, ref eee, aaa, bbb, X[2], 14); + HHH(ref bbb, ccc, ref ddd, eee, aaa, X[10], 13); + HHH(ref aaa, bbb, ref ccc, ddd, eee, X[0], 13); + HHH(ref eee, aaa, ref bbb, ccc, ddd, X[4], 7); + HHH(ref ddd, eee, ref aaa, bbb, ccc, X[13], 5); + + /* parallel round 4 */ + GGG(ref ccc, ddd, ref eee, aaa, bbb, X[8], 15); + GGG(ref bbb, ccc, ref ddd, eee, aaa, X[6], 5); + GGG(ref aaa, bbb, ref ccc, ddd, eee, X[4], 8); + GGG(ref eee, aaa, ref bbb, ccc, ddd, X[1], 11); + GGG(ref ddd, eee, ref aaa, bbb, ccc, X[3], 14); + GGG(ref ccc, ddd, ref eee, aaa, bbb, X[11], 14); + GGG(ref bbb, ccc, ref ddd, eee, aaa, X[15], 6); + GGG(ref aaa, bbb, ref ccc, ddd, eee, X[0], 14); + GGG(ref eee, aaa, ref bbb, ccc, ddd, X[5], 6); + GGG(ref ddd, eee, ref aaa, bbb, ccc, X[12], 9); + GGG(ref ccc, ddd, ref eee, aaa, bbb, X[2], 12); + GGG(ref bbb, ccc, ref ddd, eee, aaa, X[13], 9); + GGG(ref aaa, bbb, ref ccc, ddd, eee, X[9], 12); + GGG(ref eee, aaa, ref bbb, ccc, ddd, X[7], 5); + GGG(ref ddd, eee, ref aaa, bbb, ccc, X[10], 15); + GGG(ref ccc, ddd, ref eee, aaa, bbb, X[14], 8); + + /* parallel round 5 */ + FFF(ref bbb, ccc, ref ddd, eee, aaa, X[12], 8); + FFF(ref aaa, bbb, ref ccc, ddd, eee, X[15], 5); + FFF(ref eee, aaa, ref bbb, ccc, ddd, X[10], 12); + FFF(ref ddd, eee, ref aaa, bbb, ccc, X[4], 9); + FFF(ref ccc, ddd, ref eee, aaa, bbb, X[1], 12); + FFF(ref bbb, ccc, ref ddd, eee, aaa, X[5], 5); + FFF(ref aaa, bbb, ref ccc, ddd, eee, X[8], 14); + FFF(ref eee, aaa, ref bbb, ccc, ddd, X[7], 6); + FFF(ref ddd, eee, ref aaa, bbb, ccc, X[6], 8); + FFF(ref ccc, ddd, ref eee, aaa, bbb, X[2], 13); + FFF(ref bbb, ccc, ref ddd, eee, aaa, X[13], 6); + FFF(ref aaa, bbb, ref ccc, ddd, eee, X[14], 5); + FFF(ref eee, aaa, ref bbb, ccc, ddd, X[0], 15); + FFF(ref ddd, eee, ref aaa, bbb, ccc, X[3], 13); + FFF(ref ccc, ddd, ref eee, aaa, bbb, X[9], 11); + FFF(ref bbb, ccc, ref ddd, eee, aaa, X[11], 11); + + // combine results */ + ddd += cc + MDbuf[1]; /* final result for MDbuf[0] */ + MDbuf[1] = MDbuf[2] + dd + eee; + MDbuf[2] = MDbuf[3] + ee + aaa; + MDbuf[3] = MDbuf[4] + aa + bbb; + MDbuf[4] = MDbuf[0] + bb + ccc; + MDbuf[0] = ddd; + } + + static public void MDfinish(ref UInt32[] MDbuf, byte[] strptr, long index, UInt32 lswlen, UInt32 mswlen) + { + //UInt32 i; /* counter */ + var X = Enumerable.Repeat((UInt32)0, 16).ToArray(); /* message words */ + + + /* put bytes from strptr into X */ + for (var i = 0; i < (lswlen & 63); i++) + { + /* byte i goes into word X[i div 4] at pos. 8*(i mod 4) */ + X[i >> 2] ^= Convert.ToUInt32(strptr[i + index]) << (8 * (i & 3)); + } + + /* append the bit m_n == 1 */ + X[(lswlen >> 2) & 15] ^= (UInt32)1 << Convert.ToInt32(8 * (lswlen & 3) + 7); + + if ((lswlen & 63) > 55) + { + /* length goes to next block */ + compress(ref MDbuf, X); + X = Enumerable.Repeat((UInt32)0, 16).ToArray(); + } + + /* append length in bits*/ + X[14] = lswlen << 3; + X[15] = (lswlen >> 29) | (mswlen << 3); + compress(ref MDbuf, X); + } + + static int RMDsize = 160; + UInt32 [] MDbuf = new UInt32 [RMDsize / 32]; + UInt32 [] X = new UInt32[16]; + byte [] UnhashedBuffer = new byte[64]; + int UnhashedBufferLength = 0; + long HashedLength = 0; + + public RIPEMD160Managed() + { + Initialize(); + } + + protected override void HashCore (byte[] array, int ibStart, int cbSize) + { + var index = 0; + while(index < cbSize) + { + var bytesRemaining = cbSize - index; + if(UnhashedBufferLength > 0) + { + if((bytesRemaining + UnhashedBufferLength) >= (UnhashedBuffer.Length)) + { + Array.Copy(array, ibStart + index, UnhashedBuffer, UnhashedBufferLength, (UnhashedBuffer.Length) - UnhashedBufferLength); + index += (UnhashedBuffer.Length) - UnhashedBufferLength; + UnhashedBufferLength = UnhashedBuffer.Length; + + for (var i = 0; i < 16; i++) + X[i] = ReadUInt32(UnhashedBuffer, i * 4); + + compress(ref MDbuf, X); + UnhashedBufferLength = 0; + } + else + { + Array.Copy(array, ibStart + index, UnhashedBuffer, UnhashedBufferLength, bytesRemaining); + UnhashedBufferLength += bytesRemaining; + index += bytesRemaining; + } + } + else + { + if(bytesRemaining >= (UnhashedBuffer.Length)) + { + for (var i = 0; i < 16; i++) + X[i] = ReadUInt32(array, index + (i * 4)); + index += UnhashedBuffer.Length; + + compress(ref MDbuf, X); + } + else + { + Array.Copy(array, ibStart + index, UnhashedBuffer, 0, bytesRemaining); + UnhashedBufferLength = bytesRemaining; + index += bytesRemaining; + } + } + } + + HashedLength += cbSize; + } + + protected override byte[] HashFinal () + { + MDfinish(ref MDbuf, UnhashedBuffer, 0, Convert.ToUInt32(HashedLength), 0); + + var result = new byte [RMDsize / 8]; + + for (var i = 0; i < RMDsize / 8; i += 4) + { + result[i] = Convert.ToByte(MDbuf[i >> 2] & 0xFF); /* implicit cast to byte */ + result[i + 1] = Convert.ToByte((MDbuf[i >> 2] >> 8) & 0xFF); /* extracts the 8 least */ + result[i + 2] = Convert.ToByte((MDbuf[i >> 2] >> 16) & 0xFF); /* significant bits. */ + result[i + 3] = Convert.ToByte((MDbuf[i >> 2] >> 24) & 0xFF); + } + + return result; + } + + public override void Initialize () + { + MDinit(ref MDbuf); + X = Enumerable.Repeat((UInt32)0, 16).ToArray(); + HashedLength = 0; + UnhashedBufferLength = 0; + } + } +} \ No newline at end of file diff --git a/DevsDaddy/Shared/CryptoLibrary/Modules/RIPEMD-160/RIPEMD160Managed.cs.meta b/DevsDaddy/Shared/CryptoLibrary/Modules/RIPEMD-160/RIPEMD160Managed.cs.meta new file mode 100644 index 0000000..66a0570 --- /dev/null +++ b/DevsDaddy/Shared/CryptoLibrary/Modules/RIPEMD-160/RIPEMD160Managed.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 26bcc4f1c6c841829281644666d97924 +timeCreated: 1709898527 \ No newline at end of file diff --git a/DevsDaddy/Shared/CryptoLibrary/Modules/RIPEMD-160/RipemdEncryptionOptions.cs b/DevsDaddy/Shared/CryptoLibrary/Modules/RIPEMD-160/RipemdEncryptionOptions.cs new file mode 100644 index 0000000..df36007 --- /dev/null +++ b/DevsDaddy/Shared/CryptoLibrary/Modules/RIPEMD-160/RipemdEncryptionOptions.cs @@ -0,0 +1,11 @@ +using System.Text; +using DevsDaddy.Shared.CryptoLibrary.Core; + +namespace DevsDaddy.Shared.CryptoLibrary.Modules.RIPEMD_160 +{ + [System.Serializable] + public class RipemdEncryptionOptions : IProviderOptions + { + public Encoding encoding = Encoding.UTF8; + } +} \ No newline at end of file diff --git a/DevsDaddy/Shared/CryptoLibrary/Modules/RIPEMD-160/RipemdEncryptionOptions.cs.meta b/DevsDaddy/Shared/CryptoLibrary/Modules/RIPEMD-160/RipemdEncryptionOptions.cs.meta new file mode 100644 index 0000000..e152f30 --- /dev/null +++ b/DevsDaddy/Shared/CryptoLibrary/Modules/RIPEMD-160/RipemdEncryptionOptions.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 74488339489a42cebc569ec7b0afb0ef +timeCreated: 1709897381 \ No newline at end of file diff --git a/DevsDaddy/Shared/CryptoLibrary/Modules/RIPEMD-160/RipemdProvider.cs b/DevsDaddy/Shared/CryptoLibrary/Modules/RIPEMD-160/RipemdProvider.cs new file mode 100644 index 0000000..9b41157 --- /dev/null +++ b/DevsDaddy/Shared/CryptoLibrary/Modules/RIPEMD-160/RipemdProvider.cs @@ -0,0 +1,65 @@ +using System; +using DevsDaddy.Shared.CryptoLibrary.Core; + +namespace DevsDaddy.Shared.CryptoLibrary.Modules.RIPEMD_160 +{ + /// + /// Old RIPEMD-160 Hashing Provider + /// + public class RipemdProvider : ICryptoProvider + { + // Provider Options + private RipemdEncryptionOptions _options; + + /// + /// RIPEMD-160 Provider + /// + /// + public RipemdProvider(RipemdEncryptionOptions options = null) { + _options = options ?? new RipemdEncryptionOptions(); + } + + /// + /// Decrypt String (Not Supported for hashing) + /// + /// + /// + /// + public string DecryptString(string encryptedString) { + throw new Exception($"Failed to decrypt text, because {this.GetType()} doesn't support decryption."); + } + + /// + /// Decrypt Binary (Not Supported for hashing) + /// + /// + /// + /// + public byte[] DecryptBinary(byte[] encryptedBinary) { + throw new Exception($"Failed to decrypt text, because {this.GetType()} doesn't support decryption."); + } + + /// + /// Get RIPEMD-160 Hash from String + /// + /// + /// + public string EncryptString(string decryptedString) { + byte[] encrypted = EncryptBinary(_options.encoding.GetBytes(decryptedString)); + return Convert.ToBase64String(encrypted); + } + + /// + /// Get RIPEMD-160 Hash from Byte Array + /// + /// + /// + public byte[] EncryptBinary(byte[] decryptedBinary) { + using (RIPEMD160 r160 = RIPEMD160.Create()) + { + byte[] hashBytes = r160.ComputeHash(decryptedBinary); + return hashBytes; + } + } + } +} \ No newline at end of file diff --git a/DevsDaddy/Shared/CryptoLibrary/Modules/RIPEMD-160/RipemdProvider.cs.meta b/DevsDaddy/Shared/CryptoLibrary/Modules/RIPEMD-160/RipemdProvider.cs.meta new file mode 100644 index 0000000..fa07ede --- /dev/null +++ b/DevsDaddy/Shared/CryptoLibrary/Modules/RIPEMD-160/RipemdProvider.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 471108039962485781b7fb6befbd1009 +timeCreated: 1709897391 \ No newline at end of file diff --git a/DevsDaddy/Shared/CryptoLibrary/Modules/RSA.meta b/DevsDaddy/Shared/CryptoLibrary/Modules/RSA.meta new file mode 100644 index 0000000..f474689 --- /dev/null +++ b/DevsDaddy/Shared/CryptoLibrary/Modules/RSA.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 866a055b07f84eacaee1ae7b40aa148e +timeCreated: 1709889644 \ No newline at end of file diff --git a/DevsDaddy/Shared/CryptoLibrary/Modules/RSA/RSAEncryptionOptions.cs b/DevsDaddy/Shared/CryptoLibrary/Modules/RSA/RSAEncryptionOptions.cs new file mode 100644 index 0000000..6376467 --- /dev/null +++ b/DevsDaddy/Shared/CryptoLibrary/Modules/RSA/RSAEncryptionOptions.cs @@ -0,0 +1,14 @@ +using System.Text; +using DevsDaddy.Shared.CryptoLibrary.Core; + +namespace DevsDaddy.Shared.CryptoLibrary.Modules.RSA +{ + [System.Serializable] + public class RSAEncryptionOptions : IProviderOptions + { + public string publicKey = "RSAPublicKey"; + public string privateKey = "RSAPrivateKey"; + + public Encoding encoding = Encoding.UTF8; + } +} \ No newline at end of file diff --git a/DevsDaddy/Shared/CryptoLibrary/Modules/RSA/RSAEncryptionOptions.cs.meta b/DevsDaddy/Shared/CryptoLibrary/Modules/RSA/RSAEncryptionOptions.cs.meta new file mode 100644 index 0000000..a845987 --- /dev/null +++ b/DevsDaddy/Shared/CryptoLibrary/Modules/RSA/RSAEncryptionOptions.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: ee37ae4cb385462d96af708da83eadfa +timeCreated: 1709894551 \ No newline at end of file diff --git a/DevsDaddy/Shared/CryptoLibrary/Modules/RSA/RSAProvider.cs b/DevsDaddy/Shared/CryptoLibrary/Modules/RSA/RSAProvider.cs new file mode 100644 index 0000000..11259fa --- /dev/null +++ b/DevsDaddy/Shared/CryptoLibrary/Modules/RSA/RSAProvider.cs @@ -0,0 +1,86 @@ +using System; +using System.Collections.Generic; +using System.Security.Cryptography; +using DevsDaddy.Shared.CryptoLibrary.Core; + +namespace DevsDaddy.Shared.CryptoLibrary.Modules.RSA +{ + /// + /// RSA Encryption Provider + /// Using for encrypt/decrypt plain text or byte arrays + /// + public class RSAProvider : ICryptoProvider + { + // Provider Options + private RSAEncryptionOptions _options; + + /// + /// RSA Encryption Provider + /// + /// + public RSAProvider(RSAEncryptionOptions options = null) { + _options = options ?? new RSAEncryptionOptions(); + } + + /// + /// Decrypt RSA-encrypted string + /// + /// + /// + public string DecryptString(string encryptedString) { + byte[] decrypted = DecryptBinary(Convert.FromBase64String(encryptedString)); + return _options.encoding.GetString(decrypted); + } + + /// + /// Decrypt RSA-encrypted byte array + /// + /// + /// + public byte[] DecryptBinary(byte[] encryptedBinary) { + using (RSACryptoServiceProvider rsa = new RSACryptoServiceProvider()) + { + rsa.FromXmlString(_options.privateKey); + byte[] decrypted = rsa.Decrypt(encryptedBinary, false); + return decrypted; + } + } + + /// + /// Encrypt plain-text to RSA-encrypted string + /// + /// + /// + public string EncryptString(string decryptedString) { + byte[] encrypted = EncryptBinary(_options.encoding.GetBytes(decryptedString)); + return Convert.ToBase64String(encrypted); + } + + /// + /// Encrypt byte array to RSA-encrypted byte array + /// + /// + /// + public byte[] EncryptBinary(byte[] decryptedBinary) { + using (RSACryptoServiceProvider rsa = new RSACryptoServiceProvider()) + { + rsa.FromXmlString(_options.publicKey); + byte[] encrypted = rsa.Encrypt(decryptedBinary, false); + return encrypted; + } + } + + /// + /// Generate Key Pair for RSA Provider + /// + /// + /// + public static KeyValuePair GenerateKeyPair(int keySize) + { + RSACryptoServiceProvider rsa = new RSACryptoServiceProvider(keySize); + string publicKey = rsa.ToXmlString(false); + string privateKey = rsa.ToXmlString(true); + return new KeyValuePair(publicKey, privateKey); + } + } +} \ No newline at end of file diff --git a/DevsDaddy/Shared/CryptoLibrary/Modules/RSA/RSAProvider.cs.meta b/DevsDaddy/Shared/CryptoLibrary/Modules/RSA/RSAProvider.cs.meta new file mode 100644 index 0000000..5b92630 --- /dev/null +++ b/DevsDaddy/Shared/CryptoLibrary/Modules/RSA/RSAProvider.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 5d97d6eae2424e81b81c16663bc8b7c0 +timeCreated: 1709894581 \ No newline at end of file diff --git a/DevsDaddy/Shared/CryptoLibrary/Modules/SHA.meta b/DevsDaddy/Shared/CryptoLibrary/Modules/SHA.meta new file mode 100644 index 0000000..fcb9996 --- /dev/null +++ b/DevsDaddy/Shared/CryptoLibrary/Modules/SHA.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 04b40f7dc243443aa26ffe21731de7f3 +timeCreated: 1709889629 \ No newline at end of file diff --git a/DevsDaddy/Shared/CryptoLibrary/Modules/SHA/SHA1Provider.cs b/DevsDaddy/Shared/CryptoLibrary/Modules/SHA/SHA1Provider.cs new file mode 100644 index 0000000..bbc2cfe --- /dev/null +++ b/DevsDaddy/Shared/CryptoLibrary/Modules/SHA/SHA1Provider.cs @@ -0,0 +1,77 @@ +using System; +using System.Security.Cryptography; +using System.Text; +using DevsDaddy.Shared.CryptoLibrary.Core; + +namespace DevsDaddy.Shared.CryptoLibrary.Modules.SHA +{ + /// + /// SHA1 Hashing Provider + /// + public class SHA1Provider : ICryptoProvider + { + private SHAEncryptionOptions _options; + + /// + /// SHA1 Provider + /// + /// + public SHA1Provider(SHAEncryptionOptions options = null) { + _options = options ?? new SHAEncryptionOptions(); + } + + /// + /// Decrypt plain-text (Not Supported for Hashing) + /// + /// + /// + /// + public string DecryptString(string encryptedString) { + throw new Exception($"Failed to decrypt text, because {this.GetType()} doesn't support decryption."); + } + + /// + /// Decrypt Binary Data (Not Supported for Hashing) + /// + /// + /// + /// + public byte[] DecryptBinary(byte[] encryptedBinary) { + throw new Exception($"Failed to decrypt text, because {this.GetType()} doesn't support decryption."); + } + + /// + /// Get SHA1 Hash for Plain-text + /// + /// + /// + public string EncryptString(string decryptedString) { + using (SHA1Managed sha1 = new SHA1Managed()) + { + var hash = sha1.ComputeHash(_options.encoding.GetBytes(decryptedString)); + var sb = new StringBuilder(hash.Length * 2); + + foreach (byte b in hash) + { + // can be "x2" if you want lowercase + sb.Append(b.ToString("X2")); + } + + return sb.ToString(); + } + } + + /// + /// Get SHA1 Hash for Byte array + /// + /// + /// + public byte[] EncryptBinary(byte[] decryptedBinary) { + using (SHA1Managed sha1 = new SHA1Managed()) + { + var hash = sha1.ComputeHash(decryptedBinary); + return hash; + } + } + } +} \ No newline at end of file diff --git a/DevsDaddy/Shared/CryptoLibrary/Modules/SHA/SHA1Provider.cs.meta b/DevsDaddy/Shared/CryptoLibrary/Modules/SHA/SHA1Provider.cs.meta new file mode 100644 index 0000000..326ea04 --- /dev/null +++ b/DevsDaddy/Shared/CryptoLibrary/Modules/SHA/SHA1Provider.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 6d4c9e5dd260446583ebdff39bc31329 +timeCreated: 1709895806 \ No newline at end of file diff --git a/DevsDaddy/Shared/CryptoLibrary/Modules/SHA/SHA256Provider.cs b/DevsDaddy/Shared/CryptoLibrary/Modules/SHA/SHA256Provider.cs new file mode 100644 index 0000000..1ea7cc5 --- /dev/null +++ b/DevsDaddy/Shared/CryptoLibrary/Modules/SHA/SHA256Provider.cs @@ -0,0 +1,77 @@ +using System; +using System.Security.Cryptography; +using System.Text; +using DevsDaddy.Shared.CryptoLibrary.Core; + +namespace DevsDaddy.Shared.CryptoLibrary.Modules.SHA +{ + /// + /// SHA1 Hashing Provider + /// + public class SHA256Provider : ICryptoProvider + { + private SHAEncryptionOptions _options; + + /// + /// SHA256 Provider + /// + /// + public SHA256Provider(SHAEncryptionOptions options = null) { + _options = options ?? new SHAEncryptionOptions(); + } + + /// + /// Decrypt plain-text (Not Supported for Hashing) + /// + /// + /// + /// + public string DecryptString(string encryptedString) { + throw new Exception($"Failed to decrypt text, because {this.GetType()} doesn't support decryption."); + } + + /// + /// Decrypt Binary Data (Not Supported for Hashing) + /// + /// + /// + /// + public byte[] DecryptBinary(byte[] encryptedBinary) { + throw new Exception($"Failed to decrypt text, because {this.GetType()} doesn't support decryption."); + } + + /// + /// Get SHA256 Hash for Plain-text + /// + /// + /// + public string EncryptString(string decryptedString) { + using (SHA256Managed sha256 = new SHA256Managed()) + { + var hash = sha256.ComputeHash(_options.encoding.GetBytes(decryptedString)); + var sb = new StringBuilder(hash.Length * 2); + + foreach (byte b in hash) + { + // can be "x2" if you want lowercase + sb.Append(b.ToString("X2")); + } + + return sb.ToString(); + } + } + + /// + /// Get SHA256 Hash for Byte array + /// + /// + /// + public byte[] EncryptBinary(byte[] decryptedBinary) { + using (SHA256Managed sha256 = new SHA256Managed()) + { + var hash = sha256.ComputeHash(decryptedBinary); + return hash; + } + } + } +} \ No newline at end of file diff --git a/DevsDaddy/Shared/CryptoLibrary/Modules/SHA/SHA256Provider.cs.meta b/DevsDaddy/Shared/CryptoLibrary/Modules/SHA/SHA256Provider.cs.meta new file mode 100644 index 0000000..efc00c9 --- /dev/null +++ b/DevsDaddy/Shared/CryptoLibrary/Modules/SHA/SHA256Provider.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: cb92a95f816c49599c5f2b4ee4d38422 +timeCreated: 1709895861 \ No newline at end of file diff --git a/DevsDaddy/Shared/CryptoLibrary/Modules/SHA/SHA512Provider.cs b/DevsDaddy/Shared/CryptoLibrary/Modules/SHA/SHA512Provider.cs new file mode 100644 index 0000000..86ad58f --- /dev/null +++ b/DevsDaddy/Shared/CryptoLibrary/Modules/SHA/SHA512Provider.cs @@ -0,0 +1,77 @@ +using System; +using System.Security.Cryptography; +using System.Text; +using DevsDaddy.Shared.CryptoLibrary.Core; + +namespace DevsDaddy.Shared.CryptoLibrary.Modules.SHA +{ + /// + /// SHA512 Hashing Provider + /// + public class SHA512Provider : ICryptoProvider + { + private SHAEncryptionOptions _options; + + /// + /// SHA512 Provider + /// + /// + public SHA512Provider(SHAEncryptionOptions options = null) { + _options = options ?? new SHAEncryptionOptions(); + } + + /// + /// Decrypt plain-text (Not Supported for Hashing) + /// + /// + /// + /// + public string DecryptString(string encryptedString) { + throw new Exception($"Failed to decrypt text, because {this.GetType()} doesn't support decryption."); + } + + /// + /// Decrypt Binary Data (Not Supported for Hashing) + /// + /// + /// + /// + public byte[] DecryptBinary(byte[] encryptedBinary) { + throw new Exception($"Failed to decrypt text, because {this.GetType()} doesn't support decryption."); + } + + /// + /// Get SHA512 Hash for Plain-text + /// + /// + /// + public string EncryptString(string decryptedString) { + using (SHA512Managed sha256 = new SHA512Managed()) + { + var hash = sha256.ComputeHash(_options.encoding.GetBytes(decryptedString)); + var sb = new StringBuilder(hash.Length * 2); + + foreach (byte b in hash) + { + // can be "x2" if you want lowercase + sb.Append(b.ToString("X2")); + } + + return sb.ToString(); + } + } + + /// + /// Get SHA512 Hash for Byte array + /// + /// + /// + public byte[] EncryptBinary(byte[] decryptedBinary) { + using (SHA512Managed sha512 = new SHA512Managed()) + { + var hash = sha512.ComputeHash(decryptedBinary); + return hash; + } + } + } +} \ No newline at end of file diff --git a/DevsDaddy/Shared/CryptoLibrary/Modules/SHA/SHA512Provider.cs.meta b/DevsDaddy/Shared/CryptoLibrary/Modules/SHA/SHA512Provider.cs.meta new file mode 100644 index 0000000..2ca78e8 --- /dev/null +++ b/DevsDaddy/Shared/CryptoLibrary/Modules/SHA/SHA512Provider.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 2164e47f6c7a4874b422c7789539ec18 +timeCreated: 1709895868 \ No newline at end of file diff --git a/DevsDaddy/Shared/CryptoLibrary/Modules/SHA/SHAEncryptionOptions.cs b/DevsDaddy/Shared/CryptoLibrary/Modules/SHA/SHAEncryptionOptions.cs new file mode 100644 index 0000000..4a794bf --- /dev/null +++ b/DevsDaddy/Shared/CryptoLibrary/Modules/SHA/SHAEncryptionOptions.cs @@ -0,0 +1,11 @@ +using System.Text; +using DevsDaddy.Shared.CryptoLibrary.Core; + +namespace DevsDaddy.Shared.CryptoLibrary.Modules.SHA +{ + [System.Serializable] + public class SHAEncryptionOptions : IProviderOptions + { + public Encoding encoding = Encoding.UTF8; + } +} \ No newline at end of file diff --git a/DevsDaddy/Shared/CryptoLibrary/Modules/SHA/SHAEncryptionOptions.cs.meta b/DevsDaddy/Shared/CryptoLibrary/Modules/SHA/SHAEncryptionOptions.cs.meta new file mode 100644 index 0000000..38614c2 --- /dev/null +++ b/DevsDaddy/Shared/CryptoLibrary/Modules/SHA/SHAEncryptionOptions.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 329c2b00898a419ebd3501427a96764f +timeCreated: 1709895780 \ No newline at end of file diff --git a/DevsDaddy/Shared/CryptoLibrary/Modules/TripleDES.meta b/DevsDaddy/Shared/CryptoLibrary/Modules/TripleDES.meta new file mode 100644 index 0000000..1b0a6c7 --- /dev/null +++ b/DevsDaddy/Shared/CryptoLibrary/Modules/TripleDES.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: aac9be5c0d2c4e468ce9d2fe00d89460 +timeCreated: 1709896341 \ No newline at end of file diff --git a/DevsDaddy/Shared/CryptoLibrary/Modules/TripleDES/TripleDESEncryptionOptions.cs b/DevsDaddy/Shared/CryptoLibrary/Modules/TripleDES/TripleDESEncryptionOptions.cs new file mode 100644 index 0000000..1ddece4 --- /dev/null +++ b/DevsDaddy/Shared/CryptoLibrary/Modules/TripleDES/TripleDESEncryptionOptions.cs @@ -0,0 +1,16 @@ +using System.Security.Cryptography; +using System.Text; +using DevsDaddy.Shared.CryptoLibrary.Core; + +namespace DevsDaddy.Shared.CryptoLibrary.Modules.TripleDES +{ + [System.Serializable] + public class TripleDESEncryptionOptions : IProviderOptions + { + public string cryptoKey = "ABCDEFGH"; + public Encoding encoding = Encoding.UTF8; + + public CipherMode mode = CipherMode.ECB; + public PaddingMode padding = PaddingMode.PKCS7; + } +} \ No newline at end of file diff --git a/DevsDaddy/Shared/CryptoLibrary/Modules/TripleDES/TripleDESEncryptionOptions.cs.meta b/DevsDaddy/Shared/CryptoLibrary/Modules/TripleDES/TripleDESEncryptionOptions.cs.meta new file mode 100644 index 0000000..38f0e6d --- /dev/null +++ b/DevsDaddy/Shared/CryptoLibrary/Modules/TripleDES/TripleDESEncryptionOptions.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 5454f018e8874bc88dae375a8e20f892 +timeCreated: 1709896365 \ No newline at end of file diff --git a/DevsDaddy/Shared/CryptoLibrary/Modules/TripleDES/TripleDESProvider.cs b/DevsDaddy/Shared/CryptoLibrary/Modules/TripleDES/TripleDESProvider.cs new file mode 100644 index 0000000..5b82f69 --- /dev/null +++ b/DevsDaddy/Shared/CryptoLibrary/Modules/TripleDES/TripleDESProvider.cs @@ -0,0 +1,87 @@ +using System; +using System.Security.Cryptography; +using DevsDaddy.Shared.CryptoLibrary.Core; + +namespace DevsDaddy.Shared.CryptoLibrary.Modules.TripleDES +{ + /// + /// Triple DES Modern Crypto Provider + /// + public class TripleDESProvider : ICryptoProvider + { + private TripleDESEncryptionOptions _options; + + /// + /// Triple DES Provider + /// + /// + public TripleDESProvider(TripleDESEncryptionOptions options = null) { + _options = options ?? new TripleDESEncryptionOptions(); + } + + /// + /// Decrypt plain-text using Triple DES + /// + /// + /// + public string DecryptString(string encryptedString) { + byte[] txtByteData = Convert.FromBase64String(encryptedString); + byte[] decoded = DecryptBinary(txtByteData); + return _options.encoding.GetString(decoded); + } + + /// + /// Decrypt byte array using Triple DES + /// + /// + /// + public byte[] DecryptBinary(byte[] encryptedBinary) { + MD5CryptoServiceProvider MD5CryptoService = new MD5CryptoServiceProvider(); + byte[] securityKeyArray = MD5CryptoService.ComputeHash(_options.encoding.GetBytes(_options.cryptoKey)); + MD5CryptoService.Clear(); + + var tripleDESCryptoService = new TripleDESCryptoServiceProvider(); + tripleDESCryptoService.Key = securityKeyArray; + tripleDESCryptoService.Mode = _options.mode; + tripleDESCryptoService.Padding = _options.padding; + + var crytpoTransform = tripleDESCryptoService.CreateDecryptor(); + byte[] resultArray = crytpoTransform.TransformFinalBlock(encryptedBinary, 0, encryptedBinary.Length); + tripleDESCryptoService.Clear(); + return resultArray; + } + + /// + /// Encrypt Plain-Text using Triple DES + /// + /// + /// + public string EncryptString(string decryptedString) { + byte[] txtByteData = _options.encoding.GetBytes(decryptedString); + byte[] encoded = EncryptBinary(txtByteData); + return Convert.ToBase64String(encoded); + } + + /// + /// Encrypt Byte Array using Triple DES + /// + /// + /// + public byte[] EncryptBinary(byte[] decryptedBinary) { + MD5CryptoServiceProvider MD5CryptoService = new MD5CryptoServiceProvider(); + byte[] securityKeyArray = MD5CryptoService.ComputeHash(_options.encoding.GetBytes(_options.cryptoKey)); + MD5CryptoService.Clear(); + + var tripleDESCryptoService = new TripleDESCryptoServiceProvider(); + tripleDESCryptoService.Key = securityKeyArray; + tripleDESCryptoService.Mode = _options.mode; + tripleDESCryptoService.Padding = _options.padding; + + var crytpoTransform = tripleDESCryptoService.CreateEncryptor(); + byte[] resultArray = crytpoTransform.TransformFinalBlock(decryptedBinary, 0, decryptedBinary.Length); + + tripleDESCryptoService.Clear(); + return resultArray; + } + } +} \ No newline at end of file diff --git a/DevsDaddy/Shared/CryptoLibrary/Modules/TripleDES/TripleDESProvider.cs.meta b/DevsDaddy/Shared/CryptoLibrary/Modules/TripleDES/TripleDESProvider.cs.meta new file mode 100644 index 0000000..05daaea --- /dev/null +++ b/DevsDaddy/Shared/CryptoLibrary/Modules/TripleDES/TripleDESProvider.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: d899fe1793c34e3984a69625da66e8be +timeCreated: 1709896382 \ No newline at end of file diff --git a/DevsDaddy/Shared/CryptoLibrary/Modules/Twofish.meta b/DevsDaddy/Shared/CryptoLibrary/Modules/Twofish.meta new file mode 100644 index 0000000..9fe2912 --- /dev/null +++ b/DevsDaddy/Shared/CryptoLibrary/Modules/Twofish.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 533b53f6351c40b0a209b008dc6facaf +timeCreated: 1709897320 \ No newline at end of file diff --git a/DevsDaddy/Shared/CryptoLibrary/Modules/Twofish/Twofish.cs b/DevsDaddy/Shared/CryptoLibrary/Modules/Twofish/Twofish.cs new file mode 100644 index 0000000..33635e1 --- /dev/null +++ b/DevsDaddy/Shared/CryptoLibrary/Modules/Twofish/Twofish.cs @@ -0,0 +1,749 @@ +using System; +using System.Runtime.CompilerServices; +using System.Security.Cryptography; + +namespace DevsDaddy.Shared.CryptoLibrary.Modules.Twofish +{ + public sealed class Twofish : SymmetricAlgorithm + { + public Twofish() : base() { + KeySizeValue = KeySizeInBits; + BlockSizeValue = BlockSizeInBits; + FeedbackSizeValue = BlockSizeValue; + LegalBlockSizesValue = new KeySizes[] { new KeySizes(BlockSizeInBits, BlockSizeInBits, 0) }; + LegalKeySizesValue = new KeySizes[] { new KeySizes(128, 256, 64) }; // 128, 192, or 256 + + base.Mode = CipherMode.CBC; // same as default + base.Padding = PaddingMode.PKCS7; + } + + public override ICryptoTransform CreateDecryptor(byte[] rgbKey, byte[]? rgbIV) { + if (rgbKey == null) { throw new ArgumentNullException(nameof(rgbKey), "Key cannot be null."); } + if (rgbKey.Length != KeySize / 8) { throw new ArgumentOutOfRangeException(nameof(rgbKey), "Key size mismatch."); } + if (Mode == CipherMode.CBC) { + if (rgbIV == null) { throw new ArgumentNullException(nameof(rgbIV), "IV cannot be null."); } + if (rgbIV.Length != 16) { throw new ArgumentOutOfRangeException(nameof(rgbIV), "Invalid IV size."); } + } + + return new TwofishTransform(rgbKey, rgbIV, TwofishTransformMode.Decrypt, Mode, Padding); + } + + public override ICryptoTransform CreateEncryptor(byte[] rgbKey, byte[]? rgbIV) { + if (rgbKey == null) { throw new ArgumentNullException(nameof(rgbKey), "Key cannot be null."); } + if (rgbKey.Length != KeySize / 8) { throw new ArgumentOutOfRangeException(nameof(rgbKey), "Key size mismatch."); } + if (Mode == CipherMode.CBC) { + if (rgbIV == null) { throw new ArgumentNullException(nameof(rgbIV), "IV cannot be null."); } + if (rgbIV.Length != 16) { throw new ArgumentOutOfRangeException(nameof(rgbIV), "Invalid IV size."); } + } + + return new TwofishTransform(rgbKey, rgbIV, TwofishTransformMode.Encrypt, Mode, Padding); + } + + public override void GenerateIV() { + byte[] rndKey = new byte[FeedbackSizeValue / 8]; + RandomNumberGenerator generator = RandomNumberGenerator.Create(); + generator.GetBytes(rndKey); + IVValue = rndKey; + } + + public override void GenerateKey() { + byte[] rndKey = new byte[KeySizeValue / 8]; + RandomNumberGenerator generator = RandomNumberGenerator.Create(); + generator.GetBytes(rndKey); + KeyValue = rndKey; + } + + public override CipherMode Mode { + get { return base.Mode; } + set { + switch (value) { + case CipherMode.CBC: break; +#pragma warning disable CA5358 // While using ECB is not recommended, it's still supported + case CipherMode.ECB: break; +#pragma warning restore CA5358 // Review cipher mode usage with cryptography experts + default: throw new CryptographicException("Cipher mode is not supported."); + } + base.Mode = value; + } + } + + public override PaddingMode Padding { + get { return base.Padding; } + set { + base.Padding = value switch { + PaddingMode.None => value, + PaddingMode.PKCS7 => value, + PaddingMode.Zeros => value, + PaddingMode.ANSIX923 => value, + PaddingMode.ISO10126 => value, + _ => throw new CryptographicException("Padding mode is not supported."), + }; + } + } + + private const int KeySizeInBits = 256; + private const int BlockSizeInBits = 128; + } + + enum TwofishTransformMode { + Encrypt = 0, + Decrypt = 1 + } + + sealed class TwofishTransform : ICryptoTransform + { + internal TwofishTransform(byte[] rgbKey, byte[]? rgbIV, TwofishTransformMode transformMode, CipherMode cipherMode, PaddingMode paddingMode) { + if (rgbKey == null) { throw new ArgumentNullException(nameof(rgbKey), "Key cannot be null."); } + if (rgbKey.Length is not 16 and not 24 and not 32) { throw new ArgumentOutOfRangeException(nameof(rgbKey), "Key must be 128, 192, or 256 bits."); } + if ((rgbIV is not null) && (rgbIV.Length != 16)) { throw new ArgumentOutOfRangeException(nameof(rgbKey), "IV must be 128 bits."); } + CipherMode = cipherMode; + TransformMode = transformMode; + PaddingMode = paddingMode; + + DecryptionBuffer = new byte[16]; + + Key = new DWord[rgbKey.Length / 4]; + SBoxKeys = new DWord[MaxKeyBits / 64]; + SubKeys = new DWord[TotalSubkeys]; + + var key32 = new uint[Key.Length]; + Buffer.BlockCopy(rgbKey, 0, key32, 0, rgbKey.Length); + for (var i = 0; i < Key.Length; i++) { Key[i] = (DWord)key32[i]; } + Array.Clear(key32, 0, key32.Length); + + if (rgbIV != null) { + IV = new DWord[rgbIV.Length]; + var iv32 = new uint[IV.Length]; + Buffer.BlockCopy(rgbIV, 0, iv32, 0, rgbIV.Length); + for (var i = 0; i < IV.Length; i++) { IV[i] = (DWord)iv32[i]; } + Array.Clear(iv32, 0, iv32.Length); + } + + ReKey(); + } + + private readonly TwofishTransformMode TransformMode; + private readonly CipherMode CipherMode; + private readonly PaddingMode PaddingMode; + + /// + /// Gets a value indicating whether the current transform can be reused. + /// + public bool CanReuseTransform { get { return false; } } + + /// + /// Gets a value indicating whether multiple blocks can be transformed. + /// + public bool CanTransformMultipleBlocks { get { return true; } } + + /// + /// Gets the input block size (in bytes). + /// + public int InputBlockSize { get { return 16; } } //block is always 128 bits + + /// + /// Gets the output block size (in bytes). + /// + public int OutputBlockSize { get { return 16; } } //block is always 128 bits + + /// + /// Releases resources. + /// + public void Dispose() { + Dispose(true); + } + + private void Dispose(bool disposing) { + if (disposing) { + Array.Clear(Key, 0, Key.Length); + if (IV != null) { Array.Clear(IV, 0, IV.Length); } + Array.Clear(SBoxKeys, 0, SBoxKeys.Length); + Array.Clear(SubKeys, 0, SubKeys.Length); + Array.Clear(DecryptionBuffer, 0, DecryptionBuffer.Length); + } + } + + public int TransformBlock(byte[] inputBuffer, int inputOffset, int inputCount, byte[] outputBuffer, int outputOffset) { + if (inputBuffer == null) { throw new ArgumentNullException(nameof(inputBuffer), "Input buffer cannot be null."); } + if (outputBuffer == null) { throw new ArgumentNullException(nameof(outputBuffer), "Output buffer cannot be null."); } + if (inputOffset < 0) { throw new ArgumentOutOfRangeException(nameof(inputOffset), "Input offset must be non-negative number."); } + if (outputOffset < 0) { throw new ArgumentOutOfRangeException(nameof(outputOffset), "Output offset must be non-negative number."); } + if ((inputCount <= 0) || (inputCount % 16 != 0) || (inputCount > inputBuffer.Length)) { throw new ArgumentOutOfRangeException(nameof(inputCount), "Invalid input count."); } + if ((inputBuffer.Length - inputCount) < inputOffset) { throw new ArgumentOutOfRangeException(nameof(inputCount), "Invalid input length."); } + if (outputOffset + inputCount > outputBuffer.Length) { throw new ArgumentOutOfRangeException(nameof(outputOffset), "Insufficient output buffer."); } + + if (TransformMode == TwofishTransformMode.Encrypt) { + + for (var i = 0; i < inputCount; i += 16) { + BlockEncrypt(inputBuffer, inputOffset + i, outputBuffer, outputOffset + i); + } + return inputCount; + + } else { // Decrypt + + var bytesWritten = 0; + + if (DecryptionBufferInUse) { // process the last block of previous round + BlockDecrypt(DecryptionBuffer, 0, outputBuffer, outputOffset); + DecryptionBufferInUse = false; + outputOffset += 16; + bytesWritten += 16; + } + + for (var i = 0; i < inputCount - 16; i += 16) { + BlockDecrypt(inputBuffer, inputOffset + i, outputBuffer, outputOffset); + outputOffset += 16; + bytesWritten += 16; + } + + if (PaddingMode == PaddingMode.None) { + BlockDecrypt(inputBuffer, inputOffset + inputCount - 16, outputBuffer, outputOffset); + return inputCount; + } else { // save last block without processing because decryption otherwise cannot detect padding in CryptoStream + Buffer.BlockCopy(inputBuffer, inputOffset + inputCount - 16, DecryptionBuffer, 0, 16); + DecryptionBufferInUse = true; + } + + return bytesWritten; + + } + } + + public byte[] TransformFinalBlock(byte[] inputBuffer, int inputOffset, int inputCount) { + if (inputBuffer == null) { throw new ArgumentNullException(nameof(inputBuffer), "Input buffer cannot be null."); } + if (inputOffset < 0) { throw new ArgumentOutOfRangeException(nameof(inputOffset), "Input offset must be non-negative number."); } + if ((inputCount < 0) || (inputCount > inputBuffer.Length)) { throw new ArgumentOutOfRangeException(nameof(inputCount), "Invalid input count."); } + if ((PaddingMode == PaddingMode.None) && (inputCount % 16 != 0)) { throw new ArgumentOutOfRangeException(nameof(inputCount), "No padding for final block."); } + if ((inputBuffer.Length - inputCount) < inputOffset) { throw new ArgumentOutOfRangeException(nameof(inputCount), "Invalid input length."); } + + if (TransformMode == TwofishTransformMode.Encrypt) { + + int paddedLength; + byte[] paddedInputBuffer; + int paddedInputOffset; + switch (PaddingMode) { + case PaddingMode.None: + paddedLength = inputCount; + paddedInputBuffer = inputBuffer; + paddedInputOffset = inputOffset; + break; + + case PaddingMode.PKCS7: + paddedLength = inputCount / 16 * 16 + 16; //to round to next whole block + paddedInputBuffer = new byte[paddedLength]; + paddedInputOffset = 0; + Buffer.BlockCopy(inputBuffer, inputOffset, paddedInputBuffer, 0, inputCount); + var added = (byte)(paddedLength - inputCount); + for (var i = inputCount; i < inputCount + added; i++) { + paddedInputBuffer[i] = added; + } + break; + + case PaddingMode.Zeros: + paddedLength = (inputCount + 15) / 16 * 16; //to round to next whole block + paddedInputBuffer = new byte[paddedLength]; + paddedInputOffset = 0; + Buffer.BlockCopy(inputBuffer, inputOffset, paddedInputBuffer, 0, inputCount); + break; + + case PaddingMode.ANSIX923: + paddedLength = inputCount / 16 * 16 + 16; //to round to next whole block + paddedInputBuffer = new byte[paddedLength]; + paddedInputOffset = 0; + Buffer.BlockCopy(inputBuffer, inputOffset, paddedInputBuffer, 0, inputCount); + paddedInputBuffer[^1] = (byte)(paddedLength - inputCount); + break; + + case PaddingMode.ISO10126: + paddedLength = inputCount / 16 * 16 + 16; //to round to next whole block + paddedInputBuffer = new byte[paddedLength]; + RandomNumberGenerator.Fill(paddedInputBuffer.AsSpan(inputCount)); + paddedInputOffset = 0; + Buffer.BlockCopy(inputBuffer, inputOffset, paddedInputBuffer, 0, inputCount); + paddedInputBuffer[^1] = (byte)(paddedLength - inputCount); + break; + + default: throw new CryptographicException("Unsupported padding mode."); + } + + var outputBuffer = new byte[paddedLength]; + + for (var i = 0; i < paddedLength; i += 16) { + BlockEncrypt(paddedInputBuffer, paddedInputOffset + i, outputBuffer, i); + } + + return outputBuffer; + + } else { // Decrypt + + byte[] outputBuffer; + + if (PaddingMode == PaddingMode.None) { + outputBuffer = new byte[inputCount]; + } else if (inputCount % 16 != 0) { + throw new ArgumentOutOfRangeException(nameof(inputCount), "Invalid input count."); + } else { + outputBuffer = new byte[inputCount + (DecryptionBufferInUse ? 16 : 0)]; + } + + var outputOffset = 0; + + if (DecryptionBufferInUse) { // process leftover padding buffer to keep CryptoStream happy + BlockDecrypt(DecryptionBuffer, 0, outputBuffer, 0); + DecryptionBufferInUse = false; + outputOffset = 16; + } + + for (var i = 0; i < inputCount; i += 16) { + BlockDecrypt(inputBuffer, inputOffset + i, outputBuffer, outputOffset + i); + } + + return RemovePadding(outputBuffer, PaddingMode); + + } + } + + private readonly byte[] DecryptionBuffer; + private bool DecryptionBufferInUse; + + private static byte[] RemovePadding(byte[] outputBuffer, PaddingMode paddingMode) { + if (paddingMode == PaddingMode.PKCS7) { + var padding = outputBuffer[^1]; + if (padding is < 1 or > 16) { throw new CryptographicException("Invalid padding."); } + for (var i = outputBuffer.Length - padding; i < outputBuffer.Length; i++) { + if (outputBuffer[i] != padding) { throw new CryptographicException("Invalid padding."); } + } + var newOutputBuffer = new byte[outputBuffer.Length - padding]; + Buffer.BlockCopy(outputBuffer, 0, newOutputBuffer, 0, newOutputBuffer.Length); + return newOutputBuffer; + } else if (paddingMode == PaddingMode.Zeros) { + var newOutputLength = outputBuffer.Length; + for (var i = outputBuffer.Length - 1; i >= Math.Max(outputBuffer.Length - 16, 0); i--) { + if (outputBuffer[i] != 0) { + newOutputLength = i + 1; + break; + } + } + if (newOutputLength == outputBuffer.Length) { + return outputBuffer; + } else { + var newOutputBuffer = new byte[newOutputLength]; + Buffer.BlockCopy(outputBuffer, 0, newOutputBuffer, 0, newOutputBuffer.Length); + return newOutputBuffer; + } + } else if (paddingMode == PaddingMode.ANSIX923) { + var padding = outputBuffer[^1]; + if (padding is < 1 or > 16) { throw new CryptographicException("Invalid padding."); } + for (var i = outputBuffer.Length - padding; i < outputBuffer.Length - 1; i++) { + if (outputBuffer[i] != 0) { throw new CryptographicException("Invalid padding."); } + } + var newOutputBuffer = new byte[outputBuffer.Length - padding]; + Buffer.BlockCopy(outputBuffer, 0, newOutputBuffer, 0, newOutputBuffer.Length); + return newOutputBuffer; + } else if (paddingMode == PaddingMode.ISO10126) { + var padding = outputBuffer[^1]; + if (padding is < 1 or > 16) { throw new CryptographicException("Invalid padding."); } + var newOutputBuffer = new byte[outputBuffer.Length - padding]; + Buffer.BlockCopy(outputBuffer, 0, newOutputBuffer, 0, newOutputBuffer.Length); + return newOutputBuffer; + } else { // None + return outputBuffer; + } + } + + private const int BlockSize = 128; //number of bits per block + private const int Rounds = 16; //default number of rounds for 128/192/256-bit keys + private const int MaxKeyBits = 256; //max number of bits of key + + private const int InputWhiten = 0; + private const int OutputWhiten = (InputWhiten + BlockSize / 32); + private const int RoundSubkeys = (OutputWhiten + BlockSize / 32); + private const int TotalSubkeys = (RoundSubkeys + 2 * Rounds); + + private readonly DWord[] Key; + private readonly DWord[]? IV; + private readonly DWord[] SBoxKeys; + private readonly DWord[] SubKeys; + + private const int SubkeyStep = 0x02020202; + private const int SubkeyBump = 0x01010101; + private const int SubkeyRotateLeft = 9; + + private void ReKey() { + BuildMds(); //built only first time it is accessed + + var k32e = new DWord[Key.Length / 2]; + var k32o = new DWord[Key.Length / 2]; //even/odd key dwords + + var k64Cnt = Key.Length / 2; + for (var i = 0; i < k64Cnt; i++) { //split into even/odd key dwords + k32e[i] = Key[2 * i]; + k32o[i] = Key[2 * i + 1]; + SBoxKeys[k64Cnt - 1 - i] = ReedSolomonMdsEncode(k32e[i], k32o[i]); //compute S-box keys using (12,8) Reed-Solomon code over GF(256) + } + + var subkeyCnt = RoundSubkeys + 2 * Rounds; + var keyLen = Key.Length * 4 * 8; + for (var i = 0; i < subkeyCnt / 2; i++) { //compute round subkeys for PHT + var A = F32((DWord)(i * SubkeyStep), k32e, keyLen); //A uses even key dwords + var B = F32((DWord)(i * SubkeyStep + SubkeyBump), k32o, keyLen); //B uses odd key dwords + B = B.RotateLeft(8); + SubKeys[2 * i] = A + B; //combine with a PHT + SubKeys[2 * i + 1] = (A + 2 * B).RotateLeft(SubkeyRotateLeft); + } + } + + internal void BlockEncrypt(byte[] inputBuffer, int inputOffset, byte[] outputBuffer, int outputBufferOffset) { + var x = new DWord[BlockSize / 32]; + for (var i = 0; i < BlockSize / 32; i++) { //copy in the block, add whitening + x[i] = new DWord(inputBuffer, inputOffset + i * 4) ^ SubKeys[InputWhiten + i]; + if ((CipherMode == CipherMode.CBC) && (IV != null)) { x[i] ^= IV[i]; } + } + + var keyLen = Key.Length * 4 * 8; + for (var r = 0; r < Rounds; r++) { //main Twofish encryption loop + var t0 = F32(x[0], SBoxKeys, keyLen); + var t1 = F32(x[1].RotateLeft(8), SBoxKeys, keyLen); + + x[3] = x[3].RotateLeft(1); + x[2] ^= t0 + t1 + SubKeys[RoundSubkeys + 2 * r]; //PHT, round keys + x[3] ^= t0 + 2 * t1 + SubKeys[RoundSubkeys + 2 * r + 1]; + x[2] = x[2].RotateRight(1); + + if (r < Rounds - 1) { //swap for next round + (x[2], x[0]) = (x[0], x[2]); + (x[3], x[1]) = (x[1], x[3]); + } + } + + for (var i = 0; i < BlockSize / 32; i++) { //copy out, with whitening + var outValue = x[i] ^ SubKeys[OutputWhiten + i]; + outputBuffer[outputBufferOffset + i * 4 + 0] = outValue.B0; + outputBuffer[outputBufferOffset + i * 4 + 1] = outValue.B1; + outputBuffer[outputBufferOffset + i * 4 + 2] = outValue.B2; + outputBuffer[outputBufferOffset + i * 4 + 3] = outValue.B3; + if ((CipherMode == CipherMode.CBC) && (IV != null)) { IV[i] = outValue; } + } + } + + internal void BlockDecrypt(byte[] inputBuffer, int inputOffset, byte[] outputBuffer, int outputBufferOffset) { + var x = new DWord[BlockSize / 32]; + var input = new DWord[BlockSize / 32]; + for (var i = 0; i < BlockSize / 32; i++) { //copy in the block, add whitening + input[i] = new DWord(inputBuffer, inputOffset + i * 4); + x[i] = input[i] ^ SubKeys[OutputWhiten + i]; + } + + var keyLen = Key.Length * 4 * 8; + for (var r = Rounds - 1; r >= 0; r--) { //main Twofish decryption loop + var t0 = F32(x[0], SBoxKeys, keyLen); + var t1 = F32(x[1].RotateLeft(8), SBoxKeys, keyLen); + + x[2] = x[2].RotateLeft(1); + x[2] ^= t0 + t1 + SubKeys[RoundSubkeys + 2 * r]; //PHT, round keys + x[3] ^= t0 + 2 * t1 + SubKeys[RoundSubkeys + 2 * r + 1]; + x[3] = x[3].RotateRight(1); + + if (r > 0) { //unswap, except for last round + t0 = x[0]; x[0] = x[2]; x[2] = t0; + t1 = x[1]; x[1] = x[3]; x[3] = t1; + } + } + + for (var i = 0; i < BlockSize / 32; i++) { //copy out, with whitening + x[i] ^= SubKeys[InputWhiten + i]; + if ((CipherMode == CipherMode.CBC) && (IV != null)) { + x[i] ^= IV[i]; + IV[i] = input[i]; + } + outputBuffer[outputBufferOffset + i * 4 + 0] = x[i].B0; + outputBuffer[outputBufferOffset + i * 4 + 1] = x[i].B1; + outputBuffer[outputBufferOffset + i * 4 + 2] = x[i].B2; + outputBuffer[outputBufferOffset + i * 4 + 3] = x[i].B3; + } + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private static DWord F32(DWord x, DWord[] k32, int keyLen) { + if (keyLen >= 256) { + x.B0 = (byte)(P8x8[P_04][x.B0] ^ k32[3].B0); + x.B1 = (byte)(P8x8[P_14][x.B1] ^ k32[3].B1); + x.B2 = (byte)(P8x8[P_24][x.B2] ^ k32[3].B2); + x.B3 = (byte)(P8x8[P_34][x.B3] ^ k32[3].B3); + } + if (keyLen >= 192) { + x.B0 = (byte)(P8x8[P_03][x.B0] ^ k32[2].B0); + x.B1 = (byte)(P8x8[P_13][x.B1] ^ k32[2].B1); + x.B2 = (byte)(P8x8[P_23][x.B2] ^ k32[2].B2); + x.B3 = (byte)(P8x8[P_33][x.B3] ^ k32[2].B3); + } + if (keyLen >= 128) { + x = MdsTable[0][P8x8[P_01][P8x8[P_02][x.B0] ^ k32[1].B0] ^ k32[0].B0] + ^ MdsTable[1][P8x8[P_11][P8x8[P_12][x.B1] ^ k32[1].B1] ^ k32[0].B1] + ^ MdsTable[2][P8x8[P_21][P8x8[P_22][x.B2] ^ k32[1].B2] ^ k32[0].B2] + ^ MdsTable[3][P8x8[P_31][P8x8[P_32][x.B3] ^ k32[1].B3] ^ k32[0].B3]; + } + + return x; + } + + private const uint P_01 = 0; + private const uint P_02 = 0; + private const uint P_03 = (P_01 ^ 1); // "extend" to larger key sizes + private const uint P_04 = 1; + + private const uint P_11 = 0; + private const uint P_12 = 1; + private const uint P_13 = (P_11 ^ 1); + private const uint P_14 = 0; + + private const uint P_21 = 1; + private const uint P_22 = 0; + private const uint P_23 = (P_21 ^ 1); + private const uint P_24 = 0; + + private const uint P_31 = 1; + private const uint P_32 = 1; + private const uint P_33 = (P_31 ^ 1); + private const uint P_34 = 1; + + private static readonly byte[][] P8x8 = new byte[][] { + new byte[] { + 0xA9, 0x67, 0xB3, 0xE8, 0x04, 0xFD, 0xA3, 0x76, + 0x9A, 0x92, 0x80, 0x78, 0xE4, 0xDD, 0xD1, 0x38, + 0x0D, 0xC6, 0x35, 0x98, 0x18, 0xF7, 0xEC, 0x6C, + 0x43, 0x75, 0x37, 0x26, 0xFA, 0x13, 0x94, 0x48, + 0xF2, 0xD0, 0x8B, 0x30, 0x84, 0x54, 0xDF, 0x23, + 0x19, 0x5B, 0x3D, 0x59, 0xF3, 0xAE, 0xA2, 0x82, + 0x63, 0x01, 0x83, 0x2E, 0xD9, 0x51, 0x9B, 0x7C, + 0xA6, 0xEB, 0xA5, 0xBE, 0x16, 0x0C, 0xE3, 0x61, + 0xC0, 0x8C, 0x3A, 0xF5, 0x73, 0x2C, 0x25, 0x0B, + 0xBB, 0x4E, 0x89, 0x6B, 0x53, 0x6A, 0xB4, 0xF1, + 0xE1, 0xE6, 0xBD, 0x45, 0xE2, 0xF4, 0xB6, 0x66, + 0xCC, 0x95, 0x03, 0x56, 0xD4, 0x1C, 0x1E, 0xD7, + 0xFB, 0xC3, 0x8E, 0xB5, 0xE9, 0xCF, 0xBF, 0xBA, + 0xEA, 0x77, 0x39, 0xAF, 0x33, 0xC9, 0x62, 0x71, + 0x81, 0x79, 0x09, 0xAD, 0x24, 0xCD, 0xF9, 0xD8, + 0xE5, 0xC5, 0xB9, 0x4D, 0x44, 0x08, 0x86, 0xE7, + 0xA1, 0x1D, 0xAA, 0xED, 0x06, 0x70, 0xB2, 0xD2, + 0x41, 0x7B, 0xA0, 0x11, 0x31, 0xC2, 0x27, 0x90, + 0x20, 0xF6, 0x60, 0xFF, 0x96, 0x5C, 0xB1, 0xAB, + 0x9E, 0x9C, 0x52, 0x1B, 0x5F, 0x93, 0x0A, 0xEF, + 0x91, 0x85, 0x49, 0xEE, 0x2D, 0x4F, 0x8F, 0x3B, + 0x47, 0x87, 0x6D, 0x46, 0xD6, 0x3E, 0x69, 0x64, + 0x2A, 0xCE, 0xCB, 0x2F, 0xFC, 0x97, 0x05, 0x7A, + 0xAC, 0x7F, 0xD5, 0x1A, 0x4B, 0x0E, 0xA7, 0x5A, + 0x28, 0x14, 0x3F, 0x29, 0x88, 0x3C, 0x4C, 0x02, + 0xB8, 0xDA, 0xB0, 0x17, 0x55, 0x1F, 0x8A, 0x7D, + 0x57, 0xC7, 0x8D, 0x74, 0xB7, 0xC4, 0x9F, 0x72, + 0x7E, 0x15, 0x22, 0x12, 0x58, 0x07, 0x99, 0x34, + 0x6E, 0x50, 0xDE, 0x68, 0x65, 0xBC, 0xDB, 0xF8, + 0xC8, 0xA8, 0x2B, 0x40, 0xDC, 0xFE, 0x32, 0xA4, + 0xCA, 0x10, 0x21, 0xF0, 0xD3, 0x5D, 0x0F, 0x00, + 0x6F, 0x9D, 0x36, 0x42, 0x4A, 0x5E, 0xC1, 0xE0 + }, + new byte[] { + 0x75, 0xF3, 0xC6, 0xF4, 0xDB, 0x7B, 0xFB, 0xC8, + 0x4A, 0xD3, 0xE6, 0x6B, 0x45, 0x7D, 0xE8, 0x4B, + 0xD6, 0x32, 0xD8, 0xFD, 0x37, 0x71, 0xF1, 0xE1, + 0x30, 0x0F, 0xF8, 0x1B, 0x87, 0xFA, 0x06, 0x3F, + 0x5E, 0xBA, 0xAE, 0x5B, 0x8A, 0x00, 0xBC, 0x9D, + 0x6D, 0xC1, 0xB1, 0x0E, 0x80, 0x5D, 0xD2, 0xD5, + 0xA0, 0x84, 0x07, 0x14, 0xB5, 0x90, 0x2C, 0xA3, + 0xB2, 0x73, 0x4C, 0x54, 0x92, 0x74, 0x36, 0x51, + 0x38, 0xB0, 0xBD, 0x5A, 0xFC, 0x60, 0x62, 0x96, + 0x6C, 0x42, 0xF7, 0x10, 0x7C, 0x28, 0x27, 0x8C, + 0x13, 0x95, 0x9C, 0xC7, 0x24, 0x46, 0x3B, 0x70, + 0xCA, 0xE3, 0x85, 0xCB, 0x11, 0xD0, 0x93, 0xB8, + 0xA6, 0x83, 0x20, 0xFF, 0x9F, 0x77, 0xC3, 0xCC, + 0x03, 0x6F, 0x08, 0xBF, 0x40, 0xE7, 0x2B, 0xE2, + 0x79, 0x0C, 0xAA, 0x82, 0x41, 0x3A, 0xEA, 0xB9, + 0xE4, 0x9A, 0xA4, 0x97, 0x7E, 0xDA, 0x7A, 0x17, + 0x66, 0x94, 0xA1, 0x1D, 0x3D, 0xF0, 0xDE, 0xB3, + 0x0B, 0x72, 0xA7, 0x1C, 0xEF, 0xD1, 0x53, 0x3E, + 0x8F, 0x33, 0x26, 0x5F, 0xEC, 0x76, 0x2A, 0x49, + 0x81, 0x88, 0xEE, 0x21, 0xC4, 0x1A, 0xEB, 0xD9, + 0xC5, 0x39, 0x99, 0xCD, 0xAD, 0x31, 0x8B, 0x01, + 0x18, 0x23, 0xDD, 0x1F, 0x4E, 0x2D, 0xF9, 0x48, + 0x4F, 0xF2, 0x65, 0x8E, 0x78, 0x5C, 0x58, 0x19, + 0x8D, 0xE5, 0x98, 0x57, 0x67, 0x7F, 0x05, 0x64, + 0xAF, 0x63, 0xB6, 0xFE, 0xF5, 0xB7, 0x3C, 0xA5, + 0xCE, 0xE9, 0x68, 0x44, 0xE0, 0x4D, 0x43, 0x69, + 0x29, 0x2E, 0xAC, 0x15, 0x59, 0xA8, 0x0A, 0x9E, + 0x6E, 0x47, 0xDF, 0x34, 0x35, 0x6A, 0xCF, 0xDC, + 0x22, 0xC9, 0xC0, 0x9B, 0x89, 0xD4, 0xED, 0xAB, + 0x12, 0xA2, 0x0D, 0x52, 0xBB, 0x02, 0x2F, 0xA9, + 0xD7, 0x61, 0x1E, 0xB4, 0x50, 0x04, 0xF6, 0xC2, + 0x16, 0x25, 0x86, 0x56, 0x55, 0x09, 0xBE, 0x91 + } + }; + + private static readonly DWord[][] MdsTable = new DWord[4][] { new DWord[256], new DWord[256], new DWord[256], new DWord[256] }; + private static bool MdsTableBuilt; + private static readonly object SyncRootBuildMds = new(); + + private static void BuildMds() { + lock (SyncRootBuildMds) { + if (MdsTableBuilt) { return; } + + var m1 = new byte[2]; + var mX = new byte[2]; + var mY = new byte[4]; + + for (var i = 0; i < 256; i++) { + m1[0] = P8x8[0][i]; /* compute all the matrix elements */ + mX[0] = (byte)Mul_X(m1[0]); + mY[0] = (byte)Mul_Y(m1[0]); + + m1[1] = P8x8[1][i]; + mX[1] = (byte)Mul_X(m1[1]); + mY[1] = (byte)Mul_Y(m1[1]); + + MdsTable[0][i].B0 = m1[1]; + MdsTable[0][i].B1 = mX[1]; + MdsTable[0][i].B2 = mY[1]; + MdsTable[0][i].B3 = mY[1]; //SetMDS(0); + + MdsTable[1][i].B0 = mY[0]; + MdsTable[1][i].B1 = mY[0]; + MdsTable[1][i].B2 = mX[0]; + MdsTable[1][i].B3 = m1[0]; //SetMDS(1); + + MdsTable[2][i].B0 = mX[1]; + MdsTable[2][i].B1 = mY[1]; + MdsTable[2][i].B2 = m1[1]; + MdsTable[2][i].B3 = mY[1]; //SetMDS(2); + + MdsTable[3][i].B0 = mX[0]; + MdsTable[3][i].B1 = m1[0]; + MdsTable[3][i].B2 = mY[0]; + MdsTable[3][i].B3 = mX[0]; //SetMDS(3); + } + + MdsTableBuilt = true; + } + } + + private const uint RS_GF_FDBK = 0x14D; + + private static DWord ReedSolomonMdsEncode(DWord k0, DWord k1) { + var r = new DWord(); + for (var i = 0; i < 2; i++) { + r ^= (i > 0) ? k0 : k1; //merge in 32 more key bits + for (var j = 0; j < 4; j++) { //shift one byte at a time + var b = (byte)(r >> 24); + var g2 = (byte)((b << 1) ^ (((b & 0x80) > 0) ? RS_GF_FDBK : 0)); + var g3 = (byte)(((b >> 1) & 0x7F) ^ (((b & 1) > 0) ? RS_GF_FDBK >> 1 : 0) ^ g2); + r.B3 = (byte)(r.B2 ^ g3); + r.B2 = (byte)(r.B1 ^ g2); + r.B1 = (byte)(r.B0 ^ g3); + r.B0 = b; + } + } + return r; + } + + + private static uint Mul_X(uint x) { + return Mx_X(x); + } + private static uint Mul_Y(uint x) { + return Mx_Y(x); + } + + private static uint Mx_X(uint x) { + return (x ^ LFSR2(x)); //5B + } + + private static uint Mx_Y(uint x) { + return (x ^ LFSR1(x) ^ LFSR2(x)); //EF + } + + + private const uint MDS_GF_FDBK = 0x169; //primitive polynomial for GF(256) + + private static uint LFSR1(uint x) { + return ((x >> 1) ^ (((x & 0x01) > 0) ? MDS_GF_FDBK / 2 : 0)); + } + + static private uint LFSR2(uint x) { + return ((x >> 2) ^ (((x & 0x02) > 0) ? MDS_GF_FDBK / 2 : 0) + ^ (((x & 0x01) > 0) ? MDS_GF_FDBK / 4 : 0)); + } + + private struct DWord + { + public byte B0; + public byte B1; + public byte B2; + public byte B3; + + private uint Value; + + private DWord(uint value) : this() { + Value = value; + } + + internal DWord(byte[] buffer, int offset) : this() { + B0 = buffer[offset + 0]; + B1 = buffer[offset + 1]; + B2 = buffer[offset + 2]; + B3 = buffer[offset + 3]; + } + + public static explicit operator uint(DWord expr) { + return expr.Value; + } + + public static explicit operator DWord(int value) { + return new DWord((uint)value); + } + + public static explicit operator DWord(uint value) { + return new DWord(value); + } + + + public static DWord operator +(DWord expr1, DWord expr2) { + expr1.Value += expr2.Value; + return expr1; + } + + public static DWord operator *(uint value, DWord expr) { + expr.Value = value * expr.Value; + return expr; + } + + + public static DWord operator |(DWord expr1, DWord expr2) { + expr1.Value |= expr2.Value; + return expr1; + } + + public static DWord operator ^(DWord expr1, DWord expr2) { + expr1.Value ^= expr2.Value; + return expr1; + } + + public static DWord operator <<(DWord expr, int count) { + expr.Value <<= count; + return expr; + } + + public static DWord operator >>(DWord expr, int count) { + expr.Value >>= count; + return expr; + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public DWord RotateLeft(int n) { + return (DWord)((Value << n) | (Value >> (32 - n))); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public DWord RotateRight(int n) { + return (DWord)((Value >> n) | (Value << (32 - n))); + } + } + } +} \ No newline at end of file diff --git a/DevsDaddy/Shared/CryptoLibrary/Modules/Twofish/Twofish.cs.meta b/DevsDaddy/Shared/CryptoLibrary/Modules/Twofish/Twofish.cs.meta new file mode 100644 index 0000000..f2e59af --- /dev/null +++ b/DevsDaddy/Shared/CryptoLibrary/Modules/Twofish/Twofish.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 829fc27d22454e41833c7820d169d278 +timeCreated: 1709901703 \ No newline at end of file diff --git a/DevsDaddy/Shared/CryptoLibrary/Modules/Twofish/TwofishEncryptionOptions.cs b/DevsDaddy/Shared/CryptoLibrary/Modules/Twofish/TwofishEncryptionOptions.cs new file mode 100644 index 0000000..2eba8e0 --- /dev/null +++ b/DevsDaddy/Shared/CryptoLibrary/Modules/Twofish/TwofishEncryptionOptions.cs @@ -0,0 +1,18 @@ +using System.Security.Cryptography; +using System.Text; +using DevsDaddy.Shared.CryptoLibrary.Core; + +namespace DevsDaddy.Shared.CryptoLibrary.Modules.Twofish +{ + [System.Serializable] + public class TwofishEncryptionOptions : IProviderOptions + { + public Encoding encoding = Encoding.UTF8; + public int keySize = 256; + public CipherMode mode = CipherMode.CBC; + public PaddingMode padding = PaddingMode.PKCS7; + + public byte[] IV; + public byte[] cryptoKey; + } +} \ No newline at end of file diff --git a/DevsDaddy/Shared/CryptoLibrary/Modules/Twofish/TwofishEncryptionOptions.cs.meta b/DevsDaddy/Shared/CryptoLibrary/Modules/Twofish/TwofishEncryptionOptions.cs.meta new file mode 100644 index 0000000..294b785 --- /dev/null +++ b/DevsDaddy/Shared/CryptoLibrary/Modules/Twofish/TwofishEncryptionOptions.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 9b2b25c8068142dab8bd78dec03a4d3e +timeCreated: 1709901440 \ No newline at end of file diff --git a/DevsDaddy/Shared/CryptoLibrary/Modules/Twofish/TwofishProvider.cs b/DevsDaddy/Shared/CryptoLibrary/Modules/Twofish/TwofishProvider.cs new file mode 100644 index 0000000..5662fe8 --- /dev/null +++ b/DevsDaddy/Shared/CryptoLibrary/Modules/Twofish/TwofishProvider.cs @@ -0,0 +1,94 @@ +using System; +using System.IO; +using System.Security.Cryptography; +using DevsDaddy.Shared.CryptoLibrary.Core; + +namespace DevsDaddy.Shared.CryptoLibrary.Modules.Twofish +{ + /// + /// Twofish Crypto Provider + /// + public class TwofishProvider : ICryptoProvider + { + // Provider Options and Worker + private TwofishEncryptionOptions _options; + private Twofish _worker; + + /// + /// Twofish Provider + /// + /// + public TwofishProvider(TwofishEncryptionOptions options) { + _options = options ?? new TwofishEncryptionOptions(); + _worker = new Twofish() { + KeySize = _options.keySize, + Mode = _options.mode, + Padding = _options.padding + }; + + if (_options.IV == null) + _worker.GenerateIV(); + else + _worker.IV = _options.IV; + + if (_options.cryptoKey == null) + _worker.GenerateKey(); + else + _worker.Key = _options.cryptoKey; + } + + /// + /// Decrypt text encrypted by Twofish Provider + /// + /// + /// + public string DecryptString(string encryptedString) { + byte[] decrypted = DecryptBinary(Convert.FromBase64String(encryptedString)); + return _options.encoding.GetString(decrypted); + } + + /// + /// Decrypt binary data using Twofish Provider to byte array + /// + /// + /// + public byte[] DecryptBinary(byte[] encryptedBinary) { + var inputData = new MemoryStream(encryptedBinary); + var outputData = new MemoryStream(); + using var decryptor = _worker.CreateDecryptor(); + using (var csRead = new CryptoStream(inputData, decryptor, CryptoStreamMode.Read)) { + csRead.CopyTo(outputData); + } + + var bytes = outputData.ToArray(); + return bytes; + } + + /// + /// Encrypt Plain-Text using Twofish Provider + /// + /// + /// + public string EncryptString(string decryptedString) { + byte[] encrypted = EncryptBinary(_options.encoding.GetBytes(decryptedString)); + return Convert.ToBase64String(encrypted); + } + + /// + /// Encrypt byte array using Twofish Provider + /// + /// + /// + public byte[] EncryptBinary(byte[] decryptedBinary) { + var dataStream = new MemoryStream(decryptedBinary); + using var encryptor = _worker.CreateEncryptor(); + var outDataStream = new MemoryStream(); + using (var csWrite = new CryptoStream(outDataStream, encryptor, CryptoStreamMode.Write)) { + dataStream.CopyTo(csWrite); + } + + var bytes = outDataStream.ToArray(); + return bytes; + } + } +} \ No newline at end of file diff --git a/DevsDaddy/Shared/CryptoLibrary/Modules/Twofish/TwofishProvider.cs.meta b/DevsDaddy/Shared/CryptoLibrary/Modules/Twofish/TwofishProvider.cs.meta new file mode 100644 index 0000000..d3b4efa --- /dev/null +++ b/DevsDaddy/Shared/CryptoLibrary/Modules/Twofish/TwofishProvider.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: ec782e50b2934c9db2613df7db503844 +timeCreated: 1709901431 \ No newline at end of file diff --git a/DevsDaddy/Shared/CryptoLibrary/Modules/XOR.meta b/DevsDaddy/Shared/CryptoLibrary/Modules/XOR.meta new file mode 100644 index 0000000..81fe266 --- /dev/null +++ b/DevsDaddy/Shared/CryptoLibrary/Modules/XOR.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 1c083b5bf28e4653bde6d14e07c7463a +timeCreated: 1709889653 \ No newline at end of file diff --git a/DevsDaddy/Shared/CryptoLibrary/Modules/XOR/XOREncryptionOptions.cs b/DevsDaddy/Shared/CryptoLibrary/Modules/XOR/XOREncryptionOptions.cs new file mode 100644 index 0000000..2f68e91 --- /dev/null +++ b/DevsDaddy/Shared/CryptoLibrary/Modules/XOR/XOREncryptionOptions.cs @@ -0,0 +1,12 @@ +using System.Text; +using DevsDaddy.Shared.CryptoLibrary.Core; + +namespace DevsDaddy.Shared.CryptoLibrary.Modules.XOR +{ + [System.Serializable] + public class XOREncryptionOptions : IProviderOptions + { + public string cryptoKey = "123456"; + public Encoding encoding = Encoding.UTF8; + } +} \ No newline at end of file diff --git a/DevsDaddy/Shared/CryptoLibrary/Modules/XOR/XOREncryptionOptions.cs.meta b/DevsDaddy/Shared/CryptoLibrary/Modules/XOR/XOREncryptionOptions.cs.meta new file mode 100644 index 0000000..ff767bf --- /dev/null +++ b/DevsDaddy/Shared/CryptoLibrary/Modules/XOR/XOREncryptionOptions.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: d3cbc6cea79441a9a6b055fdceeff21d +timeCreated: 1709895502 \ No newline at end of file diff --git a/DevsDaddy/Shared/CryptoLibrary/Modules/XOR/XORProvider.cs b/DevsDaddy/Shared/CryptoLibrary/Modules/XOR/XORProvider.cs new file mode 100644 index 0000000..7b35ef6 --- /dev/null +++ b/DevsDaddy/Shared/CryptoLibrary/Modules/XOR/XORProvider.cs @@ -0,0 +1,86 @@ +using System; +using System.Text; +using DevsDaddy.Shared.CryptoLibrary.Core; + +namespace DevsDaddy.Shared.CryptoLibrary.Modules.XOR +{ + /// + /// XOR Crypto Provider + /// Works only with strings + /// + public class XORProvider : ICryptoProvider + { + // Provider Options + private XOREncryptionOptions _options; + + /// + /// XOR-Provicer + /// + /// + public XORProvider(XOREncryptionOptions options = null) { + _options = options ?? new XOREncryptionOptions(); + } + + /// + /// Decrypt String (Warning! For XOR Encrypt/Decrypt methods are similar, because it is XOR) + /// + /// + /// + public string DecryptString(string encryptedString) { + return EncryptOrDecrypt(encryptedString, _options.cryptoKey); + } + + /// + /// Decrypt Binary (Not Supported for XOR) + /// + /// + /// + /// + public byte[] DecryptBinary(byte[] encryptedBinary) { + throw new Exception($"Failed to decrypt byte array, because {this.GetType()} support only plain text."); + } + + /// + /// Encrypt String (Warning! For XOR Encrypt/Decrypt methods are similar, because it is XOR) + /// + /// + /// + public string EncryptString(string decryptedString) { + return EncryptOrDecrypt(decryptedString, _options.cryptoKey); + } + + /// + /// Encrypt Binary (Not Supported for XOR) + /// + /// + /// + /// + public byte[] EncryptBinary(byte[] decryptedBinary) { + throw new Exception($"Failed to decrypt byte array, because {this.GetType()} support only plain text."); + } + + + /// + /// Encrypt / Decrypt via XOR-mechanism + /// + /// + /// + /// + private string EncryptOrDecrypt(string text, string key) + { + var result = new StringBuilder(); + for (int c = 0; c < text.Length; c++) + { + char character = text[c]; + uint charCode = (uint)character; + int keyPosition = c % key.Length; + char keyChar = key[keyPosition]; + uint keyCode = (uint)keyChar; + uint combinedCode = charCode ^ keyCode; + char combinedChar = (char)combinedCode; + result.Append(combinedChar); + } + return result.ToString(); + } + } +} \ No newline at end of file diff --git a/DevsDaddy/Shared/CryptoLibrary/Modules/XOR/XORProvider.cs.meta b/DevsDaddy/Shared/CryptoLibrary/Modules/XOR/XORProvider.cs.meta new file mode 100644 index 0000000..33a7f59 --- /dev/null +++ b/DevsDaddy/Shared/CryptoLibrary/Modules/XOR/XORProvider.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 0fb964da15ef495dbb5b96bd88f8c84d +timeCreated: 1709895421 \ No newline at end of file diff --git a/DevsDaddy/Shared/CryptoLibrary/Modules/xxHash.meta b/DevsDaddy/Shared/CryptoLibrary/Modules/xxHash.meta new file mode 100644 index 0000000..0672d94 --- /dev/null +++ b/DevsDaddy/Shared/CryptoLibrary/Modules/xxHash.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 618e4675bfe348f8ba8a86b4f9ba16fc +timeCreated: 1709889657 \ No newline at end of file diff --git a/DevsDaddy/Shared/CryptoLibrary/Modules/xxHash/xxHashEncryptionOptions.cs b/DevsDaddy/Shared/CryptoLibrary/Modules/xxHash/xxHashEncryptionOptions.cs new file mode 100644 index 0000000..e7e95cf --- /dev/null +++ b/DevsDaddy/Shared/CryptoLibrary/Modules/xxHash/xxHashEncryptionOptions.cs @@ -0,0 +1,20 @@ +using System.Text; +using DevsDaddy.Shared.CryptoLibrary.Core; + +namespace DevsDaddy.Shared.CryptoLibrary.Modules.xxHash +{ + [System.Serializable] + public class xxHashEncryptionOptions : IProviderOptions + { + public uint PRIME32_1 = 2654435761U; + public uint PRIME32_2 = 2246822519U; + public uint PRIME32_3 = 3266489917U; + public uint PRIME32_4 = 668265263U; + public uint PRIME32_5 = 374761393U; + + public int length = 16; + public uint seed = 0; + + public Encoding encoding = Encoding.UTF8; + } +} \ No newline at end of file diff --git a/DevsDaddy/Shared/CryptoLibrary/Modules/xxHash/xxHashEncryptionOptions.cs.meta b/DevsDaddy/Shared/CryptoLibrary/Modules/xxHash/xxHashEncryptionOptions.cs.meta new file mode 100644 index 0000000..405cba3 --- /dev/null +++ b/DevsDaddy/Shared/CryptoLibrary/Modules/xxHash/xxHashEncryptionOptions.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 70b4efc0212345a2b0c82cd1fbfcc225 +timeCreated: 1709895026 \ No newline at end of file diff --git a/DevsDaddy/Shared/CryptoLibrary/Modules/xxHash/xxHashProvider.cs b/DevsDaddy/Shared/CryptoLibrary/Modules/xxHash/xxHashProvider.cs new file mode 100644 index 0000000..b2236fd --- /dev/null +++ b/DevsDaddy/Shared/CryptoLibrary/Modules/xxHash/xxHashProvider.cs @@ -0,0 +1,124 @@ +using System; +using DevsDaddy.Shared.CryptoLibrary.Core; + +namespace DevsDaddy.Shared.CryptoLibrary.Modules.xxHash +{ + /// + /// xxHash Provider + /// Can Hash for plain text or byte array + /// + public class xxHashProvider : ICryptoProvider + { + // Provider Options + private xxHashEncryptionOptions _options; + + /// + /// xxHash Provider + /// + /// + public xxHashProvider(xxHashEncryptionOptions options = null) { + _options = options ?? new xxHashEncryptionOptions(); + } + + /// + /// Decrypt String (Not Supported for hashing) + /// + /// + /// + /// + public string DecryptString(string encryptedString) { + throw new Exception($"Failed to decrypt text, because {this.GetType()} doesn't support decryption."); + } + + /// + /// Decrypt Binary (Not Supported for hashing) + /// + /// + /// + /// + public byte[] DecryptBinary(byte[] encryptedBinary) { + throw new Exception($"Failed to decrypt text, because {this.GetType()} doesn't support decryption."); + } + + /// + /// Get xxHash for plain-text + /// + /// + /// + public string EncryptString(string decryptedString) { + return Convert.ToString(EncryptBinary(_options.encoding.GetBytes(decryptedString))); + } + + /// + /// Get xxHash for byte array + /// + /// + /// + public byte[] EncryptBinary(byte[] decryptedBinary) { + uint h32; + int index = 0; + + if (_options.length >= 16) + { + int limit = _options.length - 16; + uint v1 = _options.seed + _options.PRIME32_1 + _options.PRIME32_2; + uint v2 = _options.seed + _options.PRIME32_2; + uint v3 = _options.seed; + uint v4 = _options.seed - _options.PRIME32_1; + + do + { + uint read_value = (uint)(decryptedBinary[index++] | decryptedBinary[index++] << 8 | decryptedBinary[index++] << 16 | decryptedBinary[index++] << 24); + v1 += read_value * _options.PRIME32_2; + v1 = (v1 << 13) | (v1 >> 19); + v1 *= _options.PRIME32_1; + + read_value = (uint)(decryptedBinary[index++] | decryptedBinary[index++] << 8 | decryptedBinary[index++] << 16 | decryptedBinary[index++] << 24); + v2 += read_value * _options.PRIME32_2; + v2 = (v2 << 13) | (v2 >> 19); + v2 *= _options.PRIME32_1; + + read_value = (uint)(decryptedBinary[index++] | decryptedBinary[index++] << 8 | decryptedBinary[index++] << 16 | decryptedBinary[index++] << 24); + v3 += read_value * _options.PRIME32_2; + v3 = (v3 << 13) | (v3 >> 19); + v3 *= _options.PRIME32_1; + + read_value = (uint)(decryptedBinary[index++] | decryptedBinary[index++] << 8 | decryptedBinary[index++] << 16 | decryptedBinary[index++] << 24); + v4 += read_value * _options.PRIME32_2; + v4 = (v4 << 13) | (v4 >> 19); + v4 *= _options.PRIME32_1; + + } while (index <= limit); + + h32 = ((v1 << 1) | (v1 >> 31)) + ((v2 << 7) | (v2 >> 25)) + ((v3 << 12) | (v3 >> 20)) + ((v4 << 18) | (v4 >> 14)); + } + else + { + h32 = _options.seed + _options.PRIME32_5; + } + + h32 += (uint)_options.length; + + while (index <= _options.length - 4) + { + h32 += (uint)(decryptedBinary[index++] | decryptedBinary[index++] << 8 | decryptedBinary[index++] << 16 | decryptedBinary[index++] << 24) * _options.PRIME32_3; + h32 = ((h32 << 17) | (h32 >> 15)) * _options.PRIME32_4; + } + + while (index < _options.length) + { + h32 += decryptedBinary[index] * _options.PRIME32_5; + h32 = ((h32 << 11) | (h32 >> 21)) * _options.PRIME32_1; + index++; + } + + h32 ^= h32 >> 15; + h32 *= _options.PRIME32_2; + h32 ^= h32 >> 13; + h32 *= _options.PRIME32_3; + h32 ^= h32 >> 16; + + return BitConverter.GetBytes(h32); + } + } +} \ No newline at end of file diff --git a/DevsDaddy/Shared/CryptoLibrary/Modules/xxHash/xxHashProvider.cs.meta b/DevsDaddy/Shared/CryptoLibrary/Modules/xxHash/xxHashProvider.cs.meta new file mode 100644 index 0000000..86d88a2 --- /dev/null +++ b/DevsDaddy/Shared/CryptoLibrary/Modules/xxHash/xxHashProvider.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 6a8f06d0ba9342b4a7586df87c38df6b +timeCreated: 1709895032 \ No newline at end of file diff --git a/DevsDaddy/Shared/CryptoLibrary/Preview.png b/DevsDaddy/Shared/CryptoLibrary/Preview.png new file mode 100644 index 0000000000000000000000000000000000000000..d0ba0d43881cd04ad67f80e26c237b6f5f30fb9e GIT binary patch literal 227447 zcmce71z3~++wWkLX3{xyjPB8)#K_Uz2xBlh1`H4sWiUFVK|(@0lujj7kanbiqJX5> zf`RcnkN)EQzj5C4Uguob;kvl??AiDE<{h8={@hQBg_!{(9Sso<8r+`aJ zG7Tm0p>@`X0{EcCqaDLQAbQqc{}iC&QZ5jPs=(LAf#6_jqUI4CDDCbUjKxV`48#Mi zL7?-R7xC^M{x||0i}UskQb)WU7(&2(J=GERil#_YybjLC7abjnvyL{i@rd^KQ1wJ; zYQWE5R0BE)#1Y)#7Xt%=!qhIRBYyX*23-HTErWpnZbI-^N1%QU2zM~Gfa?T@;^3;% zvQi#Mq%2$+xKdD(Q&Clwgv%l2cQaVyzIylr@Mpji-RR$?1BPS;Xw2%sm3L>~)lnM$H_`3&PT$o3w zFP`8V90dQ>qdPV@oS=>Xruyd^0`dQJ8x;1}J^?!>bI~0yBP)&kwWi+VWIx2C55jPYO2B{1-xA;JiH z5x_G3+K~UUb(l>Q9w%dk3kwbp^}y*x0MiuswHmydPAJZu5FBa~931fXNm=|oWw@Mz zv@%@O-Z#iII5JG^Umn2ex)X5f2;kHdq>%DbNEI94$P|>-6ci#~1vObEH3iv!*A$Q$Pj`a*|FN;BhniP#XrMc=VBbJ@Z=4K1$QuFwXB*XYf&+p> zfq{Y9$^V{(si~S_P#D2I$OC7ntBwHHEbZ&-sph3B?}=2wBBfNYD(+HpDhl#aDjuHh zQl3f*DzfrQUaE?!*uS6G4fY8Cb+W&n|5M66gFS#g{%uqRq?ebMyn>39oV=2%l!7eK zn>$WcLCRf0R#r|~!OPRr-Rtk(%tL(vMRO1M*Is|k$`j~OP7dpil~+)f@>EvFN+~D; zSMG9(s#2bwDjteTST7t7>G?~Ve+!5j+BXb1x~RYO!x|Uz*HwTo{I^V~xqJMQb#;Wt zuS3RpBL2GV`(NzG|7hgDo{#jw0iFIghyUm3VZmO6NcT`2${X0b|D$lp{O=|o<{t6i zPu&YE@1dxm=q2SP@2Mc=siNQ|rRuKeE+wz(p`wCx$0{f(sQ$h5|1|agD2)F%Q~zsQ zJbc`Pym5f#ltKJIEarbCmw(Rk|Knn0e%Z@EB~0c&3g7SF{>8Qe2l@LJV6cB({^Kfu zFaJ0jToABNp@1vtGu48Cz#&P7x+t5ArLTTm>V?^di!j{oYU=;?G%(C_lMC@GHW{Wv zGk%ZravD^bo9a^H%0(6h4`%FFr7JI#$D^rc44{|GFB;H{rHD9;nJ2z@n=5}U*K1=GNU$ zjg5C7yAIu5e#Sd=Z15;n)L~nmuF$0Lrua-UY>>&&G6o@N8dp>rK&wxx?}nlHwIj17 zQJpI0ak{IQ1<{rFlAOkmr1fa zUfR3I(`Kiyg6BzRn9#qxa0Skb89%*2n=Q~r%OXfNhdC@HSPg~Lng$%HhsOBVzKuA- z{*)|a#^;rgoeMG1sA<+qq;QM;B{dmJya9F5$8ZS6ShgW z-_a1H7ao0&cz-nf`C97su;me^f2O?p^yTSQUABkBWAEOaB@3NR=0(z!Y2Sw*6U3SR z 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�sP@b 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 daEzk
+**Unity Crypto Library** is a set of free and open source **cross-platform tools** for using **cryptographic and hash functions** in your games. +It also contains helper classes for handling files and web requests for your convenience. + +I periodically update possible algorithms based on the latest research in crypto-graphy. + +## Get Started +**Unity Crypto Library** is designed for your application and games security and using only default API's like **System** and **UnityEngine**. + +**Installation process:** +- Download and import
latest release from this page; +- See usage examples below; + +## Usage +**You can use a simple controller for fast encryption/decryption:** +```csharp +// Setup Default Crypto-Provider +CryptoController.SetDefaultProvider(new AESProvider(new AESEncryptionOptions { + cryptoKey = "myCryptoKey" +})); + +// Simple Plain-Text Encryption-Decryption +string encryptedText = CryptoController.Encrypt("MyTextToEncrypt"); +string decryptedText = CryptoController.Decrypt(encryptedText); + +// Or with in-line crypto-provider +string encryptedText2 = CryptoController.Encrypt("TextToEncrypt", new AESProvider(new AESEncryptionOptions { + cryptoKey = "myCryptoKey" +})); +``` + +**Or initial crypto providers manually:*** +```csharp +// Create your provider +AESProvider provider = new AESProvider(new AESEncryptionOptions { + cryptoKey = "myCryptoKey" +}); + +// Work with provider +string encryptedText = provider.EncryptString("MyTextToEncrypt"); +string decryptedText = provider.DecryptString(encryptedText); +``` + +**Also you can read/write files using util class (similar like CryptoController just for files):*** +```csharp +// Setup Default Crypto-provider for Files +CryptoFile.SetDefaultProvider(new AESProvider(new AESEncryptionOptions { + cryptoKey = "key" +})); + +// Read and Decrypt File +string decryptedText = CryptoFile.ReadText("path_to_encrypted_file"); + +// Encrypt plain-text and save to file +bool writtenFile = CryptoFile.WriteText("path_to_encrypted_file", decryptedText); +``` + +## Crypto-Algorithms +**Library contains popular crypto modules:** +- **AES** (Recommended); +- **Triple DES** (Recommended); +- **BlowFish** (Recommended); +- **Twofish** (Recommended); +- **RSA** (Recommended for Web); +- **DES**; +- **Base64**; +- **XOR** (Only strings support, no byte array); + +**Code Sample:** +```csharp +string encrypted = CryptoController.Encrypt("TextToEncrypt", new AESProvider(new AESEncryptionOptions { + cryptoKey = "myCryptoKey" +})); + +// Return Encrypted +Debug.Log(encrypted); +``` + +## Hashing +**Library contains popular hashing functions:** +- **SHA1** / **SHA256** / **SHA512** (Recommended); +- **PBKDF2** (Recommended); +- **MD5**; +- **xxHash**; +- **RIPEMD-160**; +- **CRC32**; + +**Code Sample:** +```csharp +string hashed = CryptoController.Encrypt("TextToEncrypt", new MD5Provider(new MD5EncryptionOptions { })); + +// Return Hashed +Debug.Log(hashed); +``` + +## Examples +See framework usage examples in other projects: +* Game Shield - Unity Game Security and Anti-Cheat Toolkit; + +## Coming Soon (TO-DO) +**I plan to add the following functionality in the near future:** +- Sending and accepting encrypted HTTP requests and working with encrypted data on sockets with server examples on NodeJS / CSharp; +- Read / Write files using chunks for large amounts of data; +- New Hashing Modules: Argon2, BCrypt, SCrypt, Whirlpool; +- New Encryption Modules like SPHINCS+; + +## Support Me +Like my libraries or assets? +Buy me a coffee. \ No newline at end of file