Bladeren bron

Initial check-in.

svn path=/trunk/mcs/; revision=446
Sergey Chaban 24 jaren geleden
bovenliggende
commit
e14e65df25
1 gewijzigde bestanden met toevoegingen van 593 en 0 verwijderingen
  1. 593 0
      mcs/class/corlib/System.Security.Cryptography/DES.cs

+ 593 - 0
mcs/class/corlib/System.Security.Cryptography/DES.cs

@@ -0,0 +1,593 @@
+//
+// System.Security.Cryptography.DES
+//
+// Author:
+//   Sergey Chaban ([email protected])
+//
+
+using System;
+using System.Security.Cryptography;
+
+// References: FIPS PUB 46-3
+
+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 byte [] ipTab;
+		private static byte [] 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 byte [] permTab)
+		{
+			permTab = new byte [8*2 * 8*2 * (64/8)];
+
+			for (int i = 0; i < 16; i++) {
+				for (int j = 0; j < 16; j++) {
+					int offs = (i << 7) + (j << 3);
+					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)] |= (byte) (0x80 >> (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, byte [] permTab)
+		{
+			Array.Clear (output, 0, BLOCK_BYTE_SIZE);
+
+			for (int i = 0, indx = 0; i < BLOCK_BYTE_SIZE*2; i += 2, indx++) {
+				int offs1 = (i << 7) + ((((int)(input [indx]) >> 4)) << 3);
+				int offs2 = ((i + 1) << 7) + ((((int)input [indx]) & 0xF) << 3);
+
+				for (int j = 0; j < 8; j++) {
+					output [j] |= (byte) (permTab [offs1++] | permTab [offs2++]);
+				}
+			}
+		}
+		*/
+
+		private static void Permutation (byte [] input, byte [] _output, byte [] permTab)
+		{
+			byte [] output = _output;
+			Array.Clear (output, 0, BLOCK_BYTE_SIZE);
+
+			int offs1 = (((int)(input [0]) >> 4)) << 3;
+			int offs2 = (1 << 7) + ((((int)input [0]) & 0xF) << 3);
+
+			output [0] |= (byte) (permTab [offs1++] | permTab [offs2++]);
+			output [1] |= (byte) (permTab [offs1++] | permTab [offs2++]);
+			output [2] |= (byte) (permTab [offs1++] | permTab [offs2++]);
+			output [3] |= (byte) (permTab [offs1++] | permTab [offs2++]);
+			output [4] |= (byte) (permTab [offs1++] | permTab [offs2++]);
+			output [5] |= (byte) (permTab [offs1++] | permTab [offs2++]);
+			output [6] |= (byte) (permTab [offs1++] | permTab [offs2++]);
+			output [7] |= (byte) (permTab [offs1]   | permTab [offs2]);
+
+			for (int i = 2, indx = 1; i < BLOCK_BYTE_SIZE*2; i += 2, indx++) {
+				offs1 = (i << 7) + ((((int)(input [indx]) >> 4)) << 3);
+				offs2 = ((i + 1) << 7) + ((((int)input [indx]) & 0xF) << 3);
+
+				output [0] |= (byte) (permTab [offs1++] | permTab [offs2++]);
+				output [1] |= (byte) (permTab [offs1++] | permTab [offs2++]);
+				output [2] |= (byte) (permTab [offs1++] | permTab [offs2++]);
+				output [3] |= (byte) (permTab [offs1++] | permTab [offs2++]);
+				output [4] |= (byte) (permTab [offs1++] | permTab [offs2++]);
+				output [5] |= (byte) (permTab [offs1++] | permTab [offs2++]);
+				output [6] |= (byte) (permTab [offs1++] | permTab [offs2++]);
+				output [7] |= (byte) (permTab [offs1]   | permTab [offs2]);
+			}
+		}
+
+
+
+
+		private void BSwap ()
+		{
+			byte t;
+
+			// byte [] byteBuff = this.byteBuff;
+
+			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);
+
+
+			BSwap ();
+			Buffer.BlockCopy (byteBuff, 0, dwordBuff, 0, BLOCK_BYTE_SIZE);
+
+			// 16 rounds
+			dwordBuff[0] ^= CipherFunct (dwordBuff [1],  0);
+			dwordBuff[1] ^= CipherFunct (dwordBuff [0],  1);
+			dwordBuff[0] ^= CipherFunct (dwordBuff [1],  2);
+			dwordBuff[1] ^= CipherFunct (dwordBuff [0],  3);
+			dwordBuff[0] ^= CipherFunct (dwordBuff [1],  4);
+			dwordBuff[1] ^= CipherFunct (dwordBuff [0],  5);
+			dwordBuff[0] ^= CipherFunct (dwordBuff [1],  6);
+			dwordBuff[1] ^= CipherFunct (dwordBuff [0],  7);
+			dwordBuff[0] ^= CipherFunct (dwordBuff [1],  8);
+			dwordBuff[1] ^= CipherFunct (dwordBuff [0],  9);
+			dwordBuff[0] ^= CipherFunct (dwordBuff [1], 10);
+			dwordBuff[1] ^= CipherFunct (dwordBuff [0], 11);
+			dwordBuff[0] ^= CipherFunct (dwordBuff [1], 12);
+			dwordBuff[1] ^= CipherFunct (dwordBuff [0], 13);
+			dwordBuff[0] ^= CipherFunct (dwordBuff [1], 14);
+			dwordBuff[1] ^= CipherFunct (dwordBuff [0], 15);
+
+
+			uint t = dwordBuff [0];
+			dwordBuff [0] = dwordBuff [1];
+			dwordBuff [1] = t;
+			Buffer.BlockCopy (dwordBuff, 0, byteBuff, 0, BLOCK_BYTE_SIZE);
+			BSwap();
+
+			Permutation (byteBuff, dest, fpTab);
+		}
+
+
+		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);
+
+			BSwap ();
+			Buffer.BlockCopy (byteBuff, 0, dwordBuff, 0, BLOCK_BYTE_SIZE);
+
+			uint t = dwordBuff [0];
+			dwordBuff [0] = dwordBuff [1];
+			dwordBuff [1] = t;
+
+			// 16 rounds in reverse order
+			dwordBuff[1] ^= CipherFunct (dwordBuff [0], 15);
+			dwordBuff[0] ^= CipherFunct (dwordBuff [1], 14);
+			dwordBuff[1] ^= CipherFunct (dwordBuff [0], 13);
+			dwordBuff[0] ^= CipherFunct (dwordBuff [1], 12);
+			dwordBuff[1] ^= CipherFunct (dwordBuff [0], 11);
+			dwordBuff[0] ^= CipherFunct (dwordBuff [1], 10);
+			dwordBuff[1] ^= CipherFunct (dwordBuff [0],  9);
+			dwordBuff[0] ^= CipherFunct (dwordBuff [1],  8);
+			dwordBuff[1] ^= CipherFunct (dwordBuff [0],  7);
+			dwordBuff[0] ^= CipherFunct (dwordBuff [1],  6);
+			dwordBuff[1] ^= CipherFunct (dwordBuff [0],  5);
+			dwordBuff[0] ^= CipherFunct (dwordBuff [1],  4);
+			dwordBuff[1] ^= CipherFunct (dwordBuff [0],  3);
+			dwordBuff[0] ^= CipherFunct (dwordBuff [1],  2);
+			dwordBuff[1] ^= CipherFunct (dwordBuff [0],  1);
+			dwordBuff[0] ^= CipherFunct (dwordBuff [1],  0);
+
+
+
+			Buffer.BlockCopy (dwordBuff, 0, byteBuff, 0, BLOCK_BYTE_SIZE);
+			BSwap();
+
+			Permutation (byteBuff, dest, fpTab);
+		}
+
+
+	} // 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