Copied remotely
[mono.git] / mcs / class / corlib / System.Security.Cryptography / DES.cs
1 //
2 // System.Security.Cryptography.DES
3 //
4 // Author:
5 //      Sergey Chaban (serge@wildwestsoftware.com)
6 //      Sebastien Pouliot <sebastien@ximian.com>
7 //
8 // Portions (C) 2002 Motus Technologies Inc. (http://www.motus.com)
9 // Copyright (C) 2004 Novell, Inc (http://www.novell.com)
10 //
11 // Permission is hereby granted, free of charge, to any person obtaining
12 // a copy of this software and associated documentation files (the
13 // "Software"), to deal in the Software without restriction, including
14 // without limitation the rights to use, copy, modify, merge, publish,
15 // distribute, sublicense, and/or sell copies of the Software, and to
16 // permit persons to whom the Software is furnished to do so, subject to
17 // the following conditions:
18 // 
19 // The above copyright notice and this permission notice shall be
20 // included in all copies or substantial portions of the Software.
21 // 
22 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
23 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
24 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
25 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
26 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
27 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
28 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
29 //
30
31 using System;
32 using System.Globalization;
33 using System.Security.Cryptography;
34
35 // References:
36 // a.   FIPS PUB 46-3: Data Encryption Standard
37 //      http://csrc.nist.gov/publications/fips/fips46-3/fips46-3.pdf
38
39 namespace System.Security.Cryptography {
40
41 public abstract class DES : SymmetricAlgorithm {
42
43         const int blockSizeByte = 8;
44
45         public DES ()
46         {
47                 KeySizeValue = 64; 
48                 BlockSizeValue = 64; 
49                 FeedbackSizeValue = 8;
50
51                 LegalKeySizesValue = new KeySizes[1];
52                 LegalKeySizesValue[0] = new KeySizes(64, 64, 0);
53
54                 LegalBlockSizesValue = new KeySizes[1];
55                 LegalBlockSizesValue[0] = new KeySizes(64, 64, 0);
56         }
57
58         public static new DES Create () 
59         {
60                 return Create ("System.Security.Cryptography.DES");
61         }
62
63         public static new DES Create (string algo) 
64         {
65                 return (DES) CryptoConfig.CreateFromName (algo);
66         }
67
68         internal static ulong PackKey (byte[] key) 
69         {
70                 byte[] paritySetKey = new byte [blockSizeByte];
71                 // adapted from bouncycastle - see bouncycastle.txt
72                 for (int i=0; i < key.Length; i++) {
73                         byte b = key [i];
74                         paritySetKey [i] = (byte)((b & 0xfe) |
75                                 ((((b >> 1) ^ (b >> 2) ^ (b >> 3) ^ (b >> 4) ^
76                                 (b >> 5) ^ (b >> 6) ^ (b >> 7)) ^ 0x01) & 0x01));
77                 }
78
79                 ulong res = 0;
80                 for (int i = 0, sh = 8*blockSizeByte; (sh = sh - 8) >= 0; i++) {
81                         res |= (ulong) paritySetKey [i] << sh;
82                 }
83
84                 Array.Clear (paritySetKey, 0, paritySetKey.Length);
85                 return res;
86         }
87
88         // Ek(Ek(m)) = m
89         internal static readonly ulong[] weakKeys = {
90                 0x0101010101010101, /* 0000000 0000000 */
91                 0xFEFEFEFEFEFEFEFE, /* FFFFFFF FFFFFFF */
92                 0x1F1F1F1F0E0E0E0E, /* 0000000 FFFFFFF */
93                 0xE0E0E0E0F1F1F1F1  /* FFFFFFF 0000000 */
94         };
95
96         // Ek1(Ek2(m)) = m
97         internal static readonly ulong[] semiweakKeys = {
98                 0x01FE01FE01FE01FE, 0xFE01FE01FE01FE01,
99                 0x1FE01FE00EF10EF1, 0xE01FE01FF10EF10E,
100                 0x01E001E001F101F1, 0xE001E001F101F101,
101                 0x1FFE1FFE0EFE0EFE, 0xFE1FFE1FFE0EFE0E,
102                 0x011F011F010E010E, 0x1F011F010E010E01,
103                 0xE0FEE0FEF1FEF1FE, 0xFEE0FEE0FEF1FEF1
104         };
105
106         public static bool IsWeakKey (byte[] rgbKey) 
107         {
108                 if (rgbKey.Length != blockSizeByte)
109                         throw new CryptographicException (Locale.GetText ("Wrong Key Length"));
110
111                 ulong lk = PackKey (rgbKey);
112                 foreach (ulong wk in weakKeys) {
113                         if (lk == wk)
114                                 return true;
115                 }
116                 return false;
117         }
118
119         public static bool IsSemiWeakKey (byte[] rgbKey)
120         {
121                 if (rgbKey.Length != blockSizeByte)
122                         throw new CryptographicException (Locale.GetText ("Wrong Key Length"));
123
124                 ulong lk = PackKey (rgbKey);
125                 foreach (ulong swk in semiweakKeys) {
126                         if (lk == swk)
127                                 return true;
128                 }
129                 return false;
130         }
131
132         public override byte[] Key {
133                 get {
134                         if (KeyValue == null) {
135                                 // GenerateKey is responsible to return a valid key
136                                 // e.g. no weak or semi-weak keys
137                                 GenerateKey ();
138                         }
139                         return (byte[]) KeyValue.Clone ();
140                 }
141                 set {
142                         if (value == null)
143                                 throw new ArgumentNullException ("Key");
144                         if (value.Length != blockSizeByte)
145                                 throw new ArgumentException (Locale.GetText ("Wrong Key Length"));
146                         if (IsWeakKey (value))
147                                 throw new CryptographicException (Locale.GetText ("Weak Key"));
148                         if (IsSemiWeakKey (value))
149                                 throw new CryptographicException (Locale.GetText ("Semi Weak Key"));
150
151                         KeyValue = (byte[]) value.Clone ();
152                 }
153         }
154 }
155
156 }