PageRenderTime 49ms CodeModel.GetById 17ms RepoModel.GetById 0ms app.codeStats 0ms

/base/Applications/Security/CryptoBvt/DesTest.cs

#
C# | 308 lines | 245 code | 50 blank | 13 comment | 26 complexity | 6982a7208dffe2da72ef47711d336802 MD5 | raw file
  1. ///////////////////////////////////////////////////////////////////////////////
  2. //
  3. // Microsoft Research Singularity
  4. //
  5. // Copyright (c) Microsoft Corporation. All rights reserved.
  6. //
  7. using System;
  8. using System.Security.Cryptography;
  9. interface IDes
  10. {
  11. void EncryptBlock(byte[] key, byte[] input, byte[] output);
  12. void DecryptBlock(byte[] key, byte[] input, byte[] output);
  13. }
  14. class ManagedDes : IDes
  15. {
  16. public void EncryptBlock(byte[] key, byte[] input, byte[] output)
  17. {
  18. Des.EncryptDecrypt(key, input, output, true);
  19. }
  20. public void DecryptBlock(byte[] key, byte[] input, byte[] output)
  21. {
  22. Des.EncryptDecrypt(key, input, output, false);
  23. }
  24. }
  25. class DesTest
  26. {
  27. public static void RunTests()
  28. {
  29. IDes![]! implementations = {
  30. new ManagedDes(),
  31. // no other implementations are available on Singularity yet
  32. };
  33. TestKnownCiphers(implementations);
  34. TestInterop(implementations);
  35. foreach (IDes! des in implementations) {
  36. TestRandomCiphers(des);
  37. }
  38. Console.WriteLine("DES TEST: All tests complete.");
  39. }
  40. static void TestRandomCiphers(IDes! des)
  41. {
  42. Console.WriteLine("DES TEST: Testing implementation '{0}' for roundtrip encrypt/decrypt.", des.GetType().Name);
  43. int tickStarted = Environment.TickCount;
  44. int tickStopped;
  45. int cipherCount = 0;
  46. Random random = new Random();
  47. for (;;) {
  48. for (int pass = 0; pass < 0x100; pass++) {
  49. byte[] key = new byte[8];
  50. for (int i = 0; i < 8; i++)
  51. key[i] = (byte)random.Next(0, 0x100);
  52. byte[] message = new byte[8];
  53. for (int i = 0; i < 8; i++)
  54. message[i] = (byte)random.Next(0, 0x100);
  55. byte[] cipher = new byte[8];
  56. byte[] roundtrip_clear = new byte[8];
  57. des.EncryptBlock(key, message, cipher);
  58. cipherCount++;
  59. des.DecryptBlock(key, cipher, roundtrip_clear);
  60. cipherCount++;
  61. if (Util.CompareArraySpans(message, 0, roundtrip_clear, 0, 8) != 0) {
  62. Console.WriteLine("DES ERROR: DES implementation '{0}' FAILED an encrypt/decrypt roundtrip test.", des.GetType().Name);
  63. Console.WriteLine(" key: " + Util.ByteArrayToStringHex(key));
  64. Console.WriteLine(" clear text (input): " + Util.ByteArrayToStringHex(message));
  65. Console.WriteLine(" cipher text: " + Util.ByteArrayToStringHex(cipher));
  66. Console.WriteLine(" clear text (output): " + Util.ByteArrayToStringHex(roundtrip_clear));
  67. return;
  68. }
  69. }
  70. int now = Environment.TickCount;
  71. int elapsed = now - tickStarted;
  72. if (elapsed > 5000) {
  73. tickStopped = now;
  74. break;
  75. }
  76. }
  77. Console.WriteLine(" PASSED.");
  78. if (cipherCount > 0) {
  79. int totalElapsedMs = tickStopped - tickStarted;
  80. double ciphersPerSecond = cipherCount / ((double)totalElapsedMs) * 1000.0;
  81. Console.WriteLine(" Approx ciphers/sec: {0}", ciphersPerSecond);
  82. }
  83. }
  84. static void TestInterop(IDes![]! imps)
  85. {
  86. Console.WriteLine("TEST: Testing interoperability between different implementations.");
  87. Random random = new Random();
  88. int failureCount = 0;
  89. for (int pass = 0; pass < 10; pass++) {
  90. byte[] key = new byte[8];
  91. for (int i = 0; i < 8; i++)
  92. key[i] = (byte)random.Next(0, 0x100);
  93. byte[] message = new byte[8];
  94. for (int i = 0; i < 8; i++)
  95. message[i] = (byte)random.Next(0, 0x100);
  96. for (int i = 0; i < imps.Length; i++) {
  97. for (int j = 0; j < imps.Length; j++) {
  98. IDes! encrypt = imps[i];
  99. IDes! decrypt = imps[j];
  100. byte[] cipher = new byte[message.Length];
  101. byte[] clear = new byte[message.Length];
  102. encrypt.EncryptBlock(key, message, cipher);
  103. decrypt.DecryptBlock(key, cipher, clear);
  104. int c = Util.CompareArraySpans(message, 0, clear, 0, message.Length);
  105. if (c != 0) {
  106. Console.WriteLine("DECRYPTED VALUES ARE DIFFERENT!");
  107. Console.WriteLine("Encryptor: " + encrypt.GetType().FullName);
  108. Console.WriteLine("Decryptor: " + decrypt.GetType().FullName);
  109. Console.WriteLine("Clear text:");
  110. Util.DumpBuffer(message);
  111. Console.WriteLine("Cipher text:");
  112. Util.DumpBuffer(cipher);
  113. Console.WriteLine("Output text");
  114. Util.DumpBuffer(clear);
  115. failureCount++;
  116. i = imps.Length; break;
  117. }
  118. else {
  119. // Console.WriteLine("TEST: encrypt {0,-20} decrypt {1,-20} - ok", encrypt.GetType().Name, decrypt.GetType().Name));
  120. }
  121. }
  122. }
  123. }
  124. if (failureCount == 0) {
  125. Console.WriteLine(" PASSED: All interoperability tests succeeded.");
  126. }
  127. else {
  128. Console.WriteLine(" FAILED: At least one interop test failed.");
  129. }
  130. }
  131. static void EmitRandomKnownCiphers()
  132. {
  133. Random random = new Random();
  134. Console.WriteLine("static readonly KnownCipher[] _knownCiphers = {");
  135. for (int i = 0; i < 0x20; i++) {
  136. byte[] key = new byte[8];
  137. random.NextBytes(key);
  138. byte[] message = new byte[8];
  139. random.NextBytes(message);
  140. byte[] cipher = new byte[8];
  141. Des.Encrypt(key, message, cipher);
  142. Console.WriteLine("new KnownCipher(\"{0}\", \"{1}\", \"{2}\"),",
  143. Util.ByteArrayToStringHex(key),
  144. Util.ByteArrayToStringHex(message),
  145. Util.ByteArrayToStringHex(cipher));
  146. }
  147. Console.WriteLine("}");
  148. }
  149. /// <summary>
  150. /// This method verifies that a DES implementation correctly encrypts and decrypts all of the
  151. /// values in the table of known ciphers.
  152. /// </summary>
  153. /// <param name="des">The implementation to test.</param>
  154. static void TestKnownCiphers(IDes![]! implementations)
  155. {
  156. Console.WriteLine("TEST: Testing all DES implementations against {0} known ciphers:", _knownCiphers.Length);
  157. foreach (IDes! des in implementations) {
  158. string! implementationName = (!)des.GetType().Name;
  159. bool passed = true;
  160. foreach (KnownCipher known in _knownCiphers) {
  161. byte[] cipher = new byte[8];
  162. des.EncryptBlock(known.Key, known.ClearText, cipher);
  163. if (Util.CompareArraySpans(cipher, 0, known.Cipher, 0, 8) != 0) {
  164. Console.WriteLine("*** DES implementation '{0}' FAILED to correctly ENCIPHER a block.", implementationName);
  165. Console.WriteLine(" key: " + Util.ByteArrayToStringHex(known.Key));
  166. Console.WriteLine(" clear text: " + Util.ByteArrayToStringHex(known.ClearText));
  167. Console.WriteLine(" known good cipher text: " + Util.ByteArrayToStringHex(known.Cipher));
  168. Console.WriteLine(" failed cipher text: " + Util.ByteArrayToStringHex(cipher));
  169. passed = false;
  170. break;
  171. }
  172. byte[] cleartext = new byte[8];
  173. des.DecryptBlock(known.Key, known.Cipher, cleartext);
  174. if (Util.CompareArraySpans(cipher, 0, known.Cipher, 0, 8) != 0) {
  175. Console.WriteLine("*** DES implementation '{0}' FAILED to correctly DECIPHER a block.", implementationName);
  176. Console.WriteLine(" key: " + Util.ByteArrayToStringHex(known.Key));
  177. Console.WriteLine(" cipher text: " + Util.ByteArrayToStringHex(known.ClearText));
  178. Console.WriteLine(" known good clear text: " + Util.ByteArrayToStringHex(known.Cipher));
  179. Console.WriteLine(" failed clear text: " + Util.ByteArrayToStringHex(cipher));
  180. passed = false;
  181. break;
  182. }
  183. }
  184. if (passed) {
  185. Console.WriteLine(" PASSED: " + implementationName);
  186. }
  187. else {
  188. Console.WriteLine(" FAILED: " + implementationName);
  189. }
  190. }
  191. }
  192. #if false
  193. void TestPerformance(DesImplementation[] imps)
  194. {
  195. Console.WriteLine("TEST: Estimating performance of implementations:");
  196. Random random = new Random();
  197. foreach (DesImplementation des in imps) {
  198. byte[] key = new byte[0];
  199. random.NextBytes(key);
  200. byte[] cleartext = new byte[0];
  201. }
  202. }
  203. #endif
  204. struct KnownCipher
  205. {
  206. public KnownCipher(string! key, string! cleartext, string! cipher)
  207. : this(
  208. Util.HexStringToByteArray(key),
  209. Util.HexStringToByteArray(cleartext),
  210. Util.HexStringToByteArray(cipher))
  211. {
  212. }
  213. public KnownCipher(byte[]! key, byte[]! cleartext, byte[]! cipher)
  214. {
  215. this.Key = key;
  216. this.ClearText = cleartext;
  217. this.Cipher = cipher;
  218. }
  219. public readonly byte[]! Key;
  220. public readonly byte[]! ClearText;
  221. public readonly byte[]! Cipher;
  222. }
  223. static readonly KnownCipher[] _knownCiphers =
  224. {
  225. new KnownCipher("26e9fc83852311d8", "e1402d0f9442d85c", "c0e394fd6490aa0f"),
  226. new KnownCipher("c95e9d039d732b6c", "2eee2417b69692a8", "bcb78b4a1215d78a"),
  227. new KnownCipher("7b331146c590b1d3", "6e376932bb2c030f", "555127f9a4111092"),
  228. new KnownCipher("e83a28ea550972b3", "be905596fff9224b", "f9656d3ec8fbab2d"),
  229. new KnownCipher("ae85936030929638", "adc9946509f9b101", "6b90762b582cad2d"),
  230. new KnownCipher("eb142f7b6da75271", "c05e88353b1ad474", "349b95d1d20d26c1"),
  231. new KnownCipher("141d833598a2df55", "a4f03d8b740ca9c4", "74507d68be5a8638"),
  232. new KnownCipher("df53abeacaa7de06", "3222a0d10961fd92", "c366707e826f47f1"),
  233. new KnownCipher("f52050eb757b6948", "35d9d77c6ac7fdb4", "738b39e892f934fd"),
  234. new KnownCipher("b5c356e76ee9aa6d", "3f7d0376020e4c42", "3b85c78032007603"),
  235. new KnownCipher("f3aa9654bbbd4f63", "ea63b4f0d0619c6a", "75609fcade3f50a3"),
  236. new KnownCipher("25ec1b450b15240b", "75e3acf777f24627", "72021f00c2d5d1ba"),
  237. new KnownCipher("8d9489bf31a8f8f8", "74f2fd0b35ba9cdd", "47b36b2a63ee1625"),
  238. new KnownCipher("e1985116f20637dd", "868aded81057ecf7", "0ef7b7b9e9253675"),
  239. new KnownCipher("1c8d623bd7dd397c", "f322d1181818d6bb", "5d9e33944c860522"),
  240. new KnownCipher("46cf16dea1303487", "5cac38a6ca1fe81d", "b665aef92e365f88"),
  241. new KnownCipher("0605eea757600504", "5ed422d0351fc46e", "744b0036d03d4d9b"),
  242. new KnownCipher("b4229141400d56ec", "59dadf2ba493b2d4", "c480de721320b5a8"),
  243. new KnownCipher("3ab31212292f63e5", "c9127fcc0d64523d", "d45e4fd7fbe7b1fe"),
  244. new KnownCipher("e7caf2a78ea6dcf8", "af024d7d81da5fcb", "37e340853ffde534"),
  245. new KnownCipher("224e95810cb24485", "beab772d8d89def5", "f5f9847dd156ab1b"),
  246. new KnownCipher("88a143daa10a4693", "d6196327e1e664ef", "e752f30bd985b91e"),
  247. new KnownCipher("b3b4aabfced03135", "856de9e22eaf6b26", "627247191de4454e"),
  248. new KnownCipher("2358f4e096852a17", "0801aaf24e1da3d7", "55da1f2d460c0d43"),
  249. new KnownCipher("47887ad8de1e26b7", "6f0e543321636427", "e04edfab22c74acc"),
  250. new KnownCipher("ae3c0389f283592d", "8a93b7cd263ee668", "50889aa8dbafb44c"),
  251. new KnownCipher("c9119ba635924704", "313c708731f6f6a4", "7637d6adbc64209a"),
  252. new KnownCipher("9c834311191ae5c3", "2f4c4e4b67599130", "6ba0e036c4584386"),
  253. new KnownCipher("28eb6a10c8bef21c", "f5fe57b512d1fc93", "e0a4ff1c86883af1"),
  254. new KnownCipher("9d1330a2fbd44fae", "2cd777e843fc9dd7", "54091b5227549171"),
  255. new KnownCipher("aa3f5f468ce5dcdd", "91261c1ac32fb05d", "dd5fe1a60c3fa9ed"),
  256. new KnownCipher("50bbae5428ef3553", "9bbbe3f04709d9f8", "ad28c355c1b48107"),
  257. };
  258. }