2005-01-06 Sebastien Pouliot <sebastien@ximian.com>
[mono.git] / mcs / class / corlib / System.Security.Cryptography / DES.cs
index b6a833564203a18c845ea84d6ce59a41b951948a..e0b7cd102b252be8468fcc652a2c2589db6bdfa7 100644 (file)
 // System.Security.Cryptography.DES
 //
 // Author:
-//   Sergey Chaban (serge@wildwestsoftware.com)
+//     Sergey Chaban (serge@wildwestsoftware.com)
+//     Sebastien Pouliot <sebastien@ximian.com>
+//
+// Portions (C) 2002 Motus Technologies Inc. (http://www.motus.com)
+// Copyright (C) 2004-2005 Novell, Inc (http://www.novell.com)
+//
+// Permission is hereby granted, free of charge, to any person obtaining
+// a copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to
+// permit persons to whom the Software is furnished to do so, subject to
+// the following conditions:
+// 
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+// 
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 //
 
-using System;
-using System.Security.Cryptography;
+using System.Globalization;
 
-// References: FIPS PUB 46-3
+// References:
+// a.  FIPS PUB 46-3: Data Encryption Standard
+//     http://csrc.nist.gov/publications/fips/fips46-3/fips46-3.pdf
 
 namespace System.Security.Cryptography {
 
-       internal sealed class DESCore {
-
-               internal static readonly int KEY_BIT_SIZE = 64;
-               internal static readonly int KEY_BYTE_SIZE = KEY_BIT_SIZE / 8;
-               internal static readonly int BLOCK_BIT_SIZE = 64;
-               internal static readonly int BLOCK_BYTE_SIZE = BLOCK_BIT_SIZE / 8;
-
-               private byte [] keySchedule;
-               private byte [] byteBuff;
-               private uint [] dwordBuff;
-
-               internal delegate void DESCall (byte [] block, byte [] output);
-
-
-               // Ek(Ek(m)) = m
-               internal static ulong [] weakKeys = {
-                       0x0101010101010101, /* 0000000 0000000 */
-                       0xFEFEFEFEFEFEFEFE, /* FFFFFFF FFFFFFF */
-                       0x1F1F1F1FE0E0E0E0, /* 0000000 FFFFFFF */
-                       0xE0E0E0E01F1F1F1F  /* FFFFFFF 0000000 */
-               };
-
-               // Ek1(Ek2(m)) = m
-               internal static ulong [] semiweakKeys = {
-                       0x01FE01FE01FE01FE, 0xFE01FE01FE01FE01,
-                       0x1FE01FE00EF10EF1, 0xE01FE01FF10EF10E,
-                       0x01E001E001F101F1, 0xE001E001F101F101,
-                       0x1FFE1FFE0EFE0EFE, 0xFE1FFE1FFE0EFE0E,
-                       0x011F011F010E010E, 0x1F011F010E010E01,
-                       0xE0FEE0FEF1FEF1FE, 0xFEE0FEE0FEF1FEF1
-               };
-
-
-
-               // S-boxes from FIPS 46-3, Appendix 1, page 17
-               private static byte [] sBoxes = {
-                                               /* S1 */
-                       14,  4, 13,  1,  2, 15, 11,  8,  3, 10,  6, 12,  5,  9,  0,  7,
-                        0, 15,  7,  4, 14,  2, 13,  1, 10,  6, 12, 11,  9,  5,  3,  8,
-                        4,  1, 14,  8, 13,  6,  2, 11, 15, 12,  9,  7,  3, 10,  5,  0,
-                       15, 12,  8,  2,  4,  9,  1,  7,  5, 11,  3, 14, 10,  0,  6, 13,
-
-                                               /* S2 */
-                       15,  1,  8, 14,  6, 11,  3,  4,  9,  7,  2, 13, 12,  0,  5, 10,
-                        3, 13,  4,  7, 15,  2,  8, 14, 12,  0,  1, 10,  6,  9, 11,  5,
-                        0, 14,  7, 11, 10,  4, 13,  1,  5,  8, 12,  6,  9,  3,  2, 15,
-                       13,  8, 10,  1,  3, 15,  4,  2, 11,  6,  7, 12,  0,  5, 14,  9,
-
-                                               /* S3 */
-                       10,  0,  9, 14,  6,  3, 15,  5,  1, 13, 12,  7, 11,  4,  2,  8,
-                       13,  7,  0,  9,  3,  4,  6, 10,  2,  8,  5, 14, 12, 11, 15,  1,
-                       13,  6,  4,  9,  8, 15,  3,  0, 11,  1,  2, 12,  5, 10, 14,  7,
-                        1, 10, 13,  0,  6,  9,  8,  7,  4, 15, 14,  3, 11,  5,  2, 12,
-
-                                               /* S4 */
-                        7, 13, 14,  3,  0,  6,  9, 10,  1,  2,  8,  5, 11, 12,  4, 15,
-                       13,  8, 11,  5,  6, 15,  0,  3,  4,  7,  2, 12,  1, 10, 14,  9,
-                       10,  6,  9,  0, 12, 11,  7, 13, 15,  1,  3, 14,  5,  2,  8,  4,
-                        3, 15,  0,  6, 10,  1, 13,  8,  9,  4,  5, 11, 12,  7,  2, 14,
-
-                                               /* S5 */
-                        2, 12,  4,  1,  7, 10, 11,  6,  8,  5,  3, 15, 13,  0, 14,  9,
-                       14, 11,  2, 12,  4,  7, 13,  1,  5,  0, 15, 10,  3,  9,  8,  6,
-                        4,  2,  1, 11, 10, 13,  7,  8, 15,  9, 12,  5,  6,  3,  0, 14,
-                       11,  8, 12,  7,  1, 14,  2, 13,  6, 15,  0,  9, 10,  4,  5,  3,
-
-                                               /* S6 */
-                       12,  1, 10, 15,  9,  2,  6,  8,  0, 13,  3,  4, 14,  7,  5, 11,
-                       10, 15,  4,  2,  7, 12,  9,  5,  6,  1, 13, 14,  0, 11,  3,  8,
-                        9, 14, 15,  5,  2,  8, 12,  3,  7,  0,  4, 10,  1, 13, 11,  6,
-                        4,  3,  2, 12,  9,  5, 15, 10, 11, 14,  1,  7,  6,  0,  8, 13,
-
-                                               /* S7 */
-                        4, 11,  2, 14, 15,  0,  8, 13,  3, 12,  9,  7,  5, 10,  6,  1,
-                       13,  0, 11,  7,  4,  9,  1, 10, 14,  3,  5, 12,  2, 15,  8,  6,
-                        1,  4, 11, 13, 12,  3,  7, 14, 10, 15,  6,  8,  0,  5,  9,  2,
-                        6, 11, 13,  8,  1,  4, 10,  7,  9,  5,  0, 15, 14,  2,  3, 12,
-
-                                               /* S8 */
-                       13,  2,  8,  4,  6, 15, 11,  1, 10,  9,  3, 14,  5,  0, 12,  7,
-                        1, 15, 13,  8, 10,  3,  7,  4, 12,  5,  6, 11,  0, 14,  9,  2,
-                        7, 11,  4,  1,  9, 12, 14,  2,  0,  6, 10, 13, 15,  3,  5,  8,
-                        2,  1, 14,  7,  4, 10,  8, 13, 15, 12,  9,  0,  3,  5,  6, 11
-               };
-
-
-               // P table from page 15, also in Appendix 1, page 18
-               private static byte [] pTab = { 
-                       16-1,  7-1, 20-1, 21-1,
-                       29-1, 12-1, 28-1, 17-1,
-                        1-1, 15-1, 23-1, 26-1,
-                        5-1, 18-1, 31-1, 10-1,
-                        2-1,  8-1, 24-1, 14-1,
-                       32-1, 27-1,  3-1,  9-1,
-                       19-1, 13-1, 30-1,  6-1,
-                       22-1, 11-1,  4-1, 25-1
-               };
-
-
-               // Permuted choice 1 table, PC-1, page 19
-               // Translated to zero-based format.
-               private static byte [] PC1 = {
-                       57-1, 49-1, 41-1, 33-1, 25-1, 17-1,  9-1,
-                        1-1, 58-1, 50-1, 42-1, 34-1, 26-1, 18-1,
-                       10-1,  2-1, 59-1, 51-1, 43-1, 35-1, 27-1,
-                       19-1, 11-1,  3-1, 60-1, 52-1, 44-1, 36-1,
-
-                       63-1, 55-1, 47-1, 39-1, 31-1, 23-1, 15-1,
-                        7-1, 62-1, 54-1, 46-1, 38-1, 30-1, 22-1,
-                       14-1,  6-1, 61-1, 53-1, 45-1, 37-1, 29-1,
-                       21-1, 13-1,  5-1, 28-1, 20-1, 12-1,  4-1
-               };
-
-
-               private static byte [] leftRot = {
-                       1, 1, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 1
-               };
-
-               private static byte [] leftRotTotal;
-
-
-
-               // Permuted choice 2 table, PC-2, page 21
-               // Translated to zero-based format.
-               private static byte [] PC2 = {
-                       14-1, 17-1, 11-1, 24-1,  1-1,  5-1,
-                        3-1, 28-1, 15-1,  6-1, 21-1, 10-1,
-                       23-1, 19-1, 12-1,  4-1, 26-1,  8-1,
-                       16-1,  7-1, 27-1, 20-1, 13-1,  2-1,
-                       41-1, 52-1, 31-1, 37-1, 47-1, 55-1,
-                       30-1, 40-1, 51-1, 45-1, 33-1, 48-1,
-                       44-1, 49-1, 39-1, 56-1, 34-1, 53-1,
-                       46-1, 42-1, 50-1, 36-1, 29-1, 32-1
-               };
-
-
-               // Initial permutation IP, page 10.
-               // Transposed to 0-based format.
-               private static byte [] ipBits = {
-                       58-1, 50-1, 42-1, 34-1, 26-1, 18-1, 10-1,  2-1,
-                       60-1, 52-1, 44-1, 36-1, 28-1, 20-1, 12-1,  4-1,
-                       62-1, 54-1, 46-1, 38-1, 30-1, 22-1, 14-1,  6-1,
-                       64-1, 56-1, 48-1, 40-1, 32-1, 24-1, 16-1,  8-1,
-                       57-1, 49-1, 41-1, 33-1, 25-1, 17-1,  9-1,  1-1,
-                       59-1, 51-1, 43-1, 35-1, 27-1, 19-1, 11-1,  3-1,
-                       61-1, 53-1, 45-1, 37-1, 29-1, 21-1, 13-1,  5-1,
-                       63-1, 55-1, 47-1, 39-1, 31-1, 23-1, 15-1,  7-1
-               };
-
-
-               // Final permutation FP = IP^(-1), page 10.
-               // Transposed to 0-based format.
-               private static byte [] fpBits = {
-                       40-1,  8-1, 48-1, 16-1, 56-1, 24-1, 64-1, 32-1,
-                       39-1,  7-1, 47-1, 15-1, 55-1, 23-1, 63-1, 31-1,
-                       38-1,  6-1, 46-1, 14-1, 54-1, 22-1, 62-1, 30-1,
-                       37-1,  5-1, 45-1, 13-1, 53-1, 21-1, 61-1, 29-1,
-                       36-1,  4-1, 44-1, 12-1, 52-1, 20-1, 60-1, 28-1,
-                       35-1,  3-1, 43-1, 11-1, 51-1, 19-1, 59-1, 27-1,
-                       34-1,  2-1, 42-1, 10-1, 50-1, 18-1, 58-1, 26-1,
-                       33-1,  1-1, 41-1,  9-1, 49-1, 17-1, 57-1, 25-1
-               };
-
-
-
-               private static uint [] spBoxes;
-               private static int [] ipTab;
-               private static int [] fpTab;
-
-
-               static DESCore ()
-               {
-                       spBoxes = new uint [64 * 8];
-
-                       int [] pBox = new int [32];
-
-                       for (int p = 0; p < 32; p++) {
-                               for (int i = 0; i < 32; i++) {
-                                       if (p == pTab [i]) {
-                                               pBox [p] = i;
-                                               break;
-                                       }
-                               }
-                       }
-
-
-                       for (int s = 0; s < 8; s++) { // for each S-box
-                               int sOff = s << 6;
-
-                               for (int i = 0; i < 64; i++) { // inputs
-                                       uint sp=0;
-
-                                       int indx = (i & 0x20) | ((i & 1) << 4) | ((i >> 1) & 0xF);
-
-                                       for (int j = 0; j < 4; j++) { // for each bit in the output
-                                               if ((sBoxes [sOff + indx] & (8 >> j)) != 0) {
-                                                       sp |= (uint) (1 << (31 - pBox [(s << 2) + j]));
-                                               }
-                                       }
-
-                                       spBoxes [sOff + i] = sp;
-                               }
-                       }
-
-
-                       leftRotTotal = new byte [leftRot.Length];
-
-
-                       for (int i = 0; i < leftRot.Length; i++) {
-                               int r = 0;
-                               for (int j = 0; j <= i; r += leftRot [j++]);
-                               leftRotTotal [i]  = (byte) r;
-                       }
-
-
-                       InitPermutationTable (ipBits, out ipTab);
-                       InitPermutationTable (fpBits, out fpTab);
-
-               } // class constructor
-
-
-
-               // Default constructor.
-               internal DESCore ()
-               {
-                       keySchedule = new byte [KEY_BYTE_SIZE * 16];
-                       byteBuff = new byte [BLOCK_BYTE_SIZE];
-                       dwordBuff = new uint [BLOCK_BYTE_SIZE / 4];
-               }
-
-
-
-
-               private static void InitPermutationTable (byte [] pBits, out int [] permTab)
-               {
-                       permTab = new int [8*2 * 8*2 * (64/32)];
-
-                       for (int i = 0; i < 16; i++) {
-                               for (int j = 0; j < 16; j++) {
-                                       int offs = (i << 5) + (j << 1);
-                                       for (int n = 0; n < 64; n++) {
-                                               int bitNum = (int) pBits [n];
-                                               if ((bitNum >> 2 == i) &&
-                                                   0 != (j & (8 >> (bitNum & 3)))) {
-                                                       permTab [offs + (n >> (3+2))] |= (int) ((0x80808080 & (0xFF << (n & (3 << 3)))) >> (n & 7));
-                                               }
-                                       }
-                               }
-                       }
-               }
-
-
-
-               internal static ulong PackKey (byte [] key)
-               {
-                       ulong res = 0;
-                       for (int i = 0, sh = 8*KEY_BYTE_SIZE; (sh = sh - 8) >= 0; i++) {
-                               res |= (ulong) key [i] << sh;
-                       }
-                       return res;
-               }
-
-
-
-               internal static byte [] UnpackKey (ulong key)
-               {
-                       byte [] res = new byte [KEY_BYTE_SIZE];
-                       for (int i = 0, sh = 8*KEY_BYTE_SIZE; (sh = sh - 8) >= 0; i++) {
-                               res [i] = (byte) (key >> sh);
-                       }
-                       return res;
-               }
-
-
-
-               internal static bool IsValidKeySize (byte [] key)
-               {
-                       return (key.Length == KEY_BYTE_SIZE);
-               }
-
-
-
-               private uint CipherFunct(uint r, int n)
-               {
-                       uint res = 0;
-                       byte [] subkey = keySchedule;
-                       int i = n << 3;
-
-                       uint rt = (r >> 1) | (r << 31); // ROR32(r)
-                       res |= spBoxes [0*64 + (((rt >> 26) ^ subkey [i++]) & 0x3F)];
-                       res |= spBoxes [1*64 + (((rt >> 22) ^ subkey [i++]) & 0x3F)];
-                       res |= spBoxes [2*64 + (((rt >> 18) ^ subkey [i++]) & 0x3F)];
-                       res |= spBoxes [3*64 + (((rt >> 14) ^ subkey [i++]) & 0x3F)];
-                       res |= spBoxes [4*64 + (((rt >> 10) ^ subkey [i++]) & 0x3F)];
-                       res |= spBoxes [5*64 + (((rt >>  6) ^ subkey [i++]) & 0x3F)];
-                       res |= spBoxes [6*64 + (((rt >>  2) ^ subkey [i++]) & 0x3F)];
-                       rt = (r << 1) | (r >> 31); // ROL32(r)
-                       res |= spBoxes [7*64 + ((rt ^ subkey [i]) & 0x3F)];
-
-                       return res;
-               }
-
-
-               private static void Permutation (byte [] input, byte [] _output, int [] permTab, bool preSwap)
-               {
-
-                       if (preSwap) BSwap (input);
-
-                       byte [] output = _output;
-
-                       int offs1 = (((int)(input [0]) >> 4)) << 1;
-                       int offs2 = (1 << 5) + ((((int)input [0]) & 0xF) << 1);
-
-                       int d1 = permTab [offs1++] | permTab [offs2++];
-                       int d2 = permTab [offs1]   | permTab [offs2];
-
-
-                       int max = BLOCK_BYTE_SIZE << 1;
-                       for (int i = 2, indx = 1; i < max; i += 2, indx++) {
-                               int ii = (int) input [indx];
-                               offs1 = (i << 5) + ((ii >> 4) << 1);
-                               offs2 = ((i + 1) << 5) + ((ii & 0xF) << 1);
-
-                               d1 |= permTab [offs1++] | permTab [offs2++];
-                               d2 |= permTab [offs1]   | permTab [offs2];
-                       }
-
-                       if (preSwap) {
-                               output [0] = (byte) (d1);
-                               output [1] = (byte) (d1 >> 8);
-                               output [2] = (byte) (d1 >> 16);
-                               output [3] = (byte) (d1 >> 24);
-                               output [4] = (byte) (d2);
-                               output [5] = (byte) (d2 >> 8);
-                               output [6] = (byte) (d2 >> 16);
-                               output [7] = (byte) (d2 >> 24);
-                       } else {
-                               output [0] = (byte) (d1 >> 24);
-                               output [1] = (byte) (d1 >> 16);
-                               output [2] = (byte) (d1 >> 8);
-                               output [3] = (byte) (d1);
-                               output [4] = (byte) (d2 >> 24);
-                               output [5] = (byte) (d2 >> 16);
-                               output [6] = (byte) (d2 >> 8);
-                               output [7] = (byte) (d2);
-                       }
-               }
-
-
-
-
-               private static void BSwap (byte [] byteBuff)
-               {
-                       byte t;
-
-                       t = byteBuff [0];
-                       byteBuff [0] = byteBuff [3];
-                       byteBuff [3] = t;
-
-                       t = byteBuff [1];
-                       byteBuff [1] = byteBuff [2];
-                       byteBuff [2] = t;
-
-                       t = byteBuff [4];
-                       byteBuff [4] = byteBuff [7];
-                       byteBuff [7] = t;
-
-                       t = byteBuff [5];
-                       byteBuff [5] = byteBuff [6];
-                       byteBuff [6] = t;
-               }
-
-
-
-               internal void SetKey (byte [] key)
-               {
-                       // NOTE: see Fig. 3, Key schedule calculation, at page 20.
-
-                       Array.Clear (keySchedule, 0, keySchedule.Length);
-
-                       int keyBitSize = PC1.Length;
-
-                       byte [] keyPC1 = new byte [keyBitSize]; // PC1-permuted key
-                       byte [] keyRot = new byte [keyBitSize]; // PC1 & rotated
-
-                       int indx = 0;
-
-                       foreach (byte bitPos in PC1) {
-                               keyPC1 [indx++] = (byte)((key [(int)bitPos >> 3] >> (7 ^ (bitPos & 7))) & 1);
-                       }
-
-
-
-
-                       int j;
-                       for (int i = 0; i < KEY_BYTE_SIZE*2; i++) {
-                               int b = keyBitSize >> 1;
-
-                               for (j = 0; j < b; j++) {
-                                       int s = j + (int) leftRotTotal [i];
-                                       keyRot [j] = keyPC1 [s < b ? s : s - b];
-                               }
-
-                               for (j = b; j < keyBitSize; j++) {
-                                       int s = j + (int) leftRotTotal [i];
-                                       keyRot [j] = keyPC1 [s < keyBitSize ? s : s - b];
-                               }
-
-                               int keyOffs = i * KEY_BYTE_SIZE;
-
-                               j = 0;
-                               foreach (byte bitPos in PC2) {
-                                       if (keyRot [(int)bitPos] != 0) {
-                                               keySchedule [keyOffs + (j/6)] |= (byte) (0x80 >> ((j % 6) + 2));
-                                       }
-                                       j++;
-                               }
-                       }
-
-               }
-
-
-
-               internal void Encrypt (byte [] block, byte [] output)
-               {
-                       byte [] dest = (output == null ? block : output);
-
-                       byte [] byteBuff = this.byteBuff;
-                       uint [] dwordBuff = this.dwordBuff;
-
-                       Permutation (block, byteBuff, ipTab, false);
-
-                       Buffer.BlockCopy (byteBuff, 0, dwordBuff, 0, BLOCK_BYTE_SIZE);
-
-                       uint d0 = dwordBuff[0];
-                       uint d1 = dwordBuff[1];
-
-                       // 16 rounds
-                       d0 ^= CipherFunct (d1,  0);
-                       d1 ^= CipherFunct (d0,  1);
-                       d0 ^= CipherFunct (d1,  2);
-                       d1 ^= CipherFunct (d0,  3);
-                       d0 ^= CipherFunct (d1,  4);
-                       d1 ^= CipherFunct (d0,  5);
-                       d0 ^= CipherFunct (d1,  6);
-                       d1 ^= CipherFunct (d0,  7);
-                       d0 ^= CipherFunct (d1,  8);
-                       d1 ^= CipherFunct (d0,  9);
-                       d0 ^= CipherFunct (d1, 10);
-                       d1 ^= CipherFunct (d0, 11);
-                       d0 ^= CipherFunct (d1, 12);
-                       d1 ^= CipherFunct (d0, 13);
-                       d0 ^= CipherFunct (d1, 14);
-                       d1 ^= CipherFunct (d0, 15);
-
-
-                       dwordBuff [0] = d1;
-                       dwordBuff [1] = d0;
-                       Buffer.BlockCopy (dwordBuff, 0, byteBuff, 0, BLOCK_BYTE_SIZE);
-
-                       Permutation (byteBuff, dest, fpTab, true);
-               }
-
-
-               internal void Decrypt (byte [] block, byte [] output)
-               {
-                       byte [] dest = (output == null ? block : output);
-
-                       byte [] byteBuff = this.byteBuff;
-                       uint [] dwordBuff = this.dwordBuff;
-
-                       Permutation (block, byteBuff, ipTab, false);
-
-                       Buffer.BlockCopy (byteBuff, 0, dwordBuff, 0, BLOCK_BYTE_SIZE);
-
-                       uint d1 = dwordBuff [0];
-                       uint d0 = dwordBuff [1];
-
-                       // 16 rounds in reverse order
-                       d1 ^= CipherFunct (d0, 15);
-                       d0 ^= CipherFunct (d1, 14);
-                       d1 ^= CipherFunct (d0, 13);
-                       d0 ^= CipherFunct (d1, 12);
-                       d1 ^= CipherFunct (d0, 11);
-                       d0 ^= CipherFunct (d1, 10);
-                       d1 ^= CipherFunct (d0,  9);
-                       d0 ^= CipherFunct (d1,  8);
-                       d1 ^= CipherFunct (d0,  7);
-                       d0 ^= CipherFunct (d1,  6);
-                       d1 ^= CipherFunct (d0,  5);
-                       d0 ^= CipherFunct (d1,  4);
-                       d1 ^= CipherFunct (d0,  3);
-                       d0 ^= CipherFunct (d1,  2);
-                       d1 ^= CipherFunct (d0,  1);
-                       d0 ^= CipherFunct (d1,  0);
-
-                       dwordBuff [0] = d0;
-                       dwordBuff [1] = d1;
-
-
-                       Buffer.BlockCopy (dwordBuff, 0, byteBuff, 0, BLOCK_BYTE_SIZE);
-
-                       Permutation (byteBuff, dest, fpTab, true);
-               }
-
-
-       } // DESCore
-
-
-
-
-       public abstract class DES : SymmetricAlgorithm {
-               private byte [] key;
-
-               public DES ()
-               {
-               }
-
-               public static new DES Create()
-               {
-                       // TODO: implement
-                       return null;
-               }
-
-               public static new DES Create(string name)
-               {
-                       // TODO: implement
-                       return null;
-               }
-
-
-               public static bool IsWeakKey (byte [] rgbKey)
-               {
-                       if (!DESCore.IsValidKeySize (rgbKey)) {
-                               throw new CryptographicException ();
-                       }
-
-                       ulong lk = DESCore.PackKey (rgbKey);
-                       foreach (ulong wk in DESCore.weakKeys) {
-                               if (lk == wk) return true;
-                       }
-                       return false;
-               }
-
-
-               public static bool IsSemiWeakKey (byte [] rgbKey)
-               {
-                       if (!DESCore.IsValidKeySize (rgbKey)) {
-                               throw new CryptographicException ();
-                       }
-
-                       ulong lk = DESCore.PackKey (rgbKey);
-                       foreach (ulong swk in DESCore.semiweakKeys) {
-                               if (lk == swk) return true;
-                       }
-                       return false;
-               }
-
-               public override byte[] Key {
-                       get {
-                               return this.key;
-                       }
-                       set {
-                               this.key = new byte [DESCore.KEY_BYTE_SIZE];
-                               Array.Copy (value, 0, this.key, 0, DESCore.KEY_BYTE_SIZE);
-                       }
-               }
-
-       } // DES
-
-} // System.Security.Cryptography
+public abstract class DES : SymmetricAlgorithm {
+
+       private const int keySizeByte = 8;
+
+       public DES ()
+       {
+               KeySizeValue = 64; 
+               BlockSizeValue = 64; 
+               FeedbackSizeValue = 8;
+
+               LegalKeySizesValue = new KeySizes[1];
+               LegalKeySizesValue[0] = new KeySizes(64, 64, 0);
+
+               LegalBlockSizesValue = new KeySizes[1];
+               LegalBlockSizesValue[0] = new KeySizes(64, 64, 0);
+       }
+
+       public static new DES Create () 
+       {
+               return Create ("System.Security.Cryptography.DES");
+       }
+
+       public static new DES Create (string algo) 
+        {
+               return (DES) CryptoConfig.CreateFromName (algo);
+       }
+
+
+       // Ek(Ek(m)) = m
+       internal static readonly byte[,] weakKeys = {
+               { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 },
+               { 0x1F, 0x1F, 0x1F, 0x1F, 0x0F, 0x0F, 0x0F, 0x0F },
+               { 0xE1, 0xE1, 0xE1, 0xE1, 0xF1, 0xF1, 0xF1, 0xF1 },
+               { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF },
+       };
+
+       // Ek1(Ek2(m)) = m
+       internal static readonly byte[,] semiWeakKeys = {
+               { 0x00, 0x1E, 0x00, 0x1E, 0x00, 0x0E, 0x00, 0x0E }, // map to packed key 011F011F010E010E\r
+               { 0x00, 0xE0, 0x00, 0xE0, 0x00, 0xF0, 0x00, 0xF0 }, // map to packed key 01E001E001F101F1\r
+               { 0x00, 0xFE, 0x00, 0xFE, 0x00, 0xFE, 0x00, 0xFE }, // map to packed key 01FE01FE01FE01FE\r
+               { 0x1E, 0x00, 0x1E, 0x00, 0x0E, 0x00, 0x0E, 0x00 }, // map to packed key 1F011F010E010E01\r
+               { 0x1E, 0xE0, 0x1E, 0xE0, 0x0E, 0xF0, 0x0E, 0xF0 }, // map to packed key 1FE01FE00EF10EF1\r
+               { 0x1E, 0xFE, 0x1E, 0xFE, 0x0E, 0xFE, 0x0E, 0xFE }, // map to packed key 1FFE1FFE0EFE0EFE\r
+               { 0xE0, 0x00, 0xE0, 0x00, 0xF0, 0x00, 0xF0, 0x00 }, // map to packed key E001E001F101F101\r
+               { 0xE0, 0x1E, 0xE0, 0x1E, 0xF0, 0x0E, 0xF0, 0x0E }, // map to packed key E01FE01FF10EF10E\r
+               { 0xE0, 0xFE, 0xE0, 0xFE, 0xF0, 0xFE, 0xF0, 0xFE }, // map to packed key E0FEE0FEF1FEF1FE\r
+               { 0xFE, 0x00, 0xFE, 0x00, 0xFE, 0x00, 0xFE, 0x00 }, // map to packed key FE01FE01FE01FE01\r
+               { 0xFE, 0x1E, 0xFE, 0x1E, 0xFE, 0x0E, 0xFE, 0x0E }, // map to packed key FE1FFE1FFE0EFE0E\r
+               { 0xFE, 0xE0, 0xFE, 0xE0, 0xFE, 0xF0, 0xFE, 0xF0 }, // map to packed key FEE0FEE0FEF1FEF1\r
+       };\r
+
+       public static bool IsWeakKey (byte[] rgbKey) 
+       {
+               if (rgbKey.Length != keySizeByte)
+                       throw new CryptographicException (Locale.GetText ("Wrong Key Length"));
+
+               // (fast) pre-check with "weak bytes"
+               for (int i=0; i < rgbKey.Length; i++) {
+                       switch (rgbKey [i] | 0x11) {
+                               case 0x11:
+                               case 0x1F:
+                               case 0xF1:
+                               case 0xFF:
+                                       break;
+                               default:
+                                       return false;
+                       }
+               }
+
+               // compare with known weak keys
+               for (int i=0; i < (weakKeys.Length >> 3); i++) {
+                       int j = 0;
+                       for (; j < rgbKey.Length; j++) {
+                               if ((rgbKey [j] ^ weakKeys [i,j]) > 1)
+                                       break;
+                       }
+                       if (j==8)
+                               return true;
+               }
+               return false;
+       }
+
+       public static bool IsSemiWeakKey (byte[] rgbKey)
+       {
+               if (rgbKey.Length != keySizeByte)
+                       throw new CryptographicException (Locale.GetText ("Wrong Key Length"));
+
+               // (fast) pre-check with "weak bytes"
+               for (int i=0; i < rgbKey.Length; i++) {
+                       switch (rgbKey [i] | 0x11) {
+                               case 0x11:
+                               case 0x1F:
+                               case 0xF1:
+                               case 0xFF:
+                                       break;
+                               default:
+                                       return false;
+                       }
+               }
+
+               // compare with known weak keys
+               for (int i=0; i < (semiWeakKeys.Length >> 3); i++) {
+                       int j = 0;
+                       for (; j < rgbKey.Length; j++) {
+                               if ((rgbKey [j] ^ semiWeakKeys [i,j]) > 1)
+                                       break;
+                       }
+                       if (j==8)
+                               return true;
+               }
+               return false;
+       }
+
+       public override byte[] Key {
+               get {
+                       if (KeyValue == null) {
+                               // GenerateKey is responsible to return a valid key
+                               // e.g. no weak or semi-weak keys
+                               GenerateKey ();
+                       }
+                       return (byte[]) KeyValue.Clone ();
+               }
+               set {
+                       if (value == null)
+                               throw new ArgumentNullException ("Key");
+                       if (value.Length != keySizeByte)
+                               throw new ArgumentException (Locale.GetText ("Wrong Key Length"));
+                       if (IsWeakKey (value))
+                               throw new CryptographicException (Locale.GetText ("Weak Key"));
+                       if (IsSemiWeakKey (value))
+                               throw new CryptographicException (Locale.GetText ("Semi Weak Key"));
+
+                       KeyValue = (byte[]) value.Clone ();
+               }
+       }
+}
+
+}