DES.cs 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585
  1. //
  2. // System.Security.Cryptography.DES
  3. //
  4. // Author:
  5. // Sergey Chaban ([email protected])
  6. //
  7. using System;
  8. using System.Security.Cryptography;
  9. // References: FIPS PUB 46-3
  10. namespace System.Security.Cryptography {
  11. internal sealed class DESCore {
  12. internal static readonly int KEY_BIT_SIZE = 64;
  13. internal static readonly int KEY_BYTE_SIZE = KEY_BIT_SIZE / 8;
  14. internal static readonly int BLOCK_BIT_SIZE = 64;
  15. internal static readonly int BLOCK_BYTE_SIZE = BLOCK_BIT_SIZE / 8;
  16. private byte [] keySchedule;
  17. private byte [] byteBuff;
  18. private uint [] dwordBuff;
  19. internal delegate void DESCall (byte [] block, byte [] output);
  20. // Ek(Ek(m)) = m
  21. internal static ulong [] weakKeys = {
  22. 0x0101010101010101, /* 0000000 0000000 */
  23. 0xFEFEFEFEFEFEFEFE, /* FFFFFFF FFFFFFF */
  24. 0x1F1F1F1FE0E0E0E0, /* 0000000 FFFFFFF */
  25. 0xE0E0E0E01F1F1F1F /* FFFFFFF 0000000 */
  26. };
  27. // Ek1(Ek2(m)) = m
  28. internal static ulong [] semiweakKeys = {
  29. 0x01FE01FE01FE01FE, 0xFE01FE01FE01FE01,
  30. 0x1FE01FE00EF10EF1, 0xE01FE01FF10EF10E,
  31. 0x01E001E001F101F1, 0xE001E001F101F101,
  32. 0x1FFE1FFE0EFE0EFE, 0xFE1FFE1FFE0EFE0E,
  33. 0x011F011F010E010E, 0x1F011F010E010E01,
  34. 0xE0FEE0FEF1FEF1FE, 0xFEE0FEE0FEF1FEF1
  35. };
  36. // S-boxes from FIPS 46-3, Appendix 1, page 17
  37. private static byte [] sBoxes = {
  38. /* S1 */
  39. 14, 4, 13, 1, 2, 15, 11, 8, 3, 10, 6, 12, 5, 9, 0, 7,
  40. 0, 15, 7, 4, 14, 2, 13, 1, 10, 6, 12, 11, 9, 5, 3, 8,
  41. 4, 1, 14, 8, 13, 6, 2, 11, 15, 12, 9, 7, 3, 10, 5, 0,
  42. 15, 12, 8, 2, 4, 9, 1, 7, 5, 11, 3, 14, 10, 0, 6, 13,
  43. /* S2 */
  44. 15, 1, 8, 14, 6, 11, 3, 4, 9, 7, 2, 13, 12, 0, 5, 10,
  45. 3, 13, 4, 7, 15, 2, 8, 14, 12, 0, 1, 10, 6, 9, 11, 5,
  46. 0, 14, 7, 11, 10, 4, 13, 1, 5, 8, 12, 6, 9, 3, 2, 15,
  47. 13, 8, 10, 1, 3, 15, 4, 2, 11, 6, 7, 12, 0, 5, 14, 9,
  48. /* S3 */
  49. 10, 0, 9, 14, 6, 3, 15, 5, 1, 13, 12, 7, 11, 4, 2, 8,
  50. 13, 7, 0, 9, 3, 4, 6, 10, 2, 8, 5, 14, 12, 11, 15, 1,
  51. 13, 6, 4, 9, 8, 15, 3, 0, 11, 1, 2, 12, 5, 10, 14, 7,
  52. 1, 10, 13, 0, 6, 9, 8, 7, 4, 15, 14, 3, 11, 5, 2, 12,
  53. /* S4 */
  54. 7, 13, 14, 3, 0, 6, 9, 10, 1, 2, 8, 5, 11, 12, 4, 15,
  55. 13, 8, 11, 5, 6, 15, 0, 3, 4, 7, 2, 12, 1, 10, 14, 9,
  56. 10, 6, 9, 0, 12, 11, 7, 13, 15, 1, 3, 14, 5, 2, 8, 4,
  57. 3, 15, 0, 6, 10, 1, 13, 8, 9, 4, 5, 11, 12, 7, 2, 14,
  58. /* S5 */
  59. 2, 12, 4, 1, 7, 10, 11, 6, 8, 5, 3, 15, 13, 0, 14, 9,
  60. 14, 11, 2, 12, 4, 7, 13, 1, 5, 0, 15, 10, 3, 9, 8, 6,
  61. 4, 2, 1, 11, 10, 13, 7, 8, 15, 9, 12, 5, 6, 3, 0, 14,
  62. 11, 8, 12, 7, 1, 14, 2, 13, 6, 15, 0, 9, 10, 4, 5, 3,
  63. /* S6 */
  64. 12, 1, 10, 15, 9, 2, 6, 8, 0, 13, 3, 4, 14, 7, 5, 11,
  65. 10, 15, 4, 2, 7, 12, 9, 5, 6, 1, 13, 14, 0, 11, 3, 8,
  66. 9, 14, 15, 5, 2, 8, 12, 3, 7, 0, 4, 10, 1, 13, 11, 6,
  67. 4, 3, 2, 12, 9, 5, 15, 10, 11, 14, 1, 7, 6, 0, 8, 13,
  68. /* S7 */
  69. 4, 11, 2, 14, 15, 0, 8, 13, 3, 12, 9, 7, 5, 10, 6, 1,
  70. 13, 0, 11, 7, 4, 9, 1, 10, 14, 3, 5, 12, 2, 15, 8, 6,
  71. 1, 4, 11, 13, 12, 3, 7, 14, 10, 15, 6, 8, 0, 5, 9, 2,
  72. 6, 11, 13, 8, 1, 4, 10, 7, 9, 5, 0, 15, 14, 2, 3, 12,
  73. /* S8 */
  74. 13, 2, 8, 4, 6, 15, 11, 1, 10, 9, 3, 14, 5, 0, 12, 7,
  75. 1, 15, 13, 8, 10, 3, 7, 4, 12, 5, 6, 11, 0, 14, 9, 2,
  76. 7, 11, 4, 1, 9, 12, 14, 2, 0, 6, 10, 13, 15, 3, 5, 8,
  77. 2, 1, 14, 7, 4, 10, 8, 13, 15, 12, 9, 0, 3, 5, 6, 11
  78. };
  79. // P table from page 15, also in Appendix 1, page 18
  80. private static byte [] pTab = {
  81. 16-1, 7-1, 20-1, 21-1,
  82. 29-1, 12-1, 28-1, 17-1,
  83. 1-1, 15-1, 23-1, 26-1,
  84. 5-1, 18-1, 31-1, 10-1,
  85. 2-1, 8-1, 24-1, 14-1,
  86. 32-1, 27-1, 3-1, 9-1,
  87. 19-1, 13-1, 30-1, 6-1,
  88. 22-1, 11-1, 4-1, 25-1
  89. };
  90. // Permuted choice 1 table, PC-1, page 19
  91. // Translated to zero-based format.
  92. private static byte [] PC1 = {
  93. 57-1, 49-1, 41-1, 33-1, 25-1, 17-1, 9-1,
  94. 1-1, 58-1, 50-1, 42-1, 34-1, 26-1, 18-1,
  95. 10-1, 2-1, 59-1, 51-1, 43-1, 35-1, 27-1,
  96. 19-1, 11-1, 3-1, 60-1, 52-1, 44-1, 36-1,
  97. 63-1, 55-1, 47-1, 39-1, 31-1, 23-1, 15-1,
  98. 7-1, 62-1, 54-1, 46-1, 38-1, 30-1, 22-1,
  99. 14-1, 6-1, 61-1, 53-1, 45-1, 37-1, 29-1,
  100. 21-1, 13-1, 5-1, 28-1, 20-1, 12-1, 4-1
  101. };
  102. private static byte [] leftRot = {
  103. 1, 1, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 1
  104. };
  105. private static byte [] leftRotTotal;
  106. // Permuted choice 2 table, PC-2, page 21
  107. // Translated to zero-based format.
  108. private static byte [] PC2 = {
  109. 14-1, 17-1, 11-1, 24-1, 1-1, 5-1,
  110. 3-1, 28-1, 15-1, 6-1, 21-1, 10-1,
  111. 23-1, 19-1, 12-1, 4-1, 26-1, 8-1,
  112. 16-1, 7-1, 27-1, 20-1, 13-1, 2-1,
  113. 41-1, 52-1, 31-1, 37-1, 47-1, 55-1,
  114. 30-1, 40-1, 51-1, 45-1, 33-1, 48-1,
  115. 44-1, 49-1, 39-1, 56-1, 34-1, 53-1,
  116. 46-1, 42-1, 50-1, 36-1, 29-1, 32-1
  117. };
  118. // Initial permutation IP, page 10.
  119. // Transposed to 0-based format.
  120. private static byte [] ipBits = {
  121. 58-1, 50-1, 42-1, 34-1, 26-1, 18-1, 10-1, 2-1,
  122. 60-1, 52-1, 44-1, 36-1, 28-1, 20-1, 12-1, 4-1,
  123. 62-1, 54-1, 46-1, 38-1, 30-1, 22-1, 14-1, 6-1,
  124. 64-1, 56-1, 48-1, 40-1, 32-1, 24-1, 16-1, 8-1,
  125. 57-1, 49-1, 41-1, 33-1, 25-1, 17-1, 9-1, 1-1,
  126. 59-1, 51-1, 43-1, 35-1, 27-1, 19-1, 11-1, 3-1,
  127. 61-1, 53-1, 45-1, 37-1, 29-1, 21-1, 13-1, 5-1,
  128. 63-1, 55-1, 47-1, 39-1, 31-1, 23-1, 15-1, 7-1
  129. };
  130. // Final permutation FP = IP^(-1), page 10.
  131. // Transposed to 0-based format.
  132. private static byte [] fpBits = {
  133. 40-1, 8-1, 48-1, 16-1, 56-1, 24-1, 64-1, 32-1,
  134. 39-1, 7-1, 47-1, 15-1, 55-1, 23-1, 63-1, 31-1,
  135. 38-1, 6-1, 46-1, 14-1, 54-1, 22-1, 62-1, 30-1,
  136. 37-1, 5-1, 45-1, 13-1, 53-1, 21-1, 61-1, 29-1,
  137. 36-1, 4-1, 44-1, 12-1, 52-1, 20-1, 60-1, 28-1,
  138. 35-1, 3-1, 43-1, 11-1, 51-1, 19-1, 59-1, 27-1,
  139. 34-1, 2-1, 42-1, 10-1, 50-1, 18-1, 58-1, 26-1,
  140. 33-1, 1-1, 41-1, 9-1, 49-1, 17-1, 57-1, 25-1
  141. };
  142. private static uint [] spBoxes;
  143. private static int [] ipTab;
  144. private static int [] fpTab;
  145. static DESCore ()
  146. {
  147. spBoxes = new uint [64 * 8];
  148. int [] pBox = new int [32];
  149. for (int p = 0; p < 32; p++) {
  150. for (int i = 0; i < 32; i++) {
  151. if (p == pTab [i]) {
  152. pBox [p] = i;
  153. break;
  154. }
  155. }
  156. }
  157. for (int s = 0; s < 8; s++) { // for each S-box
  158. int sOff = s << 6;
  159. for (int i = 0; i < 64; i++) { // inputs
  160. uint sp=0;
  161. int indx = (i & 0x20) | ((i & 1) << 4) | ((i >> 1) & 0xF);
  162. for (int j = 0; j < 4; j++) { // for each bit in the output
  163. if ((sBoxes [sOff + indx] & (8 >> j)) != 0) {
  164. sp |= (uint) (1 << (31 - pBox [(s << 2) + j]));
  165. }
  166. }
  167. spBoxes [sOff + i] = sp;
  168. }
  169. }
  170. leftRotTotal = new byte [leftRot.Length];
  171. for (int i = 0; i < leftRot.Length; i++) {
  172. int r = 0;
  173. for (int j = 0; j <= i; r += leftRot [j++]);
  174. leftRotTotal [i] = (byte) r;
  175. }
  176. InitPermutationTable (ipBits, out ipTab);
  177. InitPermutationTable (fpBits, out fpTab);
  178. } // class constructor
  179. // Default constructor.
  180. internal DESCore ()
  181. {
  182. keySchedule = new byte [KEY_BYTE_SIZE * 16];
  183. byteBuff = new byte [BLOCK_BYTE_SIZE];
  184. dwordBuff = new uint [BLOCK_BYTE_SIZE / 4];
  185. }
  186. private static void InitPermutationTable (byte [] pBits, out int [] permTab)
  187. {
  188. permTab = new int [8*2 * 8*2 * (64/32)];
  189. for (int i = 0; i < 16; i++) {
  190. for (int j = 0; j < 16; j++) {
  191. int offs = (i << 5) + (j << 1);
  192. for (int n = 0; n < 64; n++) {
  193. int bitNum = (int) pBits [n];
  194. if ((bitNum >> 2 == i) &&
  195. 0 != (j & (8 >> (bitNum & 3)))) {
  196. permTab [offs + (n >> (3+2))] |= (int) ((0x80808080 & (0xFF << (n & (3 << 3)))) >> (n & 7));
  197. }
  198. }
  199. }
  200. }
  201. }
  202. internal static ulong PackKey (byte [] key)
  203. {
  204. ulong res = 0;
  205. for (int i = 0, sh = 8*KEY_BYTE_SIZE; (sh = sh - 8) >= 0; i++) {
  206. res |= (ulong) key [i] << sh;
  207. }
  208. return res;
  209. }
  210. internal static byte [] UnpackKey (ulong key)
  211. {
  212. byte [] res = new byte [KEY_BYTE_SIZE];
  213. for (int i = 0, sh = 8*KEY_BYTE_SIZE; (sh = sh - 8) >= 0; i++) {
  214. res [i] = (byte) (key >> sh);
  215. }
  216. return res;
  217. }
  218. internal static bool IsValidKeySize (byte [] key)
  219. {
  220. return (key.Length == KEY_BYTE_SIZE);
  221. }
  222. private uint CipherFunct(uint r, int n)
  223. {
  224. uint res = 0;
  225. byte [] subkey = keySchedule;
  226. int i = n << 3;
  227. uint rt = (r >> 1) | (r << 31); // ROR32(r)
  228. res |= spBoxes [0*64 + (((rt >> 26) ^ subkey [i++]) & 0x3F)];
  229. res |= spBoxes [1*64 + (((rt >> 22) ^ subkey [i++]) & 0x3F)];
  230. res |= spBoxes [2*64 + (((rt >> 18) ^ subkey [i++]) & 0x3F)];
  231. res |= spBoxes [3*64 + (((rt >> 14) ^ subkey [i++]) & 0x3F)];
  232. res |= spBoxes [4*64 + (((rt >> 10) ^ subkey [i++]) & 0x3F)];
  233. res |= spBoxes [5*64 + (((rt >> 6) ^ subkey [i++]) & 0x3F)];
  234. res |= spBoxes [6*64 + (((rt >> 2) ^ subkey [i++]) & 0x3F)];
  235. rt = (r << 1) | (r >> 31); // ROL32(r)
  236. res |= spBoxes [7*64 + ((rt ^ subkey [i]) & 0x3F)];
  237. return res;
  238. }
  239. private static void Permutation (byte [] input, byte [] _output, int [] permTab, bool preSwap)
  240. {
  241. if (preSwap) BSwap (input);
  242. byte [] output = _output;
  243. int offs1 = (((int)(input [0]) >> 4)) << 1;
  244. int offs2 = (1 << 5) + ((((int)input [0]) & 0xF) << 1);
  245. int d1 = permTab [offs1++] | permTab [offs2++];
  246. int d2 = permTab [offs1] | permTab [offs2];
  247. int max = BLOCK_BYTE_SIZE << 1;
  248. for (int i = 2, indx = 1; i < max; i += 2, indx++) {
  249. int ii = (int) input [indx];
  250. offs1 = (i << 5) + ((ii >> 4) << 1);
  251. offs2 = ((i + 1) << 5) + ((ii & 0xF) << 1);
  252. d1 |= permTab [offs1++] | permTab [offs2++];
  253. d2 |= permTab [offs1] | permTab [offs2];
  254. }
  255. if (preSwap) {
  256. output [0] = (byte) (d1);
  257. output [1] = (byte) (d1 >> 8);
  258. output [2] = (byte) (d1 >> 16);
  259. output [3] = (byte) (d1 >> 24);
  260. output [4] = (byte) (d2);
  261. output [5] = (byte) (d2 >> 8);
  262. output [6] = (byte) (d2 >> 16);
  263. output [7] = (byte) (d2 >> 24);
  264. } else {
  265. output [0] = (byte) (d1 >> 24);
  266. output [1] = (byte) (d1 >> 16);
  267. output [2] = (byte) (d1 >> 8);
  268. output [3] = (byte) (d1);
  269. output [4] = (byte) (d2 >> 24);
  270. output [5] = (byte) (d2 >> 16);
  271. output [6] = (byte) (d2 >> 8);
  272. output [7] = (byte) (d2);
  273. }
  274. }
  275. private static void BSwap (byte [] byteBuff)
  276. {
  277. byte t;
  278. t = byteBuff [0];
  279. byteBuff [0] = byteBuff [3];
  280. byteBuff [3] = t;
  281. t = byteBuff [1];
  282. byteBuff [1] = byteBuff [2];
  283. byteBuff [2] = t;
  284. t = byteBuff [4];
  285. byteBuff [4] = byteBuff [7];
  286. byteBuff [7] = t;
  287. t = byteBuff [5];
  288. byteBuff [5] = byteBuff [6];
  289. byteBuff [6] = t;
  290. }
  291. internal void SetKey (byte [] key)
  292. {
  293. // NOTE: see Fig. 3, Key schedule calculation, at page 20.
  294. Array.Clear (keySchedule, 0, keySchedule.Length);
  295. int keyBitSize = PC1.Length;
  296. byte [] keyPC1 = new byte [keyBitSize]; // PC1-permuted key
  297. byte [] keyRot = new byte [keyBitSize]; // PC1 & rotated
  298. int indx = 0;
  299. foreach (byte bitPos in PC1) {
  300. keyPC1 [indx++] = (byte)((key [(int)bitPos >> 3] >> (7 ^ (bitPos & 7))) & 1);
  301. }
  302. int j;
  303. for (int i = 0; i < KEY_BYTE_SIZE*2; i++) {
  304. int b = keyBitSize >> 1;
  305. for (j = 0; j < b; j++) {
  306. int s = j + (int) leftRotTotal [i];
  307. keyRot [j] = keyPC1 [s < b ? s : s - b];
  308. }
  309. for (j = b; j < keyBitSize; j++) {
  310. int s = j + (int) leftRotTotal [i];
  311. keyRot [j] = keyPC1 [s < keyBitSize ? s : s - b];
  312. }
  313. int keyOffs = i * KEY_BYTE_SIZE;
  314. j = 0;
  315. foreach (byte bitPos in PC2) {
  316. if (keyRot [(int)bitPos] != 0) {
  317. keySchedule [keyOffs + (j/6)] |= (byte) (0x80 >> ((j % 6) + 2));
  318. }
  319. j++;
  320. }
  321. }
  322. }
  323. internal void Encrypt (byte [] block, byte [] output)
  324. {
  325. byte [] dest = (output == null ? block : output);
  326. byte [] byteBuff = this.byteBuff;
  327. uint [] dwordBuff = this.dwordBuff;
  328. Permutation (block, byteBuff, ipTab, false);
  329. Buffer.BlockCopy (byteBuff, 0, dwordBuff, 0, BLOCK_BYTE_SIZE);
  330. uint d0 = dwordBuff[0];
  331. uint d1 = dwordBuff[1];
  332. // 16 rounds
  333. d0 ^= CipherFunct (d1, 0);
  334. d1 ^= CipherFunct (d0, 1);
  335. d0 ^= CipherFunct (d1, 2);
  336. d1 ^= CipherFunct (d0, 3);
  337. d0 ^= CipherFunct (d1, 4);
  338. d1 ^= CipherFunct (d0, 5);
  339. d0 ^= CipherFunct (d1, 6);
  340. d1 ^= CipherFunct (d0, 7);
  341. d0 ^= CipherFunct (d1, 8);
  342. d1 ^= CipherFunct (d0, 9);
  343. d0 ^= CipherFunct (d1, 10);
  344. d1 ^= CipherFunct (d0, 11);
  345. d0 ^= CipherFunct (d1, 12);
  346. d1 ^= CipherFunct (d0, 13);
  347. d0 ^= CipherFunct (d1, 14);
  348. d1 ^= CipherFunct (d0, 15);
  349. dwordBuff [0] = d1;
  350. dwordBuff [1] = d0;
  351. Buffer.BlockCopy (dwordBuff, 0, byteBuff, 0, BLOCK_BYTE_SIZE);
  352. Permutation (byteBuff, dest, fpTab, true);
  353. }
  354. internal void Decrypt (byte [] block, byte [] output)
  355. {
  356. byte [] dest = (output == null ? block : output);
  357. byte [] byteBuff = this.byteBuff;
  358. uint [] dwordBuff = this.dwordBuff;
  359. Permutation (block, byteBuff, ipTab, false);
  360. Buffer.BlockCopy (byteBuff, 0, dwordBuff, 0, BLOCK_BYTE_SIZE);
  361. uint d1 = dwordBuff [0];
  362. uint d0 = dwordBuff [1];
  363. // 16 rounds in reverse order
  364. d1 ^= CipherFunct (d0, 15);
  365. d0 ^= CipherFunct (d1, 14);
  366. d1 ^= CipherFunct (d0, 13);
  367. d0 ^= CipherFunct (d1, 12);
  368. d1 ^= CipherFunct (d0, 11);
  369. d0 ^= CipherFunct (d1, 10);
  370. d1 ^= CipherFunct (d0, 9);
  371. d0 ^= CipherFunct (d1, 8);
  372. d1 ^= CipherFunct (d0, 7);
  373. d0 ^= CipherFunct (d1, 6);
  374. d1 ^= CipherFunct (d0, 5);
  375. d0 ^= CipherFunct (d1, 4);
  376. d1 ^= CipherFunct (d0, 3);
  377. d0 ^= CipherFunct (d1, 2);
  378. d1 ^= CipherFunct (d0, 1);
  379. d0 ^= CipherFunct (d1, 0);
  380. dwordBuff [0] = d0;
  381. dwordBuff [1] = d1;
  382. Buffer.BlockCopy (dwordBuff, 0, byteBuff, 0, BLOCK_BYTE_SIZE);
  383. Permutation (byteBuff, dest, fpTab, true);
  384. }
  385. } // DESCore
  386. public abstract class DES : SymmetricAlgorithm {
  387. private byte [] key;
  388. public DES ()
  389. {
  390. }
  391. public static new DES Create()
  392. {
  393. // TODO: implement
  394. return null;
  395. }
  396. public static new DES Create(string name)
  397. {
  398. // TODO: implement
  399. return null;
  400. }
  401. public static bool IsWeakKey (byte [] rgbKey)
  402. {
  403. if (!DESCore.IsValidKeySize (rgbKey)) {
  404. throw new CryptographicException ();
  405. }
  406. ulong lk = DESCore.PackKey (rgbKey);
  407. foreach (ulong wk in DESCore.weakKeys) {
  408. if (lk == wk) return true;
  409. }
  410. return false;
  411. }
  412. public static bool IsSemiWeakKey (byte [] rgbKey)
  413. {
  414. if (!DESCore.IsValidKeySize (rgbKey)) {
  415. throw new CryptographicException ();
  416. }
  417. ulong lk = DESCore.PackKey (rgbKey);
  418. foreach (ulong swk in DESCore.semiweakKeys) {
  419. if (lk == swk) return true;
  420. }
  421. return false;
  422. }
  423. public override byte[] Key {
  424. get {
  425. return this.key;
  426. }
  427. set {
  428. this.key = new byte [DESCore.KEY_BYTE_SIZE];
  429. Array.Copy (value, 0, this.key, 0, DESCore.KEY_BYTE_SIZE);
  430. }
  431. }
  432. } // DES
  433. } // System.Security.Cryptography