You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

170 lines
7.3 KiB

  1. using System;
  2. using System.Collections.Generic;
  3. using System.IO;
  4. using System.Linq;
  5. using System.Security.Cryptography;
  6. using System.Text;
  7. using System.Threading.Tasks;
  8. namespace API.Model
  9. {
  10. public class EncryptDecryptUtility
  11. {
  12. protected static string saltValue = "K0r3@GM3";
  13. protected static string hashAlgorithm = "SHA1";
  14. protected static int passwordIterations = 5;
  15. protected static string initVector = "P@s$w0rDGm3KoR3@";
  16. protected static int keySize = 256;
  17. /// <summary>
  18. /// Encrypts specified plaintext using Rijndael symmetric key algorithm
  19. /// and returns a base64-encoded result.
  20. /// </summary>
  21. /// <param name="plainText">Plain Text to Encrypt</param>
  22. /// <param name="passPhrase">Pass Phrase to use in Password Generation</param>
  23. /// <returns>Encrypted text encoded into Base 64 text format </returns>
  24. public static string Encrypt(string plainText, string passPhrase)
  25. {
  26. // Convert strings into byte arrays.
  27. // Let us assume that strings only contain ASCII codes.
  28. // If strings include Unicode characters, use Unicode, UTF7, or UTF8
  29. // encoding.
  30. byte[] initVectorBytes = Encoding.ASCII.GetBytes(initVector);
  31. byte[] saltValueBytes = Encoding.ASCII.GetBytes(saltValue);
  32. // Convert our plaintext into a byte array.
  33. // Let us assume that plaintext contains UTF8-encoded characters.
  34. byte[] plainTextBytes = Encoding.UTF8.GetBytes(plainText);
  35. // First, we must create a password, from which the key will be derived.
  36. // This password will be generated from the specified passphrase and
  37. // salt value. The password will be created using the specified hash
  38. // algorithm. Password creation can be done in several iterations.
  39. var password = new PasswordDeriveBytes(
  40. passPhrase,
  41. saltValueBytes,
  42. hashAlgorithm,
  43. passwordIterations);
  44. // Use the password to generate pseudo-random bytes for the encryption
  45. // key. Specify the size of the key in bytes (instead of bits).
  46. #pragma warning disable 618, 612
  47. byte[] keyBytes = password.GetBytes(keySize / 8);
  48. #pragma warning restore 618, 612
  49. // Create uninitialized Rijndael encryption object.
  50. var symmetricKey = new RijndaelManaged();
  51. // It is reasonable to set encryption mode to Cipher Block Chaining
  52. // (CBC). Use default options for other symmetric key parameters.
  53. symmetricKey.Mode = CipherMode.CBC;
  54. // Generate encryptor from the existing key bytes and initialization
  55. // vector. Key size will be defined based on the number of the key
  56. // bytes.
  57. ICryptoTransform encryptor = symmetricKey.CreateEncryptor(
  58. keyBytes,
  59. initVectorBytes);
  60. var memoryStream = new MemoryStream();
  61. // Define memory stream which will be used to hold encrypted data.
  62. var cryptoStream = new CryptoStream(memoryStream, encryptor, CryptoStreamMode.Write);
  63. // Start encrypting.
  64. cryptoStream.Write(plainTextBytes, 0, plainTextBytes.Length);
  65. // Finish encrypting.
  66. cryptoStream.FlushFinalBlock();
  67. // Convert our encrypted data from a memory stream into a byte array.
  68. byte[] cipherTextBytes = memoryStream.ToArray();
  69. // Close both streams.
  70. memoryStream.Close();
  71. cryptoStream.Close();
  72. // Convert encrypted data into a base64-encoded string.
  73. string cipherText = Convert.ToBase64String(cipherTextBytes);
  74. // Return encrypted string.
  75. return cipherText;
  76. }
  77. /// <summary>
  78. /// Decrypts specified cipherText using Rijndael symmetric key algorithm
  79. /// and returns a plain text result.
  80. /// </summary>
  81. /// <param name="cipherText">Encryted Text</param>
  82. /// <param name="passPhrase">Pass Phrase used in Password Generation</param>
  83. /// <returns></returns>
  84. public static string Decrypt(string cipherText, string passPhrase)
  85. {
  86. // Convert strings defining encryption key characteristics into byte
  87. // arrays. Let us assume that strings only contain ASCII codes.
  88. // If strings include Unicode characters, use Unicode, UTF7, or UTF8
  89. // encoding.
  90. byte[] initVectorBytes = Encoding.ASCII.GetBytes(initVector);
  91. byte[] saltValueBytes = Encoding.ASCII.GetBytes(saltValue);
  92. // Convert our ciphertext into a byte array.
  93. byte[] cipherTextBytes = Convert.FromBase64String(cipherText);
  94. // First, we must create a password, from which the key will be
  95. // derived. This password will be generated from the specified
  96. // passphrase and salt value. The password will be created using
  97. // the specified hash algorithm. Password creation can be done in
  98. // several iterations.
  99. var password = new PasswordDeriveBytes(
  100. passPhrase,
  101. saltValueBytes,
  102. hashAlgorithm,
  103. passwordIterations);
  104. // Use the password to generate pseudo-random bytes for the encryption
  105. // key. Specify the size of the key in bytes (instead of bits).
  106. #pragma warning disable 618, 612
  107. byte[] keyBytes = password.GetBytes(keySize / 8);
  108. #pragma warning restore 618, 612
  109. // Create uninitialized Rijndael encryption object.
  110. var symmetricKey = new RijndaelManaged();
  111. // It is reasonable to set encryption mode to Cipher Block Chaining
  112. // (CBC). Use default options for other symmetric key parameters.
  113. symmetricKey.Mode = CipherMode.CBC;
  114. // Generate decryptor from the existing key bytes and initialization
  115. // vector. Key size will be defined based on the number of the key
  116. // bytes.
  117. ICryptoTransform decryptor = symmetricKey.CreateDecryptor(
  118. keyBytes,
  119. initVectorBytes);
  120. // Define memory stream which will be used to hold encrypted data.
  121. var memoryStream = new MemoryStream(cipherTextBytes);
  122. // Define cryptographic stream (always use Read mode for encryption).
  123. var cryptoStream = new CryptoStream(memoryStream, decryptor, CryptoStreamMode.Read);
  124. // Since at this point we don't know what the size of decrypted data
  125. // will be, allocate the buffer long enough to hold ciphertext;
  126. // plaintext is never longer than ciphertext.
  127. var plainTextBytes = new byte[cipherTextBytes.Length];
  128. // Start decrypting.
  129. int decryptedByteCount = cryptoStream.Read(plainTextBytes, 0, plainTextBytes.Length);
  130. // Close both streams.
  131. memoryStream.Close();
  132. cryptoStream.Close();
  133. // Convert decrypted data into a string.
  134. // Let us assume that the original plaintext string was UTF8-encoded.
  135. string plainText = Encoding.UTF8.GetString(plainTextBytes, 0, decryptedByteCount);
  136. // Return decrypted string.
  137. return plainText;
  138. }
  139. }
  140. }