PageRenderTime 24ms CodeModel.GetById 1ms RepoModel.GetById 0ms app.codeStats 0ms

/Utilities/Tests/CryptographyTests.cs

#
C# | 225 lines | 144 code | 23 blank | 58 comment | 5 complexity | d488ab519c4bc9b58617ed742e15fb02 MD5 | raw file
Possible License(s): Apache-2.0
  1. using System;
  2. using System.IO;
  3. using System.Text;
  4. using Delta.Utilities.Cryptography;
  5. using Delta.Utilities.Helpers;
  6. using Delta.Utilities.Xml;
  7. using NUnit.Framework;
  8. namespace Delta.Utilities.Tests
  9. {
  10. /// <summary>
  11. /// Tests for the Cryptography classes.
  12. /// </summary>
  13. internal class CryptographyTests
  14. {
  15. #region EncryptAndDecryptData (LongRunning)
  16. /// <summary>
  17. /// Testing to encrypt and decrypt some data.
  18. /// </summary>
  19. [Test]
  20. [Category("LongRunning")]
  21. public static void EncryptAndDecryptData()
  22. {
  23. // Create a private key and 100 bytes of some boring data.
  24. byte[] privateKey = AES.CreatePrivateKey();
  25. // Write out generated AES key for copy and pasting into code :)
  26. Console.WriteLine("Generated AES key: " + privateKey.Write());
  27. MemoryStream someData = new MemoryStream();
  28. for (int num = 0; num < 100; num++)
  29. {
  30. someData.WriteByte((byte)num);
  31. }
  32. // Encrypting and decrypting is really easy :)
  33. MemoryStream encrypted = AES.Encrypt(someData, privateKey);
  34. MemoryStream decrypted = AES.Decrypt(encrypted, privateKey);
  35. // And finally check if we got all the original data back
  36. Assert.Equal(decrypted.Length, 100);
  37. for (int num = 0; num < 100; num++)
  38. {
  39. // Make sure the decrypted data is the same
  40. Assert.Equal(decrypted.ReadByte(), num);
  41. }
  42. }
  43. #endregion
  44. #region TestEncryptDecryptPerformance (LongRunning)
  45. /// <summary>
  46. /// Test encrypt and decrypt performance with the simple static methods
  47. /// and with the optimized instance methods that to be constructed
  48. /// first (and all their internals are kept around, no need to recreate)
  49. /// </summary>
  50. [Test]
  51. [Category("LongRunning")]
  52. public static void TestEncryptDecryptPerformance()
  53. {
  54. // Iterate 10000 times with 100 bytes of data = 1 MB! Takes ~100ms.
  55. // Note: Before we had a bit better performance with 60-70ms, but we
  56. // cached the encryptor and decryptor, which causes the next test to
  57. // fail: EncryptAndDecryptTwoStrings, so don't do that anymore!
  58. const int Iterations = 10000;
  59. // For 1000 the performance is almost the same, for 100 the instance,
  60. // but for small data arrays like 10 bytes instance methods are almost
  61. // 8 times faster :) The key thing here is not to send too much data
  62. // encrypted, keep it to a minimum, encrypting everything can be slow.
  63. // With instance methods we can encrypt 1 MB of data in about 50ms,
  64. // no matter how big or small each data packet is (for 10 byte packets
  65. // the overhead is slightly bigger with 100ms extra, but usually it
  66. // can be ignored). We can encrypt and decrypt about 20 MB per second,
  67. // which is more than most network connections can handle and we surely
  68. // do not need to encrypt every network message, only secure server
  69. // client stuff like authentication, passwords, shops, build data, etc.
  70. const int DataArraySize = 100; //10;//1000;
  71. byte[] privateKey = AES.CreatePrivateKey();
  72. MemoryStream someData = new MemoryStream();
  73. for (int num = 0; num < DataArraySize; num++)
  74. {
  75. someData.WriteByte((byte)num);
  76. }
  77. byte[] someDataArray = someData.ToArray();
  78. // Start the timer and iterate
  79. DateTime start = DateTime.Now;
  80. // Note: takes 14-15s for 1 million iterations, way too long!
  81. for (int count = 0; count < Iterations; count++)
  82. {
  83. MemoryStream encrypted = AES.Encrypt(someData, privateKey);
  84. MemoryStream decrypted = AES.Decrypt(encrypted, privateKey);
  85. }
  86. Console.WriteLine(Iterations + " iterations took " +
  87. (DateTime.Now - start).TotalMilliseconds +
  88. "ms for static calls.");
  89. // Now do the same with the instance methods, which is 1.2-10x faster.
  90. AES crypto = new AES(privateKey);
  91. start = DateTime.Now;
  92. byte[] encryptedBytes = null;
  93. byte[] decryptedBytes = null;
  94. for (int count = 0; count < Iterations; count++)
  95. {
  96. encryptedBytes = crypto.Encrypt(someDataArray);
  97. decryptedBytes = crypto.Decrypt(encryptedBytes,
  98. someDataArray.Length);
  99. }
  100. Console.WriteLine(Iterations + " iterations took " +
  101. (DateTime.Now - start).TotalMilliseconds +
  102. "ms for instance calls.");
  103. // Also check result, must still fit!
  104. Assert.Equal(someDataArray, decryptedBytes);
  105. }
  106. #endregion
  107. #region EncryptAndDecryptTwoStrings (LongRunning)
  108. /// <summary>
  109. /// Helper test to see if we can decrypt and encrypt multiple times.
  110. /// </summary>
  111. [Test]
  112. [Category("LongRunning")]
  113. public static void EncryptAndDecryptTwoStrings()
  114. {
  115. byte[] commonPrivateKey = AES.CreatePrivateKey();
  116. AES crypto = new AES(commonPrivateKey);
  117. // Create another instance of AES for decryption
  118. AES decryptor = new AES(commonPrivateKey, crypto.Seed);
  119. byte[] string1Array = StringHelper.StringToBytes("Hi there");
  120. byte[] encrypted1Bytes = crypto.Encrypt(string1Array);
  121. byte[] decrypted1Bytes = decryptor.Decrypt(encrypted1Bytes,
  122. string1Array.Length);
  123. Assert.Equal("Hi there", StringHelper.BytesToString(string1Array));
  124. byte[] string2Array = StringHelper.StringToBytes("What is up");
  125. byte[] encrypted2Bytes = crypto.Encrypt(string2Array);
  126. byte[] decrypted2Bytes = decryptor.Decrypt(encrypted2Bytes,
  127. string2Array.Length);
  128. Assert.Equal("What is up", StringHelper.BytesToString(string2Array));
  129. }
  130. #endregion
  131. #region TestRsaCrypto (LongRunning)
  132. /// <summary>
  133. /// Takes the RSA class for a test run.
  134. /// </summary>
  135. [Test]
  136. [Category("LongRunning")]
  137. public static void TestRsaCrypto()
  138. {
  139. DateTime start = DateTime.Now;
  140. RSA rsa = new RSA(null);
  141. Console.WriteLine("Done generating keys (took " +
  142. (DateTime.Now - start).TotalMilliseconds + "ms)");
  143. Console.WriteLine();
  144. Console.WriteLine("rsa.Save(false)=" +
  145. rsa.Save(false).GetWholeDocumentXmlText());
  146. Console.WriteLine();
  147. Console.WriteLine("rsa.Save(true)=" +
  148. rsa.Save(true).GetWholeDocumentXmlText());
  149. Console.WriteLine();
  150. // Save public and private keys to file (used in the tests below)
  151. rsa.Save(false).Save("Public.RSA.key");
  152. rsa.Save(true).Save("Private.RSA.key");
  153. string inputText = "abc123";
  154. //Convert your text to a byte array
  155. byte[] rawBytes = Encoding.UTF8.GetBytes(inputText);
  156. Console.WriteLine("rawBytes.Length=" + rawBytes.Length);
  157. //Encrypt your raw bytes and return the encrypted bytes
  158. byte[] encBytes = rsa.Encrypt(rawBytes);
  159. Console.WriteLine("encBytes.Length=" + encBytes.Length);
  160. //Now decrypt your encrypted bytes
  161. byte[] decBytes = rsa.Decrypt(encBytes);
  162. Console.WriteLine("decBytes.Length=" + decBytes.Length);
  163. //Convert your decrypted bytes back to a string
  164. Assert.Equal(inputText,
  165. Encoding.UTF8.GetString(decBytes, 0, decBytes.Length));
  166. }
  167. #endregion
  168. #region EncryptWithPublicRSAKey (LongRunning)
  169. /// <summary>
  170. /// Encrypt with public key and save result to file, which can be
  171. /// tested later with DecryptWithPrivateRSAKey (even using a different RSA
  172. /// implementation, which is the whole purpose of this test).
  173. /// </summary>
  174. [Test]
  175. [Category("LongRunning")]
  176. public static void EncryptWithPublicRSAKey()
  177. {
  178. RSA rsa = new RSA(XmlNode.FromFile("Public.RSA.key"));
  179. // Note: The resulting file is always 256 bytes long (2048 bits).
  180. FileHelper.CreateBinaryFile("EncryptedMessage.RSA",
  181. rsa.Encrypt(Encoding.UTF8.GetBytes("Hi there ;)")));
  182. Console.WriteLine("Wrote 'EncryptedMessage.RSA' file out.");
  183. }
  184. #endregion
  185. #region DecryptWithPrivateRSAKey (LongRunning)
  186. /// <summary>
  187. /// The opposite of EncryptWithPublicRSAKey, this one decrypts the
  188. /// message again and needs the matching "Private.RSA.key" file.
  189. /// </summary>
  190. [Test]
  191. [Category("LongRunning")]
  192. public static void DecryptWithPrivateRSAKey()
  193. {
  194. // First make sure we have the encrypted file!
  195. EncryptWithPublicRSAKey();
  196. RSA rsa = new RSA(XmlNode.FromFile("Private.RSA.key"));
  197. byte[] bytes = rsa.Decrypt(FileHelper.GetBytes("EncryptedMessage.RSA"));
  198. Console.WriteLine(Encoding.UTF8.GetString(bytes, 0, bytes.Length));
  199. }
  200. #endregion
  201. }
  202. }