[C#] AES+RC2 Encryption Class


SUBMITTED BY: eddysix

DATE: March 13, 2017, 7:59 a.m.

FORMAT: C#

SIZE: 18.7 kB

HITS: 550

  1. using System;
  2. using System.Collections.Generic;
  3. using System.Text;
  4. using System.Security.Cryptography;
  5. using System.IO;
  6. namespace Server
  7. {
  8. public class DataCryption
  9. {
  10. public static byte[] PolyAESEncrypt(byte[] plainText, string Key)
  11. {
  12. byte[] salt;
  13. SymmetricAlgorithm algo = new RijndaelManaged();
  14. RNGCryptoServiceProvider rngAlgo = new RNGCryptoServiceProvider();
  15. algo.Mode = CipherMode.CBC;
  16. byte[] key = System.Text.Encoding.ASCII.GetBytes(Key);
  17. algo.GenerateIV();
  18. salt = new byte[32];
  19. rngAlgo.GetBytes(salt);
  20. Rfc2898DeriveBytes pwDeriveAlg = new Rfc2898DeriveBytes(key, salt, 2000);
  21. algo.Key = pwDeriveAlg.GetBytes(32);
  22. ICryptoTransform encTransform = algo.CreateEncryptor();
  23. byte[] enced = encTransform.TransformFinalBlock(plainText, 0, plainText.Length);
  24. int origLength = enced.Length;
  25. Array.Resize(ref enced, enced.Length + salt.Length);
  26. Buffer.BlockCopy(salt, 0, enced, origLength, salt.Length);
  27. origLength = enced.Length;
  28. Array.Resize(ref enced, enced.Length + algo.IV.Length);
  29. Buffer.BlockCopy(algo.IV, 0, enced, origLength, algo.IV.Length);
  30. return enced;
  31. }
  32. public static byte[] PolyAESDecrypt(byte[] cipherText, string Key)
  33. {
  34. try
  35. {
  36. byte[] salt;
  37. SymmetricAlgorithm algo = new RijndaelManaged();
  38. algo.Mode = CipherMode.CBC;
  39. RNGCryptoServiceProvider rngAlgo = new RNGCryptoServiceProvider();
  40. byte[] key = System.Text.Encoding.ASCII.GetBytes(Key);
  41. byte[] cipherTextWithSalt = new byte[1];
  42. byte[] encSalt = new byte[1];
  43. byte[] origCipherText = new byte[1];
  44. byte[] encIv = new byte[1];
  45. Array.Resize(ref encIv, 16);
  46. Buffer.BlockCopy(cipherText, (int)(cipherText.Length - 16), encIv, 0, 16);
  47. Array.Resize(ref cipherTextWithSalt, (int)(cipherText.Length - 16));
  48. Buffer.BlockCopy(cipherText, 0, cipherTextWithSalt, 0, (int)(cipherText.Length - 16));
  49. Array.Resize(ref encSalt, 32);
  50. Buffer.BlockCopy(cipherTextWithSalt, (int)(cipherTextWithSalt.Length - 32), encSalt, 0, 32);
  51. Array.Resize(ref origCipherText, (int)(cipherTextWithSalt.Length - 32));
  52. Buffer.BlockCopy(cipherTextWithSalt, 0, origCipherText, 0, (int)(cipherTextWithSalt.Length - 32));
  53. algo.IV = encIv;
  54. salt = encSalt;
  55. Rfc2898DeriveBytes pwDeriveAlg = new Rfc2898DeriveBytes(key, salt, 2000);
  56. algo.Key = pwDeriveAlg.GetBytes(32);
  57. ICryptoTransform decTransform = algo.CreateDecryptor();
  58. byte[] plainText = decTransform.TransformFinalBlock(origCipherText, 0, origCipherText.Length);
  59. return plainText;
  60. }
  61. catch (CryptographicException e)
  62. {
  63. throw e;
  64. }
  65. }
  66. static string strRC2Encryption(string strInput, string strKey, string strIV)
  67. {
  68. try
  69. {
  70. byte[] byteInput = Encoding.UTF8.GetBytes(strInput);
  71. byte[] byteKey = Encoding.ASCII.GetBytes(strKey);
  72. byte[] byteIV = Encoding.ASCII.GetBytes(strIV);
  73. MemoryStream MS = new MemoryStream();
  74. RC2CryptoServiceProvider CryptoMethod = new RC2CryptoServiceProvider();
  75. CryptoStream CS = new CryptoStream(MS, CryptoMethod.CreateEncryptor(byteKey, byteIV), CryptoStreamMode.Write);
  76. CS.Write(byteInput, 0, byteInput.Length);
  77. CS.FlushFinalBlock();
  78. return Convert.ToBase64String(MS.ToArray());
  79. }
  80. catch (Exception up)
  81. {
  82. throw up; //YUCK! ;D
  83. }
  84. }
  85. static string strRC2Decryption(string strInput, string strKey, string strIV)
  86. {
  87. try
  88. {
  89. byte[] byteInput = Convert.FromBase64String(strInput);
  90. byte[] byteKey = Encoding.ASCII.GetBytes(strKey);
  91. byte[] byteIV = Encoding.ASCII.GetBytes(strIV);
  92. MemoryStream MS = new MemoryStream();
  93. RC2CryptoServiceProvider RC2 = new RC2CryptoServiceProvider();
  94. CryptoStream CS = new CryptoStream(MS, RC2.CreateDecryptor(byteKey, byteIV), CryptoStreamMode.Write);
  95. CS.Write(byteInput, 0, byteInput.Length);
  96. CS.FlushFinalBlock();
  97. return Encoding.UTF8.GetString(MS.ToArray());
  98. }
  99. catch (Exception up)
  100. {
  101. throw up; //YUCK! ;D
  102. }
  103. }
  104. public static byte[] EncryptFromByte(byte[] plainByte, string Key, string IV)
  105. {
  106. //KEY AND IV MUST BE 8CHARS (1Byte
  107. if ((Key.Length + IV.Length) == 16)
  108. {
  109. //Van string na bytes, dan een randompass generate geencrypt in RC2
  110. //met de Client/Server Pass&IV. Encryptie van pass en van AES DATA
  111. //encrypt na een base dan weer na bytes om daarna te kunnen worden
  112. //gesplit in Decrypt().
  113. string plainPass = RandomPassword.Generate(32);
  114. string encPass = strRC2Encryption(plainPass, Key, IV);
  115. string encByte = Convert.ToBase64String(PolyAESEncrypt(plainByte, plainPass));
  116. return Encoding.Default.GetBytes(encByte + "$" + encPass);
  117. }
  118. else
  119. throw new Exception("Error in IV or Key Size.");
  120. }
  121. public static byte[] DecryptToByte(byte[] encData, string Key, string IV)
  122. {
  123. //Data is samengevoegd met een $, AES = 0, PASS = 1.
  124. string[] splitData = Encoding.Default.GetString(encData).Split('$');
  125. string plainPass = strRC2Decryption(splitData[1], Key, IV);
  126. byte[] aesData = Convert.FromBase64String(splitData[0]);
  127. byte[] plainByte = PolyAESDecrypt(aesData, plainPass);
  128. return plainByte;
  129. }
  130. public static byte[] EncryptFromText(string plainTxt, string Key, string IV)
  131. {
  132. //KEY AND IV MUST BE 8CHARS (1Byte
  133. if ((Key.Length + IV.Length) == 16)
  134. {
  135. //Van string na bytes, dan een randompass generate geencrypt in RC2
  136. //met de Client/Server Pass&IV. Encryptie van pass en van AES DATA
  137. //encrypt na een base dan weer na bytes om daarna te kunnen worden
  138. //gesplit in Decrypt().
  139. byte[] plainByte = Encoding.Default.GetBytes(plainTxt);
  140. string plainPass = RandomPassword.Generate(32);
  141. string encPass = strRC2Encryption(plainPass, Key, IV);
  142. string encByte = Convert.ToBase64String(PolyAESEncrypt(plainByte, plainPass));
  143. return Encoding.Default.GetBytes(encByte + "$" + encPass);
  144. }
  145. else
  146. throw new Exception("Error in IV or Key Size.");
  147. }
  148. public static string DecryptToString(byte[] encData, string Key, string IV)
  149. {
  150. //Data is samengevoegd met een $, AES = 0, PASS = 1.
  151. string[] splitData = Encoding.Default.GetString(encData).Split('$');
  152. string plainPass = strRC2Decryption(splitData[1], Key, IV);
  153. byte[] aesData = Convert.FromBase64String(splitData[0]);
  154. byte[] plainByte = PolyAESDecrypt(aesData, plainPass);
  155. return Encoding.Default.GetString(plainByte);
  156. }
  157. static public string EncodeTo64(string toEncode)
  158. {
  159. byte[] toEncodeAsBytes = Encoding.Default.GetBytes(toEncode);
  160. return Convert.ToBase64String(toEncodeAsBytes);
  161. }
  162. static public string DecodeFrom64(string encodedData)
  163. {
  164. byte[] encodedDataAsBytes = Convert.FromBase64String(encodedData);
  165. return Encoding.Default.GetString(encodedDataAsBytes);
  166. }
  167. public class RandomPassword
  168. {
  169. // Define default min and max password lengths.
  170. private static int DEFAULT_MIN_PASSWORD_LENGTH = 8;
  171. private static int DEFAULT_MAX_PASSWORD_LENGTH = 10;
  172. // Define supported password characters divided into groups.
  173. // You can add (or remove) characters to (from) these groups.
  174. private static string PASSWORD_CHARS_LCASE = "abcdefgijkmnopqrstwxyz";
  175. private static string PASSWORD_CHARS_UCASE = "ABCDEFGHJKLMNPQRSTWXYZ";
  176. private static string PASSWORD_CHARS_NUMERIC = "23456789";
  177. private static string PASSWORD_CHARS_SPECIAL = "*-+?_&=!%{}/";
  178. /// <summary>
  179. /// Generates a random password.
  180. /// </summary>
  181. /// <returns>
  182. /// Randomly generated password.
  183. /// </returns>
  184. /// <remarks>
  185. /// The length of the generated password will be determined at
  186. /// random. It will be no shorter than the minimum default and
  187. /// no longer than maximum default.
  188. /// </remarks>
  189. public static string Generate()
  190. {
  191. return Generate(DEFAULT_MIN_PASSWORD_LENGTH,
  192. DEFAULT_MAX_PASSWORD_LENGTH);
  193. }
  194. /// <summary>
  195. /// Generates a random password of the exact length.
  196. /// </summary>
  197. /// <param name="length">
  198. /// Exact password length.
  199. /// </param>
  200. /// <returns>
  201. /// Randomly generated password.
  202. /// </returns>
  203. public static string Generate(int length)
  204. {
  205. return Generate(length, length);
  206. }
  207. /// <summary>
  208. /// Generates a random password.
  209. /// </summary>
  210. /// <param name="minLength">
  211. /// Minimum password length.
  212. /// </param>
  213. /// <param name="maxLength">
  214. /// Maximum password length.
  215. /// </param>
  216. /// <returns>
  217. /// Randomly generated password.
  218. /// </returns>
  219. /// <remarks>
  220. /// The length of the generated password will be determined at
  221. /// random and it will fall with the range determined by the
  222. /// function parameters.
  223. /// </remarks>
  224. public static string Generate(int minLength,
  225. int maxLength)
  226. {
  227. // Make sure that input parameters are valid.
  228. if (minLength <= 0 || maxLength <= 0 || minLength > maxLength)
  229. return null;
  230. // Create a local array containing supported password characters
  231. // grouped by types. You can remove character groups from this
  232. // array, but doing so will weaken the password strength.
  233. char[][] charGroups = new char[][]
  234. {
  235. PASSWORD_CHARS_LCASE.ToCharArray(),
  236. PASSWORD_CHARS_UCASE.ToCharArray(),
  237. PASSWORD_CHARS_NUMERIC.ToCharArray(),
  238. PASSWORD_CHARS_SPECIAL.ToCharArray()
  239. };
  240. // Use this array to track the number of unused characters in each
  241. // character group.
  242. int[] charsLeftInGroup = new int[charGroups.Length];
  243. // Initially, all characters in each group are not used.
  244. for (int i = 0; i < charsLeftInGroup.Length; i++)
  245. charsLeftInGroup[i] = charGroups[i].Length;
  246. // Use this array to track (iterate through) unused character groups.
  247. int[] leftGroupsOrder = new int[charGroups.Length];
  248. // Initially, all character groups are not used.
  249. for (int i = 0; i < leftGroupsOrder.Length; i++)
  250. leftGroupsOrder[i] = i;
  251. // Because we cannot use the default randomizer, which is based on the
  252. // current time (it will produce the same "random" number within a
  253. // second), we will use a random number generator to seed the
  254. // randomizer.
  255. // Use a 4-byte array to fill it with random bytes and convert it then
  256. // to an integer value.
  257. byte[] randomBytes = new byte[4];
  258. // Generate 4 random bytes.
  259. RNGCryptoServiceProvider rng = new RNGCryptoServiceProvider();
  260. rng.GetBytes(randomBytes);
  261. // Convert 4 bytes into a 32-bit integer value.
  262. int seed = (randomBytes[0] & 0x7f) << 24 |
  263. randomBytes[1] << 16 |
  264. randomBytes[2] << 8 |
  265. randomBytes[3];
  266. // Now, this is real randomization.
  267. Random random = new Random(seed);
  268. // This array will hold password characters.
  269. char[] password = null;
  270. // Allocate appropriate memory for the password.
  271. if (minLength < maxLength)
  272. password = new char[random.Next(minLength, maxLength + 1)];
  273. else
  274. password = new char[minLength];
  275. // Index of the next character to be added to password.
  276. int nextCharIdx;
  277. // Index of the next character group to be processed.
  278. int nextGroupIdx;
  279. // Index which will be used to track not processed character groups.
  280. int nextLeftGroupsOrderIdx;
  281. // Index of the last non-processed character in a group.
  282. int lastCharIdx;
  283. // Index of the last non-processed group.
  284. int lastLeftGroupsOrderIdx = leftGroupsOrder.Length - 1;
  285. // Generate password characters one at a time.
  286. for (int i = 0; i < password.Length; i++)
  287. {
  288. // If only one character group remained unprocessed, process it;
  289. // otherwise, pick a random character group from the unprocessed
  290. // group list. To allow a special character to appear in the
  291. // first position, increment the second parameter of the Next
  292. // function call by one, i.e. lastLeftGroupsOrderIdx + 1.
  293. if (lastLeftGroupsOrderIdx == 0)
  294. nextLeftGroupsOrderIdx = 0;
  295. else
  296. nextLeftGroupsOrderIdx = random.Next(0,
  297. lastLeftGroupsOrderIdx);
  298. // Get the actual index of the character group, from which we will
  299. // pick the next character.
  300. nextGroupIdx = leftGroupsOrder[nextLeftGroupsOrderIdx];
  301. // Get the index of the last unprocessed characters in this group.
  302. lastCharIdx = charsLeftInGroup[nextGroupIdx] - 1;
  303. // If only one unprocessed character is left, pick it; otherwise,
  304. // get a random character from the unused character list.
  305. if (lastCharIdx == 0)
  306. nextCharIdx = 0;
  307. else
  308. nextCharIdx = random.Next(0, lastCharIdx + 1);
  309. // Add this character to the password.
  310. password[i] = charGroups[nextGroupIdx][nextCharIdx];
  311. // If we processed the last character in this group, start over.
  312. if (lastCharIdx == 0)
  313. charsLeftInGroup[nextGroupIdx] =
  314. charGroups[nextGroupIdx].Length;
  315. // There are more unprocessed characters left.
  316. else
  317. {
  318. // Swap processed character with the last unprocessed character
  319. // so that we don't pick it until we process all characters in
  320. // this group.
  321. if (lastCharIdx != nextCharIdx)
  322. {
  323. char temp = charGroups[nextGroupIdx][lastCharIdx];
  324. charGroups[nextGroupIdx][lastCharIdx] =
  325. charGroups[nextGroupIdx][nextCharIdx];
  326. charGroups[nextGroupIdx][nextCharIdx] = temp;
  327. }
  328. // Decrement the number of unprocessed characters in
  329. // this group.
  330. charsLeftInGroup[nextGroupIdx]--;
  331. }
  332. // If we processed the last group, start all over.
  333. if (lastLeftGroupsOrderIdx == 0)
  334. lastLeftGroupsOrderIdx = leftGroupsOrder.Length - 1;
  335. // There are more unprocessed groups left.
  336. else
  337. {
  338. // Swap processed group with the last unprocessed group
  339. // so that we don't pick it until we process all groups.
  340. if (lastLeftGroupsOrderIdx != nextLeftGroupsOrderIdx)
  341. {
  342. int temp = leftGroupsOrder[lastLeftGroupsOrderIdx];
  343. leftGroupsOrder[lastLeftGroupsOrderIdx] =
  344. leftGroupsOrder[nextLeftGroupsOrderIdx];
  345. leftGroupsOrder[nextLeftGroupsOrderIdx] = temp;
  346. }
  347. // Decrement the number of unprocessed groups.
  348. lastLeftGroupsOrderIdx--;
  349. }
  350. }
  351. // Convert password characters into a string and return the result.
  352. return new string(password);
  353. }
  354. }
  355. }
  356. }

comments powered by Disqus